08c3a6
commit c66c92181ddbd82306537a608e8c0282587131de
08c3a6
Author: DJ Delorie <dj@redhat.com>
08c3a6
Date:   Wed Mar 30 17:44:02 2022 -0400
08c3a6
08c3a6
    posix/glob.c: update from gnulib
08c3a6
    
08c3a6
    Copied from gnulib/lib/glob.c in order to fix rhbz 1982608
08c3a6
    Also fixes swbz 25659
08c3a6
    
08c3a6
    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
08c3a6
    Tested-by: Carlos O'Donell <carlos@redhat.com>
08c3a6
    (cherry picked from commit 7c477b57a31487eda516db02b9e04f22d1a6e6af)
08c3a6
08c3a6
diff --git a/posix/glob.c b/posix/glob.c
08c3a6
index 593a4c358f3d42e5..6af310a1aa31401a 100644
08c3a6
--- a/posix/glob.c
08c3a6
+++ b/posix/glob.c
08c3a6
@@ -21,13 +21,14 @@
08c3a6
    optimizes away the pattern == NULL test below.  */
08c3a6
 # define _GL_ARG_NONNULL(params)
08c3a6
 
08c3a6
-# include <config.h>
08c3a6
+# include <libc-config.h>
08c3a6
 
08c3a6
 #endif
08c3a6
 
08c3a6
 #include <glob.h>
08c3a6
 
08c3a6
 #include <errno.h>
08c3a6
+#include <fcntl.h>
08c3a6
 #include <sys/types.h>
08c3a6
 #include <sys/stat.h>
08c3a6
 #include <stdbool.h>
08c3a6
@@ -56,6 +57,8 @@
08c3a6
 # define sysconf(id) __sysconf (id)
08c3a6
 # define closedir(dir) __closedir (dir)
08c3a6
 # define opendir(name) __opendir (name)
08c3a6
+# undef dirfd
08c3a6
+# define dirfd(str) __dirfd (str)
08c3a6
 # define readdir(str) __readdir64 (str)
08c3a6
 # define getpwnam_r(name, bufp, buf, len, res) \
08c3a6
     __getpwnam_r (name, bufp, buf, len, res)
08c3a6
@@ -69,11 +72,8 @@
08c3a6
 # ifndef GLOB_LSTAT
08c3a6
 #  define GLOB_LSTAT            gl_lstat
08c3a6
 # endif
08c3a6
-# ifndef GLOB_STAT64
08c3a6
-#  define GLOB_STAT64           __stat64
08c3a6
-# endif
08c3a6
-# ifndef GLOB_LSTAT64
08c3a6
-#  define GLOB_LSTAT64          __lstat64
08c3a6
+# ifndef GLOB_FSTATAT64
08c3a6
+#  define GLOB_FSTATAT64        __fstatat64
08c3a6
 # endif
08c3a6
 # include <shlib-compat.h>
08c3a6
 #else /* !_LIBC */
08c3a6
@@ -88,8 +88,7 @@
08c3a6
 # define struct_stat            struct stat
08c3a6
 # define struct_stat64          struct stat
08c3a6
 # define GLOB_LSTAT             gl_lstat
08c3a6
-# define GLOB_STAT64            stat
08c3a6
-# define GLOB_LSTAT64           lstat
08c3a6
+# define GLOB_FSTATAT64         fstatat
08c3a6
 #endif /* _LIBC */
08c3a6
 
08c3a6
 #include <fnmatch.h>
08c3a6
@@ -215,7 +214,8 @@ glob_lstat (glob_t *pglob, int flags, const char *fullname)
08c3a6
   } ust;
08c3a6
   return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC)
08c3a6
           ? pglob->GLOB_LSTAT (fullname, &ust.st)
08c3a6
-          : GLOB_LSTAT64 (fullname, &ust.st64));
08c3a6
+          : GLOB_FSTATAT64 (AT_FDCWD, fullname, &ust.st64,
08c3a6
+                            AT_SYMLINK_NOFOLLOW));
08c3a6
 }
08c3a6
 
08c3a6
 /* Set *R = A + B.  Return true if the answer is mathematically
08c3a6
@@ -257,7 +257,8 @@ is_dir (char const *filename, int flags, glob_t const *pglob)
08c3a6
   struct_stat64 st64;
08c3a6
   return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC)
08c3a6
           ? pglob->gl_stat (filename, &st) == 0 && S_ISDIR (st.st_mode)
08c3a6
-          : GLOB_STAT64 (filename, &st64) == 0 && S_ISDIR (st64.st_mode));
08c3a6
+          : (GLOB_FSTATAT64 (AT_FDCWD, filename, &st64, 0) == 0
08c3a6
+             && S_ISDIR (st64.st_mode)));
08c3a6
 }
08c3a6
 
08c3a6
 /* Find the end of the sub-pattern in a brace expression.  */
08c3a6
@@ -747,6 +748,8 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
08c3a6
       else
08c3a6
         {
08c3a6
 #ifndef WINDOWS32
08c3a6
+          /* Recognize ~user as a shorthand for the specified user's home
08c3a6
+             directory.  */
08c3a6
           char *end_name = strchr (dirname, '/');
08c3a6
           char *user_name;
08c3a6
           int malloc_user_name = 0;
08c3a6
@@ -885,7 +888,22 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
08c3a6
               }
