Blame posix/glob.c

Packit Service 82fcde
/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <glob.h>
Packit Service 82fcde
Packit Service 82fcde
#include <errno.h>
Packit Service 82fcde
#include <sys/types.h>
Packit Service 82fcde
#include <sys/stat.h>
Packit Service 82fcde
#include <stdbool.h>
Packit Service 82fcde
#include <stddef.h>
Packit Service 82fcde
#include <stdint.h>
Packit Service 82fcde
#include <assert.h>
Packit Service 82fcde
#include <unistd.h>
Packit Service 82fcde
Packit Service 82fcde
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
Packit Service 82fcde
# define WINDOWS32
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#ifndef WINDOWS32
Packit Service 82fcde
# include <pwd.h>
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#include <errno.h>
Packit Service 82fcde
#include <dirent.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <alloca.h>
Packit Service 82fcde
Packit Service 82fcde
#ifdef _LIBC
Packit Service 82fcde
# undef strdup
Packit Service 82fcde
# define strdup(str) __strdup (str)
Packit Service 82fcde
# define sysconf(id) __sysconf (id)
Packit Service 82fcde
# define closedir(dir) __closedir (dir)
Packit Service 82fcde
# define opendir(name) __opendir (name)
Packit Service 82fcde
# define readdir(str) __readdir64 (str)
Packit Service 82fcde
# define getpwnam_r(name, bufp, buf, len, res) \
Packit Service 82fcde
    __getpwnam_r (name, bufp, buf, len, res)
Packit Service 82fcde
# ifndef __lstat64
Packit Service 82fcde
#  define __lstat64(fname, buf) __lxstat64 (_STAT_VER, fname, buf)
Packit Service 82fcde
# endif
Packit Service 82fcde
# ifndef __stat64
Packit Service 82fcde
#  define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf)
Packit Service 82fcde
# endif
Packit Service 82fcde
# define struct_stat64		struct stat64
Packit Service 82fcde
# define FLEXIBLE_ARRAY_MEMBER
Packit Service 82fcde
# include <shlib-compat.h>
Packit Service 82fcde
#else /* !_LIBC */
Packit Service 82fcde
# define __glob                 glob
Packit Service 82fcde
# define __getlogin_r(buf, len) getlogin_r (buf, len)
Packit Service 82fcde
# define __lstat64(fname, buf)  lstat (fname, buf)
Packit Service 82fcde
# define __stat64(fname, buf)   stat (fname, buf)
Packit Service 82fcde
# define __fxstatat64(_, d, f, st, flag) fstatat (d, f, st, flag)
Packit Service 82fcde
# define struct_stat64          struct stat
Packit Service 82fcde
# ifndef __MVS__
Packit Service 82fcde
#  define __alloca              alloca
Packit Service 82fcde
# endif
Packit Service 82fcde
# define __readdir              readdir
Packit Service 82fcde
# define COMPILE_GLOB64
Packit Service 82fcde
#endif /* _LIBC */
Packit Service 82fcde
Packit Service 82fcde
#include <fnmatch.h>
Packit Service 82fcde
Packit Service 82fcde
#include <flexmember.h>
Packit Service 82fcde
#include <glob_internal.h>
Packit Service 82fcde
#include <scratch_buffer.h>
Packit Service 82fcde

Packit Service 82fcde
static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
Packit Service 82fcde
Packit Service 82fcde
typedef uint_fast8_t dirent_type;
Packit Service 82fcde
Packit Service 82fcde
#if !defined _LIBC && !defined HAVE_STRUCT_DIRENT_D_TYPE
Packit Service 82fcde
/* Any distinct values will do here.
Packit Service 82fcde
   Undef any existing macros out of the way.  */
Packit Service 82fcde
# undef DT_UNKNOWN
Packit Service 82fcde
# undef DT_DIR
Packit Service 82fcde
# undef DT_LNK
Packit Service 82fcde
# define DT_UNKNOWN 0
Packit Service 82fcde
# define DT_DIR 1
Packit Service 82fcde
# define DT_LNK 2
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* A representation of a directory entry which does not depend on the
Packit Service 82fcde
   layout of struct dirent, or the size of ino_t.  */
