From a51ab0a5abfa7b65783ff5a73cfa5dd2eb5840a2 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Tue, 27 Nov 2018 16:02:37 +0100 Subject: [PATCH] genviron: make g_environ_* case-insensitive on Windows g_environ_getenv(env, "PATH") and g_environ_setenv(env, "PATH", newpath) did not have the intended effect on Windows due to the environment block containing "Path=". Make these functions case-insensitive for Windows. --- glib/genviron.c | 22 +++++++++++++++++----- glib/tests/environment.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/glib/genviron.c b/glib/genviron.c index 9c8151c20..c6edb8354 100644 --- a/glib/genviron.c +++ b/glib/genviron.c @@ -44,11 +44,24 @@ #include "gquark.h" /* Environ array functions {{{1 */ +static gboolean +g_environ_matches (const gchar *env, const gchar *variable, gsize len) +{ +#ifdef G_OS_WIN32 + /* TODO handle Unicode environment variable names */ + /* Like filesystem paths, environment variables are case-insensitive. */ + return g_ascii_strncasecmp (env, variable, len) == 0 && env[len] == '='; +#else + return strncmp (env, variable, len) == 0 && env[len] == '='; +#endif +} + static gint g_environ_find (gchar **envp, const gchar *variable) { - gint len, i; + gsize len; + gint i; if (envp == NULL) return -1; @@ -57,8 +70,7 @@ g_environ_find (gchar **envp, for (i = 0; envp[i]; i++) { - if (strncmp (envp[i], variable, len) == 0 && - envp[i][len] == '=') + if (g_environ_matches (envp[i], variable, len)) return i; } @@ -155,7 +167,7 @@ g_environ_unsetenv_internal (gchar **envp, const gchar *variable, gboolean free_value) { - gint len; + gsize len; gchar **e, **f; len = strlen (variable); @@ -166,7 +178,7 @@ g_environ_unsetenv_internal (gchar **envp, e = f = envp; while (*e != NULL) { - if (strncmp (*e, variable, len) != 0 || (*e)[len] != '=') + if (!g_environ_matches (*e, variable, len)) { *f = *e; f++; diff --git a/glib/tests/environment.c b/glib/tests/environment.c index 65ee7b092..aba19a7ae 100644 --- a/glib/tests/environment.c +++ b/glib/tests/environment.c @@ -116,6 +116,44 @@ test_environ_null (void) g_assert (env == NULL); } +static void +test_environ_case (void) +{ + gchar **env; + const gchar *value; + + env = NULL; + + env = g_environ_setenv (env, "foo", "bar", TRUE); + value = g_environ_getenv (env, "foo"); + g_assert_cmpstr (value, ==, "bar"); + + value = g_environ_getenv (env, "Foo"); +#ifdef G_OS_WIN32 + g_assert_cmpstr (value, ==, "bar"); +#else + g_assert (value == NULL); +#endif + + env = g_environ_setenv (env, "FOO", "x", TRUE); + value = g_environ_getenv (env, "foo"); +#ifdef G_OS_WIN32 + g_assert_cmpstr (value, ==, "x"); +#else + g_assert_cmpstr (value, ==, "bar"); +#endif + + env = g_environ_unsetenv (env, "Foo"); + value = g_environ_getenv (env, "foo"); +#ifdef G_OS_WIN32 + g_assert (value == NULL); +#else + g_assert_cmpstr (value, ==, "bar"); +#endif + + g_strfreev (env); +} + int main (int argc, char **argv) { @@ -125,6 +163,7 @@ main (int argc, char **argv) g_test_add_func ("/environ/setenv", test_setenv); g_test_add_func ("/environ/array", test_environ_array); g_test_add_func ("/environ/null", test_environ_null); + g_test_add_func ("/environ/case", test_environ_case); return g_test_run (); }