Fix #117925 (Dov Grobgeld):

2003-08-16  Tor Lillqvist  <tml@iki.fi>

	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.
This commit is contained in:
Tor Lillqvist 2003-08-16 19:45:25 +00:00 committed by Tor Lillqvist
parent ed23bef565
commit 55d624d80c
10 changed files with 364 additions and 33 deletions

View File

@ -1,3 +1,22 @@
2003-08-16 Tor Lillqvist <tml@iki.fi>
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 <tml@iki.fi>
* glib/gmain.c (g_poll): [Win32] Don't exceed handle array

View File

@ -1,3 +1,22 @@
2003-08-16 Tor Lillqvist <tml@iki.fi>
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 <tml@iki.fi>
* glib/gmain.c (g_poll): [Win32] Don't exceed handle array

View File

@ -1,3 +1,22 @@
2003-08-16 Tor Lillqvist <tml@iki.fi>
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 <tml@iki.fi>
* glib/gmain.c (g_poll): [Win32] Don't exceed handle array

View File

@ -1,3 +1,22 @@
2003-08-16 Tor Lillqvist <tml@iki.fi>
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 <tml@iki.fi>
* glib/gmain.c (g_poll): [Win32] Don't exceed handle array

View File

@ -1,3 +1,22 @@
2003-08-16 Tor Lillqvist <tml@iki.fi>
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 <tml@iki.fi>
* glib/gmain.c (g_poll): [Win32] Don't exceed handle array

View File

@ -1,3 +1,22 @@
2003-08-16 Tor Lillqvist <tml@iki.fi>
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 <tml@iki.fi>
* glib/gmain.c (g_poll): [Win32] Don't exceed handle array

View File

@ -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 <literal>g_build_path (G_DIR_SEPARATOR_S, first_element, ....)</literal>.
* separator for filenames.
*
* On Unix, this function behaves identically to <literal>g_build_path
* (G_DIR_SEPARATOR_S, first_element, ....)</literal>.
*
* On Windows, it takes into account that either the backslash
* (<literal>\</literal> or slash (<literal>/</literal>) 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, &current_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
}
/**

View File

@ -83,6 +83,13 @@
#include <libintl.h>
#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

View File

@ -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
{

View File

@ -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)