3 /* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 /* AIX requires this to be the first thing in the file. */
21 #if defined _AIX && !defined __GNUC__
31 #include <sys/stat.h> /* S_ISDIR */
33 /* Bits set in the FLAGS argument to `glob'. */
34 #define GLOB_ERR (1 << 0) /* Return on read errors. */
35 #define GLOB_MARK (1 << 1) /* Append a slash to each name. */
36 #define GLOB_NOSORT (1 << 2) /* Don't sort the names. */
37 #define GLOB_DOOFFS (1 << 3) /* Insert PGLOB->gl_offs NULLs. */
38 #define GLOB_NOCHECK (1 << 4) /* If nothing matches, return the pattern. */
39 #define GLOB_APPEND (1 << 5) /* Append to results of a previous call. */
40 #define GLOB_NOESCAPE (1 << 6) /* Backslashes don't quote metacharacters. */
41 #define GLOB_PERIOD (1 << 7) /* Leading `.' can be matched by metachars. */
43 #define GLOB_MAGCHAR (1 << 8) /* Set in gl_flags if any metachars seen. */
44 #define GLOB_ALTDIRFUNC (1 << 9) /* Use gl_opendir et al functions. */
45 #define GLOB_BRACE (1 << 10) /* Expand "{a,b}" to "a" "b". */
46 #define GLOB_NOMAGIC (1 << 11) /* If no magic chars, return the pattern. */
47 #define GLOB_TILDE (1 << 12) /* Expand ~user and ~ to home directories. */
48 #define GLOB_ONLYDIR (1 << 13) /* Match only directories. */
49 #define GLOB_TILDE_CHECK (1 << 14) /* Like GLOB_TILDE but return an error
50 if the user name is not available. */
51 #define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
52 GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \
53 GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE| \
54 GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR|GLOB_TILDE_CHECK)
56 /* Error returns from `glob'. */
57 #define GLOB_NOSPACE 1 /* Ran out of memory. */
58 #define GLOB_ABORTED 2 /* Read error. */
59 #define GLOB_NOMATCH 3 /* No matches found. */
60 #define GLOB_NOSYS 4 /* Not implemented. */
62 /* Structure describing a globbing run. */
64 size_t gl_pathc; /* Count of paths matched by the pattern. */
65 char **gl_pathv; /* List of matched pathnames. */
66 size_t gl_offs; /* Slots to reserve in `gl_pathv'. */
67 int gl_flags; /* Set to FLAGS, maybe | GLOB_MAGCHAR. */
69 /* If the GLOB_ALTDIRFUNC flag is set, the following functions
70 are used instead of the normal file access functions. */
71 void (*gl_closedir)(void *);
72 struct dirent *(*gl_readdir)(void *);
73 void *(*gl_opendir)(const char *);
74 int (*gl_lstat)(const char *, struct stat *);
75 int (*gl_stat)(const char *, struct stat *);
78 #define NAMLEN(_d) NLENGTH(_d)
80 #if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
81 /* Posix does not require that the d_ino field be present, and some
82 systems do not provide it. */
83 #define REAL_DIR_ENTRY(dp) 1
85 #define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
90 #define __set_errno(val) errno = (val)
94 #include <rpm/rpmfileutil.h>
95 #include <rpm/rpmurl.h>
99 /* Outcomment the following line for production quality code. */
100 /* #define NDEBUG 1 */
102 #define GLOB_INTERFACE_VERSION 1
104 static void globfree(glob_t * pglob);
105 static inline const char *next_brace_sub(const char *begin);
106 static int glob_in_dir(const char *pattern, const char *directory,
108 int (*errfunc) (const char *, int),
110 static int prefix_array(const char *prefix, char **array, size_t n);
111 static int collated_compare(const void *, const void *);
114 static void * mempcpy(void *dest, const void *src, size_t n)
116 return (char *) memcpy(dest, src, n) + n;
120 /* Find the end of the sub-pattern in a brace expression. We define
121 this as an inline function if the compiler permits. */
122 static inline const char *next_brace_sub(const char *begin)
124 unsigned int depth = 0;
125 const char *cp = begin;
129 if (*cp != ',' && *cp != '}' && *cp != '\0') {
136 while (*cp != '\0' && (*cp != '}' || depth > 0)) {
142 /* An incorrectly terminated brace expression. */
153 static int __glob_pattern_p(const char *pattern, int quote);
155 /* Do glob searching for PATTERN, placing results in PGLOB.
156 The bits defined above may be set in FLAGS.
157 If a directory cannot be opened or read and ERRFUNC is not nil,
158 it is called with the pathname that caused the error, and the
159 `errno' value from the failing call; if it returns non-zero
160 `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
161 If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
162 Otherwise, `glob' returns zero. */
164 glob(const char *pattern, int flags,
165 int (*errfunc)(const char *, int), glob_t * pglob)
167 const char *filename;
173 if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) {
178 if (flags & GLOB_BRACE) {
179 const char *begin = strchr(pattern, '{');
181 /* Allocate working buffer large enough for our work. Note that
182 we have at least an opening and closing brace. */
189 char onealt[strlen(pattern) - 1];
191 /* We know the prefix for all sub-patterns. */
192 alt_start = mempcpy(onealt, pattern, begin - pattern);
194 /* Find the first sub-pattern and at the same time find the
195 rest after the closing brace. */
196 next = next_brace_sub(begin + 1);
198 /* It is an illegal expression. */
199 return glob(pattern, flags & ~GLOB_BRACE, errfunc, pglob);
202 /* Now find the end of the whole brace expression. */
204 while (*rest != '}') {
205 rest = next_brace_sub(rest + 1);
207 /* It is an illegal expression. */
208 return glob(pattern, flags & ~GLOB_BRACE, errfunc,
212 /* Please note that we now can be sure the brace expression
214 rest_len = strlen(++rest) + 1;
216 /* We have a brace expression. BEGIN points to the opening {,
217 NEXT points past the terminator of the first element, and END
218 points past the final }. We will accumulate result names from
219 recursive runs for each brace alternative in the buffer using
222 if (!(flags & GLOB_APPEND)) {
223 /* This call is to set a new vector, so clear out the
224 vector so we can append to it. */
226 pglob->gl_pathv = NULL;
228 firstc = pglob->gl_pathc;
234 /* Construct the new glob expression. */
235 mempcpy(mempcpy(alt_start, p, next - p), rest, rest_len);
237 result = glob(onealt,
238 ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
239 | GLOB_APPEND), errfunc, pglob);
241 /* If we got an error, return it. */
242 if (result && result != GLOB_NOMATCH) {
243 if (!(flags & GLOB_APPEND))
249 /* We saw the last entry. */
253 next = next_brace_sub(p);
254 assert(next != NULL);
257 if (pglob->gl_pathc != firstc)
258 /* We found some entries. */
260 else if (!(flags & (GLOB_NOCHECK | GLOB_NOMAGIC)))
265 /* Find the filename. */
266 filename = strrchr(pattern, '/');
267 if (filename == NULL) {
268 /* This can mean two things: a simple name or "~name". The latter
269 case is nothing but a notation for a directory. */
270 if ((flags & (GLOB_TILDE | GLOB_TILDE_CHECK)) && pattern[0] == '~') {
272 dirlen = strlen(pattern);
274 /* Set FILENAME to NULL as a special flag. This is ugly but
275 other solutions would require much more code. We test for
276 this special case below. */
283 } else if (filename == pattern) {
290 dirlen = filename - pattern;
291 newp = (char *) alloca(dirlen + 1);
292 *((char *) mempcpy(newp, pattern, dirlen)) = '\0';
296 if (filename[0] == '\0' && dirlen > 1) {
297 /* "pattern/". Expand "pattern", appending slashes. */
298 int val = glob(dirname, flags | GLOB_MARK, errfunc, pglob);
300 pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
301 | (flags & GLOB_MARK));
306 if (!(flags & GLOB_APPEND)) {
308 pglob->gl_pathv = NULL;
311 oldcount = pglob->gl_pathc;
313 if ((flags & (GLOB_TILDE | GLOB_TILDE_CHECK)) && dirname[0] == '~') {
314 if (dirname[1] == '\0' || dirname[1] == '/') {
315 /* Look up home directory. */
316 const char *home_dir = getenv("HOME");
317 if (home_dir == NULL || home_dir[0] == '\0') {
320 success = (name = getlogin()) != NULL;
325 home_dir = p->pw_dir;
328 if (home_dir == NULL || home_dir[0] == '\0') {
329 if (flags & GLOB_TILDE_CHECK)
332 home_dir = "~"; /* No luck. */
334 /* Now construct the full directory. */
335 if (dirname[1] == '\0')
339 size_t home_len = strlen(home_dir);
340 newp = (char *) alloca(home_len + dirlen);
341 mempcpy(mempcpy(newp, home_dir, home_len),
342 &dirname[1], dirlen);
347 char *end_name = strchr(dirname, '/');
348 const char *user_name;
349 const char *home_dir;
351 if (end_name == NULL)
352 user_name = dirname + 1;
355 newp = (char *) alloca(end_name - dirname);
356 *((char *) mempcpy(newp, dirname + 1, end_name - dirname))
361 /* Look up specific user's home directory. */
364 p = getpwnam(user_name);
366 home_dir = p->pw_dir;
370 /* If we found a home directory use this. */
371 if (home_dir != NULL) {
373 size_t home_len = strlen(home_dir);
374 size_t rest_len = end_name == NULL ? 0 : strlen(end_name);
375 newp = (char *) alloca(home_len + rest_len + 1);
376 *((char *) mempcpy(mempcpy(newp, home_dir, home_len),
377 end_name, rest_len)) = '\0';
379 } else if (flags & GLOB_TILDE_CHECK)
380 /* We have to regard it as an error if we cannot find the
386 /* Now test whether we looked for "~" or "~NAME". In this case we
387 can give the answer now. */
388 if (filename == NULL) {
391 /* Return the directory if we don't check for error or if it exists. */
392 if ((flags & GLOB_NOCHECK)
393 || (((flags & GLOB_ALTDIRFUNC)
394 ? (*pglob->gl_stat) (dirname, &st)
395 : stat(dirname, &st)) == 0 && S_ISDIR(st.st_mode))) {
397 = (char **) xrealloc(pglob->gl_pathv,
399 ((flags & GLOB_DOOFFS) ?
400 pglob->gl_offs : 0) +
401 1 + 1) * sizeof(char *));
403 if (flags & GLOB_DOOFFS)
404 while (pglob->gl_pathc < pglob->gl_offs)
405 pglob->gl_pathv[pglob->gl_pathc++] = NULL;
407 pglob->gl_pathv[pglob->gl_pathc] = xstrdup(dirname);
408 if (pglob->gl_pathv[pglob->gl_pathc] == NULL) {
409 free(pglob->gl_pathv);
412 pglob->gl_pathv[++pglob->gl_pathc] = NULL;
413 pglob->gl_flags = flags;
422 if (__glob_pattern_p(dirname, !(flags & GLOB_NOESCAPE))) {
423 /* The directory name contains metacharacters, so we
424 have to glob for the directory, and then glob for
425 the pattern in each directory found. */
429 if ((flags & GLOB_ALTDIRFUNC) != 0) {
430 /* Use the alternative access functions also in the recursive
432 dirs.gl_opendir = pglob->gl_opendir;
433 dirs.gl_readdir = pglob->gl_readdir;
434 dirs.gl_closedir = pglob->gl_closedir;
435 dirs.gl_stat = pglob->gl_stat;
436 dirs.gl_lstat = pglob->gl_lstat;
439 status = glob(dirname,
440 ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE
442 | GLOB_NOSORT | GLOB_ONLYDIR), errfunc, &dirs);
446 /* We have successfully globbed the preceding directory name.
447 For each name we found, call glob_in_dir on it and FILENAME,
448 appending the results to PGLOB. */
449 for (i = 0; i < dirs.gl_pathc; ++i) {
450 int old_pathc = pglob->gl_pathc;
451 status = glob_in_dir(filename, dirs.gl_pathv[i],
452 ((flags | GLOB_APPEND)
453 & ~(GLOB_NOCHECK | GLOB_ERR)),
455 if (status == GLOB_NOMATCH)
456 /* No matches in this directory. Try the next. */
465 /* Stick the directory on the front of each name. */
466 if (prefix_array(dirs.gl_pathv[i],
467 &pglob->gl_pathv[old_pathc],
468 pglob->gl_pathc - old_pathc)) {
475 flags |= GLOB_MAGCHAR;
477 /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.
478 But if we have not found any matching entry and thie GLOB_NOCHECK
479 flag was set we must return the list consisting of the disrectory
480 names followed by the filename. */
481 if (pglob->gl_pathc == oldcount) {
483 if (flags & GLOB_NOCHECK) {
484 size_t filename_len = strlen(filename) + 1;
488 /* This is an pessimistic guess about the size. */
490 = (char **) xrealloc(pglob->gl_pathv,
492 ((flags & GLOB_DOOFFS) ?
493 pglob->gl_offs : 0) +
497 if (flags & GLOB_DOOFFS)
498 while (pglob->gl_pathc < pglob->gl_offs)
499 pglob->gl_pathv[pglob->gl_pathc++] = NULL;
501 for (i = 0; i < dirs.gl_pathc; ++i) {
502 const char *dir = dirs.gl_pathv[i];
503 size_t dir_len = strlen(dir);
505 /* First check whether this really is a directory. */
506 if (((flags & GLOB_ALTDIRFUNC)
507 ? (*pglob->gl_stat) (dir, &st) : stat(dir,
509 || !S_ISDIR(st.st_mode))
510 /* No directory, ignore this entry. */
513 pglob->gl_pathv[pglob->gl_pathc] = xmalloc(dir_len + 1
518 (pglob->gl_pathv[pglob->gl_pathc], dir,
519 dir_len), "/", 1), filename, filename_len);
523 pglob->gl_pathv[pglob->gl_pathc] = NULL;
524 pglob->gl_flags = flags;
526 /* Now we know how large the gl_pathv vector must be. */
527 new_pathv = (char **) xrealloc(pglob->gl_pathv,
528 ((pglob->gl_pathc + 1)
530 pglob->gl_pathv = new_pathv;
537 status = glob_in_dir(filename, dirname, flags, errfunc, pglob);
542 /* Stick the directory on the front of each name. */
543 int ignore = oldcount;
545 if ((flags & GLOB_DOOFFS) && ignore < pglob->gl_offs)
546 ignore = pglob->gl_offs;
548 if (prefix_array(dirname,
549 &pglob->gl_pathv[ignore],
550 pglob->gl_pathc - ignore)) {
557 if (flags & GLOB_MARK) {
558 /* Append slashes to directory names. */
561 for (i = oldcount; i < pglob->gl_pathc; ++i)
562 if (((flags & GLOB_ALTDIRFUNC)
563 ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st)
564 : stat(pglob->gl_pathv[i], &st)) == 0
565 && S_ISDIR(st.st_mode)) {
566 size_t len = strlen(pglob->gl_pathv[i]) + 2;
567 char *new = xrealloc(pglob->gl_pathv[i], len);
568 strcpy(&new[len - 2], "/");
569 pglob->gl_pathv[i] = new;
573 if (!(flags & GLOB_NOSORT)) {
574 /* Sort the vector. */
575 int non_sort = oldcount;
577 if ((flags & GLOB_DOOFFS) && pglob->gl_offs > oldcount)
578 non_sort = pglob->gl_offs;
580 qsort(& pglob->gl_pathv[non_sort],
581 pglob->gl_pathc - non_sort,
582 sizeof(char *), collated_compare);
589 /* Free storage allocated in PGLOB by a previous `glob' call. */
590 static void globfree(glob_t * pglob)
592 if (pglob->gl_pathv != NULL) {
594 for (i = 0; i < pglob->gl_pathc; ++i)
595 if (pglob->gl_pathv[i] != NULL)
596 free(pglob->gl_pathv[i]);
597 free(pglob->gl_pathv);
602 /* Do a collated comparison of A and B. */
603 static int collated_compare(const void * a, const void * b)
605 const char *const s1 = *(const char *const *const) a;
606 const char *const s2 = *(const char *const *const) b;
614 return strcoll(s1, s2);
618 /* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
619 elements in place. Return nonzero if out of memory, zero if successful.
620 A slash is inserted between DIRNAME and each elt of ARRAY,
621 unless DIRNAME is just "/". Each old element of ARRAY is freed. */
622 static int prefix_array(const char *dirname, char **array, size_t n)
625 size_t dirlen = strlen(dirname);
627 if (dirlen == 1 && dirname[0] == '/')
628 /* DIRNAME is just "/", so normal prepending would get us "//foo".
629 We want "/foo" instead, so don't prepend any chars from DIRNAME. */
632 for (i = 0; i < n; ++i) {
633 size_t eltlen = strlen(array[i]) + 1;
634 char *new = (char *) xmalloc(dirlen + 1 + eltlen);
636 char *endp = (char *) mempcpy(new, dirname, dirlen);
638 mempcpy(endp, array[i], eltlen);
647 /* Return nonzero if PATTERN contains any metacharacters.
648 Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
649 static int __glob_pattern_p(const char *pattern, int quote)
651 register const char *p;
654 for (p = pattern; *p != '\0'; ++p)
661 if (quote && p[1] != '\0')
678 /* Like `glob', but PATTERN is a final pathname component,
679 and matches are searched for in DIRECTORY.
680 The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done.
681 The GLOB_APPEND flag is assumed to be set (always appends). */
683 glob_in_dir(const char *pattern, const char *directory, int flags,
684 int (*errfunc)(const char *, int), glob_t * pglob)
686 void * stream = NULL;
689 struct globlink *next;
692 struct globlink *names = NULL;
697 meta = __glob_pattern_p(pattern, !(flags & GLOB_NOESCAPE));
699 if (flags & (GLOB_NOCHECK | GLOB_NOMAGIC))
700 /* We need not do any tests. The PATTERN contains no meta
701 characters and we must not return an error therefore the
702 result will always contain exactly one name. */
703 flags |= GLOB_NOCHECK;
705 /* Since we use the normal file functions we can also use stat()
706 to verify the file is there. */
708 size_t patlen = strlen(pattern);
709 size_t dirlen = strlen(directory);
710 char *fullname = (char *) alloca(dirlen + 1 + patlen + 1);
712 mempcpy(mempcpy(mempcpy(fullname, directory, dirlen),
713 "/", 1), pattern, patlen + 1);
714 if (((flags & GLOB_ALTDIRFUNC)
715 ? (*pglob->gl_stat) (fullname, &st)
716 : stat(fullname, &st)) == 0)
717 /* We found this file to be existing. Now tell the rest
718 of the function to copy this name into the result. */
719 flags |= GLOB_NOCHECK;
724 if (pattern[0] == '\0') {
725 /* This is a special case for matching directories like in
727 names = (struct globlink *) alloca(sizeof(struct globlink));
728 names->name = (char *) xmalloc(1);
729 names->name[0] = '\0';
734 stream = ((flags & GLOB_ALTDIRFUNC)
735 ? (*pglob->gl_opendir) (directory)
736 : opendir(directory));
737 if (stream == NULL) {
739 && ((errfunc != NULL && (*errfunc) (directory, errno))
740 || (flags & GLOB_ERR)))
745 int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) |
746 ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0));
748 flags |= GLOB_MAGCHAR;
753 struct dirent *d = ((flags & GLOB_ALTDIRFUNC)
754 ? (*pglob->gl_readdir) (stream)
755 : readdir((DIR *) stream));
758 if (!REAL_DIR_ENTRY(d))
761 #ifdef HAVE_STRUCT_DIRENT_D_TYPE
762 /* If we shall match only directories use the information
763 provided by the dirent call if possible. */
764 if ((flags & GLOB_ONLYDIR)
765 && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
771 if (fnmatch(pattern, name, fnm_flags) == 0) {
772 struct globlink *new = (struct globlink *)
773 alloca(sizeof(struct globlink));
775 new->name = (char *) xmalloc(len + 1);
776 *((char *) mempcpy(new->name, name, len))
787 if (nfound == 0 && (flags & GLOB_NOCHECK)) {
788 size_t len = strlen(pattern);
790 names = (struct globlink *) alloca(sizeof(struct globlink));
792 names->name = (char *) xmalloc(len + 1);
793 *((char *) mempcpy(names->name, pattern, len)) = '\0';
798 = (char **) xrealloc(pglob->gl_pathv,
800 ((flags & GLOB_DOOFFS) ? pglob->
801 gl_offs : 0) + nfound +
802 1) * sizeof(char *));
804 if (flags & GLOB_DOOFFS)
805 while (pglob->gl_pathc < pglob->gl_offs)
806 pglob->gl_pathv[pglob->gl_pathc++] = NULL;
808 for (; names != NULL; names = names->next)
809 pglob->gl_pathv[pglob->gl_pathc++] = names->name;
810 pglob->gl_pathv[pglob->gl_pathc] = NULL;
812 pglob->gl_flags = flags;
816 if (stream != NULL) {
817 if (flags & GLOB_ALTDIRFUNC)
818 (*pglob->gl_closedir) (stream);
820 closedir((DIR *) stream);
824 return nfound == 0 ? GLOB_NOMATCH : 0;
827 /* librpmio exported interfaces */
829 int rpmGlob(const char * patterns, int * argcPtr, ARGV_t * argvPtr)
832 const char ** av = NULL;
835 char * globRoot = NULL;
836 const char *home = getenv("HOME");
839 char * old_collate = NULL;
840 char * old_ctype = NULL;
847 if (home != NULL && strlen(home) > 0)
848 gflags |= GLOB_TILDE;
850 /* Can't use argvSplit() here, it doesn't handle whitespace etc escapes */
851 rc = poptParseArgvString(patterns, &ac, &av);
856 t = setlocale(LC_COLLATE, NULL);
858 old_collate = xstrdup(t);
859 t = setlocale(LC_CTYPE, NULL);
861 old_ctype = xstrdup(t);
862 (void) setlocale(LC_COLLATE, "C");
863 (void) setlocale(LC_CTYPE, "C");
867 for (j = 0; j < ac; j++) {
870 int ut = urlPath(av[j], &path);
871 int local = (ut == URL_IS_PATH) || (ut == URL_IS_UNKNOWN);
872 size_t plen = strlen(path);
874 int dir_only = (plen > 0 && path[plen-1] == '/');
877 if (!local || (!rpmIsGlob(av[j], 0) && strchr(path, '~') == NULL)) {
878 argvAdd(&argv, av[j]);
883 flags |= GLOB_ONLYDIR;
888 rc = glob(av[j], flags, NULL, &gl);
892 /* XXX Prepend the URL leader for globs that have stripped it off */
894 for (i = 0; i < gl.gl_pathc; i++) {
895 if ((nb = strlen(&(gl.gl_pathv[i][0]))) > maxb)
899 nb = ((ut == URL_IS_PATH) ? (path - av[j]) : 0);
902 globURL = globRoot = xmalloc(maxb);
907 strncpy(globRoot, av[j], nb);
920 for (i = 0; i < gl.gl_pathc; i++) {
921 const char * globFile = &(gl.gl_pathv[i][0]);
925 if (lstat(gl.gl_pathv[i], &sb) || !S_ISDIR(sb.st_mode))
929 if (globRoot > globURL && globRoot[-1] == '/')
930 while (*globFile == '/') globFile++;
931 strcpy(globRoot, globFile);
932 argvAdd(&argv, globURL);
938 argc = argvCount(argv);
952 (void) setlocale(LC_COLLATE, old_collate);
956 (void) setlocale(LC_CTYPE, old_ctype);
961 if (rc || argvPtr == NULL) {
967 int rpmIsGlob(const char * pattern, int quote)
969 return __glob_pattern_p(pattern, quote);