08c3a6
             scratch_buffer_free (&pwtmpbuf);
08c3a6
           }
08c3a6
-#endif /* !WINDOWS32 */
08c3a6
+#else /* WINDOWS32 */
08c3a6
+          /* On native Windows, access to a user's home directory
08c3a6
+             (via GetUserProfileDirectory) or to a user's environment
08c3a6
+             variables (via ExpandEnvironmentStringsForUser) requires
08c3a6
+             the credentials of the user.  Therefore we cannot support
08c3a6
+             the ~user syntax on this platform.
08c3a6
+             Handling ~user specially (and treat it like plain ~) if
08c3a6
+             user is getenv ("USERNAME") would not be a good idea,
08c3a6
+             since it would make people think that ~user is supported
08c3a6
+             in general.  */
08c3a6
+          if (flags & GLOB_TILDE_CHECK)
08c3a6
+            {
08c3a6
+              retval = GLOB_NOMATCH;
08c3a6
+              goto out;
08c3a6
+            }
08c3a6
+#endif /* WINDOWS32 */
08c3a6
         }
08c3a6
     }
08c3a6
 
08c3a6
@@ -1266,6 +1284,8 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
08c3a6
 {
08c3a6
   size_t dirlen = strlen (directory);
08c3a6
   void *stream = NULL;
08c3a6
+  struct scratch_buffer s;
08c3a6
+  scratch_buffer_init (&s);
08c3a6
 # define GLOBNAMES_MEMBERS(nnames) \
08c3a6
     struct globnames *next; size_t count; char *name[nnames];
08c3a6
   struct globnames { GLOBNAMES_MEMBERS (FLEXIBLE_ARRAY_MEMBER) };
08c3a6
@@ -1337,6 +1357,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
08c3a6
         }
08c3a6
       else
08c3a6
         {
08c3a6
+          int dfd = dirfd (stream);
08c3a6
           int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
08c3a6
                            | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0));
08c3a6
           flags |= GLOB_MAGCHAR;
08c3a6
@@ -1364,8 +1385,32 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
08c3a6
               if (flags & GLOB_ONLYDIR)
08c3a6
                 switch (readdir_result_type (d))
08c3a6
                   {
08c3a6
-                  case DT_DIR: case DT_LNK: case DT_UNKNOWN: break;
08c3a6
                   default: continue;
08c3a6
+                  case DT_DIR: break;
08c3a6
+                  case DT_LNK: case DT_UNKNOWN:
08c3a6
+                    /* The filesystem was too lazy to give us a hint,
08c3a6
+                       so we have to do it the hard way.  */
08c3a6
+                    if (__glibc_unlikely (dfd < 0 || flags & GLOB_ALTDIRFUNC))
08c3a6
+                      {
08c3a6
+                        size_t namelen = strlen (d.name);
08c3a6
+                        size_t need = dirlen + 1 + namelen + 1;
08c3a6
+                        if (s.length < need
08c3a6
+                            && !scratch_buffer_set_array_size (&s, need, 1))
08c3a6
+                          goto memory_error;
08c3a6
+                        char *p = mempcpy (s.data, directory, dirlen);
08c3a6
+                        *p = '/';
08c3a6
+                        p += p[-1] != '/';
08c3a6
+                        memcpy (p, d.name, namelen + 1);
08c3a6
+                        if (! is_dir (s.data, flags, pglob))
08c3a6
+                          continue;
08c3a6
+                      }
08c3a6
+                    else
08c3a6
+                      {
08c3a6
+                        struct_stat64 st64;
08c3a6
+                        if (! (GLOB_FSTATAT64 (dfd, d.name, &st64, 0) == 0
08c3a6
+                               && S_ISDIR (st64.st_mode)))
08c3a6
+                          continue;
08c3a6
+                      }
08c3a6
                   }
08c3a6
 
08c3a6
               if (fnmatch (pattern, d.name, fnm_flags) == 0)
08c3a6
@@ -1497,5 +1542,6 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
08c3a6
       __set_errno (save);
08c3a6
     }
08c3a6
 
08c3a6
+  scratch_buffer_free (&s);
08c3a6
   return result;
08c3a6
 }
08c3a6
diff --git a/sysdeps/unix/sysv/linux/glob64-time64.c b/sysdeps/unix/sysv/linux/glob64-time64.c
08c3a6
index a465f70905e5a8a3..95efe4c4f4624967 100644
08c3a6
--- a/sysdeps/unix/sysv/linux/glob64-time64.c
08c3a6
+++ b/sysdeps/unix/sysv/linux/glob64-time64.c
08c3a6
@@ -37,6 +37,7 @@
08c3a6
 # define GLOB_LSTAT      gl_lstat
08c3a6
 # define GLOB_STAT64     __stat64_time64
08c3a6
 # define GLOB_LSTAT64    __lstat64_time64
08c3a6
+# define GLOB_FSTATAT64    __fstatat64_time64
08c3a6
 
08c3a6
 # define COMPILE_GLOB64	1
08c3a6