Update.
authorUlrich Drepper <drepper@redhat.com>
Thu, 30 Sep 2004 06:42:39 +0000 (06:42 +0000)
committerUlrich Drepper <drepper@redhat.com>
Thu, 30 Sep 2004 06:42:39 +0000 (06:42 +0000)
2004-09-29  Ulrich Drepper  <drepper@redhat.com>

* sysdeps/generic/glob.c (glob_in_dir): Don't blindly trust
readdir results; for symlinks or files of unknown type check using
stat whether the file exists.

* posix/tst-gnuglob.c (find_file): Handle leading "./".  Fix
recognition of files.

ChangeLog
posix/tst-gnuglob.c
sysdeps/generic/glob.c

index 8e07c9b..1ed4d7e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2004-09-29  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/generic/glob.c (glob_in_dir): Don't blindly trust
+       readdir results; for symlinks or files of unknown type check using
+       stat whether the file exists.
+
+       * posix/tst-gnuglob.c (find_file): Handle leading "./".  Fix
+       recognition of files.
+
 2004-09-29  Jakub Jelinek  <jakub@redhat.com>
 
        * time/tzfile.c (tzfile_mtime): New variable.
index b15dad1..72f3fa4 100644 (file)
@@ -30,7 +30,7 @@
 #include <sys/stat.h>
 
 
-/* #define DEBUG */
+// #define DEBUG
 #ifdef DEBUG
 # define PRINTF(fmt, args...) printf (fmt, ##args)
 #else
@@ -106,6 +106,9 @@ find_file (const char *s)
   if (strcmp (s, ".") == 0)
     return 0;
 
+  if (s[0] == '.' && s[1] == '/')
+    s += 2;
+
   while (*s != '\0')
     {
       char *endp = strchrnul (s, '/');
@@ -126,6 +129,10 @@ find_file (const char *s)
          errno = ENOENT;
          return -1;
        }
+
+      if (*endp == '\0')
+       return idx + 1;
+
       if (filesystem[idx].type != DT_DIR
          && (idx + 1 >= nfiles
              || filesystem[idx].level >= filesystem[idx + 1].level))
@@ -136,9 +143,6 @@ find_file (const char *s)
 
       ++idx;
 
-      if (*endp == '\0')
-       return idx;
-
       s = endp + 1;
       ++level;
     }
index a6d6ada..658599e 100644 (file)
@@ -1273,6 +1273,34 @@ weak_alias (__glob_pattern_p, glob_pattern_p)
 #endif /* !GLOB_ONLY_P */
 
 
+/* We put this in a separate function mainly to allow the memory
+   allocated with alloca to be recycled.  */
+#if !defined _LIBC || !defined GLOB_ONLY_P
+static int
+link_exists_p (const char *dir, size_t dirlen, const char *fname,
+              glob_t *pglob, int flags)
+{
+  size_t fnamelen = strlen (fname);
+  char *fullname = (char *) __alloca (dirlen + 1 + fnamelen + 1);
+  struct stat st;
+  struct stat64 st64;
+
+# ifdef HAVE_MEMPCPY
+  mempcpy (mempcpy (mempcpy (fullname, dir, dirlen), "/", 1),
+          fname, fnamelen + 1);
+# else
+  memcpy (fullname, dir, dirlen);
+  fullname[dirlen] = '/';
+  memcpy (&fullname[dirlen + 1], fname, fnamelen + 1);
+# endif
+
+  return (((flags & GLOB_ALTDIRFUNC)
+          ? (*pglob->gl_stat) (fullname, &st)
+          : __stat64 (fullname, &st64)) == 0);
+}
+#endif
+
+
 /* Like `glob', but PATTERN is a final pathname component,
    and matches are searched for in DIRECTORY.
    The GLOB_NOSORT bit in FLAGS is ignored.  No sorting is ever done.
@@ -1285,6 +1313,7 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
      int (*errfunc) (const char *, int);
      glob_t *pglob;
 {
+  size_t dirlen = strlen (directory);
   __ptr_t stream = NULL;
   struct globlink
     {
@@ -1315,7 +1344,6 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
       struct stat64 st64;
 # endif
       size_t patlen = strlen (pattern);
-      size_t dirlen = strlen (directory);
       char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);
 
 # ifdef HAVE_MEMPCPY
@@ -1428,22 +1456,32 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
 
                  if (fnmatch (pattern, name, fnm_flags) == 0)
                    {
-                     struct globlink *new = (struct globlink *)
-                       __alloca (sizeof (struct globlink));
-                     len = NAMLEN (d);
-                     new->name = (char *) malloc (len + 1);
-                     if (new->name == NULL)
-                       goto memory_error;
+                     /* If the file we found is a symlink we have to
+                        make sure the target file exists.  */
+                     if (
+#ifdef HAVE_D_TYPE
+                         (d->d_type != DT_UNKNOWN && d->d_type != DT_LNK) ||
+#endif
+                         link_exists_p (directory, dirlen, name, pglob,
+                                        flags))
+                       {
+                         struct globlink *new = (struct globlink *)
+                           __alloca (sizeof (struct globlink));
+                         len = NAMLEN (d);
+                         new->name = (char *) malloc (len + 1);
+                         if (new->name == NULL)
+                           goto memory_error;
 #ifdef HAVE_MEMPCPY
-                     *((char *) mempcpy ((__ptr_t) new->name, name, len))
-                       = '\0';
+                         *((char *) mempcpy ((__ptr_t) new->name, name, len))
+                           = '\0';
 #else
-                     memcpy ((__ptr_t) new->name, name, len);
-                     new->name[len] = '\0';
+                         memcpy ((__ptr_t) new->name, name, len);
+                         new->name[len] = '\0';
 #endif
-                     new->next = names;
-                     names = new;
-                     ++nfound;
+                         new->next = names;
+                         names = new;
+                         ++nfound;
+                       }
                    }
                }
            }