mirror of
git://sourceware.org/git/glibc.git
synced 2025-04-06 14:10:30 +08:00
Carry over changes from 2.1 which increase the speed and fix some bugs.
This commit is contained in:
parent
e7a4703700
commit
37c6743250
539
posix/glob.c
539
posix/glob.c
@ -155,6 +155,12 @@ extern void abort (), exit ();
|
||||
|
||||
#endif /* Standard headers. */
|
||||
|
||||
#ifdef HAVE_GETLOGIN_R
|
||||
extern int getlogin_r __P ((char *, size_t));
|
||||
#else
|
||||
extern char *getlogin __P ((void));
|
||||
#endif
|
||||
|
||||
#ifndef ANSI_STRING
|
||||
|
||||
# ifndef bzero
|
||||
@ -180,7 +186,6 @@ extern void bcopy ();
|
||||
# define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __GNU_LIBRARY__
|
||||
# ifdef __GNUC__
|
||||
__inline
|
||||
@ -239,6 +244,17 @@ extern char *alloca ();
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# undef strdup
|
||||
# define strdup(str) __strdup (str)
|
||||
# define sysconf(id) __sysconf (id)
|
||||
# define closedir(dir) __closedir (dir)
|
||||
# define opendir(name) __opendir (name)
|
||||
# define readdir(str) __readdir (str)
|
||||
# define getpwnam_r(name, bufp, buf, len, res) \
|
||||
__getpwnam_r (name, bufp, buf, len, res)
|
||||
#endif
|
||||
|
||||
#if !(defined STDC_HEADERS || defined __GNU_LIBRARY__)
|
||||
# undef size_t
|
||||
# define size_t unsigned int
|
||||
@ -246,21 +262,25 @@ extern char *alloca ();
|
||||
|
||||
/* Some system header files erroneously define these.
|
||||
We want our own definitions from <fnmatch.h> to take precedence. */
|
||||
#undef FNM_PATHNAME
|
||||
#undef FNM_NOESCAPE
|
||||
#undef FNM_PERIOD
|
||||
#ifndef __GNU_LIBRARY__
|
||||
# undef FNM_PATHNAME
|
||||
# undef FNM_NOESCAPE
|
||||
# undef FNM_PERIOD
|
||||
#endif
|
||||
#include <fnmatch.h>
|
||||
|
||||
/* Some system header files erroneously define these.
|
||||
We want our own definitions from <glob.h> to take precedence. */
|
||||
#undef GLOB_ERR
|
||||
#undef GLOB_MARK
|
||||
#undef GLOB_NOSORT
|
||||
#undef GLOB_DOOFFS
|
||||
#undef GLOB_NOCHECK
|
||||
#undef GLOB_APPEND
|
||||
#undef GLOB_NOESCAPE
|
||||
#undef GLOB_PERIOD
|
||||
#ifndef __GNU_LIBRARY__
|
||||
# undef GLOB_ERR
|
||||
# undef GLOB_MARK
|
||||
# undef GLOB_NOSORT
|
||||
# undef GLOB_DOOFFS
|
||||
# undef GLOB_NOCHECK
|
||||
# undef GLOB_APPEND
|
||||
# undef GLOB_NOESCAPE
|
||||
# undef GLOB_PERIOD
|
||||
#endif
|
||||
#include <glob.h>
|
||||
|
||||
static
|
||||
@ -337,7 +357,7 @@ glob (pattern, flags, errfunc, pglob)
|
||||
glob_t *pglob;
|
||||
{
|
||||
const char *filename;
|
||||
char *dirname;
|
||||
const char *dirname;
|
||||
size_t dirlen;
|
||||
int status;
|
||||
int oldcount;
|
||||
@ -477,43 +497,98 @@ 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)
|
||||
{
|
||||
filename = pattern;
|
||||
/* This can mean two things: a simple name or "~name". The later
|
||||
case is nothing but a notation for a directory. */
|
||||
if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
|
||||
{
|
||||
dirname = pattern;
|
||||
dirlen = strlen (pattern);
|
||||
|
||||
/* Set FILENAME to NULL as a special flag. This is ugly but
|
||||
other solutions would require much more code. We test for
|
||||
this special case below. */
|
||||
filename = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
filename = pattern;
|
||||
#ifdef _AMIGA
|
||||
dirname = (char *) "";
|
||||
dirname = "";
|
||||
#else
|
||||
dirname = (char *) ".";
|
||||
dirname = ".";
|
||||
#endif
|
||||
dirlen = 0;
|
||||
dirlen = 0;
|
||||
}
|
||||
}
|
||||
else if (filename == pattern)
|
||||
{
|
||||
/* "/pattern". */
|
||||
dirname = (char *) "/";
|
||||
dirname = "/";
|
||||
dirlen = 1;
|
||||
++filename;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *newp;
|
||||
dirlen = filename - pattern;
|
||||
dirname = (char *) __alloca (dirlen + 1);
|
||||
#ifdef HAVE_MEMPCPY
|
||||
*((char *) mempcpy (dirname, pattern, dirlen)) = '\0';
|
||||
#else
|
||||
memcpy (dirname, pattern, dirlen);
|
||||
dirname[dirlen] = '\0';
|
||||
#endif
|
||||
++filename;
|
||||
}
|
||||
#if defined __MSDOS__ || defined WINDOWS32
|
||||
if (*filename == ':'
|
||||
|| (filename > pattern + 1 && filename[-1] == ':'))
|
||||
{
|
||||
char *drive_spec;
|
||||
|
||||
if (filename[0] == '\0' && dirlen > 1)
|
||||
/* "pattern/". Expand "pattern", appending slashes. */
|
||||
{
|
||||
int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
|
||||
if (val == 0)
|
||||
pglob->gl_flags = (pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK);
|
||||
return val;
|
||||
++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';
|
||||
#else
|
||||
memcpy (newp, pattern, dirlen);
|
||||
newp[dirlen] = '\0';
|
||||
#endif
|
||||
dirname = newp;
|
||||
++filename;
|
||||
|
||||
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);
|
||||
if (val == 0)
|
||||
pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
|
||||
| (flags & GLOB_MARK));
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(flags & GLOB_APPEND))
|
||||
@ -525,12 +600,12 @@ glob (pattern, flags, errfunc, pglob)
|
||||
oldcount = pglob->gl_pathc;
|
||||
|
||||
#ifndef VMS
|
||||
if ((flags & GLOB_TILDE) && dirname[0] == '~')
|
||||
if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
|
||||
{
|
||||
if (dirname[1] == '\0' || dirname[1] == '/')
|
||||
{
|
||||
/* Look up home directory. */
|
||||
char *home_dir = getenv ("HOME");
|
||||
const char *home_dir = getenv ("HOME");
|
||||
# ifdef _AMIGA
|
||||
if (home_dir == NULL || home_dir[0] == '\0')
|
||||
home_dir = "SYS:";
|
||||
@ -542,37 +617,38 @@ glob (pattern, flags, errfunc, pglob)
|
||||
if (home_dir == NULL || home_dir[0] == '\0')
|
||||
{
|
||||
int success;
|
||||
# if defined HAVE_GETLOGIN_R || defined _LIBC
|
||||
extern int getlogin_r __P ((char *, size_t));
|
||||
size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1;
|
||||
char *name;
|
||||
# if defined HAVE_GETLOGIN_R || defined _LIBC
|
||||
size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1;
|
||||
|
||||
if (buflen == 0)
|
||||
/* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try
|
||||
a moderate value. */
|
||||
buflen = 16;
|
||||
buflen = 20;
|
||||
name = (char *) __alloca (buflen);
|
||||
|
||||
success = getlogin_r (name, buflen) >= 0;
|
||||
# else
|
||||
extern char *getlogin __P ((void));
|
||||
char *name;
|
||||
|
||||
success = (name = getlogin ()) != NULL;
|
||||
# endif
|
||||
if (success)
|
||||
{
|
||||
struct passwd *p;
|
||||
# if defined HAVE_GETPWNAM_R || defined _LIBC
|
||||
size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX);
|
||||
char *pwtmpbuf;
|
||||
struct passwd pwbuf, *p;
|
||||
struct passwd pwbuf;
|
||||
|
||||
if (pwbuflen == -1)
|
||||
/* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
|
||||
Try a moderate value. */
|
||||
pwbuflen = 1024;
|
||||
pwtmpbuf = (char *) __alloca (pwbuflen);
|
||||
|
||||
success = (__getpwnam_r (name, &pwbuf, pwtmpbuf,
|
||||
pwbuflen, &p) >= 0);
|
||||
success = (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
|
||||
>= 0);
|
||||
# else
|
||||
struct passwd *p = getpwnam (name);
|
||||
p = getpwnam (name);
|
||||
success = p != NULL;
|
||||
# endif
|
||||
if (success)
|
||||
@ -580,7 +656,10 @@ glob (pattern, flags, errfunc, pglob)
|
||||
}
|
||||
}
|
||||
if (home_dir == NULL || home_dir[0] == '\0')
|
||||
home_dir = (char *) "~"; /* No luck. */
|
||||
if (flags & GLOB_TILDE_CHECK)
|
||||
return GLOB_NOMATCH;
|
||||
else
|
||||
home_dir = "~"; /* No luck. */
|
||||
# endif /* WINDOWS32 */
|
||||
# endif
|
||||
/* Now construct the full directory. */
|
||||
@ -605,35 +684,45 @@ glob (pattern, flags, errfunc, pglob)
|
||||
else
|
||||
{
|
||||
char *end_name = strchr (dirname, '/');
|
||||
char *user_name;
|
||||
char *home_dir;
|
||||
const char *user_name;
|
||||
const char *home_dir;
|
||||
|
||||
if (end_name == NULL)
|
||||
user_name = dirname + 1;
|
||||
else
|
||||
{
|
||||
user_name = (char *) __alloca (end_name - dirname);
|
||||
char *newp;
|
||||
newp = (char *) __alloca (end_name - dirname);
|
||||
# ifdef HAVE_MEMPCPY
|
||||
*((char *) mempcpy (user_name, dirname + 1, end_name - dirname))
|
||||
*((char *) mempcpy (newp, dirname + 1, end_name - dirname))
|
||||
= '\0';
|
||||
# else
|
||||
memcpy (user_name, dirname + 1, end_name - dirname);
|
||||
user_name[end_name - dirname - 1] = '\0';
|
||||
memcpy (newp, dirname + 1, end_name - dirname);
|
||||
newp[end_name - dirname - 1] = '\0';
|
||||
# endif
|
||||
user_name = newp;
|
||||
}
|
||||
|
||||
/* Look up specific user's home directory. */
|
||||
{
|
||||
struct passwd *p;
|
||||
# if defined HAVE_GETPWNAM_R || defined _LIBC
|
||||
size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
|
||||
char *pwtmpbuf = (char *) __alloca (buflen);
|
||||
struct passwd pwbuf, *p;
|
||||
if (__getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) >= 0)
|
||||
char *pwtmpbuf;
|
||||
struct passwd pwbuf;
|
||||
|
||||
if (buflen == -1)
|
||||
/* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a
|
||||
moderate value. */
|
||||
buflen = 1024;
|
||||
pwtmpbuf = (char *) __alloca (buflen);
|
||||
|
||||
if (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) >= 0)
|
||||
home_dir = p->pw_dir;
|
||||
else
|
||||
home_dir = NULL;
|
||||
# else
|
||||
struct passwd *p = getpwnam (user_name);
|
||||
p = getpwnam (user_name);
|
||||
if (p != NULL)
|
||||
home_dir = p->pw_dir;
|
||||
else
|
||||
@ -657,11 +746,69 @@ glob (pattern, flags, errfunc, pglob)
|
||||
# endif
|
||||
dirname = newp;
|
||||
}
|
||||
else
|
||||
if (flags & GLOB_TILDE_CHECK)
|
||||
/* We have to regard it as an error if we cannot find the
|
||||
home directory. */
|
||||
return GLOB_NOMATCH;
|
||||
}
|
||||
# endif /* Not Amiga && not WINDOWS32. */
|
||||
}
|
||||
#endif /* Not VMS. */
|
||||
|
||||
/* Now test whether we looked for "~" or "~NAME". In this case we
|
||||
can give the answer now. */
|
||||
if (filename == NULL)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
/* Return the directory if we don't check for error or if it exists. */
|
||||
if ((flags & GLOB_NOCHECK)
|
||||
|| (((flags & GLOB_ALTDIRFUNC)
|
||||
? (*pglob->gl_stat) (dirname, &st)
|
||||
: __stat (dirname, &st)) == 0
|
||||
&& S_ISDIR (st.st_mode)))
|
||||
{
|
||||
pglob->gl_pathv
|
||||
= (char **) realloc (pglob->gl_pathv,
|
||||
(pglob->gl_pathc +
|
||||
((flags & GLOB_DOOFFS) ?
|
||||
pglob->gl_offs : 0) +
|
||||
1 + 1) *
|
||||
sizeof (char *));
|
||||
if (pglob->gl_pathv == NULL)
|
||||
return GLOB_NOSPACE;
|
||||
|
||||
if (flags & GLOB_DOOFFS)
|
||||
while (pglob->gl_pathc < pglob->gl_offs)
|
||||
pglob->gl_pathv[pglob->gl_pathc++] = NULL;
|
||||
|
||||
#if defined HAVE_STRDUP || defined _LIBC
|
||||
pglob->gl_pathv[pglob->gl_pathc] = strdup (dirname);
|
||||
#else
|
||||
{
|
||||
size_t len = strlen (dirname) + 1;
|
||||
char *dircopy = malloc (len);
|
||||
if (dircopy != NULL)
|
||||
pglob->gl_pathv[pglob->gl_pathc] = memcpy (dircopy, dirname,
|
||||
len);
|
||||
}
|
||||
#endif
|
||||
if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
|
||||
{
|
||||
free (pglob->gl_pathv);
|
||||
return GLOB_NOSPACE;
|
||||
}
|
||||
pglob->gl_pathv[++pglob->gl_pathc] = NULL;
|
||||
pglob->gl_flags = flags;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Not found. */
|
||||
return GLOB_NOMATCH;
|
||||
}
|
||||
|
||||
if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
|
||||
{
|
||||
/* The directory name contains metacharacters, so we
|
||||
@ -727,26 +874,29 @@ glob (pattern, flags, errfunc, pglob)
|
||||
|
||||
flags |= GLOB_MAGCHAR;
|
||||
|
||||
/* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.
|
||||
But if we have not found any matching entry and thie GLOB_NOCHECK
|
||||
flag was set we must return the list consisting of the disrectory
|
||||
names followed by the filename. */
|
||||
if (pglob->gl_pathc == oldcount)
|
||||
/* No matches. */
|
||||
if (flags & GLOB_NOCHECK)
|
||||
{
|
||||
size_t len = strlen (pattern) + 1;
|
||||
char *patcopy = (char *) malloc (len);
|
||||
if (patcopy == NULL)
|
||||
return GLOB_NOSPACE;
|
||||
memcpy (patcopy, pattern, len);
|
||||
size_t filename_len = strlen (filename) + 1;
|
||||
char **new_pathv;
|
||||
struct stat st;
|
||||
|
||||
/* This is an pessimistic guess about the size. */
|
||||
pglob->gl_pathv
|
||||
= (char **) realloc (pglob->gl_pathv,
|
||||
(pglob->gl_pathc +
|
||||
((flags & GLOB_DOOFFS) ?
|
||||
pglob->gl_offs : 0) +
|
||||
1 + 1) *
|
||||
dirs.gl_pathc + 1) *
|
||||
sizeof (char *));
|
||||
if (pglob->gl_pathv == NULL)
|
||||
{
|
||||
free (patcopy);
|
||||
globfree (&dirs);
|
||||
return GLOB_NOSPACE;
|
||||
}
|
||||
|
||||
@ -754,12 +904,55 @@ glob (pattern, flags, errfunc, pglob)
|
||||
while (pglob->gl_pathc < pglob->gl_offs)
|
||||
pglob->gl_pathv[pglob->gl_pathc++] = NULL;
|
||||
|
||||
pglob->gl_pathv[pglob->gl_pathc++] = patcopy;
|
||||
for (i = 0; i < dirs.gl_pathc; ++i)
|
||||
{
|
||||
const char *dir = dirs.gl_pathv[i];
|
||||
size_t dir_len = strlen (dir);
|
||||
|
||||
/* First check whether this really is a directory. */
|
||||
if (((flags & GLOB_ALTDIRFUNC)
|
||||
? (*pglob->gl_stat) (dir, &st) : __stat (dir, &st)) != 0
|
||||
|| !S_ISDIR (st.st_mode))
|
||||
/* No directory, ignore this entry. */
|
||||
continue;
|
||||
|
||||
pglob->gl_pathv[pglob->gl_pathc] = malloc (dir_len + 1
|
||||
+ filename_len);
|
||||
if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
|
||||
{
|
||||
globfree (&dirs);
|
||||
globfree (pglob);
|
||||
return GLOB_NOSPACE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MEMPCPY
|
||||
mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc],
|
||||
dir, dir_len),
|
||||
"/", 1),
|
||||
filename, filename_len);
|
||||
#else
|
||||
memcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len);
|
||||
pglob->gl_pathv[pglob->gl_pathc][dir_len] = '/';
|
||||
memcpy (&pglob->gl_pathv[pglob->gl_pathc][dir_len + 1],
|
||||
filename, filename_len);
|
||||
#endif
|
||||
++pglob->gl_pathc;
|
||||
}
|
||||
|
||||
pglob->gl_pathv[pglob->gl_pathc] = NULL;
|
||||
pglob->gl_flags = flags;
|
||||
|
||||
/* Now we know how large the gl_pathv vector must be. */
|
||||
new_pathv = (char **) realloc (pglob->gl_pathv,
|
||||
((pglob->gl_pathc + 1)
|
||||
* sizeof (char *)));
|
||||
if (new_pathv != NULL)
|
||||
pglob->gl_pathv = new_pathv;
|
||||
}
|
||||
else
|
||||
return GLOB_NOMATCH;
|
||||
|
||||
globfree (&dirs);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -791,10 +984,10 @@ glob (pattern, flags, errfunc, pglob)
|
||||
int i;
|
||||
struct stat st;
|
||||
for (i = oldcount; i < pglob->gl_pathc; ++i)
|
||||
if (((flags & GLOB_ALTDIRFUNC) ?
|
||||
(*pglob->gl_stat) (pglob->gl_pathv[i], &st) :
|
||||
__stat (pglob->gl_pathv[i], &st)) == 0 &&
|
||||
S_ISDIR (st.st_mode))
|
||||
if (((flags & GLOB_ALTDIRFUNC)
|
||||
? (*pglob->gl_stat) (pglob->gl_pathv[i], &st)
|
||||
: __stat (pglob->gl_pathv[i], &st)) == 0
|
||||
&& S_ISDIR (st.st_mode))
|
||||
{
|
||||
size_t len = strlen (pglob->gl_pathv[i]) + 2;
|
||||
char *new = realloc (pglob->gl_pathv[i], len);
|
||||
@ -872,11 +1065,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)
|
||||
{
|
||||
@ -892,12 +1105,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]);
|
||||
@ -959,7 +1172,7 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
|
||||
int (*errfunc) __P ((const char *, int));
|
||||
glob_t *pglob;
|
||||
{
|
||||
__ptr_t stream;
|
||||
__ptr_t stream = NULL;
|
||||
|
||||
struct globlink
|
||||
{
|
||||
@ -971,92 +1184,127 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
|
||||
int meta;
|
||||
int save;
|
||||
|
||||
stream = ((flags & GLOB_ALTDIRFUNC) ?
|
||||
(*pglob->gl_opendir) (directory) :
|
||||
(__ptr_t) opendir (directory));
|
||||
if (stream == NULL)
|
||||
meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
|
||||
if (meta == 0)
|
||||
{
|
||||
if ((errfunc != NULL && (*errfunc) (directory, errno)) ||
|
||||
(flags & GLOB_ERR))
|
||||
return GLOB_ABORTED;
|
||||
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 one name. */
|
||||
flags |= GLOB_NOCHECK;
|
||||
else
|
||||
{
|
||||
/* Since we use the normal file functions we can also use stat()
|
||||
to verify the file is there. */
|
||||
struct stat st;
|
||||
size_t patlen = strlen (pattern);
|
||||
size_t dirlen = strlen (directory);
|
||||
char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);
|
||||
|
||||
# ifdef HAVE_MEMPCPY
|
||||
mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
|
||||
"/", 1),
|
||||
pattern, patlen + 1);
|
||||
# else
|
||||
memcpy (fullname, directory, dirlen);
|
||||
fullname[dirlen] = '/';
|
||||
memcpy (&fullname[dirlen + 1], pattern, patlen + 1);
|
||||
# endif
|
||||
if (((flags & GLOB_ALTDIRFUNC)
|
||||
? (*pglob->gl_stat) (fullname, &st)
|
||||
: __stat (fullname, &st)) == 0)
|
||||
/* We found this file to be existing. Now tell the rest
|
||||
of the function to copy this name into the result. */
|
||||
flags |= GLOB_NOCHECK;
|
||||
}
|
||||
|
||||
nfound = 0;
|
||||
meta = 0;
|
||||
}
|
||||
else if (pattern[0] == '\0')
|
||||
{
|
||||
/* This is a special case for matching directories like in
|
||||
"*a/". */
|
||||
names = (struct globlink *) __alloca (sizeof (struct globlink));
|
||||
names->name = (char *) malloc (1);
|
||||
if (names->name == NULL)
|
||||
goto memory_error;
|
||||
names->name[0] = '\0';
|
||||
names->next = NULL;
|
||||
nfound = 1;
|
||||
meta = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
nfound = 0;
|
||||
meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
|
||||
if(meta)
|
||||
flags |= GLOB_MAGCHAR;
|
||||
|
||||
while (1)
|
||||
if (pattern[0] == '\0')
|
||||
{
|
||||
const char *name;
|
||||
size_t len;
|
||||
struct dirent *d = ((flags & GLOB_ALTDIRFUNC) ?
|
||||
(*pglob->gl_readdir) (stream) :
|
||||
readdir ((DIR *) stream));
|
||||
if (d == NULL)
|
||||
break;
|
||||
if (! REAL_DIR_ENTRY (d))
|
||||
continue;
|
||||
/* This is a special case for matching directories like in
|
||||
"*a/". */
|
||||
names = (struct globlink *) __alloca (sizeof (struct globlink));
|
||||
names->name = (char *) malloc (1);
|
||||
if (names->name == NULL)
|
||||
goto memory_error;
|
||||
names->name[0] = '\0';
|
||||
names->next = NULL;
|
||||
nfound = 1;
|
||||
meta = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream = ((flags & GLOB_ALTDIRFUNC)
|
||||
? (*pglob->gl_opendir) (directory)
|
||||
: (__ptr_t) opendir (directory));
|
||||
if (stream == NULL)
|
||||
{
|
||||
if ((errfunc != NULL && (*errfunc) (directory, errno))
|
||||
|| (flags & GLOB_ERR))
|
||||
return GLOB_ABORTED;
|
||||
nfound = 0;
|
||||
meta = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
|
||||
| ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
|
||||
#if defined _AMIGA || defined VMS
|
||||
| FNM_CASEFOLD
|
||||
#endif
|
||||
);
|
||||
nfound = 0;
|
||||
flags |= GLOB_MAGCHAR;
|
||||
|
||||
while (1)
|
||||
{
|
||||
const char *name;
|
||||
size_t len;
|
||||
struct dirent *d = ((flags & GLOB_ALTDIRFUNC)
|
||||
? (*pglob->gl_readdir) (stream)
|
||||
: readdir ((DIR *) stream));
|
||||
if (d == NULL)
|
||||
break;
|
||||
if (! REAL_DIR_ENTRY (d))
|
||||
continue;
|
||||
|
||||
#ifdef HAVE_D_TYPE
|
||||
/* If we shall match only directories use the information
|
||||
provided by the dirent call if possible. */
|
||||
if ((flags & GLOB_ONLYDIR)
|
||||
&& d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
|
||||
continue;
|
||||
/* If we shall match only directories use the information
|
||||
provided by the dirent call if possible. */
|
||||
if ((flags & GLOB_ONLYDIR)
|
||||
&& d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
name = d->d_name;
|
||||
name = d->d_name;
|
||||
|
||||
if ((!meta && strcmp (pattern, name) == 0)
|
||||
|| fnmatch (pattern, name,
|
||||
(!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) |
|
||||
((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
|
||||
#ifdef _AMIGA
|
||||
| FNM_CASEFOLD
|
||||
#endif
|
||||
) == 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 (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;
|
||||
#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;
|
||||
if (!meta)
|
||||
break;
|
||||
new->next = names;
|
||||
names = new;
|
||||
++nfound;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nfound == 0 && (flags & GLOB_NOMAGIC) && !meta)
|
||||
flags |= GLOB_NOCHECK;
|
||||
|
||||
if (nfound == 0 && (flags & GLOB_NOCHECK))
|
||||
{
|
||||
size_t len = strlen (pattern);
|
||||
@ -1097,10 +1345,11 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
|
||||
}
|
||||
|
||||
save = errno;
|
||||
if (flags & GLOB_ALTDIRFUNC)
|
||||
(*pglob->gl_closedir) (stream);
|
||||
else
|
||||
closedir ((DIR *) stream);
|
||||
if (stream != NULL)
|
||||
if (flags & GLOB_ALTDIRFUNC)
|
||||
(*pglob->gl_closedir) (stream);
|
||||
else
|
||||
closedir ((DIR *) stream);
|
||||
__set_errno (save);
|
||||
|
||||
return nfound == 0 ? GLOB_NOMATCH : 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user