summaryrefslogtreecommitdiff
path: root/sysdeps/generic/glob.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/generic/glob.c')
-rw-r--r--sysdeps/generic/glob.c76
1 files changed, 67 insertions, 9 deletions
diff --git a/sysdeps/generic/glob.c b/sysdeps/generic/glob.c
index 2d7ee67ca3..7ab48995e2 100644
--- a/sysdeps/generic/glob.c
+++ b/sysdeps/generic/glob.c
@@ -496,6 +496,14 @@ glob (pattern, flags, errfunc, pglob)
/* Find the filename. */
filename = strrchr (pattern, '/');
+#if defined __MSDOS__ || defined WINDOWS32
+ /* The case of "d:pattern". Since `:' is not allowed in
+ file names, we can safely assume that wherever it
+ happens in pattern, it signals the filename part. This
+ is so we could some day support patterns like "[a-z]:foo". */
+ if (filename == NULL)
+ filename = strchr (pattern, ':');
+#endif /* __MSDOS__ || WINDOWS32 */
if (filename == NULL)
{
/* This can mean two things: a simple name or "~name". The later
@@ -506,7 +514,7 @@ glob (pattern, flags, errfunc, pglob)
dirlen = strlen (pattern);
/* Set FILENAME to NULL as a special flag. This is ugly but
- other solutions would requiremuch more code. We test for
+ other solutions would require much more code. We test for
this special case below. */
filename = NULL;
}
@@ -532,6 +540,29 @@ glob (pattern, flags, errfunc, pglob)
{
char *newp;
dirlen = filename - pattern;
+#if defined __MSDOS__ || defined WINDOWS32
+ if (*filename == ':'
+ || (filename > pattern + 1 && filename[-1] == ':'))
+ {
+ char *drive_spec;
+
+ ++dirlen;
+ drive_spec = (char *) __alloca (dirlen + 1);
+#ifdef HAVE_MEMPCPY
+ *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
+#else
+ memcpy (drive_spec, pattern, dirlen);
+ drive_spec[dirlen] = '\0';
+#endif
+ /* For now, disallow wildcards in the drive spec, to
+ prevent infinite recursion in glob. */
+ if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
+ return GLOB_NOMATCH;
+ /* If this is "d:pattern", we need to copy `:' to DIRNAME
+ as well. If it's "d:/pattern", don't remove the slash
+ from "d:/", since "d:" and "d:/" are not the same.*/
+ }
+#endif
newp = (char *) __alloca (dirlen + 1);
#ifdef HAVE_MEMPCPY
*((char *) mempcpy (newp, pattern, dirlen)) = '\0';
@@ -542,7 +573,13 @@ glob (pattern, flags, errfunc, pglob)
dirname = newp;
++filename;
- if (filename[0] == '\0' && dirlen > 1)
+ if (filename[0] == '\0'
+#if defined __MSDOS__ || defined WINDOWS32
+ && dirname[dirlen - 1] != ':'
+ && (dirlen < 3 || dirname[dirlen - 2] != ':'
+ || dirname[dirlen - 1] != '/')
+#endif
+ && dirlen > 1)
/* "pattern/". Expand "pattern", appending slashes. */
{
int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
@@ -905,8 +942,9 @@ glob (pattern, flags, errfunc, pglob)
pglob->gl_flags = flags;
/* Now we know how large the gl_pathv vector must be. */
- new_pathv = realloc (pglob->gl_pathv,
- (pglob->gl_pathc + 1) * sizeof (char *));
+ new_pathv = (char **) realloc (pglob->gl_pathv,
+ ((pglob->gl_pathc + 1)
+ * sizeof (char *)));
if (new_pathv != NULL)
pglob->gl_pathv = new_pathv;
}
@@ -1026,11 +1064,31 @@ prefix_array (dirname, array, n)
{
register size_t i;
size_t dirlen = strlen (dirname);
+#if defined __MSDOS__ || defined WINDOWS32
+ int sep_char = '/';
+# define DIRSEP_CHAR sep_char
+#else
+# define DIRSEP_CHAR '/'
+#endif
if (dirlen == 1 && dirname[0] == '/')
/* DIRNAME is just "/", so normal prepending would get us "//foo".
We want "/foo" instead, so don't prepend any chars from DIRNAME. */
dirlen = 0;
+#if defined __MSDOS__ || defined WINDOWS32
+ else if (dirlen > 1)
+ {
+ if (dirname[dirlen - 1] == '/')
+ /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */
+ --dirlen;
+ else if (dirname[dirlen - 1] == ':')
+ {
+ /* DIRNAME is "d:". Use `:' instead of `/'. */
+ --dirlen;
+ sep_char = ':';
+ }
+ }
+#endif
for (i = 0; i < n; ++i)
{
@@ -1046,12 +1104,12 @@ prefix_array (dirname, array, n)
#ifdef HAVE_MEMPCPY
{
char *endp = (char *) mempcpy (new, dirname, dirlen);
- *endp++ = '/';
+ *endp++ = DIRSEP_CHAR;
mempcpy (endp, array[i], eltlen);
}
#else
memcpy (new, dirname, dirlen);
- new[dirlen] = '/';
+ new[dirlen] = DIRSEP_CHAR;
memcpy (&new[dirlen + 1], array[i], eltlen);
#endif
free ((__ptr_t) array[i]);
@@ -1131,7 +1189,7 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
if (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))
/* We need not do any tests. The PATTERN contains no meta
characters and we must not return an error therefore the
- result will always contain exactly the one name. */
+ result will always contain exactly one name. */
flags |= GLOB_NOCHECK;
else
{
@@ -1140,7 +1198,7 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
struct stat st;
size_t patlen = strlen (pattern);
size_t dirlen = strlen (directory);
- char *fullname = __alloca (dirlen + 1 + patlen + 1);
+ char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);
# ifdef HAVE_MEMPCPY
mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
@@ -1154,7 +1212,7 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
if (((flags & GLOB_ALTDIRFUNC)
? (*pglob->gl_stat) (fullname, &st)
: __stat (fullname, &st)) == 0)
- /* We found this file to be existing. No tell the rest
+ /* We found this file to be existing. Now tell the rest
of the function to copy this name into the result. */
flags |= GLOB_NOCHECK;
}