From: Tor Lillqvist Date: Sat, 16 Aug 2003 19:45:25 +0000 (+0000) Subject: Fix #117925 (Dov Grobgeld): X-Git-Tag: GLIB_2_3_0~81 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=55d624d80cbc962c0dfbdecfba7e128b3b332e31;p=platform%2Fupstream%2Fglib.git Fix #117925 (Dov Grobgeld): 2003-08-16 Tor Lillqvist Fix #117925 (Dov Grobgeld): * glib/gutils.c (g_find_program_in_path, g_basename, g_path_get_basename, g_path_is_absolute, g_path_skip_root, g_path_get_dirname, g_get_any_init): On Win32, look also for slashes ('/') as pathname separators. * glib/gfileutils.c (g_file_open_tmp): Ditto. If the template contains a pathname separator, include the actual one in the error message, instead of always the canonical one. (g_build_filename): Separate implementation on Win32 that looks for either slash or backslash. Document Unix/Windows differences. * tests/testglib.c * tests/strfunc-test.c: Test above functionality on Win32. --- diff --git a/ChangeLog b/ChangeLog index 6b3a18e..841bcc6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2003-08-16 Tor Lillqvist + + Fix #117925 (Dov Grobgeld): + + * glib/gutils.c (g_find_program_in_path, g_basename, + g_path_get_basename, g_path_is_absolute, g_path_skip_root, + g_path_get_dirname, g_get_any_init): On Win32, look also for + slashes ('/') as pathname separators. + + * glib/gfileutils.c (g_file_open_tmp): Ditto. If the template + contains a pathname separator, include the actual one in the error + message, instead of always the canonical one. + + (g_build_filename): Separate implementation on Win32 that looks + for either slash or backslash. Document Unix/Windows differences. + + * tests/testglib.c + * tests/strfunc-test.c: Test above functionality on Win32. + 2003-08-15 Tor Lillqvist * glib/gmain.c (g_poll): [Win32] Don't exceed handle array diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 6b3a18e..841bcc6 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,22 @@ +2003-08-16 Tor Lillqvist + + Fix #117925 (Dov Grobgeld): + + * glib/gutils.c (g_find_program_in_path, g_basename, + g_path_get_basename, g_path_is_absolute, g_path_skip_root, + g_path_get_dirname, g_get_any_init): On Win32, look also for + slashes ('/') as pathname separators. + + * glib/gfileutils.c (g_file_open_tmp): Ditto. If the template + contains a pathname separator, include the actual one in the error + message, instead of always the canonical one. + + (g_build_filename): Separate implementation on Win32 that looks + for either slash or backslash. Document Unix/Windows differences. + + * tests/testglib.c + * tests/strfunc-test.c: Test above functionality on Win32. + 2003-08-15 Tor Lillqvist * glib/gmain.c (g_poll): [Win32] Don't exceed handle array diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 6b3a18e..841bcc6 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,22 @@ +2003-08-16 Tor Lillqvist + + Fix #117925 (Dov Grobgeld): + + * glib/gutils.c (g_find_program_in_path, g_basename, + g_path_get_basename, g_path_is_absolute, g_path_skip_root, + g_path_get_dirname, g_get_any_init): On Win32, look also for + slashes ('/') as pathname separators. + + * glib/gfileutils.c (g_file_open_tmp): Ditto. If the template + contains a pathname separator, include the actual one in the error + message, instead of always the canonical one. + + (g_build_filename): Separate implementation on Win32 that looks + for either slash or backslash. Document Unix/Windows differences. + + * tests/testglib.c + * tests/strfunc-test.c: Test above functionality on Win32. + 2003-08-15 Tor Lillqvist * glib/gmain.c (g_poll): [Win32] Don't exceed handle array diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 6b3a18e..841bcc6 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,22 @@ +2003-08-16 Tor Lillqvist + + Fix #117925 (Dov Grobgeld): + + * glib/gutils.c (g_find_program_in_path, g_basename, + g_path_get_basename, g_path_is_absolute, g_path_skip_root, + g_path_get_dirname, g_get_any_init): On Win32, look also for + slashes ('/') as pathname separators. + + * glib/gfileutils.c (g_file_open_tmp): Ditto. If the template + contains a pathname separator, include the actual one in the error + message, instead of always the canonical one. + + (g_build_filename): Separate implementation on Win32 that looks + for either slash or backslash. Document Unix/Windows differences. + + * tests/testglib.c + * tests/strfunc-test.c: Test above functionality on Win32. + 2003-08-15 Tor Lillqvist * glib/gmain.c (g_poll): [Win32] Don't exceed handle array diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 6b3a18e..841bcc6 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,22 @@ +2003-08-16 Tor Lillqvist + + Fix #117925 (Dov Grobgeld): + + * glib/gutils.c (g_find_program_in_path, g_basename, + g_path_get_basename, g_path_is_absolute, g_path_skip_root, + g_path_get_dirname, g_get_any_init): On Win32, look also for + slashes ('/') as pathname separators. + + * glib/gfileutils.c (g_file_open_tmp): Ditto. If the template + contains a pathname separator, include the actual one in the error + message, instead of always the canonical one. + + (g_build_filename): Separate implementation on Win32 that looks + for either slash or backslash. Document Unix/Windows differences. + + * tests/testglib.c + * tests/strfunc-test.c: Test above functionality on Win32. + 2003-08-15 Tor Lillqvist * glib/gmain.c (g_poll): [Win32] Don't exceed handle array diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 6b3a18e..841bcc6 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,22 @@ +2003-08-16 Tor Lillqvist + + Fix #117925 (Dov Grobgeld): + + * glib/gutils.c (g_find_program_in_path, g_basename, + g_path_get_basename, g_path_is_absolute, g_path_skip_root, + g_path_get_dirname, g_get_any_init): On Win32, look also for + slashes ('/') as pathname separators. + + * glib/gfileutils.c (g_file_open_tmp): Ditto. If the template + contains a pathname separator, include the actual one in the error + message, instead of always the canonical one. + + (g_build_filename): Separate implementation on Win32 that looks + for either slash or backslash. Document Unix/Windows differences. + + * tests/testglib.c + * tests/strfunc-test.c: Test above functionality on Win32. + 2003-08-15 Tor Lillqvist * glib/gmain.c (g_poll): [Win32] Don't exceed handle array diff --git a/glib/gfileutils.c b/glib/gfileutils.c index 121d81b..0381c80 100644 --- a/glib/gfileutils.c +++ b/glib/gfileutils.c @@ -65,6 +65,12 @@ #include "glibintl.h" +#ifdef G_OS_WIN32 +#define G_IS_DIR_SEPARATOR(c) (c == G_DIR_SEPARATOR || c == '/') +#else +#define G_IS_DIR_SEPARATOR(c) (c == G_DIR_SEPARATOR) +#endif + /** * g_file_test: * @filename: a filename to test @@ -749,21 +755,26 @@ g_file_open_tmp (const gchar *tmpl, const char *tmpdir; char *sep; char *fulltemplate; + const char *slash; if (tmpl == NULL) tmpl = ".XXXXXX"; - if (strchr (tmpl, G_DIR_SEPARATOR) + if ((slash = strchr (tmpl, G_DIR_SEPARATOR)) != NULL #ifdef G_OS_WIN32 - || strchr (tmpl, '/') + || (strchr (tmpl, '/') != NULL && (slash = "/")) #endif - ) + ) { + char c[2]; + c[0] = *slash; + c[1] = '\0'; + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Template '%s' invalid, should not contain a '%s'"), - tmpl, G_DIR_SEPARATOR_S); + tmpl, c); return -1; } @@ -781,7 +792,7 @@ g_file_open_tmp (const gchar *tmpl, tmpdir = g_get_tmp_dir (); - if (tmpdir [strlen (tmpdir) - 1] == G_DIR_SEPARATOR) + if (G_IS_DIR_SEPARATOR (tmpdir [strlen (tmpdir) - 1])) sep = ""; else sep = G_DIR_SEPARATOR_S; @@ -964,8 +975,17 @@ g_build_path (const gchar *separator, * @Varargs: remaining elements in path, terminated by %NULL * * Creates a filename from a series of elements using the correct - * separator for filenames. This function behaves identically - * to g_build_path (G_DIR_SEPARATOR_S, first_element, ....). + * separator for filenames. + * + * On Unix, this function behaves identically to g_build_path + * (G_DIR_SEPARATOR_S, first_element, ....). + * + * On Windows, it takes into account that either the backslash + * (\ or slash (/) can be used + * as separator in filenames, but otherwise behaves as on Unix. When + * file pathname separators need to be inserted, the one that last + * previously occurred in the parameters (reading from left to right) + * is used. * * No attempt is made to force the resulting filename to be an absolute * path. If the first element is a relative path, the result will @@ -977,6 +997,7 @@ gchar * g_build_filename (const gchar *first_element, ...) { +#ifndef G_OS_WIN32 gchar *str; va_list args; @@ -985,6 +1006,111 @@ g_build_filename (const gchar *first_element, va_end (args); return str; +#else + /* Code copied from g_build_pathv(), and modifed to use two + * alternative single-character separators. + */ + va_list args; + GString *result; + gboolean is_first = TRUE; + gboolean have_leading = FALSE; + const gchar *single_element = NULL; + const gchar *next_element; + const gchar *last_trailing = NULL; + gchar current_separator = '\\'; + + va_start (args, first_element); + + result = g_string_new (NULL); + + next_element = first_element; + + while (TRUE) + { + const gchar *element; + const gchar *start; + const gchar *end; + + if (next_element) + { + element = next_element; + next_element = va_arg (args, gchar *); + } + else + break; + + /* Ignore empty elements */ + if (!*element) + continue; + + start = element; + + if (TRUE) + { + while (start && + (*start == '\\' || *start == '/')) + { + current_separator = *start; + start++; + } + } + + end = start + strlen (start); + + if (TRUE) + { + while (end >= start + 1 && + (end[-1] == '\\' || end[-1] == '/')) + { + current_separator = end[-1]; + end--; + } + + last_trailing = end; + while (last_trailing >= element + 1 && + (last_trailing[-1] == '\\' || last_trailing[-1] == '/')) + last_trailing--; + + if (!have_leading) + { + /* If the leading and trailing separator strings are in the + * same element and overlap, the result is exactly that element + */ + if (last_trailing <= start) + single_element = element; + + g_string_append_len (result, element, start - element); + have_leading = TRUE; + } + else + single_element = NULL; + } + + if (end == start) + continue; + + if (!is_first) + g_string_append_len (result, ¤t_separator, 1); + + g_string_append_len (result, start, end - start); + is_first = FALSE; + } + + va_end (args); + + if (single_element) + { + g_string_free (result, TRUE); + return g_strdup (single_element); + } + else + { + if (last_trailing) + g_string_append (result, last_trailing); + + return g_string_free (result, FALSE); + } +#endif } /** diff --git a/glib/gutils.c b/glib/gutils.c index 6ea3b71..a90d3a3 100644 --- a/glib/gutils.c +++ b/glib/gutils.c @@ -83,6 +83,13 @@ #include #endif +/* G_IS_DIR_SEPARATOR probably should be made public in GLib 2.4 */ +#ifdef G_OS_WIN32 +#define G_IS_DIR_SEPARATOR(c) (c == G_DIR_SEPARATOR || c == '/') +#else +#define G_IS_DIR_SEPARATOR(c) (c == G_DIR_SEPARATOR) +#endif + const guint glib_major_version = GLIB_MAJOR_VERSION; const guint glib_minor_version = GLIB_MINOR_VERSION; const guint glib_micro_version = GLIB_MICRO_VERSION; @@ -250,7 +257,11 @@ g_find_program_in_path (const gchar *program) * don't look in PATH. */ if (g_path_is_absolute (program) - || strchr (program, G_DIR_SEPARATOR) != NULL) + || strchr (program, G_DIR_SEPARATOR) != NULL +#ifdef G_OS_WIN32 + || strchr (program, '/') != NULL +#endif + ) { if (g_file_test (program, G_FILE_TEST_IS_EXECUTABLE)) return g_strdup (program); @@ -402,6 +413,15 @@ g_basename (const gchar *file_name) g_return_val_if_fail (file_name != NULL, NULL); base = strrchr (file_name, G_DIR_SEPARATOR); + +#ifdef G_OS_WIN32 + { + gchar *q = strrchr (file_name, '/'); + if (base == NULL || (q != NULL && q > base)) + base = q; + } +#endif + if (base) return base + 1; @@ -442,7 +462,7 @@ g_path_get_basename (const gchar *file_name) last_nonslash = strlen (file_name) - 1; - while (last_nonslash >= 0 && file_name [last_nonslash] == G_DIR_SEPARATOR) + while (last_nonslash >= 0 && G_IS_DIR_SEPARATOR (file_name [last_nonslash])) last_nonslash--; if (last_nonslash == -1) @@ -457,7 +477,7 @@ g_path_get_basename (const gchar *file_name) base = last_nonslash; - while (base >=0 && file_name [base] != G_DIR_SEPARATOR) + while (base >=0 && !G_IS_DIR_SEPARATOR (file_name [base])) base--; #ifdef G_OS_WIN32 @@ -477,16 +497,12 @@ g_path_is_absolute (const gchar *file_name) { g_return_val_if_fail (file_name != NULL, FALSE); - if (file_name[0] == G_DIR_SEPARATOR -#ifdef G_OS_WIN32 - || file_name[0] == '/' -#endif - ) + if (G_IS_DIR_SEPARATOR (file_name[0])) return TRUE; #ifdef G_OS_WIN32 /* Recognize drive letter on native Windows */ - if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':' && (file_name[2] == G_DIR_SEPARATOR || file_name[2] == '/')) + if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2])) return TRUE; #endif /* G_OS_WIN32 */ @@ -499,23 +515,32 @@ g_path_skip_root (const gchar *file_name) g_return_val_if_fail (file_name != NULL, NULL); #ifdef G_PLATFORM_WIN32 - /* Skip \\server\share (Win32) or //server/share (Cygwin) */ - if (file_name[0] == G_DIR_SEPARATOR && - file_name[1] == G_DIR_SEPARATOR && + /* Skip \\server\share or //server/share */ + if (G_IS_DIR_SEPARATOR (file_name[0]) && + G_IS_DIR_SEPARATOR (file_name[1]) && file_name[2]) { gchar *p; - if ((p = strchr (file_name + 2, G_DIR_SEPARATOR)) > file_name + 2 && + p = strchr (file_name + 2, G_DIR_SEPARATOR); +#ifdef G_OS_WIN32 + { + gchar *q = strchr (file_name + 2, '/'); + if (p == NULL || (q != NULL && q < p)) + p = q; + } +#endif + if (p && + p > file_name + 2 && p[1]) { file_name = p + 1; - while (file_name[0] && file_name[0] != G_DIR_SEPARATOR) + while (file_name[0] && !G_IS_DIR_SEPARATOR (file_name[0])) file_name++; /* Possibly skip a backslash after the share name */ - if (file_name[0] == G_DIR_SEPARATOR) + if (G_IS_DIR_SEPARATOR (file_name[0])) file_name++; return (gchar *)file_name; @@ -524,16 +549,16 @@ g_path_skip_root (const gchar *file_name) #endif /* Skip initial slashes */ - if (file_name[0] == G_DIR_SEPARATOR) + if (G_IS_DIR_SEPARATOR (file_name[0])) { - while (file_name[0] == G_DIR_SEPARATOR) + while (G_IS_DIR_SEPARATOR (file_name[0])) file_name++; return (gchar *)file_name; } #ifdef G_OS_WIN32 /* Skip X:\ */ - if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR) + if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2])) return (gchar *)file_name + 3; #endif @@ -549,9 +574,16 @@ g_path_get_dirname (const gchar *file_name) g_return_val_if_fail (file_name != NULL, NULL); base = strrchr (file_name, G_DIR_SEPARATOR); +#ifdef G_OS_WIN32 + { + gchar *q = strrchr (file_name, '/'); + if (base == NULL || (q != NULL && q > base)) + base = q; + } +#endif if (!base) return g_strdup ("."); - while (base > file_name && *base == G_DIR_SEPARATOR) + while (base > file_name && G_IS_DIR_SEPARATOR (*base)) base--; len = (guint) 1 + base - file_name; @@ -792,7 +824,7 @@ g_get_any_init (void) gsize k; g_tmp_dir = g_strdup (P_tmpdir); k = strlen (g_tmp_dir); - if (k > 1 && g_tmp_dir[k - 1] == G_DIR_SEPARATOR) + if (k > 1 && G_IS_DIR_SEPARATOR (g_tmp_dir[k - 1])) g_tmp_dir[k - 1] = '\0'; } #endif diff --git a/tests/strfunc-test.c b/tests/strfunc-test.c index eeb7c97..dbac5e1 100644 --- a/tests/strfunc-test.c +++ b/tests/strfunc-test.c @@ -441,6 +441,39 @@ main (int argc, TEST (NULL, str_check (g_build_filename (S"x"S, S"y"S, S"z"S, NULL), S"x"S"y"S"z"S)); TEST (NULL, str_check (g_build_filename (S S"x"S S, S S"y"S S, S S"z"S S, NULL), S S"x"S"y"S"z"S S)); +#ifdef G_OS_WIN32 + + /* Test also using the slash as file name separator */ +#define U "/" + TEST (NULL, str_check (g_build_filename (NULL), "")); + TEST (NULL, str_check (g_build_filename (U, NULL), U)); + TEST (NULL, str_check (g_build_filename (U"x", NULL), U"x")); + TEST (NULL, str_check (g_build_filename ("x"U, NULL), "x"U)); + TEST (NULL, str_check (g_build_filename ("", U"x", NULL), U"x")); + TEST (NULL, str_check (g_build_filename ("", U"x", NULL), U"x")); + TEST (NULL, str_check (g_build_filename (U, "x", NULL), U"x")); + TEST (NULL, str_check (g_build_filename (U U, "x", NULL), U U"x")); + TEST (NULL, str_check (g_build_filename (U S, "x", NULL), U S"x")); + TEST (NULL, str_check (g_build_filename ("x"U, "", NULL), "x"U)); + TEST (NULL, str_check (g_build_filename ("x"S"y", "z"U"a", NULL), "x"S"y"S"z"U"a")); + TEST (NULL, str_check (g_build_filename ("x", U, NULL), "x"U)); + TEST (NULL, str_check (g_build_filename ("x", U U, NULL), "x"U U)); + TEST (NULL, str_check (g_build_filename ("x", S U, NULL), "x"S U)); + TEST (NULL, str_check (g_build_filename (U"x", "y", NULL), U"x"U"y")); + TEST (NULL, str_check (g_build_filename ("x", "y"U, NULL), "x"U"y"U)); + TEST (NULL, str_check (g_build_filename (U"x"U, U"y"U, NULL), U"x"U"y"U)); + TEST (NULL, str_check (g_build_filename (U"x"U U, U U"y"U, NULL), U"x"U"y"U)); + TEST (NULL, str_check (g_build_filename ("x", U, "y", NULL), "x"U"y")); + TEST (NULL, str_check (g_build_filename ("x", U U, "y", NULL), "x"U"y")); + TEST (NULL, str_check (g_build_filename ("x", U S, "y", NULL), "x"S"y")); + TEST (NULL, str_check (g_build_filename ("x", S U, "y", NULL), "x"U"y")); + TEST (NULL, str_check (g_build_filename ("x", U "y", "z", NULL), "x"U"y"U"z")); + TEST (NULL, str_check (g_build_filename ("x", S "y", "z", NULL), "x"S"y"S"z")); + TEST (NULL, str_check (g_build_filename ("x", S "y", "z", U, "a", "b", NULL), "x"S"y"S"z"U"a"U"b")); + TEST (NULL, str_check (g_build_filename (U"x"U, U"y"U, U"z"U, NULL), U"x"U"y"U"z"U)); + TEST (NULL, str_check (g_build_filename (U U"x"U U, U U"y"U U, U U"z"U U, NULL), U U"x"U"y"U"z"U U)); +#endif /* G_OS_WIN32 */ + #undef S { diff --git a/tests/testglib.c b/tests/testglib.c index 5695754..54a9153 100644 --- a/tests/testglib.c +++ b/tests/testglib.c @@ -336,7 +336,6 @@ main (int argc, gchar *filename; gchar *dirname; } dirname_checks[] = { -#ifndef G_OS_WIN32 { "/", "/" }, { "////", "/" }, { ".////", "." }, @@ -345,14 +344,16 @@ main (int argc, { "a/b", "a" }, { "a/b/", "a/b" }, { "c///", "c" }, -#else +#ifdef G_OS_WIN32 { "\\", "\\" }, { ".\\\\\\\\", "." }, { "..\\", ".." }, { "..\\\\\\\\", ".." }, { "a\\b", "a" }, - { "a\\b\\", "a\\b" }, - { "c\\\\\\", "c" }, + { "a\\b/", "a\\b" }, + { "a/b\\", "a/b" }, + { "c\\\\/", "c" }, + { "//\\", "/" }, #endif #ifdef G_WITH_CYGWIN { "//server/share///x", "//server/share" }, @@ -367,13 +368,12 @@ main (int argc, gchar *filename; gchar *without_root; } skip_root_checks[] = { -#ifndef G_OS_WIN32 { "/", "" }, { "//", "" }, { "/foo", "foo" }, { "//foo", "foo" }, { "a/b", NULL }, -#else +#ifdef G_OS_WIN32 { "\\", "" }, { "\\foo", "foo" }, { "\\\\server\\foo", "" }, @@ -448,6 +448,15 @@ main (int argc, g_assert (strcmp (string, "file") == 0); g_free (string); g_print ("ok\n"); +#ifdef G_OS_WIN32 + string = g_path_get_basename ("/foo/dir/"); + g_assert (strcmp (string, "dir") == 0); + g_free (string); + string = g_path_get_basename ("/foo/file"); + g_assert (strcmp (string, "file") == 0); + g_free (string); + g_print ("ok\n"); +#endif g_print ("checking g_path_get_dirname()..."); for (i = 0; i < n_dirname_checks; i++) @@ -1171,6 +1180,11 @@ main (int argc, g_print ("ok\n"); + if (g_get_charset (&string)) + g_print ("current charset is UTF-8: %s\n", string); + else + g_print ("current charset is not UTF-8: %s\n", string); + #ifdef G_PLATFORM_WIN32 g_print ("current locale: %s\n", g_win32_getlocale ()); g_print ("GLib DLL name tested for: %s\n", glib_dll); @@ -1235,6 +1249,18 @@ main (int argc, close (fd); g_clear_error (&error); +#ifdef G_OS_WIN32 + strcpy (template, "zap/barXXXXXX"); + fd = g_file_open_tmp (template, &name_used, &error); + if (fd != -1) + g_print ("g_file_open_tmp works even if template contains '/'\n"); + else + g_print ("g_file_open_tmp correctly returns error: %s\n", + error->message); + close (fd); + g_clear_error (&error); +#endif + strcpy (template, "zapXXXXXX"); fd = g_file_open_tmp (template, &name_used, &error); if (fd == -1)