about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-09-30 06:42:39 +0000
committerUlrich Drepper <drepper@redhat.com>2004-09-30 06:42:39 +0000
commit66b38fc99ecc3835502fae6851908b0d11d6b175 (patch)
tree1d27136d28fdf13ab181b367310012ed59108c32 /sysdeps
parent8930fcf9beee6c0d1ace2e4a67be1525f5d6b8aa (diff)
downloadglibc-66b38fc99ecc3835502fae6851908b0d11d6b175.tar.gz
glibc-66b38fc99ecc3835502fae6851908b0d11d6b175.tar.xz
glibc-66b38fc99ecc3835502fae6851908b0d11d6b175.zip
Update.
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.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/generic/glob.c66
1 files changed, 52 insertions, 14 deletions
diff --git a/sysdeps/generic/glob.c b/sysdeps/generic/glob.c
index a6d6ada8bd..658599ec1f 100644
--- a/sysdeps/generic/glob.c
+++ b/sysdeps/generic/glob.c
@@ -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;
+			}
 		    }
 		}
 	    }