|
@@ -40,19 +40,11 @@ libc_hidden_proto(qsort)
|
|
|
libc_hidden_proto(lstat)
|
|
|
|
|
|
|
|
|
-extern __ptr_t (*__glob_opendir_hook) __P ((const char *directory)) attribute_hidden;
|
|
|
-extern void (*__glob_closedir_hook) __P ((__ptr_t stream)) attribute_hidden;
|
|
|
-extern const char *(*__glob_readdir_hook) __P ((__ptr_t stream)) attribute_hidden;
|
|
|
+extern __ptr_t (*__glob_opendir_hook) (const char *directory) attribute_hidden;
|
|
|
+extern void (*__glob_closedir_hook) (__ptr_t stream) attribute_hidden;
|
|
|
+extern const char *(*__glob_readdir_hook) (__ptr_t stream) attribute_hidden;
|
|
|
|
|
|
|
|
|
-static int glob_in_dir __P ((const char *pattern, const char *directory,
|
|
|
- int flags,
|
|
|
- int (*errfunc) __P ((const char *, int)),
|
|
|
- glob_t *pglob));
|
|
|
-static int prefix_array __P ((const char *prefix, char **array, size_t n,
|
|
|
- int add_slash));
|
|
|
-static int collated_compare __P ((const __ptr_t, const __ptr_t));
|
|
|
-
|
|
|
libc_hidden_proto(glob_pattern_p)
|
|
|
#ifdef __GLOB64
|
|
|
libc_hidden_proto(glob64)
|
|
@@ -99,6 +91,204 @@ libc_hidden_def(glob_pattern_p)
|
|
|
#endif
|
|
|
|
|
|
|
|
|
+/* Do a collated comparison of A and B. */
|
|
|
+static int
|
|
|
+collated_compare (const __ptr_t a, const __ptr_t b)
|
|
|
+{
|
|
|
+ const char *const s1 = *(const char *const *) a;
|
|
|
+ const char *const s2 = *(const char *const *) b;
|
|
|
+
|
|
|
+ if (s1 == s2)
|
|
|
+ return 0;
|
|
|
+ if (s1 == NULL)
|
|
|
+ return 1;
|
|
|
+ if (s2 == NULL)
|
|
|
+ return -1;
|
|
|
+ return strcoll (s1, s2);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
|
|
|
+ elements in place. Return nonzero if out of memory, zero if successful.
|
|
|
+ A slash is inserted between DIRNAME and each elt of ARRAY,
|
|
|
+ unless DIRNAME is just "/". Each old element of ARRAY is freed.
|
|
|
+ If ADD_SLASH is non-zero, allocate one character more than
|
|
|
+ necessary, so that a slash can be appended later. */
|
|
|
+static int
|
|
|
+prefix_array (const char *dirname, char **array, size_t n, int add_slash)
|
|
|
+{
|
|
|
+ register size_t i;
|
|
|
+ size_t dirlen = strlen (dirname);
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ for (i = 0; i < n; ++i)
|
|
|
+ {
|
|
|
+ size_t eltlen = strlen (array[i]) + 1;
|
|
|
+ char *new = (char *) malloc (dirlen + 1 + eltlen + (add_slash ? 1 : 0));
|
|
|
+ if (new == NULL)
|
|
|
+ {
|
|
|
+ while (i > 0)
|
|
|
+ free ((__ptr_t) array[--i]);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy (new, dirname, dirlen);
|
|
|
+ new[dirlen] = '/';
|
|
|
+ memcpy (&new[dirlen + 1], array[i], eltlen);
|
|
|
+ free ((__ptr_t) array[i]);
|
|
|
+ array[i] = new;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/* Like `glob', but PATTERN is a final pathname component,
|
|
|
+ and matches are searched for in DIRECTORY.
|
|
|
+ The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done.
|
|
|
+ The GLOB_APPEND flag is assumed to be set (always appends). */
|
|
|
+static int
|
|
|
+glob_in_dir (const char *pattern, const char *directory, int flags, int (*errfunc) (const char *, int), glob_t *pglob)
|
|
|
+{
|
|
|
+ __ptr_t stream;
|
|
|
+
|
|
|
+ struct globlink
|
|
|
+ {
|
|
|
+ struct globlink *next;
|
|
|
+ char *name;
|
|
|
+ };
|
|
|
+ struct globlink *names = NULL;
|
|
|
+ size_t nfound = 0;
|
|
|
+ int meta;
|
|
|
+
|
|
|
+ stream = (__glob_opendir_hook ? (*__glob_opendir_hook) (directory)
|
|
|
+ : (__ptr_t) opendir (directory));
|
|
|
+ if (stream == NULL)
|
|
|
+ {
|
|
|
+ if ((errfunc != NULL && (*errfunc) (directory, errno)) ||
|
|
|
+ (flags & GLOB_ERR))
|
|
|
+ return GLOB_ABORTED;
|
|
|
+ }
|
|
|
+
|
|
|
+ meta = glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
|
|
|
+
|
|
|
+ if (meta)
|
|
|
+ flags |= GLOB_MAGCHAR;
|
|
|
+
|
|
|
+ while (1)
|
|
|
+ {
|
|
|
+ const char *name;
|
|
|
+ size_t len;
|
|
|
+
|
|
|
+ if (__glob_readdir_hook)
|
|
|
+ {
|
|
|
+ name = (*__glob_readdir_hook) (stream);
|
|
|
+ if (name == NULL)
|
|
|
+ break;
|
|
|
+ len = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ struct dirent *d = __readdir ((DIR *) stream);
|
|
|
+ if (d == NULL)
|
|
|
+ break;
|
|
|
+ if (! (d->d_ino != 0))
|
|
|
+ continue;
|
|
|
+ name = d->d_name;
|
|
|
+#ifdef _DIRENT_HAVE_D_NAMLEN
|
|
|
+ len = d->d_namlen;
|
|
|
+#else
|
|
|
+ len = 0;
|
|
|
+#endif
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((!meta && strcmp (pattern, name) == 0)
|
|
|
+ || fnmatch (pattern, name,
|
|
|
+ (!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) |
|
|
|
+ ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)) == 0)
|
|
|
+ {
|
|
|
+ struct globlink *new
|
|
|
+ = (struct globlink *) alloca (sizeof (struct globlink));
|
|
|
+ if (len == 0)
|
|
|
+ len = strlen (name);
|
|
|
+ new->name
|
|
|
+ = (char *) malloc (len + ((flags & GLOB_MARK) ? 1 : 0) + 1);
|
|
|
+ if (new->name == NULL)
|
|
|
+ goto memory_error;
|
|
|
+ memcpy ((__ptr_t) new->name, name, len);
|
|
|
+ new->name[len] = '\0';
|
|
|
+ new->next = names;
|
|
|
+ names = new;
|
|
|
+ ++nfound;
|
|
|
+ if (!meta)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (nfound == 0 && (flags & GLOB_NOCHECK))
|
|
|
+ {
|
|
|
+ size_t len = strlen (pattern);
|
|
|
+ nfound = 1;
|
|
|
+ names = (struct globlink *) alloca (sizeof (struct globlink));
|
|
|
+ names->next = NULL;
|
|
|
+ names->name = (char *) malloc (len + (flags & GLOB_MARK ? 1 : 0) + 1);
|
|
|
+ if (names->name == NULL)
|
|
|
+ goto memory_error;
|
|
|
+ memcpy (names->name, pattern, len);
|
|
|
+ names->name[len] = '\0';
|
|
|
+ }
|
|
|
+
|
|
|
+ pglob->gl_pathv
|
|
|
+ = (char **) realloc (pglob->gl_pathv,
|
|
|
+ (pglob->gl_pathc +
|
|
|
+ ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
|
|
|
+ nfound + 1) *
|
|
|
+ sizeof (char *));
|
|
|
+ if (pglob->gl_pathv == NULL)
|
|
|
+ goto memory_error;
|
|
|
+
|
|
|
+ if (flags & GLOB_DOOFFS)
|
|
|
+ while (pglob->gl_pathc < pglob->gl_offs)
|
|
|
+ pglob->gl_pathv[pglob->gl_pathc++] = NULL;
|
|
|
+
|
|
|
+ for (; names != NULL; names = names->next)
|
|
|
+ pglob->gl_pathv[pglob->gl_pathc++] = names->name;
|
|
|
+ pglob->gl_pathv[pglob->gl_pathc] = NULL;
|
|
|
+
|
|
|
+ pglob->gl_flags = flags;
|
|
|
+
|
|
|
+ {
|
|
|
+ int save = errno;
|
|
|
+ if (__glob_closedir_hook)
|
|
|
+ (*__glob_closedir_hook) (stream);
|
|
|
+ else
|
|
|
+ (void) closedir ((DIR *) stream);
|
|
|
+ errno = save;
|
|
|
+ }
|
|
|
+ return nfound == 0 ? GLOB_NOMATCH : 0;
|
|
|
+
|
|
|
+ memory_error:
|
|
|
+ {
|
|
|
+ int save = errno;
|
|
|
+ if (__glob_closedir_hook)
|
|
|
+ (*__glob_closedir_hook) (stream);
|
|
|
+ else
|
|
|
+ (void) closedir ((DIR *) stream);
|
|
|
+ errno = save;
|
|
|
+ }
|
|
|
+ while (names != NULL)
|
|
|
+ {
|
|
|
+ if (names->name != NULL)
|
|
|
+ free ((__ptr_t) names->name);
|
|
|
+ names = names->next;
|
|
|
+ }
|
|
|
+ return GLOB_NOSPACE;
|
|
|
+}
|
|
|
+
|
|
|
/* Do glob searching for PATTERN, placing results in PGLOB.
|
|
|
The bits defined above may be set in FLAGS.
|
|
|
If a directory cannot be opened or read and ERRFUNC is not nil,
|
|
@@ -111,7 +301,7 @@ int
|
|
|
glob (pattern, flags, errfunc, pglob)
|
|
|
const char *pattern;
|
|
|
int flags;
|
|
|
- int (*errfunc) __P ((const char *, int));
|
|
|
+ int (*errfunc) (const char *, int);
|
|
|
glob_t *pglob;
|
|
|
{
|
|
|
const char *filename;
|
|
@@ -334,214 +524,3 @@ libc_hidden_def(globfree64)
|
|
|
#else
|
|
|
libc_hidden_def(globfree)
|
|
|
#endif
|
|
|
-
|
|
|
-
|
|
|
-/* Do a collated comparison of A and B. */
|
|
|
-static int
|
|
|
-collated_compare (a, b)
|
|
|
- const __ptr_t a;
|
|
|
- const __ptr_t b;
|
|
|
-{
|
|
|
- const char *const s1 = *(const char *const *) a;
|
|
|
- const char *const s2 = *(const char *const *) b;
|
|
|
-
|
|
|
- if (s1 == s2)
|
|
|
- return 0;
|
|
|
- if (s1 == NULL)
|
|
|
- return 1;
|
|
|
- if (s2 == NULL)
|
|
|
- return -1;
|
|
|
- return strcoll (s1, s2);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
|
|
|
- elements in place. Return nonzero if out of memory, zero if successful.
|
|
|
- A slash is inserted between DIRNAME and each elt of ARRAY,
|
|
|
- unless DIRNAME is just "/". Each old element of ARRAY is freed.
|
|
|
- If ADD_SLASH is non-zero, allocate one character more than
|
|
|
- necessary, so that a slash can be appended later. */
|
|
|
-static int
|
|
|
-prefix_array (dirname, array, n, add_slash)
|
|
|
- const char *dirname;
|
|
|
- char **array;
|
|
|
- size_t n;
|
|
|
- int add_slash;
|
|
|
-{
|
|
|
- register size_t i;
|
|
|
- size_t dirlen = strlen (dirname);
|
|
|
-
|
|
|
- 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;
|
|
|
-
|
|
|
- for (i = 0; i < n; ++i)
|
|
|
- {
|
|
|
- size_t eltlen = strlen (array[i]) + 1;
|
|
|
- char *new = (char *) malloc (dirlen + 1 + eltlen + (add_slash ? 1 : 0));
|
|
|
- if (new == NULL)
|
|
|
- {
|
|
|
- while (i > 0)
|
|
|
- free ((__ptr_t) array[--i]);
|
|
|
- return 1;
|
|
|
- }
|
|
|
-
|
|
|
- memcpy (new, dirname, dirlen);
|
|
|
- new[dirlen] = '/';
|
|
|
- memcpy (&new[dirlen + 1], array[i], eltlen);
|
|
|
- free ((__ptr_t) array[i]);
|
|
|
- array[i] = new;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/* Like `glob', but PATTERN is a final pathname component,
|
|
|
- and matches are searched for in DIRECTORY.
|
|
|
- The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done.
|
|
|
- The GLOB_APPEND flag is assumed to be set (always appends). */
|
|
|
-static int
|
|
|
-glob_in_dir (pattern, directory, flags, errfunc, pglob)
|
|
|
- const char *pattern;
|
|
|
- const char *directory;
|
|
|
- int flags;
|
|
|
- int (*errfunc) __P ((const char *, int));
|
|
|
- glob_t *pglob;
|
|
|
-{
|
|
|
- __ptr_t stream;
|
|
|
-
|
|
|
- struct globlink
|
|
|
- {
|
|
|
- struct globlink *next;
|
|
|
- char *name;
|
|
|
- };
|
|
|
- struct globlink *names = NULL;
|
|
|
- size_t nfound = 0;
|
|
|
- int meta;
|
|
|
-
|
|
|
- stream = (__glob_opendir_hook ? (*__glob_opendir_hook) (directory)
|
|
|
- : (__ptr_t) opendir (directory));
|
|
|
- if (stream == NULL)
|
|
|
- {
|
|
|
- if ((errfunc != NULL && (*errfunc) (directory, errno)) ||
|
|
|
- (flags & GLOB_ERR))
|
|
|
- return GLOB_ABORTED;
|
|
|
- }
|
|
|
-
|
|
|
- meta = glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
|
|
|
-
|
|
|
- if (meta)
|
|
|
- flags |= GLOB_MAGCHAR;
|
|
|
-
|
|
|
- while (1)
|
|
|
- {
|
|
|
- const char *name;
|
|
|
- size_t len;
|
|
|
-
|
|
|
- if (__glob_readdir_hook)
|
|
|
- {
|
|
|
- name = (*__glob_readdir_hook) (stream);
|
|
|
- if (name == NULL)
|
|
|
- break;
|
|
|
- len = 0;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- struct dirent *d = __readdir ((DIR *) stream);
|
|
|
- if (d == NULL)
|
|
|
- break;
|
|
|
- if (! (d->d_ino != 0))
|
|
|
- continue;
|
|
|
- name = d->d_name;
|
|
|
-#ifdef _DIRENT_HAVE_D_NAMLEN
|
|
|
- len = d->d_namlen;
|
|
|
-#else
|
|
|
- len = 0;
|
|
|
-#endif
|
|
|
- }
|
|
|
-
|
|
|
- if ((!meta && strcmp (pattern, name) == 0)
|
|
|
- || fnmatch (pattern, name,
|
|
|
- (!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) |
|
|
|
- ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)) == 0)
|
|
|
- {
|
|
|
- struct globlink *new
|
|
|
- = (struct globlink *) alloca (sizeof (struct globlink));
|
|
|
- if (len == 0)
|
|
|
- len = strlen (name);
|
|
|
- new->name
|
|
|
- = (char *) malloc (len + ((flags & GLOB_MARK) ? 1 : 0) + 1);
|
|
|
- if (new->name == NULL)
|
|
|
- goto memory_error;
|
|
|
- memcpy ((__ptr_t) new->name, name, len);
|
|
|
- new->name[len] = '\0';
|
|
|
- new->next = names;
|
|
|
- names = new;
|
|
|
- ++nfound;
|
|
|
- if (!meta)
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (nfound == 0 && (flags & GLOB_NOCHECK))
|
|
|
- {
|
|
|
- size_t len = strlen (pattern);
|
|
|
- nfound = 1;
|
|
|
- names = (struct globlink *) alloca (sizeof (struct globlink));
|
|
|
- names->next = NULL;
|
|
|
- names->name = (char *) malloc (len + (flags & GLOB_MARK ? 1 : 0) + 1);
|
|
|
- if (names->name == NULL)
|
|
|
- goto memory_error;
|
|
|
- memcpy (names->name, pattern, len);
|
|
|
- names->name[len] = '\0';
|
|
|
- }
|
|
|
-
|
|
|
- pglob->gl_pathv
|
|
|
- = (char **) realloc (pglob->gl_pathv,
|
|
|
- (pglob->gl_pathc +
|
|
|
- ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
|
|
|
- nfound + 1) *
|
|
|
- sizeof (char *));
|
|
|
- if (pglob->gl_pathv == NULL)
|
|
|
- goto memory_error;
|
|
|
-
|
|
|
- if (flags & GLOB_DOOFFS)
|
|
|
- while (pglob->gl_pathc < pglob->gl_offs)
|
|
|
- pglob->gl_pathv[pglob->gl_pathc++] = NULL;
|
|
|
-
|
|
|
- for (; names != NULL; names = names->next)
|
|
|
- pglob->gl_pathv[pglob->gl_pathc++] = names->name;
|
|
|
- pglob->gl_pathv[pglob->gl_pathc] = NULL;
|
|
|
-
|
|
|
- pglob->gl_flags = flags;
|
|
|
-
|
|
|
- {
|
|
|
- int save = errno;
|
|
|
- if (__glob_closedir_hook)
|
|
|
- (*__glob_closedir_hook) (stream);
|
|
|
- else
|
|
|
- (void) closedir ((DIR *) stream);
|
|
|
- errno = save;
|
|
|
- }
|
|
|
- return nfound == 0 ? GLOB_NOMATCH : 0;
|
|
|
-
|
|
|
- memory_error:
|
|
|
- {
|
|
|
- int save = errno;
|
|
|
- if (__glob_closedir_hook)
|
|
|
- (*__glob_closedir_hook) (stream);
|
|
|
- else
|
|
|
- (void) closedir ((DIR *) stream);
|
|
|
- errno = save;
|
|
|
- }
|
|
|
- while (names != NULL)
|
|
|
- {
|
|
|
- if (names->name != NULL)
|
|
|
- free ((__ptr_t) names->name);
|
|
|
- names = names->next;
|
|
|
- }
|
|
|
- return GLOB_NOSPACE;
|
|
|
-}
|
|
|
-
|