Packit Service 82fcde
struct readdir_result
Packit Service 82fcde
{
Packit Service 82fcde
  const char *name;
Packit Service 82fcde
#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
Packit Service 82fcde
  dirent_type type;
Packit Service 82fcde
#endif
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
/* Initialize and return type member of struct readdir_result.  */
Packit Service 82fcde
static dirent_type
Packit Service 82fcde
readdir_result_type (struct readdir_result d)
Packit Service 82fcde
{
Packit Service 82fcde
#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
Packit Service 82fcde
# define D_TYPE_TO_RESULT(source) (source)->d_type,
Packit Service 82fcde
  return d.type;
Packit Service 82fcde
#else
Packit Service 82fcde
# define D_TYPE_TO_RESULT(source)
Packit Service 82fcde
  return DT_UNKNOWN;
Packit Service 82fcde
#endif
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Construct an initializer for a struct readdir_result object from a
Packit Service 82fcde
   struct dirent *.  No copy of the name is made.  */
Packit Service 82fcde
#define READDIR_RESULT_INITIALIZER(source) \
Packit Service 82fcde
  {					   \
Packit Service 82fcde
    source->d_name,			   \
Packit Service 82fcde
    D_TYPE_TO_RESULT (source)		   \
Packit Service 82fcde
  }
Packit Service 82fcde
Packit Service 82fcde
/* Call gl_readdir on STREAM.  This macro can be overridden to reduce
Packit Service 82fcde
   type safety if an old interface version needs to be supported.  */
Packit Service 82fcde
#ifndef GL_READDIR
Packit Service 82fcde
# define GL_READDIR(pglob, stream) ((pglob)->gl_readdir (stream))
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Extract name and type from directory entry.  No copy of the name is
Packit Service 82fcde
   made.  If SOURCE is NULL, result name is NULL.  Keep in sync with
Packit Service 82fcde
   convert_dirent64 below.  */
Packit Service 82fcde
static struct readdir_result
Packit Service 82fcde
convert_dirent (const struct dirent *source)
Packit Service 82fcde
{
Packit Service 82fcde
  if (source == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      struct readdir_result result = { NULL, };
Packit Service 82fcde
      return result;
Packit Service 82fcde
    }
Packit Service 82fcde
  struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
Packit Service 82fcde
  return result;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#ifndef COMPILE_GLOB64
Packit Service 82fcde
/* Like convert_dirent, but works on struct dirent64 instead.  Keep in
Packit Service 82fcde
   sync with convert_dirent above.  */
Packit Service 82fcde
static struct readdir_result
Packit Service 82fcde
convert_dirent64 (const struct dirent64 *source)
Packit Service 82fcde
{
Packit Service 82fcde
  if (source == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      struct readdir_result result = { NULL, };
Packit Service 82fcde
      return result;
Packit Service 82fcde
    }
Packit Service 82fcde
  struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
Packit Service 82fcde
  return result;
Packit Service 82fcde
}
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#ifndef _LIBC
Packit Service 82fcde
/* The results of opendir() in this file are not used with dirfd and fchdir,
Packit Service 82fcde
   and we do not leak fds to any single-threaded code that could use stdio,
Packit Service 82fcde
   therefore save some unnecessary recursion in fchdir.c and opendir_safer.c.
Packit Service 82fcde
   FIXME - if the kernel ever adds support for multi-thread safety for
Packit Service 82fcde
   avoiding standard fds, then we should use opendir_safer.  */
Packit Service 82fcde
# ifdef GNULIB_defined_opendir
Packit Service 82fcde
#  undef opendir
Packit Service 82fcde
# endif
Packit Service 82fcde
# ifdef GNULIB_defined_closedir
Packit Service 82fcde
#  undef closedir
Packit Service 82fcde
# endif
Packit Service 82fcde
Packit Service 82fcde
/* Just use malloc.  */
Packit Service 82fcde
# define __libc_use_alloca(n) false
Packit Service 82fcde
# define alloca_account(len, avar) ((void) (len), (void) (avar), (void *) 0)
Packit Service 82fcde
# define extend_alloca_account(buf, len, newlen, avar) \
Packit Service 82fcde
    ((void) (buf), (void) (len), (void) (newlen), (void) (avar), (void *) 0)
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
static int
Packit Service 82fcde
glob_lstat (glob_t *pglob, int flags, const char *fullname)
Packit Service 82fcde
{
Packit Service 82fcde
/* Use on glob-lstat-compat.c to provide a compat symbol which does not
Packit Service 82fcde
   use lstat / gl_lstat.  */
Packit Service 82fcde
#ifdef GLOB_NO_LSTAT
Packit Service 82fcde
# define GL_LSTAT gl_stat
Packit Service 82fcde
# define LSTAT64 __stat64
Packit Service 82fcde
#else
Packit Service 82fcde
# define GL_LSTAT gl_lstat
Packit Service 82fcde
# define LSTAT64 __lstat64
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
  union
Packit Service 82fcde
  {
Packit Service 82fcde
    struct stat st;
Packit Service 82fcde
    struct_stat64 st64;
Packit Service 82fcde
  } ust;
Packit Service 82fcde
  return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC)
Packit Service 82fcde
          ? pglob->GL_LSTAT (fullname, &ust.st)
Packit Service 82fcde
          : LSTAT64 (fullname, &ust.st64));
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Set *R = A + B.  Return true if the answer is mathematically
Packit Service 82fcde
   incorrect due to overflow; in this case, *R is the low order
Packit Service 82fcde
   bits of the correct answer.  */
Packit Service 82fcde
Packit Service 82fcde
static bool
Packit Service 82fcde
size_add_wrapv (size_t a, size_t b, size_t *r)
Packit Service 82fcde
{
Packit Service 82fcde
#if 5 <= __GNUC__ && !defined __ICC
Packit Service 82fcde
  return __builtin_add_overflow (a, b, r);
Packit Service 82fcde
#else
Packit Service 82fcde
  *r = a + b;
Packit Service 82fcde
  return *r < a;
Packit Service 82fcde
#endif
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static bool
Packit Service 82fcde
glob_use_alloca (size_t alloca_used, size_t len)
Packit Service 82fcde
{
Packit Service 82fcde
  size_t size;
Packit Service 82fcde
  return (!size_add_wrapv (alloca_used, len, &size)
Packit Service 82fcde
          && __libc_use_alloca (size));
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static int glob_in_dir (const char *pattern, const char *directory,
Packit Service 82fcde
			int flags, int (*errfunc) (const char *, int),
Packit Service 82fcde
			glob_t *pglob, size_t alloca_used);
Packit Service 82fcde
static int prefix_array (const char *prefix, char **array, size_t n) __THROWNL;
Packit Service 82fcde
static int collated_compare (const void *, const void *) __THROWNL;
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Return true if FILENAME is a directory or a symbolic link to a directory.
Packit Service 82fcde
   Use FLAGS and PGLOB to resolve the filename.  */
Packit Service 82fcde
static bool
Packit Service 82fcde
is_dir (char const *filename, int flags, glob_t const *pglob)
Packit Service 82fcde
{
Packit Service 82fcde
  struct stat st;
Packit Service 82fcde
  struct_stat64 st64;
Packit Service 82fcde
  return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC)
Packit Service 82fcde
          ? pglob->gl_stat (filename, &st) == 0 && S_ISDIR (st.st_mode)
Packit Service 82fcde
          : __stat64 (filename, &st64) == 0 && S_ISDIR (st64.st_mode));
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Find the end of the sub-pattern in a brace expression.  */
Packit Service 82fcde
static const char *
Packit Service 82fcde
next_brace_sub (const char *cp, int flags)
Packit Service 82fcde
{
Packit Service 82fcde
  size_t depth = 0;
Packit Service 82fcde
  while (*cp != '\0')
Packit Service 82fcde
    if ((flags & GLOB_NOESCAPE) == 0 && *cp == '\\')
Packit Service 82fcde
      {
Packit Service 82fcde
	if (*++cp == '\0')
Packit Service 82fcde
	  break;
Packit Service 82fcde
	++cp;
Packit Service 82fcde
      }
Packit Service 82fcde
    else
Packit Service 82fcde
      {
Packit Service 82fcde
	if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
Packit Service 82fcde
	  break;
Packit Service 82fcde
Packit Service 82fcde
	if (*cp++ == '{')
Packit Service 82fcde
	  depth++;
Packit Service 82fcde
      }
Packit Service 82fcde
Packit Service 82fcde
  return *cp != '\0' ? cp : NULL;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#ifndef GLOB_ATTRIBUTE
Packit Service 82fcde
# define GLOB_ATTRIBUTE
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Do glob searching for PATTERN, placing results in PGLOB.
Packit Service 82fcde
   The bits defined above may be set in FLAGS.
Packit Service 82fcde
   If a directory cannot be opened or read and ERRFUNC is not nil,
Packit Service 82fcde
   it is called with the pathname that caused the error, and the
Packit Service 82fcde
   'errno' value from the failing call; if it returns non-zero
Packit Service 82fcde
   'glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
Packit Service 82fcde
   If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
Packit Service 82fcde
   Otherwise, 'glob' returns zero.  */
Packit Service 82fcde
int
Packit Service 82fcde
GLOB_ATTRIBUTE
Packit Service 82fcde
__glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
Packit Service 82fcde
	glob_t *pglob)
Packit Service 82fcde
{
Packit Service 82fcde
  const char *filename;
Packit Service 82fcde
  char *dirname = NULL;
Packit Service 82fcde
  size_t dirlen;
Packit Service 82fcde
  int status;
Packit Service 82fcde
  size_t oldcount;
Packit Service 82fcde
  int meta;
Packit Service 82fcde
  int dirname_modified;
Packit Service 82fcde
  int malloc_dirname = 0;
Packit Service 82fcde
  glob_t dirs;
Packit Service 82fcde
  int retval = 0;
Packit Service 82fcde
  size_t alloca_used = 0;
Packit Service 82fcde
Packit Service 82fcde
  if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      __set_errno (EINVAL);
Packit Service 82fcde
      return -1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* POSIX requires all slashes to be matched.  This means that with
Packit Service 82fcde
     a trailing slash we must match only directories.  */
Packit Service 82fcde
  if (pattern[0] && pattern[strlen (pattern) - 1] == '/')
Packit Service 82fcde
    flags |= GLOB_ONLYDIR;
Packit Service 82fcde
Packit Service 82fcde
  if (!(flags & GLOB_DOOFFS))
Packit Service 82fcde
    /* Have to do this so 'globfree' knows where to start freeing.  It
Packit Service 82fcde
       also makes all the code that uses gl_offs simpler. */
Packit Service 82fcde
    pglob->gl_offs = 0;
Packit Service 82fcde
Packit Service 82fcde
  if (!(flags & GLOB_APPEND))
Packit Service 82fcde
    {
Packit Service 82fcde
      pglob->gl_pathc = 0;
Packit Service 82fcde
      if (!(flags & GLOB_DOOFFS))
Packit Service 82fcde
	pglob->gl_pathv = NULL;
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  size_t i;
Packit Service 82fcde
Packit Service 82fcde
	  if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *))
Packit Service 82fcde
	    return GLOB_NOSPACE;
Packit Service 82fcde
Packit Service 82fcde
	  pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
Packit Service 82fcde
					      * sizeof (char *));
Packit Service 82fcde
	  if (pglob->gl_pathv == NULL)
Packit Service 82fcde
	    return GLOB_NOSPACE;
Packit Service 82fcde
Packit Service 82fcde
	  for (i = 0; i <= pglob->gl_offs; ++i)
Packit Service 82fcde
	    pglob->gl_pathv[i] = NULL;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (flags & GLOB_BRACE)
Packit Service 82fcde
    {
Packit Service 82fcde
      const char *begin;
Packit Service 82fcde
Packit Service 82fcde
      if (flags & GLOB_NOESCAPE)
Packit Service 82fcde
	begin = strchr (pattern, '{');
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  begin = pattern;
Packit Service 82fcde
	  while (1)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      if (*begin == '\0')
Packit Service 82fcde
		{
Packit Service 82fcde
		  begin = NULL;
Packit Service 82fcde
		  break;
Packit Service 82fcde
		}
Packit Service 82fcde
Packit Service 82fcde
	      if (*begin == '\\' && begin[1] != '\0')
Packit Service 82fcde
		++begin;
Packit Service 82fcde
	      else if (*begin == '{')
Packit Service 82fcde
		break;
Packit Service 82fcde
Packit Service 82fcde
	      ++begin;
Packit Service 82fcde
	    }
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      if (begin != NULL)
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Allocate working buffer large enough for our work.  Note that
Packit Service 82fcde
	    we have at least an opening and closing brace.  */
Packit Service 82fcde
	  size_t firstc;
Packit Service 82fcde
	  char *alt_start;
Packit Service 82fcde
	  const char *p;
Packit Service 82fcde
	  const char *next;
Packit Service 82fcde
	  const char *rest;
Packit Service 82fcde
	  size_t rest_len;
Packit Service 82fcde
	  char *onealt;
Packit Service 82fcde
	  size_t pattern_len = strlen (pattern) - 1;
Packit Service 82fcde
	  int alloca_onealt = glob_use_alloca (alloca_used, pattern_len);
Packit Service 82fcde
	  if (alloca_onealt)
Packit Service 82fcde
	    onealt = alloca_account (pattern_len, alloca_used);
Packit Service 82fcde
	  else
Packit Service 82fcde
	    {
Packit Service 82fcde
	      onealt = malloc (pattern_len);
Packit Service 82fcde
	      if (onealt == NULL)
Packit Service 82fcde
		return GLOB_NOSPACE;
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
	  /* We know the prefix for all sub-patterns.  */
Packit Service 82fcde
	  alt_start = mempcpy (onealt, pattern, begin - pattern);
Packit Service 82fcde
Packit Service 82fcde
	  /* Find the first sub-pattern and at the same time find the
Packit Service 82fcde
	     rest after the closing brace.  */
Packit Service 82fcde
	  next = next_brace_sub (begin + 1, flags);
Packit Service 82fcde
	  if (next == NULL)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      /* It is an invalid expression.  */
Packit Service 82fcde
	    illegal_brace:
Packit Service 82fcde
	      if (__glibc_unlikely (!alloca_onealt))
Packit Service 82fcde
		free (onealt);
Packit Service 82fcde
	      flags &= ~GLOB_BRACE;
Packit Service 82fcde
	      goto no_brace;
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
	  /* Now find the end of the whole brace expression.  */
Packit Service 82fcde
	  rest = next;
Packit Service 82fcde
	  while (*rest != '}')
Packit Service 82fcde
	    {
Packit Service 82fcde
	      rest = next_brace_sub (rest + 1, flags);
Packit Service 82fcde
	      if (rest == NULL)
Packit Service 82fcde
		/* It is an illegal expression.  */
Packit Service 82fcde
		goto illegal_brace;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  /* Please note that we now can be sure the brace expression
Packit Service 82fcde
	     is well-formed.  */
Packit Service 82fcde
	  rest_len = strlen (++rest) + 1;
Packit Service 82fcde
Packit Service 82fcde
	  /* We have a brace expression.  BEGIN points to the opening {,
Packit Service 82fcde
	     NEXT points past the terminator of the first element, and END
Packit Service 82fcde
	     points past the final }.  We will accumulate result names from
Packit Service 82fcde
	     recursive runs for each brace alternative in the buffer using
Packit Service 82fcde
	     GLOB_APPEND.  */
Packit Service 82fcde
	  firstc = pglob->gl_pathc;
Packit Service 82fcde
Packit Service 82fcde
	  p = begin + 1;
Packit Service 82fcde
	  while (1)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      int result;
Packit Service 82fcde
Packit Service 82fcde
	      /* Construct the new glob expression.  */
Packit Service 82fcde
	      mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
Packit Service 82fcde
Packit Service 82fcde
	      result = __glob (onealt,
Packit Service 82fcde
			       ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
Packit Service 82fcde
				| GLOB_APPEND),
Packit Service 82fcde
			       errfunc, pglob);
Packit Service 82fcde
Packit Service 82fcde
	      /* If we got an error, return it.  */
Packit Service 82fcde
	      if (result && result != GLOB_NOMATCH)
Packit Service 82fcde
		{
Packit Service 82fcde
		  if (__glibc_unlikely (!alloca_onealt))
Packit Service 82fcde
		    free (onealt);
Packit Service 82fcde
		  if (!(flags & GLOB_APPEND))
Packit Service 82fcde
		    {
Packit Service 82fcde
		      globfree (pglob);
Packit Service 82fcde
		      pglob->gl_pathc = 0;
Packit Service 82fcde
		    }
Packit Service 82fcde
		  return result;
Packit Service 82fcde
		}
Packit Service 82fcde
Packit Service 82fcde
	      if (*next == '}')
Packit Service 82fcde
		/* We saw the last entry.  */
Packit Service 82fcde
		break;
Packit Service 82fcde
Packit Service 82fcde
	      p = next + 1;
Packit Service 82fcde
	      next = next_brace_sub (p, flags);
Packit Service 82fcde
	      assert (next != NULL);
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
	  if (__glibc_unlikely (!alloca_onealt))
Packit Service 82fcde
	    free (onealt);
Packit Service 82fcde
Packit Service 82fcde
	  if (pglob->gl_pathc != firstc)
Packit Service 82fcde
	    /* We found some entries.  */
Packit Service 82fcde
	    return 0;
Packit Service 82fcde
	  else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
Packit Service 82fcde
	    return GLOB_NOMATCH;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
 no_brace:
Packit Service 82fcde
  oldcount = pglob->gl_pathc + pglob->gl_offs;
Packit Service 82fcde
Packit Service 82fcde
  /* Find the filename.  */
Packit Service 82fcde
  filename = strrchr (pattern, '/');
Packit Service 82fcde
Packit Service 82fcde
#if defined __MSDOS__ || defined WINDOWS32
Packit Service 82fcde
  /* The case of "d:pattern".  Since ':' is not allowed in
Packit Service 82fcde
     file names, we can safely assume that wherever it
Packit Service 82fcde
     happens in pattern, it signals the filename part.  This
Packit Service 82fcde
     is so we could some day support patterns like "[a-z]:foo".  */
Packit Service 82fcde
  if (filename == NULL)
Packit Service 82fcde
    filename = strchr (pattern, ':');
Packit Service 82fcde
#endif /* __MSDOS__ || WINDOWS32 */
Packit Service 82fcde
Packit Service 82fcde
  dirname_modified = 0;
Packit Service 82fcde
  if (filename == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* This can mean two things: a simple name or "~name".  The latter
Packit Service 82fcde
	 case is nothing but a notation for a directory.  */
Packit Service 82fcde
      if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
Packit Service 82fcde
	{
Packit Service 82fcde
	  dirname = (char *) pattern;
Packit Service 82fcde
	  dirlen = strlen (pattern);
Packit Service 82fcde
Packit Service 82fcde
	  /* Set FILENAME to NULL as a special flag.  This is ugly but
Packit Service 82fcde
	     other solutions would require much more code.  We test for
Packit Service 82fcde
	     this special case below.  */
Packit Service 82fcde
	  filename = NULL;
Packit Service 82fcde
	}
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  if (__glibc_unlikely (pattern[0] == '\0'))
Packit Service 82fcde
	    {
Packit Service 82fcde
	      dirs.gl_pathv = NULL;
Packit Service 82fcde
	      goto no_matches;
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
	  filename = pattern;
Packit Service 82fcde
	  dirname = (char *) ".";
Packit Service 82fcde
	  dirlen = 0;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (filename == pattern
Packit Service 82fcde
	   || (filename == pattern + 1 && pattern[0] == '\\'
Packit Service 82fcde
	       && (flags & GLOB_NOESCAPE) == 0))
Packit Service 82fcde
    {
Packit Service 82fcde
      /* "/pattern" or "\\/pattern".  */
Packit Service 82fcde
      dirname = (char *) "/";
Packit Service 82fcde
      dirlen = 1;
Packit Service 82fcde
      ++filename;
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      char *newp;
Packit Service 82fcde
      dirlen = filename - pattern;
Packit Service 82fcde
#if defined __MSDOS__ || defined WINDOWS32
Packit Service 82fcde
      if (*filename == ':'
Packit Service 82fcde
	  || (filename > pattern + 1 && filename[-1] == ':'))
Packit Service 82fcde
	{
Packit Service 82fcde
	  char *drive_spec;
Packit Service 82fcde
Packit Service 82fcde
	  ++dirlen;
Packit Service 82fcde
	  drive_spec = __alloca (dirlen + 1);
Packit Service 82fcde
	  *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
Packit Service 82fcde
	  /* For now, disallow wildcards in the drive spec, to
Packit Service 82fcde
	     prevent infinite recursion in glob.  */
Packit Service 82fcde
	  if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
Packit Service 82fcde
	    return GLOB_NOMATCH;
Packit Service 82fcde
	  /* If this is "d:pattern", we need to copy ':' to DIRNAME
Packit Service 82fcde
	     as well.  If it's "d:/pattern", don't remove the slash
Packit Service 82fcde
	     from "d:/", since "d:" and "d:/" are not the same.*/
Packit Service 82fcde
	}
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
      if (glob_use_alloca (alloca_used, dirlen + 1))
Packit Service 82fcde
	newp = alloca_account (dirlen + 1, alloca_used);
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  newp = malloc (dirlen + 1);
Packit Service 82fcde
	  if (newp == NULL)
Packit Service 82fcde
	    return GLOB_NOSPACE;
Packit Service 82fcde
	  malloc_dirname = 1;
Packit Service 82fcde
	}
Packit Service 82fcde
      *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
Packit Service 82fcde
      dirname = newp;
Packit Service 82fcde
      ++filename;
Packit Service 82fcde
Packit Service 82fcde
#if defined __MSDOS__ || defined WINDOWS32
Packit Service 82fcde
      bool drive_root = (dirlen > 1
Packit Service 82fcde
                         && (dirname[dirlen - 1] == ':'
Packit Service 82fcde
                             || (dirlen > 2 && dirname[dirlen - 2] == ':'
Packit Service 82fcde
                                 && dirname[dirlen - 1] == '/')));
Packit Service 82fcde
#else
Packit Service 82fcde
      bool drive_root = false;
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
      if (filename[0] == '\0' && dirlen > 1 && !drive_root)
Packit Service 82fcde
        /* "pattern/".  Expand "pattern", appending slashes.  */
Packit Service 82fcde
	{
Packit Service 82fcde
	  int orig_flags = flags;
Packit Service 82fcde
	  if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\')
Packit Service 82fcde
	    {
Packit Service 82fcde
	      /* "pattern\\/".  Remove the final backslash if it hasn't
Packit Service 82fcde
		 been quoted.  */
Packit Service 82fcde
	      char *p = (char *) &dirname[dirlen - 1];
Packit Service 82fcde
Packit Service 82fcde
	      while (p > dirname && p[-1] == '\\') --p;
Packit Service 82fcde
	      if ((&dirname[dirlen] - p) & 1)
Packit Service 82fcde
		{
Packit Service 82fcde
		  *(char *) &dirname[--dirlen] = '\0';
Packit Service 82fcde
		  flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
Packit Service 82fcde
		}
Packit Service 82fcde
	    }
Packit Service 82fcde
	  int val = __glob (dirname, flags | GLOB_MARK, errfunc, pglob);
Packit Service 82fcde
	  if (val == 0)
Packit Service 82fcde
	    pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
Packit Service 82fcde
			       | (flags & GLOB_MARK));
Packit Service 82fcde
	  else if (val == GLOB_NOMATCH && flags != orig_flags)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      /* Make sure globfree (&dirs); is a nop.  */
Packit Service 82fcde
	      dirs.gl_pathv = NULL;
Packit Service 82fcde
	      flags = orig_flags;
Packit Service 82fcde
	      oldcount = pglob->gl_pathc + pglob->gl_offs;
Packit Service 82fcde
	      goto no_matches;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  retval = val;
Packit Service 82fcde
	  goto out;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
Packit Service 82fcde
    {
Packit Service 82fcde
      if (dirname[1] == '\0' || dirname[1] == '/'
Packit Service 82fcde
	  || (!(flags & GLOB_NOESCAPE) && dirname[1] == '\\'
Packit Service 82fcde
	      && (dirname[2] == '\0' || dirname[2] == '/')))
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Look up home directory.  */
Packit Service 82fcde
	  char *home_dir = getenv ("HOME");
Packit Service 82fcde
	  int malloc_home_dir = 0;
Packit Service 82fcde
	  if (home_dir == NULL || home_dir[0] == '\0')
Packit Service 82fcde
	    {
Packit Service 82fcde
#ifdef WINDOWS32
Packit Service 82fcde
	      /* Windows NT defines HOMEDRIVE and HOMEPATH.  But give
Packit Service 82fcde
		 preference to HOME, because the user can change HOME.  */
Packit Service 82fcde
	      const char *home_drive = getenv ("HOMEDRIVE");
Packit Service 82fcde
	      const char *home_path = getenv ("HOMEPATH");
Packit Service 82fcde
Packit Service 82fcde
	      if (home_drive != NULL && home_path != NULL)
Packit Service 82fcde
		{
Packit Service 82fcde
		  size_t home_drive_len = strlen (home_drive);
Packit Service 82fcde
		  size_t home_path_len = strlen (home_path);
Packit Service 82fcde
		  char *mem = alloca (home_drive_len + home_path_len + 1);
Packit Service 82fcde
Packit Service 82fcde
		  memcpy (mem, home_drive, home_drive_len);
Packit Service 82fcde
		  memcpy (mem + home_drive_len, home_path, home_path_len + 1);
Packit Service 82fcde
		  home_dir = mem;
Packit Service 82fcde
		}
Packit Service 82fcde
	      else
Packit Service 82fcde
		home_dir = "c:/users/default"; /* poor default */
Packit Service 82fcde
#else
Packit Service 82fcde
	      int err;
Packit Service 82fcde
	      struct passwd *p;
Packit Service 82fcde
	      struct passwd pwbuf;
Packit Service 82fcde
	      struct scratch_buffer s;
Packit Service 82fcde
	      scratch_buffer_init (&s);
Packit Service 82fcde
	      while (true)
Packit Service 82fcde
		{
Packit Service 82fcde
		  p = NULL;
Packit Service 82fcde
		  err = __getlogin_r (s.data, s.length);
Packit Service 82fcde
		  if (err == 0)
Packit Service 82fcde
		    {
Packit Service 82fcde
# if defined HAVE_GETPWNAM_R || defined _LIBC
Packit Service 82fcde
		      size_t ssize = strlen (s.data) + 1;
Packit Service 82fcde
		      char *sdata = s.data;
Packit Service 82fcde
		      err = getpwnam_r (sdata, &pwbuf, sdata + ssize,
Packit Service 82fcde
					s.length - ssize, &p);
Packit Service 82fcde
# else
Packit Service 82fcde
		      p = getpwnam (s.data);
Packit Service 82fcde
		      if (p == NULL)
Packit Service 82fcde
			err = errno;
Packit Service 82fcde
# endif
Packit Service 82fcde
		    }
Packit Service 82fcde
		  if (err != ERANGE)
Packit Service 82fcde
		    break;
Packit Service 82fcde
		  if (!scratch_buffer_grow (&s))
Packit Service 82fcde
		    {
Packit Service 82fcde
		      retval = GLOB_NOSPACE;
Packit Service 82fcde
		      goto out;
Packit Service 82fcde
		    }
Packit Service 82fcde
		}
Packit Service 82fcde
	      if (err == 0)
Packit Service 82fcde
		{
Packit Service 82fcde
		  home_dir = strdup (p->pw_dir);
Packit Service 82fcde
		  malloc_home_dir = 1;
Packit Service 82fcde
		}
Packit Service 82fcde
	      scratch_buffer_free (&s);
Packit Service 82fcde
	      if (err == 0 && home_dir == NULL)
Packit Service 82fcde
		{
Packit Service 82fcde
		  retval = GLOB_NOSPACE;
Packit Service 82fcde
		  goto out;
Packit Service 82fcde
		}
Packit Service 82fcde
#endif /* WINDOWS32 */
Packit Service 82fcde
	    }
Packit Service 82fcde
	  if (home_dir == NULL || home_dir[0] == '\0')
Packit Service 82fcde
	    {
Packit Service 82fcde
	      if (__glibc_unlikely (malloc_home_dir))
Packit Service 82fcde
		free (home_dir);
Packit Service 82fcde
	      if (flags & GLOB_TILDE_CHECK)
Packit Service 82fcde
		{
Packit Service 82fcde
		  retval = GLOB_NOMATCH;
Packit Service 82fcde
		  goto out;
Packit Service 82fcde
		}
Packit Service 82fcde
	      else
Packit Service 82fcde
		{
Packit Service 82fcde
		  home_dir = (char *) "~"; /* No luck.  */
Packit Service 82fcde
		  malloc_home_dir = 0;
Packit Service 82fcde
		}
Packit Service 82fcde
	    }
Packit Service 82fcde
	  /* Now construct the full directory.  */
Packit Service 82fcde
	  if (dirname[1] == '\0')
Packit Service 82fcde
	    {
Packit Service 82fcde
	      if (__glibc_unlikely (malloc_dirname))
Packit Service 82fcde
		free (dirname);
Packit Service 82fcde
Packit Service 82fcde
	      dirname = home_dir;
Packit Service 82fcde
	      dirlen = strlen (dirname);
Packit Service 82fcde
	      malloc_dirname = malloc_home_dir;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  else
Packit Service 82fcde
	    {
Packit Service 82fcde
	      char *newp;
Packit Service 82fcde
	      size_t home_len = strlen (home_dir);
Packit Service 82fcde
	      int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen);
Packit Service 82fcde
	      if (use_alloca)
Packit Service 82fcde
		newp = alloca_account (home_len + dirlen, alloca_used);
Packit Service 82fcde
	      else
Packit Service 82fcde
		{
Packit Service 82fcde
		  newp = malloc (home_len + dirlen);
Packit Service 82fcde
		  if (newp == NULL)
Packit Service 82fcde
		    {
Packit Service 82fcde
		      if (__glibc_unlikely (malloc_home_dir))
Packit Service 82fcde
			free (home_dir);
Packit Service 82fcde
		      retval = GLOB_NOSPACE;
Packit Service 82fcde
		      goto out;
Packit Service 82fcde
		    }
Packit Service 82fcde
		}
Packit Service 82fcde
Packit Service 82fcde
	      mempcpy (mempcpy (newp, home_dir, home_len),
Packit Service 82fcde
		       &dirname[1], dirlen);
Packit Service 82fcde
Packit Service 82fcde
	      if (__glibc_unlikely (malloc_dirname))
Packit Service 82fcde
		free (dirname);
Packit Service 82fcde
Packit Service 82fcde
	      dirname = newp;
Packit Service 82fcde
	      dirlen += home_len - 1;
Packit Service 82fcde
	      malloc_dirname = !use_alloca;
Packit Service 82fcde
Packit Service 82fcde
	      if (__glibc_unlikely (malloc_home_dir))
Packit Service 82fcde
		free (home_dir);
Packit Service 82fcde
	    }
Packit Service 82fcde
	  dirname_modified = 1;
Packit Service 82fcde
	}
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
#ifndef WINDOWS32
Packit Service 82fcde
	  char *end_name = strchr (dirname, '/');
Packit Service 82fcde
	  char *user_name;
Packit Service 82fcde
	  int malloc_user_name = 0;
Packit Service 82fcde
	  char *unescape = NULL;
Packit Service 82fcde
Packit Service 82fcde
	  if (!(flags & GLOB_NOESCAPE))
Packit Service 82fcde
	    {
Packit Service 82fcde
	      if (end_name == NULL)
Packit Service 82fcde
		{
Packit Service 82fcde
		  unescape = strchr (dirname, '\\');
Packit Service 82fcde
		  if (unescape)
Packit Service 82fcde
		    end_name = strchr (unescape, '\0');
Packit Service 82fcde
		}
Packit Service 82fcde
	      else
Packit Service 82fcde
		unescape = memchr (dirname, '\\', end_name - dirname);
Packit Service 82fcde
	    }
Packit Service 82fcde
	  if (end_name == NULL)
Packit Service 82fcde
	    user_name = dirname + 1;
Packit Service 82fcde
	  else
Packit Service 82fcde
	    {
Packit Service 82fcde
	      char *newp;
Packit Service 82fcde
	      if (glob_use_alloca (alloca_used, end_name - dirname))
Packit Service 82fcde
		newp = alloca_account (end_name - dirname, alloca_used);
Packit Service 82fcde
	      else
Packit Service 82fcde
		{
Packit Service 82fcde
		  newp = malloc (end_name - dirname);
Packit Service 82fcde
		  if (newp == NULL)
Packit Service 82fcde
		    {
Packit Service 82fcde
		      retval = GLOB_NOSPACE;
Packit Service 82fcde
		      goto out;
Packit Service 82fcde
		    }
Packit Service 82fcde
		  malloc_user_name = 1;
Packit Service 82fcde
		}
Packit Service 82fcde
	      if (unescape != NULL)
Packit Service 82fcde
		{
Packit Service 82fcde
		  char *p = mempcpy (newp, dirname + 1,
Packit Service 82fcde
				     unescape - dirname - 1);
Packit Service 82fcde
		  char *q = unescape;
Packit Service 82fcde
		  while (q != end_name)
Packit Service 82fcde
		    {
Packit Service 82fcde
		      if (*q == '\\')
Packit Service 82fcde
			{
Packit Service 82fcde
			  if (q + 1 == end_name)
Packit Service 82fcde
			    {
Packit Service 82fcde
			      /* "~fo\\o\\" unescape to user_name "foo\\",
Packit Service 82fcde
				 but "~fo\\o\\/" unescape to user_name
Packit Service 82fcde
				 "foo".  */
Packit Service 82fcde
			      if (filename == NULL)
Packit Service 82fcde
				*p++ = '\\';
Packit Service 82fcde
			      break;
Packit Service 82fcde
			    }
Packit Service 82fcde
			  ++q;
Packit Service 82fcde
			}
Packit Service 82fcde
		      *p++ = *q++;
Packit Service 82fcde
		    }
Packit Service 82fcde
		  *p = '\0';
Packit Service 82fcde
		}
Packit Service 82fcde
	      else
Packit Service 82fcde
		*((char *) mempcpy (newp, dirname + 1, end_name - dirname - 1))
Packit Service 82fcde
		  = '\0';
Packit Service 82fcde
	      user_name = newp;
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
	  /* Look up specific user's home directory.  */
Packit Service 82fcde
	  {
Packit Service 82fcde
	    struct passwd *p;
Packit Service 82fcde
	    struct scratch_buffer pwtmpbuf;
Packit Service 82fcde
	    scratch_buffer_init (&pwtmpbuf);
Packit Service 82fcde
Packit Service 82fcde
#  if defined HAVE_GETPWNAM_R || defined _LIBC
Packit Service 82fcde
	    struct passwd pwbuf;
Packit Service 82fcde
Packit Service 82fcde
	    while (getpwnam_r (user_name, &pwbuf,
Packit Service 82fcde
			       pwtmpbuf.data, pwtmpbuf.length, &p)
Packit Service 82fcde
		   == ERANGE)
Packit Service 82fcde
	      {
Packit Service 82fcde
		if (!scratch_buffer_grow (&pwtmpbuf))
Packit Service 82fcde
		  {
Packit Service 82fcde
		    retval = GLOB_NOSPACE;
Packit Service 82fcde
		    goto out;
Packit Service 82fcde
		  }
Packit Service 82fcde
	      }
Packit Service 82fcde
#  else
Packit Service 82fcde
	    p = getpwnam (user_name);
Packit Service 82fcde
#  endif
Packit Service 82fcde
Packit Service 82fcde
	    if (__glibc_unlikely (malloc_user_name))
Packit Service 82fcde
	      free (user_name);
Packit Service 82fcde
Packit Service 82fcde
	    /* If we found a home directory use this.  */
Packit Service 82fcde
	    if (p != NULL)
Packit Service 82fcde
	      {
Packit Service 82fcde
		size_t home_len = strlen (p->pw_dir);
Packit Service 82fcde
		size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
Packit Service 1c5418
		char *d;
Packit Service 82fcde
Packit Service 1c5418
		if (__glibc_unlikely (malloc_dirname))
Packit Service 1c5418
		  free (dirname);
Packit Service 1c5418
		malloc_dirname = 0;
Packit Service 1c5418
Packit Service 1c5418
		if (glob_use_alloca (alloca_used, home_len + rest_len + 1))
Packit Service 1c5418
		  dirname = alloca_account (home_len + rest_len + 1,
Packit Service 1c5418
					    alloca_used);
Packit Service 82fcde
		else
Packit Service 82fcde
		  {
Packit Service 1c5418
		    dirname = malloc (home_len + rest_len + 1);
Packit Service 1c5418
		    if (dirname == NULL)
Packit Service 82fcde
		      {
Packit Service 82fcde
			scratch_buffer_free (&pwtmpbuf);
Packit Service 82fcde
			retval = GLOB_NOSPACE;
Packit Service 82fcde
			goto out;
Packit Service 82fcde
		      }
Packit Service 1c5418
		    malloc_dirname = 1;
Packit Service 82fcde
		  }
Packit Service 1c5418
		d = mempcpy (dirname, p->pw_dir, home_len);
Packit Service 82fcde
		if (end_name != NULL)
Packit Service 82fcde
		  d = mempcpy (d, end_name, rest_len);
Packit Service 82fcde
		*d = '\0';
Packit Service 82fcde
Packit Service 82fcde
		dirlen = home_len + rest_len;
Packit Service 82fcde
		dirname_modified = 1;
Packit Service 82fcde
	      }
Packit Service 82fcde
	    else
Packit Service 82fcde
	      {
Packit Service 82fcde
		if (flags & GLOB_TILDE_CHECK)
Packit Service 82fcde
		  {
Packit Service 82fcde
		    /* We have to regard it as an error if we cannot find the
Packit Service 82fcde
		       home directory.  */
Packit Service 82fcde
		    retval = GLOB_NOMATCH;
Packit Service 82fcde
		    goto out;
Packit Service 82fcde
		  }
Packit Service 82fcde
	      }
Packit Service 82fcde
	    scratch_buffer_free (&pwtmpbuf);
Packit Service 82fcde
	  }
Packit Service 82fcde
#endif /* !WINDOWS32 */
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Now test whether we looked for "~" or "~NAME".  In this case we
Packit Service 82fcde
     can give the answer now.  */
Packit Service 82fcde
  if (filename == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
	size_t newcount = pglob->gl_pathc + pglob->gl_offs;
Packit Service 82fcde
	char **new_gl_pathv;
Packit Service 82fcde
Packit Service 82fcde
	if (newcount > SIZE_MAX / sizeof (char *) - 2)
Packit Service 82fcde
	  {
Packit Service 82fcde
	  nospace:
Packit Service 82fcde
	    free (pglob->gl_pathv);
Packit Service 82fcde
	    pglob->gl_pathv = NULL;
Packit Service 82fcde
	    pglob->gl_pathc = 0;
Packit Service 82fcde
	    retval = GLOB_NOSPACE;
Packit Service 82fcde
	    goto out;
Packit Service 82fcde
	  }
Packit Service 82fcde
Packit Service 82fcde
	new_gl_pathv = realloc (pglob->gl_pathv,
Packit Service 82fcde
				(newcount + 2) * sizeof (char *));
Packit Service 82fcde
	if (new_gl_pathv == NULL)
Packit Service 82fcde
	  goto nospace;
Packit Service 82fcde
	pglob->gl_pathv = new_gl_pathv;
Packit Service 82fcde
Packit Service 82fcde
	if (flags & GLOB_MARK && is_dir (dirname, flags, pglob))
Packit Service 82fcde
	  {
Packit Service 82fcde
	    char *p;
Packit Service 82fcde
	    pglob->gl_pathv[newcount] = malloc (dirlen + 2);
Packit Service 82fcde
	    if (pglob->gl_pathv[newcount] == NULL)
Packit Service 82fcde
	      goto nospace;
Packit Service 82fcde
	    p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen);
Packit Service 82fcde
	    p[0] = '/';
Packit Service 82fcde
	    p[1] = '\0';
Packit Service 82fcde
	    if (__glibc_unlikely (malloc_dirname))
Packit Service 82fcde
	      free (dirname);
Packit Service 82fcde
	  }
Packit Service 82fcde
	else
Packit Service 82fcde
	  {
Packit Service 82fcde
	    if (__glibc_unlikely (malloc_dirname))
Packit Service 82fcde
	      pglob->gl_pathv[newcount] = dirname;
Packit Service 82fcde
	    else
Packit Service 82fcde
	      {
Packit Service 82fcde
		pglob->gl_pathv[newcount] = strdup (dirname);
Packit Service 82fcde
		if (pglob->gl_pathv[newcount] == NULL)
Packit Service 82fcde
		  goto nospace;
Packit Service 82fcde
	      }
Packit Service 82fcde
	  }
Packit Service 82fcde
	pglob->gl_pathv[++newcount] = NULL;
Packit Service 82fcde
	++pglob->gl_pathc;
Packit Service 82fcde
	pglob->gl_flags = flags;
Packit Service 82fcde
Packit Service 82fcde
	return 0;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  meta = __glob_pattern_type (dirname, !(flags & GLOB_NOESCAPE));
Packit Service 82fcde
  /* meta is 1 if correct glob pattern containing metacharacters.
Packit Service 82fcde
     If meta has bit (1 << 2) set, it means there was an unterminated
Packit Service 82fcde
     [ which we handle the same, using fnmatch.  Broken unterminated
Packit Service 82fcde
     pattern bracket expressions ought to be rare enough that it is
Packit Service 82fcde
     not worth special casing them, fnmatch will do the right thing.  */
Packit Service 82fcde
  if (meta & (GLOBPAT_SPECIAL | GLOBPAT_BRACKET))
Packit Service 82fcde
    {
Packit Service 82fcde
      /* The directory name contains metacharacters, so we
Packit Service 82fcde
	 have to glob for the directory, and then glob for
Packit Service 82fcde
	 the pattern in each directory found.  */
Packit Service 82fcde
      size_t i;
Packit Service 82fcde
Packit Service 82fcde
      if (!(flags & GLOB_NOESCAPE) && dirlen > 0 && dirname[dirlen - 1] == '\\')
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* "foo\\/bar".  Remove the final backslash from dirname
Packit Service 82fcde
	     if it has not been quoted.  */
Packit Service 82fcde
	  char *p = (char *) &dirname[dirlen - 1];
Packit Service 82fcde
Packit Service 82fcde
	  while (p > dirname && p[-1] == '\\') --p;
Packit Service 82fcde
	  if ((&dirname[dirlen] - p) & 1)
Packit Service 82fcde
	    *(char *) &dirname[--dirlen] = '\0';
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      if (__glibc_unlikely ((flags & GLOB_ALTDIRFUNC) != 0))
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Use the alternative access functions also in the recursive
Packit Service 82fcde
	     call.  */
Packit Service 82fcde
	  dirs.gl_opendir = pglob->gl_opendir;
Packit Service 82fcde
	  dirs.gl_readdir = pglob->gl_readdir;
Packit Service 82fcde
	  dirs.gl_closedir = pglob->gl_closedir;
Packit Service 82fcde
	  dirs.gl_stat = pglob->gl_stat;
Packit Service 82fcde
	  dirs.gl_lstat = pglob->gl_lstat;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      status = __glob (dirname,
Packit Service 82fcde
		       ((flags & (GLOB_ERR | GLOB_NOESCAPE | GLOB_ALTDIRFUNC))
Packit Service 82fcde
			| GLOB_NOSORT | GLOB_ONLYDIR),
Packit Service 82fcde
		       errfunc, &dirs);
Packit Service 82fcde
      if (status != 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      retval = status;
Packit Service 82fcde
	      goto out;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  goto no_matches;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      /* We have successfully globbed the preceding directory name.
Packit Service 82fcde
	 For each name we found, call glob_in_dir on it and FILENAME,
Packit Service 82fcde
	 appending the results to PGLOB.  */
Packit Service 82fcde
      for (i = 0; i < dirs.gl_pathc; ++i)
Packit Service 82fcde
	{
Packit Service 82fcde
	  size_t old_pathc;
Packit Service 82fcde
Packit Service 82fcde
	  old_pathc = pglob->gl_pathc;
Packit Service 82fcde
	  status = glob_in_dir (filename, dirs.gl_pathv[i],
Packit Service 82fcde
				((flags | GLOB_APPEND)
Packit Service 82fcde
				 & ~(GLOB_NOCHECK | GLOB_NOMAGIC)),
Packit Service 82fcde
				errfunc, pglob, alloca_used);
Packit Service 82fcde
	  if (status == GLOB_NOMATCH)
Packit Service 82fcde
	    /* No matches in this directory.  Try the next.  */
Packit Service 82fcde
	    continue;
Packit Service 82fcde
Packit Service 82fcde
	  if (status != 0)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      globfree (&dirs);
Packit Service 82fcde
	      globfree (pglob);
Packit Service 82fcde
	      pglob->gl_pathc = 0;
Packit Service 82fcde
	      retval = status;
Packit Service 82fcde
	      goto out;
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
	  /* Stick the directory on the front of each name.  */
Packit Service 82fcde
	  if (prefix_array (dirs.gl_pathv[i],
Packit Service 82fcde
			    &pglob->gl_pathv[old_pathc + pglob->gl_offs],
Packit Service 82fcde
			    pglob->gl_pathc - old_pathc))
Packit Service 82fcde
	    {
Packit Service 82fcde
	      globfree (&dirs);
Packit Service 82fcde
	      globfree (pglob);
Packit Service 82fcde
	      pglob->gl_pathc = 0;
Packit Service 82fcde
	      retval = GLOB_NOSPACE;
Packit Service 82fcde
	      goto out;
Packit Service 82fcde
	    }
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      flags |= GLOB_MAGCHAR;
Packit Service 82fcde
Packit Service 82fcde
      /* We have ignored the GLOB_NOCHECK flag in the 'glob_in_dir' calls.
Packit Service 82fcde
	 But if we have not found any matching entry and the GLOB_NOCHECK
Packit Service 82fcde
	 flag was set we must return the input pattern itself.  */
Packit Service 82fcde
      if (pglob->gl_pathc + pglob->gl_offs == oldcount)
Packit Service 82fcde
	{
Packit Service 82fcde
	no_matches:
Packit Service 82fcde
	  /* No matches.  */
Packit Service 82fcde
	  if (flags & GLOB_NOCHECK)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      size_t newcount = pglob->gl_pathc + pglob->gl_offs;
Packit Service 82fcde
	      char **new_gl_pathv;
Packit Service 82fcde
Packit Service 82fcde
	      if (newcount > SIZE_MAX / sizeof (char *) - 2)
Packit Service 82fcde
		{
Packit Service 82fcde
		nospace2:
Packit Service 82fcde
		  globfree (&dirs);
Packit Service 82fcde
		  retval = GLOB_NOSPACE;
Packit Service 82fcde
		  goto out;
Packit Service 82fcde
		}
Packit Service 82fcde
Packit Service 82fcde
	      new_gl_pathv = realloc (pglob->gl_pathv,
Packit Service 82fcde
				      (newcount + 2) * sizeof (char *));
Packit Service 82fcde
	      if (new_gl_pathv == NULL)
Packit Service 82fcde
		goto nospace2;
Packit Service 82fcde
	      pglob->gl_pathv = new_gl_pathv;
Packit Service 82fcde
Packit Service 82fcde
	      pglob->gl_pathv[newcount] = strdup (pattern);
Packit Service 82fcde
	      if (pglob->gl_pathv[newcount] == NULL)
Packit Service 82fcde
		{
Packit Service 82fcde
		  globfree (&dirs);
Packit Service 82fcde
		  globfree (pglob);
Packit Service 82fcde
		  pglob->gl_pathc = 0;
Packit Service 82fcde
		  retval = GLOB_NOSPACE;
Packit Service 82fcde
		  goto out;
Packit Service 82fcde
		}
Packit Service 82fcde
Packit Service 82fcde
	      ++pglob->gl_pathc;
Packit Service 82fcde
	      ++newcount;
Packit Service 82fcde
Packit Service 82fcde
	      pglob->gl_pathv[newcount] = NULL;
Packit Service 82fcde
	      pglob->gl_flags = flags;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  else
Packit Service 82fcde
	    {
Packit Service 82fcde
	      globfree (&dirs);
Packit Service 82fcde
	      retval = GLOB_NOMATCH;
Packit Service 82fcde
	      goto out;
Packit Service 82fcde
	    }
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      globfree (&dirs);
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      size_t old_pathc = pglob->gl_pathc;
Packit Service 82fcde
      int orig_flags = flags;
Packit Service 82fcde
Packit Service 82fcde
      if (meta & GLOBPAT_BACKSLASH)
Packit Service 82fcde
	{
Packit Service 82fcde
	  char *p = strchr (dirname, '\\'), *q;
Packit Service 82fcde
	  /* We need to unescape the dirname string.  It is certainly
Packit Service 82fcde
	     allocated by alloca, as otherwise filename would be NULL
Packit Service 82fcde
	     or dirname wouldn't contain backslashes.  */
Packit Service 82fcde
	  q = p;
Packit Service 82fcde
	  do
Packit Service 82fcde
	    {
Packit Service 82fcde
	      if (*p == '\\')
Packit Service 82fcde
		{
Packit Service 82fcde
		  *q = *++p;
Packit Service 82fcde
		  --dirlen;
Packit Service 82fcde
		}
Packit Service 82fcde
	      else
Packit Service 82fcde
		*q = *p;
Packit Service 82fcde
	      ++q;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  while (*p++ != '\0');
Packit Service 82fcde
	  dirname_modified = 1;
Packit Service 82fcde
	}
Packit Service 82fcde
      if (dirname_modified)
Packit Service 82fcde
	flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
Packit Service 82fcde
      status = glob_in_dir (filename, dirname, flags, errfunc, pglob,
Packit Service 82fcde
			    alloca_used);
Packit Service 82fcde
      if (status != 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  if (status == GLOB_NOMATCH && flags != orig_flags
Packit Service 82fcde
	      && pglob->gl_pathc + pglob->gl_offs == oldcount)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      /* Make sure globfree (&dirs); is a nop.  */
Packit Service 82fcde
	      dirs.gl_pathv = NULL;
Packit Service 82fcde
	      flags = orig_flags;
Packit Service 82fcde
	      goto no_matches;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  retval = status;
Packit Service 82fcde
	  goto out;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      if (dirlen > 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Stick the directory on the front of each name.  */
Packit Service 82fcde
	  if (prefix_array (dirname,
Packit Service 82fcde
			    &pglob->gl_pathv[old_pathc + pglob->gl_offs],
Packit Service 82fcde
			    pglob->gl_pathc - old_pathc))
Packit Service 82fcde
	    {
Packit Service 82fcde
	      globfree (pglob);
Packit Service 82fcde
	      pglob->gl_pathc = 0;
Packit Service 82fcde
	      retval = GLOB_NOSPACE;
Packit Service 82fcde
	      goto out;
Packit Service 82fcde
	    }
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (flags & GLOB_MARK)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Append slashes to directory names.  */
Packit Service 82fcde
      size_t i;
Packit Service 82fcde
Packit Service 82fcde
      for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i)
Packit Service 82fcde
	if (is_dir (pglob->gl_pathv[i], flags, pglob))
Packit Service 82fcde
	  {
Packit Service 82fcde
	    size_t len = strlen (pglob->gl_pathv[i]) + 2;
Packit Service 82fcde
	    char *new = realloc (pglob->gl_pathv[i], len);
Packit Service 82fcde
	    if (new == NULL)
Packit Service 82fcde
	      {
Packit Service 82fcde
		globfree (pglob);
Packit Service 82fcde
		pglob->gl_pathc = 0;
Packit Service 82fcde
		retval = GLOB_NOSPACE;
Packit Service 82fcde
		goto out;
Packit Service 82fcde
	      }
Packit Service 82fcde
	    strcpy (&new[len - 2], "/");
Packit Service 82fcde
	    pglob->gl_pathv[i] = new;
Packit Service 82fcde
	  }
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (!(flags & GLOB_NOSORT))
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Sort the vector.  */
Packit Service 82fcde
      qsort (&pglob->gl_pathv[oldcount],
Packit Service 82fcde
	     pglob->gl_pathc + pglob->gl_offs - oldcount,
Packit Service 82fcde
	     sizeof (char *), collated_compare);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
 out:
Packit Service 82fcde
  if (__glibc_unlikely (malloc_dirname))
Packit Service 82fcde
    free (dirname);
Packit Service 82fcde
Packit Service 82fcde
  return retval;
Packit Service 82fcde
}
Packit Service 82fcde
#if defined _LIBC && !defined __glob
Packit Service 82fcde
versioned_symbol (libc, __glob, glob, GLIBC_2_27);
Packit Service 82fcde
libc_hidden_ver (__glob, glob)
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Do a collated comparison of A and B.  */
Packit Service 82fcde
static int
Packit Service 82fcde
collated_compare (const void *a, const void *b)
Packit Service 82fcde
{
Packit Service 82fcde
  char *const *ps1 = a; char *s1 = *ps1;
Packit Service 82fcde
  char *const *ps2 = b; char *s2 = *ps2;
Packit Service 82fcde
Packit Service 82fcde
  if (s1 == s2)
Packit Service 82fcde
    return 0;
Packit Service 82fcde
  if (s1 == NULL)
Packit Service 82fcde
    return 1;
Packit Service 82fcde
  if (s2 == NULL)
Packit Service 82fcde
    return -1;
Packit Service 82fcde
  return strcoll (s1, s2);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
Packit Service 82fcde
   elements in place.  Return nonzero if out of memory, zero if successful.
Packit Service 82fcde
   A slash is inserted between DIRNAME and each elt of ARRAY,
Packit Service 82fcde
   unless DIRNAME is just "/".  Each old element of ARRAY is freed.  */
Packit Service 82fcde
static int
Packit Service 82fcde
prefix_array (const char *dirname, char **array, size_t n)
Packit Service 82fcde
{
Packit Service 82fcde
  size_t i;
Packit Service 82fcde
  size_t dirlen = strlen (dirname);
Packit Service 82fcde
  char dirsep_char = '/';
Packit Service 82fcde
Packit Service 82fcde
  if (dirlen == 1 && dirname[0] == '/')
Packit Service 82fcde
    /* DIRNAME is just "/", so normal prepending would get us "//foo".
Packit Service 82fcde
       We want "/foo" instead, so don't prepend any chars from DIRNAME.  */
Packit Service 82fcde
    dirlen = 0;
Packit Service 82fcde
Packit Service 82fcde
#if defined __MSDOS__ || defined WINDOWS32
Packit Service 82fcde
  if (dirlen > 1)
Packit Service 82fcde
    {
Packit Service 82fcde
      if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
Packit Service 82fcde
	/* DIRNAME is "d:/".  Don't prepend the slash from DIRNAME.  */
Packit Service 82fcde
	--dirlen;
Packit Service 82fcde
      else if (dirname[dirlen - 1] == ':')
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* DIRNAME is "d:".  Use ':' instead of '/'.  */
Packit Service 82fcde
	  --dirlen;
Packit Service 82fcde
	  dirsep_char = ':';
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
  for (i = 0; i < n; ++i)
Packit Service 82fcde
    {
Packit Service 82fcde
      size_t eltlen = strlen (array[i]) + 1;
Packit Service 82fcde
      char *new = malloc (dirlen + 1 + eltlen);
Packit Service 82fcde
      if (new == NULL)
Packit Service 82fcde
	{
Packit Service 82fcde
	  while (i > 0)
Packit Service 82fcde
	    free (array[--i]);
Packit Service 82fcde
	  return 1;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      {
Packit Service 82fcde
	char *endp = mempcpy (new, dirname, dirlen);
Packit Service 82fcde
	*endp++ = dirsep_char;
Packit Service 82fcde
	mempcpy (endp, array[i], eltlen);
Packit Service 82fcde
      }
Packit Service 82fcde
      free (array[i]);
Packit Service 82fcde
      array[i] = new;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Like 'glob', but PATTERN is a final pathname component,
Packit Service 82fcde
   and matches are searched for in DIRECTORY.
Packit Service 82fcde
   The GLOB_NOSORT bit in FLAGS is ignored.  No sorting is ever done.
Packit Service 82fcde
   The GLOB_APPEND flag is assumed to be set (always appends).  */
Packit Service 82fcde
static int
Packit Service 82fcde
glob_in_dir (const char *pattern, const char *directory, int flags,
Packit Service 82fcde
	     int (*errfunc) (const char *, int),
Packit Service 82fcde
	     glob_t *pglob, size_t alloca_used)
Packit Service 82fcde
{
Packit Service 82fcde
  size_t dirlen = strlen (directory);
Packit Service 82fcde
  void *stream = NULL;
Packit Service 82fcde
# define GLOBNAMES_MEMBERS(nnames) \
Packit Service 82fcde
    struct globnames *next; size_t count; char *name[nnames];
Packit Service 82fcde
  struct globnames { GLOBNAMES_MEMBERS (FLEXIBLE_ARRAY_MEMBER) };
Packit Service 82fcde
  struct { GLOBNAMES_MEMBERS (64) } init_names_buf;
Packit Service 82fcde
  struct globnames *init_names = (struct globnames *) &init_names_buf;
Packit Service 82fcde
  struct globnames *names = init_names;
Packit Service 82fcde
  struct globnames *names_alloca = init_names;
Packit Service 82fcde
  size_t nfound = 0;
Packit Service 82fcde
  size_t cur = 0;
Packit Service 82fcde
  int meta;
Packit Service 82fcde
  int save;
Packit Service 82fcde
  int result;
Packit Service 82fcde
Packit Service 82fcde
  alloca_used += sizeof init_names_buf;
Packit Service 82fcde
Packit Service 82fcde
  init_names->next = NULL;
Packit Service 82fcde
  init_names->count = ((sizeof init_names_buf
Packit Service 82fcde
                        - offsetof (struct globnames, name))
Packit Service 82fcde
                       / sizeof init_names->name[0]);
Packit Service 82fcde
Packit Service 82fcde
  meta = __glob_pattern_type (pattern, !(flags & GLOB_NOESCAPE));
Packit Service 82fcde
  if (meta == GLOBPAT_NONE && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
Packit Service 82fcde
    {
Packit Service 82fcde
      /* We need not do any tests.  The PATTERN contains no meta
Packit Service 82fcde
	 characters and we must not return an error therefore the
Packit Service 82fcde
	 result will always contain exactly one name.  */
Packit Service 82fcde
      flags |= GLOB_NOCHECK;
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (meta == GLOBPAT_NONE)
Packit Service 82fcde
    {
Packit Service 82fcde
      size_t patlen = strlen (pattern);
Packit Service 82fcde
      size_t fullsize;
Packit Service 82fcde
      bool alloca_fullname
Packit Service 82fcde
        = (! size_add_wrapv (dirlen + 1, patlen + 1, &fullsize)
Packit Service 82fcde
           && glob_use_alloca (alloca_used, fullsize));
Packit Service 82fcde
      char *fullname;
Packit Service 82fcde
      if (alloca_fullname)
Packit Service 82fcde
        fullname = alloca_account (fullsize, alloca_used);
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  fullname = malloc (fullsize);
Packit Service 82fcde
	  if (fullname == NULL)
Packit Service 82fcde
	    return GLOB_NOSPACE;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
Packit Service 82fcde
			"/", 1),
Packit Service 82fcde
	       pattern, patlen + 1);
Packit Service 82fcde
      if (glob_lstat (pglob, flags, fullname) == 0
Packit Service 82fcde
	  || errno == EOVERFLOW)
Packit Service 82fcde
	/* We found this file to be existing.  Now tell the rest
Packit Service 82fcde
	   of the function to copy this name into the result.  */
Packit Service 82fcde
	flags |= GLOB_NOCHECK;
Packit Service 82fcde
Packit Service 82fcde
      if (__glibc_unlikely (!alloca_fullname))
Packit Service 82fcde
	free (fullname);
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      stream = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
Packit Service 82fcde
		? (*pglob->gl_opendir) (directory)
Packit Service 82fcde
		: opendir (directory));
Packit Service 82fcde
      if (stream == NULL)
Packit Service 82fcde
	{
Packit Service 82fcde
	  if (errno != ENOTDIR
Packit Service 82fcde
	      && ((errfunc != NULL && (*errfunc) (directory, errno))
Packit Service 82fcde
		  || (flags & GLOB_ERR)))
Packit Service 82fcde
	    return GLOB_ABORTED;
Packit Service 82fcde
	}
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
Packit Service 82fcde
			   | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0));
Packit Service 82fcde
	  flags |= GLOB_MAGCHAR;
Packit Service 82fcde
Packit Service 82fcde
	  while (1)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      struct readdir_result d;
Packit Service 82fcde
	      {
Packit Service 82fcde
		if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
Packit Service 82fcde
		  d = convert_dirent (GL_READDIR (pglob, stream));
Packit Service 82fcde
		else
Packit Service 82fcde
		  {
Packit Service 82fcde
#ifdef COMPILE_GLOB64
Packit Service 82fcde
		    d = convert_dirent (__readdir (stream));
Packit Service 82fcde
#else
Packit Service 82fcde
		    d = convert_dirent64 (__readdir64 (stream));
Packit Service 82fcde
#endif
Packit Service 82fcde
		  }
Packit Service 82fcde
	      }
Packit Service 82fcde
	      if (d.name == NULL)
Packit Service 82fcde
		break;
Packit Service 82fcde
Packit Service 82fcde
	      /* If we shall match only directories use the information
Packit Service 82fcde
		 provided by the dirent call if possible.  */
Packit Service 82fcde
	      if (flags & GLOB_ONLYDIR)
Packit Service 82fcde
		switch (readdir_result_type (d))
Packit Service 82fcde
		  {
Packit Service 82fcde
		  case DT_DIR: case DT_LNK: case DT_UNKNOWN: break;
Packit Service 82fcde
		  default: continue;
Packit Service 82fcde
		  }
Packit Service 82fcde
Packit Service 82fcde
	      if (fnmatch (pattern, d.name, fnm_flags) == 0)
Packit Service 82fcde
		{
Packit Service 82fcde
		  if (cur == names->count)
Packit Service 82fcde
		    {
Packit Service 82fcde
		      struct globnames *newnames;
Packit Service 82fcde
		      size_t count = names->count * 2;
Packit Service 82fcde
		      size_t nameoff = offsetof (struct globnames, name);
Packit Service 82fcde
		      size_t size = FLEXSIZEOF (struct globnames, name,
Packit Service 82fcde
						count * sizeof (char *));
Packit Service 82fcde
		      if ((SIZE_MAX - nameoff) / 2 / sizeof (char *)
Packit Service 82fcde
			  < names->count)
Packit Service 82fcde
			goto memory_error;
Packit Service 82fcde
		      if (glob_use_alloca (alloca_used, size))
Packit Service 82fcde
			newnames = names_alloca
Packit Service 82fcde
			  = alloca_account (size, alloca_used);
Packit Service 82fcde
		      else if ((newnames = malloc (size))
Packit Service 82fcde
			       == NULL)
Packit Service 82fcde
			goto memory_error;
Packit Service 82fcde
		      newnames->count = count;
Packit Service 82fcde
		      newnames->next = names;
Packit Service 82fcde
		      names = newnames;
Packit Service 82fcde
		      cur = 0;
Packit Service 82fcde
		    }
Packit Service 82fcde
		  names->name[cur] = strdup (d.name);
Packit Service 82fcde
		  if (names->name[cur] == NULL)
Packit Service 82fcde
		    goto memory_error;
Packit Service 82fcde
		  ++cur;
Packit Service 82fcde
		  ++nfound;
Packit Service 82fcde
		  if (SIZE_MAX - pglob->gl_offs <= nfound)
Packit Service 82fcde
		    goto memory_error;
Packit Service 82fcde
		}
Packit Service 82fcde
	    }
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (nfound == 0 && (flags & GLOB_NOCHECK))
Packit Service 82fcde
    {
Packit Service 82fcde
      size_t len = strlen (pattern);
Packit Service 82fcde
      nfound = 1;
Packit Service 82fcde
      names->name[cur] = malloc (len + 1);
Packit Service 82fcde
      if (names->name[cur] == NULL)
Packit Service 82fcde
	goto memory_error;
Packit Service 82fcde
      *((char *) mempcpy (names->name[cur++], pattern, len)) = '\0';
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  result = GLOB_NOMATCH;
Packit Service 82fcde
  if (nfound != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      char **new_gl_pathv;
Packit Service 82fcde
      result = 0;
Packit Service 82fcde
Packit Service 82fcde
      if (SIZE_MAX / sizeof (char *) - pglob->gl_pathc
Packit Service 82fcde
	  < pglob->gl_offs + nfound + 1)
Packit Service 82fcde
	goto memory_error;
Packit Service 82fcde
Packit Service 82fcde
      new_gl_pathv
Packit Service 82fcde
	= realloc (pglob->gl_pathv,
Packit Service 82fcde
		   (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
Packit Service 82fcde
		    * sizeof (char *));
Packit Service 82fcde
Packit Service 82fcde
      if (new_gl_pathv == NULL)
Packit Service 82fcde
	{
Packit Service 82fcde
	memory_error:
Packit Service 82fcde
	  while (1)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      struct globnames *old = names;
Packit Service 82fcde
	      for (size_t i = 0; i < cur; ++i)
Packit Service 82fcde
		free (names->name[i]);
Packit Service 82fcde
	      names = names->next;
Packit Service 82fcde
	      /* NB: we will not leak memory here if we exit without
Packit Service 82fcde
		 freeing the current block assigned to OLD.  At least
Packit Service 82fcde
		 the very first block is always allocated on the stack
Packit Service 82fcde
		 and this is the block assigned to OLD here.  */
Packit Service 82fcde
	      if (names == NULL)
Packit Service 82fcde
		{
Packit Service 82fcde
		  assert (old == init_names);
Packit Service 82fcde
		  break;
Packit Service 82fcde
		}
Packit Service 82fcde
	      cur = names->count;
Packit Service 82fcde
	      if (old == names_alloca)
Packit Service 82fcde
		names_alloca = names;
Packit Service 82fcde
	      else
Packit Service 82fcde
		free (old);
Packit Service 82fcde
	    }
Packit Service 82fcde
	  result = GLOB_NOSPACE;
Packit Service 82fcde
	}
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  while (1)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      struct globnames *old = names;
Packit Service 82fcde
	      for (size_t i = 0; i < cur; ++i)
Packit Service 82fcde
		new_gl_pathv[pglob->gl_offs + pglob->gl_pathc++]
Packit Service 82fcde
		  = names->name[i];
Packit Service 82fcde
	      names = names->next;
Packit Service 82fcde
	      /* NB: we will not leak memory here if we exit without
Packit Service 82fcde
		 freeing the current block assigned to OLD.  At least
Packit Service 82fcde
		 the very first block is always allocated on the stack
Packit Service 82fcde
		 and this is the block assigned to OLD here.  */
Packit Service 82fcde
	      if (names == NULL)
Packit Service 82fcde
		{
Packit Service 82fcde
		  assert (old == init_names);
Packit Service 82fcde
		  break;
Packit Service 82fcde
		}
Packit Service 82fcde
	      cur = names->count;
Packit Service 82fcde
	      if (old == names_alloca)
Packit Service 82fcde
		names_alloca = names;
Packit Service 82fcde
	      else
Packit Service 82fcde
		free (old);
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
	  pglob->gl_pathv = new_gl_pathv;
Packit Service 82fcde
Packit Service 82fcde
	  pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
Packit Service 82fcde
Packit Service 82fcde
	  pglob->gl_flags = flags;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (stream != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      save = errno;
Packit Service 82fcde
      if (__glibc_unlikely (flags & GLOB_ALTDIRFUNC))
Packit Service 82fcde
	(*pglob->gl_closedir) (stream);
Packit Service 82fcde
      else
Packit Service 82fcde
	closedir (stream);
Packit Service 82fcde
      __set_errno (save);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return result;
Packit Service 82fcde
}