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);