line |
stmt |
bran |
cond |
sub |
time |
code |
1
|
|
|
|
|
|
/* |
2
|
|
|
|
|
|
* Copyright (c) 1989, 1993 |
3
|
|
|
|
|
|
* The Regents of the University of California. All rights reserved. |
4
|
|
|
|
|
|
* |
5
|
|
|
|
|
|
* This code is derived from software contributed to Berkeley by |
6
|
|
|
|
|
|
* Guido van Rossum. |
7
|
|
|
|
|
|
* |
8
|
|
|
|
|
|
* Redistribution and use in source and binary forms, with or without |
9
|
|
|
|
|
|
* modification, are permitted provided that the following conditions |
10
|
|
|
|
|
|
* are met: |
11
|
|
|
|
|
|
* 1. Redistributions of source code must retain the above copyright |
12
|
|
|
|
|
|
* notice, this list of conditions and the following disclaimer. |
13
|
|
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
14
|
|
|
|
|
|
* notice, this list of conditions and the following disclaimer in the |
15
|
|
|
|
|
|
* documentation and/or other materials provided with the distribution. |
16
|
|
|
|
|
|
* 3. Neither the name of the University nor the names of its contributors |
17
|
|
|
|
|
|
* may be used to endorse or promote products derived from this software |
18
|
|
|
|
|
|
* without specific prior written permission. |
19
|
|
|
|
|
|
* |
20
|
|
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND |
21
|
|
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
22
|
|
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
23
|
|
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
24
|
|
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
25
|
|
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
26
|
|
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
27
|
|
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
28
|
|
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
29
|
|
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
30
|
|
|
|
|
|
* SUCH DAMAGE. |
31
|
|
|
|
|
|
*/ |
32
|
|
|
|
|
|
|
33
|
|
|
|
|
|
#if defined(LIBC_SCCS) && !defined(lint) |
34
|
|
|
|
|
|
static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; |
35
|
|
|
|
|
|
/* most changes between the version above and the one below have been ported: |
36
|
|
|
|
|
|
static char sscsid[]= "$OpenBSD: glob.c,v 1.8.10.1 2001/04/10 jason Exp $"; |
37
|
|
|
|
|
|
*/ |
38
|
|
|
|
|
|
#endif /* LIBC_SCCS and not lint */ |
39
|
|
|
|
|
|
|
40
|
|
|
|
|
|
/* |
41
|
|
|
|
|
|
* glob(3) -- a superset of the one defined in POSIX 1003.2. |
42
|
|
|
|
|
|
* |
43
|
|
|
|
|
|
* The [!...] convention to negate a range is supported (SysV, Posix, ksh). |
44
|
|
|
|
|
|
* |
45
|
|
|
|
|
|
* Optional extra services, controlled by flags not defined by POSIX: |
46
|
|
|
|
|
|
* |
47
|
|
|
|
|
|
* GLOB_QUOTE: |
48
|
|
|
|
|
|
* Escaping convention: \ inhibits any special meaning the following |
49
|
|
|
|
|
|
* character might have (except \ at end of string is retained). |
50
|
|
|
|
|
|
* GLOB_MAGCHAR: |
51
|
|
|
|
|
|
* Set in gl_flags if pattern contained a globbing character. |
52
|
|
|
|
|
|
* GLOB_NOMAGIC: |
53
|
|
|
|
|
|
* Same as GLOB_NOCHECK, but it will only append pattern if it did |
54
|
|
|
|
|
|
* not contain any magic characters. [Used in csh style globbing] |
55
|
|
|
|
|
|
* GLOB_ALTDIRFUNC: |
56
|
|
|
|
|
|
* Use alternately specified directory access functions. |
57
|
|
|
|
|
|
* GLOB_TILDE: |
58
|
|
|
|
|
|
* expand ~user/foo to the /home/dir/of/user/foo |
59
|
|
|
|
|
|
* GLOB_BRACE: |
60
|
|
|
|
|
|
* expand {1,2}{a,b} to 1a 1b 2a 2b |
61
|
|
|
|
|
|
* gl_matchc: |
62
|
|
|
|
|
|
* Number of matches in the current invocation of glob. |
63
|
|
|
|
|
|
* GLOB_ALPHASORT: |
64
|
|
|
|
|
|
* sort alphabetically like csh (case doesn't matter) instead of in ASCII |
65
|
|
|
|
|
|
* order |
66
|
|
|
|
|
|
*/ |
67
|
|
|
|
|
|
|
68
|
|
|
|
|
|
#include |
69
|
|
|
|
|
|
#include |
70
|
|
|
|
|
|
#include |
71
|
|
|
|
|
|
|
72
|
|
|
|
|
|
#include "bsd_glob.h" |
73
|
|
|
|
|
|
#ifdef I_PWD |
74
|
|
|
|
|
|
# include |
75
|
|
|
|
|
|
#else |
76
|
|
|
|
|
|
#if defined(HAS_PASSWD) && !defined(VMS) |
77
|
|
|
|
|
|
struct passwd *getpwnam(char *); |
78
|
|
|
|
|
|
struct passwd *getpwuid(Uid_t); |
79
|
|
|
|
|
|
#endif |
80
|
|
|
|
|
|
#endif |
81
|
|
|
|
|
|
|
82
|
|
|
|
|
|
#ifndef MAXPATHLEN |
83
|
|
|
|
|
|
# ifdef PATH_MAX |
84
|
|
|
|
|
|
# define MAXPATHLEN PATH_MAX |
85
|
|
|
|
|
|
# else |
86
|
|
|
|
|
|
# define MAXPATHLEN 1024 |
87
|
|
|
|
|
|
# endif |
88
|
|
|
|
|
|
#endif |
89
|
|
|
|
|
|
|
90
|
|
|
|
|
|
#ifdef I_LIMITS |
91
|
|
|
|
|
|
#include |
92
|
|
|
|
|
|
#endif |
93
|
|
|
|
|
|
|
94
|
|
|
|
|
|
#ifndef ARG_MAX |
95
|
|
|
|
|
|
# ifdef _SC_ARG_MAX |
96
|
|
|
|
|
|
# define ARG_MAX (sysconf(_SC_ARG_MAX)) |
97
|
|
|
|
|
|
# else |
98
|
|
|
|
|
|
# ifdef _POSIX_ARG_MAX |
99
|
|
|
|
|
|
# define ARG_MAX _POSIX_ARG_MAX |
100
|
|
|
|
|
|
# else |
101
|
|
|
|
|
|
# ifdef WIN32 |
102
|
|
|
|
|
|
# define ARG_MAX 14500 /* from VC's limits.h */ |
103
|
|
|
|
|
|
# else |
104
|
|
|
|
|
|
# define ARG_MAX 4096 /* from POSIX, be conservative */ |
105
|
|
|
|
|
|
# endif |
106
|
|
|
|
|
|
# endif |
107
|
|
|
|
|
|
# endif |
108
|
|
|
|
|
|
#endif |
109
|
|
|
|
|
|
|
110
|
|
|
|
|
|
#define BG_DOLLAR '$' |
111
|
|
|
|
|
|
#define BG_DOT '.' |
112
|
|
|
|
|
|
#define BG_EOS '\0' |
113
|
|
|
|
|
|
#define BG_LBRACKET '[' |
114
|
|
|
|
|
|
#define BG_NOT '!' |
115
|
|
|
|
|
|
#define BG_QUESTION '?' |
116
|
|
|
|
|
|
#define BG_QUOTE '\\' |
117
|
|
|
|
|
|
#define BG_RANGE '-' |
118
|
|
|
|
|
|
#define BG_RBRACKET ']' |
119
|
|
|
|
|
|
#define BG_SEP '/' |
120
|
|
|
|
|
|
#ifdef DOSISH |
121
|
|
|
|
|
|
#define BG_SEP2 '\\' |
122
|
|
|
|
|
|
#endif |
123
|
|
|
|
|
|
#define BG_STAR '*' |
124
|
|
|
|
|
|
#define BG_TILDE '~' |
125
|
|
|
|
|
|
#define BG_UNDERSCORE '_' |
126
|
|
|
|
|
|
#define BG_LBRACE '{' |
127
|
|
|
|
|
|
#define BG_RBRACE '}' |
128
|
|
|
|
|
|
#define BG_SLASH '/' |
129
|
|
|
|
|
|
#define BG_COMMA ',' |
130
|
|
|
|
|
|
|
131
|
|
|
|
|
|
#ifndef GLOB_DEBUG |
132
|
|
|
|
|
|
|
133
|
|
|
|
|
|
#define M_QUOTE 0x8000 |
134
|
|
|
|
|
|
#define M_PROTECT 0x4000 |
135
|
|
|
|
|
|
#define M_MASK 0xffff |
136
|
|
|
|
|
|
#define M_ASCII 0x00ff |
137
|
|
|
|
|
|
|
138
|
|
|
|
|
|
typedef U16 Char; |
139
|
|
|
|
|
|
|
140
|
|
|
|
|
|
#else |
141
|
|
|
|
|
|
|
142
|
|
|
|
|
|
#define M_QUOTE 0x80 |
143
|
|
|
|
|
|
#define M_PROTECT 0x40 |
144
|
|
|
|
|
|
#define M_MASK 0xff |
145
|
|
|
|
|
|
#define M_ASCII 0x7f |
146
|
|
|
|
|
|
|
147
|
|
|
|
|
|
typedef U8 Char; |
148
|
|
|
|
|
|
|
149
|
|
|
|
|
|
#endif /* !GLOB_DEBUG */ |
150
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
152
|
|
|
|
|
|
#define CHAR(c) ((Char)((c)&M_ASCII)) |
153
|
|
|
|
|
|
#define META(c) ((Char)((c)|M_QUOTE)) |
154
|
|
|
|
|
|
#define M_ALL META('*') |
155
|
|
|
|
|
|
#define M_END META(']') |
156
|
|
|
|
|
|
#define M_NOT META('!') |
157
|
|
|
|
|
|
#define M_ONE META('?') |
158
|
|
|
|
|
|
#define M_RNG META('-') |
159
|
|
|
|
|
|
#define M_SET META('[') |
160
|
|
|
|
|
|
#define ismeta(c) (((c)&M_QUOTE) != 0) |
161
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
163
|
|
|
|
|
|
static int compare(const void *, const void *); |
164
|
|
|
|
|
|
static int ci_compare(const void *, const void *); |
165
|
|
|
|
|
|
static int g_Ctoc(const Char *, char *, STRLEN); |
166
|
|
|
|
|
|
static int g_lstat(Char *, Stat_t *, glob_t *); |
167
|
|
|
|
|
|
static DIR *g_opendir(Char *, glob_t *); |
168
|
|
|
|
|
|
static Char *g_strchr(Char *, int); |
169
|
|
|
|
|
|
static int g_stat(Char *, Stat_t *, glob_t *); |
170
|
|
|
|
|
|
static int glob0(const Char *, glob_t *); |
171
|
|
|
|
|
|
static int glob1(Char *, Char *, glob_t *, size_t *); |
172
|
|
|
|
|
|
static int glob2(Char *, Char *, Char *, Char *, Char *, Char *, |
173
|
|
|
|
|
|
glob_t *, size_t *); |
174
|
|
|
|
|
|
static int glob3(Char *, Char *, Char *, Char *, Char *, Char *, |
175
|
|
|
|
|
|
Char *, Char *, glob_t *, size_t *); |
176
|
|
|
|
|
|
static int globextend(const Char *, glob_t *, size_t *); |
177
|
|
|
|
|
|
static const Char * |
178
|
|
|
|
|
|
globtilde(const Char *, Char *, size_t, glob_t *); |
179
|
|
|
|
|
|
static int globexp1(const Char *, glob_t *); |
180
|
|
|
|
|
|
static int globexp2(const Char *, const Char *, glob_t *, int *); |
181
|
|
|
|
|
|
static int match(Char *, Char *, Char *, int); |
182
|
|
|
|
|
|
#ifdef GLOB_DEBUG |
183
|
|
|
|
|
|
static void qprintf(const char *, Char *); |
184
|
|
|
|
|
|
#endif /* GLOB_DEBUG */ |
185
|
|
|
|
|
|
|
186
|
|
|
|
|
|
#ifdef PERL_IMPLICIT_CONTEXT |
187
|
|
|
|
|
|
static Direntry_t * my_readdir(DIR*); |
188
|
|
|
|
|
|
|
189
|
|
|
|
|
|
static Direntry_t * |
190
|
|
|
|
|
|
my_readdir(DIR *d) |
191
|
|
|
|
|
|
{ |
192
|
|
|
|
|
|
#ifndef NETWARE |
193
|
|
|
|
|
|
return PerlDir_read(d); |
194
|
|
|
|
|
|
#else |
195
|
|
|
|
|
|
return (DIR *)PerlDir_read(d); |
196
|
|
|
|
|
|
#endif |
197
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
#else |
199
|
|
|
|
|
|
|
200
|
|
|
|
|
|
/* ReliantUNIX (OS formerly known as SINIX) defines readdir |
201
|
|
|
|
|
|
* in LFS-mode to be a 64-bit version of readdir. */ |
202
|
|
|
|
|
|
|
203
|
|
|
|
|
|
# ifdef sinix |
204
|
|
|
|
|
|
static Direntry_t * my_readdir(DIR*); |
205
|
|
|
|
|
|
|
206
|
|
|
|
|
|
static Direntry_t * |
207
|
|
|
|
|
|
my_readdir(DIR *d) |
208
|
|
|
|
|
|
{ |
209
|
|
|
|
|
|
return readdir(d); |
210
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
# else |
212
|
|
|
|
|
|
|
213
|
|
|
|
|
|
# define my_readdir readdir |
214
|
|
|
|
|
|
|
215
|
|
|
|
|
|
# endif |
216
|
|
|
|
|
|
|
217
|
|
|
|
|
|
#endif |
218
|
|
|
|
|
|
|
219
|
|
|
|
|
|
int |
220
|
2296
|
|
|
|
|
bsd_glob(const char *pattern, int flags, |
221
|
|
|
|
|
|
int (*errfunc)(const char *, int), glob_t *pglob) |
222
|
|
|
|
|
|
{ |
223
|
|
|
|
|
|
const U8 *patnext; |
224
|
|
|
|
|
|
int c; |
225
|
|
|
|
|
|
Char *bufnext, *bufend, patbuf[MAXPATHLEN]; |
226
|
|
|
|
|
|
patnext = (U8 *) pattern; |
227
|
|
|
|
|
|
/* TODO: GLOB_APPEND / GLOB_DOOFFS aren't supported yet */ |
228
|
|
|
|
|
|
#if 0 |
229
|
|
|
|
|
|
if (!(flags & GLOB_APPEND)) { |
230
|
|
|
|
|
|
pglob->gl_pathc = 0; |
231
|
|
|
|
|
|
pglob->gl_pathv = NULL; |
232
|
|
|
|
|
|
if (!(flags & GLOB_DOOFFS)) |
233
|
|
|
|
|
|
pglob->gl_offs = 0; |
234
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
#else |
236
|
2296
|
|
|
|
|
pglob->gl_pathc = 0; |
237
|
2296
|
|
|
|
|
pglob->gl_pathv = NULL; |
238
|
2296
|
|
|
|
|
pglob->gl_offs = 0; |
239
|
|
|
|
|
|
#endif |
240
|
2296
|
|
|
|
|
pglob->gl_flags = flags & ~GLOB_MAGCHAR; |
241
|
2296
|
|
|
|
|
pglob->gl_errfunc = errfunc; |
242
|
2296
|
|
|
|
|
pglob->gl_matchc = 0; |
243
|
|
|
|
|
|
|
244
|
|
|
|
|
|
bufnext = patbuf; |
245
|
|
|
|
|
|
bufend = bufnext + MAXPATHLEN - 1; |
246
|
|
|
|
|
|
#ifdef DOSISH |
247
|
|
|
|
|
|
/* Nasty hack to treat patterns like "C:*" correctly. In this |
248
|
|
|
|
|
|
* case, the * should match any file in the current directory |
249
|
|
|
|
|
|
* on the C: drive. However, the glob code does not treat the |
250
|
|
|
|
|
|
* colon specially, so it looks for files beginning "C:" in |
251
|
|
|
|
|
|
* the current directory. To fix this, change the pattern to |
252
|
|
|
|
|
|
* add an explicit "./" at the start (just after the drive |
253
|
|
|
|
|
|
* letter and colon - ie change to "C:./"). |
254
|
|
|
|
|
|
*/ |
255
|
|
|
|
|
|
if (isalpha(pattern[0]) && pattern[1] == ':' && |
256
|
|
|
|
|
|
pattern[2] != BG_SEP && pattern[2] != BG_SEP2 && |
257
|
|
|
|
|
|
bufend - bufnext > 4) { |
258
|
|
|
|
|
|
*bufnext++ = pattern[0]; |
259
|
|
|
|
|
|
*bufnext++ = ':'; |
260
|
|
|
|
|
|
*bufnext++ = '.'; |
261
|
|
|
|
|
|
*bufnext++ = BG_SEP; |
262
|
|
|
|
|
|
patnext += 2; |
263
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
#endif |
265
|
|
|
|
|
|
|
266
|
2296
|
|
|
|
|
if (flags & GLOB_QUOTE) { |
267
|
|
|
|
|
|
/* Protect the quoted characters. */ |
268
|
29262
|
|
|
|
|
while (bufnext < bufend && (c = *patnext++) != BG_EOS) |
269
|
26970
|
|
|
|
|
if (c == BG_QUOTE) { |
270
|
|
|
|
|
|
#ifdef DOSISH |
271
|
|
|
|
|
|
/* To avoid backslashitis on Win32, |
272
|
|
|
|
|
|
* we only treat \ as a quoting character |
273
|
|
|
|
|
|
* if it precedes one of the |
274
|
|
|
|
|
|
* metacharacters []-{}~\ |
275
|
|
|
|
|
|
*/ |
276
|
|
|
|
|
|
if ((c = *patnext++) != '[' && c != ']' && |
277
|
|
|
|
|
|
c != '-' && c != '{' && c != '}' && |
278
|
|
|
|
|
|
c != '~' && c != '\\') { |
279
|
|
|
|
|
|
#else |
280
|
0
|
|
|
|
|
if ((c = *patnext++) == BG_EOS) { |
281
|
|
|
|
|
|
#endif |
282
|
|
|
|
|
|
c = BG_QUOTE; |
283
|
|
|
|
|
|
--patnext; |
284
|
|
|
|
|
|
} |
285
|
0
|
|
|
|
|
*bufnext++ = c | M_PROTECT; |
286
|
|
|
|
|
|
} else |
287
|
26970
|
|
|
|
|
*bufnext++ = c; |
288
|
|
|
|
|
|
} else |
289
|
20
|
|
|
|
|
while (bufnext < bufend && (c = *patnext++) != BG_EOS) |
290
|
16
|
|
|
|
|
*bufnext++ = c; |
291
|
2296
|
|
|
|
|
*bufnext = BG_EOS; |
292
|
|
|
|
|
|
|
293
|
2296
|
|
|
|
|
if (flags & GLOB_BRACE) |
294
|
2292
|
|
|
|
|
return globexp1(patbuf, pglob); |
295
|
|
|
|
|
|
else |
296
|
4
|
|
|
|
|
return glob0(patbuf, pglob); |
297
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
299
|
|
|
|
|
|
/* |
300
|
|
|
|
|
|
* Expand recursively a glob {} pattern. When there is no more expansion |
301
|
|
|
|
|
|
* invoke the standard globbing routine to glob the rest of the magic |
302
|
|
|
|
|
|
* characters |
303
|
|
|
|
|
|
*/ |
304
|
|
|
|
|
|
static int |
305
|
2928
|
|
|
|
|
globexp1(const Char *pattern, glob_t *pglob) |
306
|
|
|
|
|
|
{ |
307
|
|
|
|
|
|
const Char* ptr = pattern; |
308
|
|
|
|
|
|
int rv; |
309
|
|
|
|
|
|
|
310
|
|
|
|
|
|
/* Protect a single {}, for find(1), like csh */ |
311
|
2928
|
|
|
|
|
if (pattern[0] == BG_LBRACE && pattern[1] == BG_RBRACE && pattern[2] == BG_EOS) |
312
|
0
|
|
|
|
|
return glob0(pattern, pglob); |
313
|
|
|
|
|
|
|
314
|
2928
|
|
|
|
|
while ((ptr = (const Char *) g_strchr((Char *) ptr, BG_LBRACE)) != NULL) |
315
|
312
|
|
|
|
|
if (!globexp2(ptr, pattern, pglob, &rv)) |
316
|
312
|
|
|
|
|
return rv; |
317
|
|
|
|
|
|
|
318
|
2616
|
|
|
|
|
return glob0(pattern, pglob); |
319
|
|
|
|
|
|
} |
320
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
322
|
|
|
|
|
|
/* |
323
|
|
|
|
|
|
* Recursive brace globbing helper. Tries to expand a single brace. |
324
|
|
|
|
|
|
* If it succeeds then it invokes globexp1 with the new pattern. |
325
|
|
|
|
|
|
* If it fails then it tries to glob the rest of the pattern and returns. |
326
|
|
|
|
|
|
*/ |
327
|
|
|
|
|
|
static int |
328
|
312
|
|
|
|
|
globexp2(const Char *ptr, const Char *pattern, |
329
|
|
|
|
|
|
glob_t *pglob, int *rv) |
330
|
|
|
|
|
|
{ |
331
|
|
|
|
|
|
int i; |
332
|
|
|
|
|
|
Char *lm, *ls; |
333
|
|
|
|
|
|
const Char *pe, *pm, *pm1, *pl; |
334
|
|
|
|
|
|
Char patbuf[MAXPATHLEN]; |
335
|
|
|
|
|
|
|
336
|
|
|
|
|
|
/* copy part up to the brace */ |
337
|
312
|
|
|
|
|
for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) |
338
|
|
|
|
|
|
; |
339
|
312
|
|
|
|
|
*lm = BG_EOS; |
340
|
|
|
|
|
|
ls = lm; |
341
|
|
|
|
|
|
|
342
|
|
|
|
|
|
/* Find the balanced brace */ |
343
|
1678
|
|
|
|
|
for (i = 0, pe = ++ptr; *pe; pe++) |
344
|
1678
|
|
|
|
|
if (*pe == BG_LBRACKET) { |
345
|
|
|
|
|
|
/* Ignore everything between [] */ |
346
|
0
|
|
|
|
|
for (pm = pe++; *pe != BG_RBRACKET && *pe != BG_EOS; pe++) |
347
|
|
|
|
|
|
; |
348
|
0
|
|
|
|
|
if (*pe == BG_EOS) { |
349
|
|
|
|
|
|
/* |
350
|
|
|
|
|
|
* We could not find a matching BG_RBRACKET. |
351
|
|
|
|
|
|
* Ignore and just look for BG_RBRACE |
352
|
|
|
|
|
|
*/ |
353
|
|
|
|
|
|
pe = pm; |
354
|
|
|
|
|
|
} |
355
|
1678
|
|
|
|
|
} else if (*pe == BG_LBRACE) |
356
|
0
|
|
|
|
|
i++; |
357
|
1678
|
|
|
|
|
else if (*pe == BG_RBRACE) { |
358
|
312
|
|
|
|
|
if (i == 0) |
359
|
|
|
|
|
|
break; |
360
|
0
|
|
|
|
|
i--; |
361
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
363
|
|
|
|
|
|
/* Non matching braces; just glob the pattern */ |
364
|
312
|
|
|
|
|
if (i != 0 || *pe == BG_EOS) { |
365
|
0
|
|
|
|
|
*rv = glob0(patbuf, pglob); |
366
|
0
|
|
|
|
|
return 0; |
367
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
369
|
1678
|
|
|
|
|
for (i = 0, pl = pm = ptr; pm <= pe; pm++) { |
370
|
1678
|
|
|
|
|
switch (*pm) { |
371
|
|
|
|
|
|
case BG_LBRACKET: |
372
|
|
|
|
|
|
/* Ignore everything between [] */ |
373
|
0
|
|
|
|
|
for (pm1 = pm++; *pm != BG_RBRACKET && *pm != BG_EOS; pm++) |
374
|
|
|
|
|
|
; |
375
|
0
|
|
|
|
|
if (*pm == BG_EOS) { |
376
|
|
|
|
|
|
/* |
377
|
|
|
|
|
|
* We could not find a matching BG_RBRACKET. |
378
|
|
|
|
|
|
* Ignore and just look for BG_RBRACE |
379
|
|
|
|
|
|
*/ |
380
|
|
|
|
|
|
pm = pm1; |
381
|
|
|
|
|
|
} |
382
|
|
|
|
|
|
break; |
383
|
|
|
|
|
|
|
384
|
|
|
|
|
|
case BG_LBRACE: |
385
|
0
|
|
|
|
|
i++; |
386
|
0
|
|
|
|
|
break; |
387
|
|
|
|
|
|
|
388
|
|
|
|
|
|
case BG_RBRACE: |
389
|
312
|
|
|
|
|
if (i) { |
390
|
0
|
|
|
|
|
i--; |
391
|
0
|
|
|
|
|
break; |
392
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
/* FALLTHROUGH */ |
394
|
|
|
|
|
|
case BG_COMMA: |
395
|
636
|
|
|
|
|
if (i && *pm == BG_COMMA) |
396
|
|
|
|
|
|
break; |
397
|
|
|
|
|
|
else { |
398
|
|
|
|
|
|
/* Append the current string */ |
399
|
1042
|
|
|
|
|
for (lm = ls; (pl < pm); *lm++ = *pl++) |
400
|
|
|
|
|
|
; |
401
|
|
|
|
|
|
|
402
|
|
|
|
|
|
/* |
403
|
|
|
|
|
|
* Append the rest of the pattern after the |
404
|
|
|
|
|
|
* closing brace |
405
|
|
|
|
|
|
*/ |
406
|
636
|
|
|
|
|
for (pl = pe + 1; (*lm++ = *pl++) != BG_EOS; ) |
407
|
|
|
|
|
|
; |
408
|
|
|
|
|
|
|
409
|
|
|
|
|
|
/* Expand the current pattern */ |
410
|
|
|
|
|
|
#ifdef GLOB_DEBUG |
411
|
|
|
|
|
|
qprintf("globexp2:", patbuf); |
412
|
|
|
|
|
|
#endif /* GLOB_DEBUG */ |
413
|
636
|
|
|
|
|
*rv = globexp1(patbuf, pglob); |
414
|
|
|
|
|
|
|
415
|
|
|
|
|
|
/* move after the comma, to the next string */ |
416
|
636
|
|
|
|
|
pl = pm + 1; |
417
|
|
|
|
|
|
} |
418
|
636
|
|
|
|
|
break; |
419
|
|
|
|
|
|
|
420
|
|
|
|
|
|
default: |
421
|
|
|
|
|
|
break; |
422
|
|
|
|
|
|
} |
423
|
|
|
|
|
|
} |
424
|
312
|
|
|
|
|
*rv = 0; |
425
|
312
|
|
|
|
|
return 0; |
426
|
|
|
|
|
|
} |
427
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
430
|
|
|
|
|
|
/* |
431
|
|
|
|
|
|
* expand tilde from the passwd file. |
432
|
|
|
|
|
|
*/ |
433
|
|
|
|
|
|
static const Char * |
434
|
2620
|
|
|
|
|
globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) |
435
|
|
|
|
|
|
{ |
436
|
|
|
|
|
|
char *h; |
437
|
|
|
|
|
|
const Char *p; |
438
|
|
|
|
|
|
Char *b, *eb; |
439
|
|
|
|
|
|
|
440
|
2620
|
|
|
|
|
if (*pattern != BG_TILDE || !(pglob->gl_flags & GLOB_TILDE)) |
441
|
|
|
|
|
|
return pattern; |
442
|
|
|
|
|
|
|
443
|
|
|
|
|
|
/* Copy up to the end of the string or / */ |
444
|
80
|
|
|
|
|
eb = &patbuf[patbuf_len - 1]; |
445
|
160
|
|
|
|
|
for (p = pattern + 1, h = (char *) patbuf; |
446
|
80
|
|
|
|
|
h < (char*)eb && *p && *p != BG_SLASH; *h++ = (char)*p++) |
447
|
|
|
|
|
|
; |
448
|
|
|
|
|
|
|
449
|
80
|
|
|
|
|
*h = BG_EOS; |
450
|
|
|
|
|
|
|
451
|
|
|
|
|
|
#if 0 |
452
|
|
|
|
|
|
if (h == (char *)eb) |
453
|
|
|
|
|
|
return what; |
454
|
|
|
|
|
|
#endif |
455
|
|
|
|
|
|
|
456
|
80
|
|
|
|
|
if (((char *) patbuf)[0] == BG_EOS) { |
457
|
|
|
|
|
|
/* |
458
|
|
|
|
|
|
* handle a plain ~ or ~/ by expanding $HOME |
459
|
|
|
|
|
|
* first and then trying the password file |
460
|
|
|
|
|
|
* or $USERPROFILE on DOSISH systems |
461
|
|
|
|
|
|
*/ |
462
|
80
|
|
|
|
|
if ((h = getenv("HOME")) == NULL) { |
463
|
|
|
|
|
|
#ifdef HAS_PASSWD |
464
|
|
|
|
|
|
struct passwd *pwd; |
465
|
0
|
|
|
|
|
if ((pwd = getpwuid(getuid())) == NULL) |
466
|
|
|
|
|
|
return pattern; |
467
|
|
|
|
|
|
else |
468
|
0
|
|
|
|
|
h = pwd->pw_dir; |
469
|
|
|
|
|
|
#elif DOSISH |
470
|
|
|
|
|
|
/* |
471
|
|
|
|
|
|
* When no passwd file, fallback to the USERPROFILE |
472
|
|
|
|
|
|
* environment variable on DOSish systems. |
473
|
|
|
|
|
|
*/ |
474
|
|
|
|
|
|
if ((h = getenv("USERPROFILE")) == NULL) { |
475
|
|
|
|
|
|
return pattern; |
476
|
|
|
|
|
|
} |
477
|
|
|
|
|
|
#else |
478
|
|
|
|
|
|
return pattern; |
479
|
|
|
|
|
|
#endif |
480
|
|
|
|
|
|
} |
481
|
|
|
|
|
|
} else { |
482
|
|
|
|
|
|
/* |
483
|
|
|
|
|
|
* Expand a ~user |
484
|
|
|
|
|
|
*/ |
485
|
|
|
|
|
|
#ifdef HAS_PASSWD |
486
|
|
|
|
|
|
struct passwd *pwd; |
487
|
0
|
|
|
|
|
if ((pwd = getpwnam((char*) patbuf)) == NULL) |
488
|
|
|
|
|
|
return pattern; |
489
|
|
|
|
|
|
else |
490
|
0
|
|
|
|
|
h = pwd->pw_dir; |
491
|
|
|
|
|
|
#else |
492
|
|
|
|
|
|
return pattern; |
493
|
|
|
|
|
|
#endif |
494
|
|
|
|
|
|
} |
495
|
|
|
|
|
|
|
496
|
|
|
|
|
|
/* Copy the home directory */ |
497
|
800
|
|
|
|
|
for (b = patbuf; b < eb && *h; *b++ = *h++) |
498
|
|
|
|
|
|
; |
499
|
|
|
|
|
|
|
500
|
|
|
|
|
|
/* Append the rest of the pattern */ |
501
|
782
|
|
|
|
|
while (b < eb && (*b++ = *p++) != BG_EOS) |
502
|
|
|
|
|
|
; |
503
|
80
|
|
|
|
|
*b = BG_EOS; |
504
|
|
|
|
|
|
|
505
|
0
|
|
|
|
|
return patbuf; |
506
|
|
|
|
|
|
} |
507
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
509
|
|
|
|
|
|
/* |
510
|
|
|
|
|
|
* The main glob() routine: compiles the pattern (optionally processing |
511
|
|
|
|
|
|
* quotes), calls glob1() to do the real pattern matching, and finally |
512
|
|
|
|
|
|
* sorts the list (unless unsorted operation is requested). Returns 0 |
513
|
|
|
|
|
|
* if things went well, nonzero if errors occurred. It is not an error |
514
|
|
|
|
|
|
* to find no matches. |
515
|
|
|
|
|
|
*/ |
516
|
|
|
|
|
|
static int |
517
|
2620
|
|
|
|
|
glob0(const Char *pattern, glob_t *pglob) |
518
|
|
|
|
|
|
{ |
519
|
|
|
|
|
|
const Char *qpat, *qpatnext; |
520
|
|
|
|
|
|
int c, err, oldflags, oldpathc; |
521
|
|
|
|
|
|
Char *bufnext, patbuf[MAXPATHLEN]; |
522
|
2620
|
|
|
|
|
size_t limit = 0; |
523
|
|
|
|
|
|
|
524
|
2620
|
|
|
|
|
qpat = globtilde(pattern, patbuf, MAXPATHLEN, pglob); |
525
|
|
|
|
|
|
qpatnext = qpat; |
526
|
2620
|
|
|
|
|
oldflags = pglob->gl_flags; |
527
|
2620
|
|
|
|
|
oldpathc = pglob->gl_pathc; |
528
|
|
|
|
|
|
bufnext = patbuf; |
529
|
|
|
|
|
|
|
530
|
|
|
|
|
|
/* We don't need to check for buffer overflow any more. */ |
531
|
36278
|
|
|
|
|
while ((c = *qpatnext++) != BG_EOS) { |
532
|
31038
|
|
|
|
|
switch (c) { |
533
|
|
|
|
|
|
case BG_LBRACKET: |
534
|
6
|
|
|
|
|
c = *qpatnext; |
535
|
6
|
|
|
|
|
if (c == BG_NOT) |
536
|
0
|
|
|
|
|
++qpatnext; |
537
|
12
|
|
|
|
|
if (*qpatnext == BG_EOS || |
538
|
6
|
|
|
|
|
g_strchr((Char *) qpatnext+1, BG_RBRACKET) == NULL) { |
539
|
0
|
|
|
|
|
*bufnext++ = BG_LBRACKET; |
540
|
0
|
|
|
|
|
if (c == BG_NOT) |
541
|
0
|
|
|
|
|
--qpatnext; |
542
|
|
|
|
|
|
break; |
543
|
|
|
|
|
|
} |
544
|
6
|
|
|
|
|
*bufnext++ = M_SET; |
545
|
6
|
|
|
|
|
if (c == BG_NOT) |
546
|
0
|
|
|
|
|
*bufnext++ = M_NOT; |
547
|
6
|
|
|
|
|
c = *qpatnext++; |
548
|
|
|
|
|
|
do { |
549
|
42
|
|
|
|
|
*bufnext++ = CHAR(c); |
550
|
44
|
|
|
|
|
if (*qpatnext == BG_RANGE && |
551
|
2
|
|
|
|
|
(c = qpatnext[1]) != BG_RBRACKET) { |
552
|
2
|
|
|
|
|
*bufnext++ = M_RNG; |
553
|
2
|
|
|
|
|
*bufnext++ = CHAR(c); |
554
|
2
|
|
|
|
|
qpatnext += 2; |
555
|
|
|
|
|
|
} |
556
|
42
|
|
|
|
|
} while ((c = *qpatnext++) != BG_RBRACKET); |
557
|
6
|
|
|
|
|
pglob->gl_flags |= GLOB_MAGCHAR; |
558
|
6
|
|
|
|
|
*bufnext++ = M_END; |
559
|
6
|
|
|
|
|
break; |
560
|
|
|
|
|
|
case BG_QUESTION: |
561
|
30
|
|
|
|
|
pglob->gl_flags |= GLOB_MAGCHAR; |
562
|
30
|
|
|
|
|
*bufnext++ = M_ONE; |
563
|
30
|
|
|
|
|
break; |
564
|
|
|
|
|
|
case BG_STAR: |
565
|
2644
|
|
|
|
|
pglob->gl_flags |= GLOB_MAGCHAR; |
566
|
|
|
|
|
|
/* collapse adjacent stars to one, |
567
|
|
|
|
|
|
* to avoid exponential behavior |
568
|
|
|
|
|
|
*/ |
569
|
2644
|
|
|
|
|
if (bufnext == patbuf || bufnext[-1] != M_ALL) |
570
|
2644
|
|
|
|
|
*bufnext++ = M_ALL; |
571
|
|
|
|
|
|
break; |
572
|
|
|
|
|
|
default: |
573
|
28358
|
|
|
|
|
*bufnext++ = CHAR(c); |
574
|
28358
|
|
|
|
|
break; |
575
|
|
|
|
|
|
} |
576
|
|
|
|
|
|
} |
577
|
2620
|
|
|
|
|
*bufnext = BG_EOS; |
578
|
|
|
|
|
|
#ifdef GLOB_DEBUG |
579
|
|
|
|
|
|
qprintf("glob0:", patbuf); |
580
|
|
|
|
|
|
#endif /* GLOB_DEBUG */ |
581
|
|
|
|
|
|
|
582
|
2620
|
|
|
|
|
if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, &limit)) != 0) { |
583
|
0
|
|
|
|
|
pglob->gl_flags = oldflags; |
584
|
0
|
|
|
|
|
return(err); |
585
|
|
|
|
|
|
} |
586
|
|
|
|
|
|
|
587
|
|
|
|
|
|
/* |
588
|
|
|
|
|
|
* If there was no match we are going to append the pattern |
589
|
|
|
|
|
|
* if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified |
590
|
|
|
|
|
|
* and the pattern did not contain any magic characters |
591
|
|
|
|
|
|
* GLOB_NOMAGIC is there just for compatibility with csh. |
592
|
|
|
|
|
|
*/ |
593
|
2836
|
|
|
|
|
if (pglob->gl_pathc == oldpathc && |
594
|
432
|
|
|
|
|
((pglob->gl_flags & GLOB_NOCHECK) || |
595
|
216
|
|
|
|
|
((pglob->gl_flags & GLOB_NOMAGIC) && |
596
|
|
|
|
|
|
!(pglob->gl_flags & GLOB_MAGCHAR)))) |
597
|
|
|
|
|
|
{ |
598
|
|
|
|
|
|
#ifdef GLOB_DEBUG |
599
|
|
|
|
|
|
printf("calling globextend from glob0\n"); |
600
|
|
|
|
|
|
#endif /* GLOB_DEBUG */ |
601
|
118
|
|
|
|
|
pglob->gl_flags = oldflags; |
602
|
118
|
|
|
|
|
return(globextend(qpat, pglob, &limit)); |
603
|
|
|
|
|
|
} |
604
|
2502
|
|
|
|
|
else if (!(pglob->gl_flags & GLOB_NOSORT)) |
605
|
5004
|
|
|
|
|
qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, |
606
|
2502
|
|
|
|
|
pglob->gl_pathc - oldpathc, sizeof(char *), |
607
|
2502
|
|
|
|
|
(pglob->gl_flags & (GLOB_ALPHASORT|GLOB_NOCASE)) |
608
|
|
|
|
|
|
? ci_compare : compare); |
609
|
2502
|
|
|
|
|
pglob->gl_flags = oldflags; |
610
|
2502
|
|
|
|
|
return(0); |
611
|
|
|
|
|
|
} |
612
|
|
|
|
|
|
|
613
|
|
|
|
|
|
static int |
614
|
92896
|
|
|
|
|
ci_compare(const void *p, const void *q) |
615
|
|
|
|
|
|
{ |
616
|
92896
|
|
|
|
|
const char *pp = *(const char **)p; |
617
|
92896
|
|
|
|
|
const char *qq = *(const char **)q; |
618
|
|
|
|
|
|
int ci; |
619
|
654528
|
|
|
|
|
while (*pp && *qq) { |
620
|
561532
|
|
|
|
|
if (toFOLD(*pp) != toFOLD(*qq)) |
621
|
|
|
|
|
|
break; |
622
|
468736
|
|
|
|
|
++pp; |
623
|
468736
|
|
|
|
|
++qq; |
624
|
|
|
|
|
|
} |
625
|
92896
|
|
|
|
|
ci = toFOLD(*pp) - toFOLD(*qq); |
626
|
92896
|
|
|
|
|
if (ci == 0) |
627
|
0
|
|
|
|
|
return compare(p, q); |
628
|
|
|
|
|
|
return ci; |
629
|
|
|
|
|
|
} |
630
|
|
|
|
|
|
|
631
|
|
|
|
|
|
static int |
632
|
0
|
|
|
|
|
compare(const void *p, const void *q) |
633
|
|
|
|
|
|
{ |
634
|
0
|
|
|
|
|
return(strcmp(*(char **)p, *(char **)q)); |
635
|
|
|
|
|
|
} |
636
|
|
|
|
|
|
|
637
|
|
|
|
|
|
static int |
638
|
|
|
|
|
|
glob1(Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp) |
639
|
|
|
|
|
|
{ |
640
|
|
|
|
|
|
Char pathbuf[MAXPATHLEN]; |
641
|
|
|
|
|
|
|
642
|
|
|
|
|
|
/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ |
643
|
2620
|
|
|
|
|
if (*pattern == BG_EOS) |
644
|
|
|
|
|
|
return(0); |
645
|
2620
|
|
|
|
|
return(glob2(pathbuf, pathbuf+MAXPATHLEN-1, |
646
|
|
|
|
|
|
pathbuf, pathbuf+MAXPATHLEN-1, |
647
|
|
|
|
|
|
pattern, pattern_last, pglob, limitp)); |
648
|
|
|
|
|
|
} |
649
|
|
|
|
|
|
|
650
|
|
|
|
|
|
/* |
651
|
|
|
|
|
|
* The functions glob2 and glob3 are mutually recursive; there is one level |
652
|
|
|
|
|
|
* of recursion for each segment in the pattern that contains one or more |
653
|
|
|
|
|
|
* meta characters. |
654
|
|
|
|
|
|
*/ |
655
|
|
|
|
|
|
static int |
656
|
24660
|
|
|
|
|
glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, |
657
|
|
|
|
|
|
Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp) |
658
|
|
|
|
|
|
{ |
659
|
|
|
|
|
|
Stat_t sb; |
660
|
|
|
|
|
|
Char *p, *q; |
661
|
|
|
|
|
|
int anymeta; |
662
|
|
|
|
|
|
|
663
|
|
|
|
|
|
/* |
664
|
|
|
|
|
|
* Loop over pattern segments until end of pattern or until |
665
|
|
|
|
|
|
* segment with meta character found. |
666
|
|
|
|
|
|
*/ |
667
|
|
|
|
|
|
for (anymeta = 0;;) { |
668
|
29040
|
|
|
|
|
if (*pattern == BG_EOS) { /* End of pattern? */ |
669
|
21648
|
|
|
|
|
*pathend = BG_EOS; |
670
|
21648
|
|
|
|
|
if (g_lstat(pathbuf, &sb, pglob)) |
671
|
|
|
|
|
|
return(0); |
672
|
|
|
|
|
|
|
673
|
21530
|
|
|
|
|
if (((pglob->gl_flags & GLOB_MARK) && |
674
|
0
|
|
|
|
|
pathend[-1] != BG_SEP |
675
|
|
|
|
|
|
#ifdef DOSISH |
676
|
|
|
|
|
|
&& pathend[-1] != BG_SEP2 |
677
|
|
|
|
|
|
#endif |
678
|
0
|
|
|
|
|
) && (S_ISDIR(sb.st_mode) || |
679
|
0
|
|
|
|
|
(S_ISLNK(sb.st_mode) && |
680
|
0
|
|
|
|
|
(g_stat(pathbuf, &sb, pglob) == 0) && |
681
|
0
|
|
|
|
|
S_ISDIR(sb.st_mode)))) { |
682
|
0
|
|
|
|
|
if (pathend+1 > pathend_last) |
683
|
|
|
|
|
|
return (1); |
684
|
0
|
|
|
|
|
*pathend++ = BG_SEP; |
685
|
0
|
|
|
|
|
*pathend = BG_EOS; |
686
|
|
|
|
|
|
} |
687
|
21530
|
|
|
|
|
++pglob->gl_matchc; |
688
|
|
|
|
|
|
#ifdef GLOB_DEBUG |
689
|
|
|
|
|
|
printf("calling globextend from glob2\n"); |
690
|
|
|
|
|
|
#endif /* GLOB_DEBUG */ |
691
|
21530
|
|
|
|
|
return(globextend(pathbuf, pglob, limitp)); |
692
|
|
|
|
|
|
} |
693
|
|
|
|
|
|
|
694
|
|
|
|
|
|
/* Find end of next segment, copy tentatively to pathend. */ |
695
|
|
|
|
|
|
q = pathend; |
696
|
|
|
|
|
|
p = pattern; |
697
|
36554
|
|
|
|
|
while (*p != BG_EOS && *p != BG_SEP |
698
|
|
|
|
|
|
#ifdef DOSISH |
699
|
|
|
|
|
|
&& *p != BG_SEP2 |
700
|
|
|
|
|
|
#endif |
701
|
|
|
|
|
|
) { |
702
|
29162
|
|
|
|
|
if (ismeta(*p)) |
703
|
|
|
|
|
|
anymeta = 1; |
704
|
29162
|
|
|
|
|
if (q+1 > pathend_last) |
705
|
|
|
|
|
|
return (1); |
706
|
29162
|
|
|
|
|
*q++ = *p++; |
707
|
|
|
|
|
|
} |
708
|
|
|
|
|
|
|
709
|
7392
|
|
|
|
|
if (!anymeta) { /* No expansion, do next segment. */ |
710
|
|
|
|
|
|
pathend = q; |
711
|
|
|
|
|
|
pattern = p; |
712
|
7780
|
|
|
|
|
while (*pattern == BG_SEP |
713
|
|
|
|
|
|
#ifdef DOSISH |
714
|
|
|
|
|
|
|| *pattern == BG_SEP2 |
715
|
|
|
|
|
|
#endif |
716
|
|
|
|
|
|
) { |
717
|
3400
|
|
|
|
|
if (pathend+1 > pathend_last) |
718
|
|
|
|
|
|
return (1); |
719
|
3400
|
|
|
|
|
*pathend++ = *pattern++; |
720
|
|
|
|
|
|
} |
721
|
|
|
|
|
|
} else |
722
|
|
|
|
|
|
/* Need expansion, recurse. */ |
723
|
3012
|
|
|
|
|
return(glob3(pathbuf, pathbuf_last, pathend, |
724
|
|
|
|
|
|
pathend_last, pattern, pattern_last, |
725
|
|
|
|
|
|
p, pattern_last, pglob, limitp)); |
726
|
|
|
|
|
|
} |
727
|
|
|
|
|
|
/* NOTREACHED */ |
728
|
|
|
|
|
|
} |
729
|
|
|
|
|
|
|
730
|
|
|
|
|
|
static int |
731
|
3012
|
|
|
|
|
glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, |
732
|
|
|
|
|
|
Char *pattern, Char *pattern_last, |
733
|
|
|
|
|
|
Char *restpattern, Char *restpattern_last, glob_t *pglob, size_t *limitp) |
734
|
|
|
|
|
|
{ |
735
|
|
|
|
|
|
Direntry_t *dp; |
736
|
|
|
|
|
|
DIR *dirp; |
737
|
|
|
|
|
|
int err; |
738
|
|
|
|
|
|
int nocase; |
739
|
|
|
|
|
|
char buf[MAXPATHLEN]; |
740
|
|
|
|
|
|
|
741
|
|
|
|
|
|
/* |
742
|
|
|
|
|
|
* The readdirfunc declaration can't be prototyped, because it is |
743
|
|
|
|
|
|
* assigned, below, to two functions which are prototyped in glob.h |
744
|
|
|
|
|
|
* and dirent.h as taking pointers to differently typed opaque |
745
|
|
|
|
|
|
* structures. |
746
|
|
|
|
|
|
*/ |
747
|
|
|
|
|
|
Direntry_t *(*readdirfunc)(DIR*); |
748
|
|
|
|
|
|
|
749
|
3012
|
|
|
|
|
if (pathend > pathend_last) |
750
|
|
|
|
|
|
return (1); |
751
|
3012
|
|
|
|
|
*pathend = BG_EOS; |
752
|
3012
|
|
|
|
|
errno = 0; |
753
|
|
|
|
|
|
|
754
|
|
|
|
|
|
#ifdef VMS |
755
|
|
|
|
|
|
{ |
756
|
|
|
|
|
|
Char *q = pathend; |
757
|
|
|
|
|
|
if (q - pathbuf > 5) { |
758
|
|
|
|
|
|
q -= 5; |
759
|
|
|
|
|
|
if (q[0] == '.' && |
760
|
|
|
|
|
|
tolower(q[1]) == 'd' && tolower(q[2]) == 'i' && |
761
|
|
|
|
|
|
tolower(q[3]) == 'r' && q[4] == '/') |
762
|
|
|
|
|
|
{ |
763
|
|
|
|
|
|
q[0] = '/'; |
764
|
|
|
|
|
|
q[1] = BG_EOS; |
765
|
|
|
|
|
|
pathend = q+1; |
766
|
|
|
|
|
|
} |
767
|
|
|
|
|
|
} |
768
|
|
|
|
|
|
} |
769
|
|
|
|
|
|
#endif |
770
|
|
|
|
|
|
|
771
|
3012
|
|
|
|
|
if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { |
772
|
|
|
|
|
|
/* TODO: don't call for ENOENT or ENOTDIR? */ |
773
|
134
|
|
|
|
|
if (pglob->gl_errfunc) { |
774
|
134
|
|
|
|
|
if (g_Ctoc(pathbuf, buf, sizeof(buf))) |
775
|
|
|
|
|
|
return (GLOB_ABEND); |
776
|
268
|
|
|
|
|
if (pglob->gl_errfunc(buf, errno) || |
777
|
134
|
|
|
|
|
(pglob->gl_flags & GLOB_ERR)) |
778
|
|
|
|
|
|
return (GLOB_ABEND); |
779
|
|
|
|
|
|
} |
780
|
0
|
|
|
|
|
return(0); |
781
|
|
|
|
|
|
} |
782
|
|
|
|
|
|
|
783
|
|
|
|
|
|
err = 0; |
784
|
2878
|
|
|
|
|
nocase = ((pglob->gl_flags & GLOB_NOCASE) != 0); |
785
|
|
|
|
|
|
|
786
|
|
|
|
|
|
/* Search directory for matching names. */ |
787
|
2878
|
|
|
|
|
if (pglob->gl_flags & GLOB_ALTDIRFUNC) |
788
|
0
|
|
|
|
|
readdirfunc = (Direntry_t *(*)(DIR *))pglob->gl_readdir; |
789
|
|
|
|
|
|
else |
790
|
|
|
|
|
|
readdirfunc = (Direntry_t *(*)(DIR *))my_readdir; |
791
|
62820
|
|
|
|
|
while ((dp = (*readdirfunc)(dirp))) { |
792
|
|
|
|
|
|
U8 *sc; |
793
|
|
|
|
|
|
Char *dc; |
794
|
|
|
|
|
|
|
795
|
|
|
|
|
|
/* Initial BG_DOT must be matched literally. */ |
796
|
59942
|
|
|
|
|
if (dp->d_name[0] == BG_DOT && *pattern != BG_DOT) |
797
|
5782
|
|
|
|
|
continue; |
798
|
|
|
|
|
|
dc = pathend; |
799
|
54160
|
|
|
|
|
sc = (U8 *) dp->d_name; |
800
|
415484
|
|
|
|
|
while (dc < pathend_last && (*dc++ = *sc++) != BG_EOS) |
801
|
|
|
|
|
|
; |
802
|
54160
|
|
|
|
|
if (dc >= pathend_last) { |
803
|
0
|
|
|
|
|
*dc = BG_EOS; |
804
|
|
|
|
|
|
err = 1; |
805
|
0
|
|
|
|
|
break; |
806
|
|
|
|
|
|
} |
807
|
|
|
|
|
|
|
808
|
54160
|
|
|
|
|
if (!match(pathend, pattern, restpattern, nocase)) { |
809
|
32120
|
|
|
|
|
*pathend = BG_EOS; |
810
|
32120
|
|
|
|
|
continue; |
811
|
|
|
|
|
|
} |
812
|
22040
|
|
|
|
|
err = glob2(pathbuf, pathbuf_last, --dc, pathend_last, |
813
|
|
|
|
|
|
restpattern, restpattern_last, pglob, limitp); |
814
|
22040
|
|
|
|
|
if (err) |
815
|
|
|
|
|
|
break; |
816
|
|
|
|
|
|
} |
817
|
|
|
|
|
|
|
818
|
2878
|
|
|
|
|
if (pglob->gl_flags & GLOB_ALTDIRFUNC) |
819
|
0
|
|
|
|
|
(*pglob->gl_closedir)(dirp); |
820
|
|
|
|
|
|
else |
821
|
2878
|
|
|
|
|
PerlDir_close(dirp); |
822
|
|
|
|
|
|
return(err); |
823
|
|
|
|
|
|
} |
824
|
|
|
|
|
|
|
825
|
|
|
|
|
|
|
826
|
|
|
|
|
|
/* |
827
|
|
|
|
|
|
* Extend the gl_pathv member of a glob_t structure to accommodate a new item, |
828
|
|
|
|
|
|
* add the new item, and update gl_pathc. |
829
|
|
|
|
|
|
* |
830
|
|
|
|
|
|
* This assumes the BSD realloc, which only copies the block when its size |
831
|
|
|
|
|
|
* crosses a power-of-two boundary; for v7 realloc, this would cause quadratic |
832
|
|
|
|
|
|
* behavior. |
833
|
|
|
|
|
|
* |
834
|
|
|
|
|
|
* Return 0 if new item added, error code if memory couldn't be allocated. |
835
|
|
|
|
|
|
* |
836
|
|
|
|
|
|
* Invariant of the glob_t structure: |
837
|
|
|
|
|
|
* Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and |
838
|
|
|
|
|
|
* gl_pathv points to (gl_offs + gl_pathc + 1) items. |
839
|
|
|
|
|
|
*/ |
840
|
|
|
|
|
|
static int |
841
|
21648
|
|
|
|
|
globextend(const Char *path, glob_t *pglob, size_t *limitp) |
842
|
|
|
|
|
|
{ |
843
|
|
|
|
|
|
char **pathv; |
844
|
|
|
|
|
|
int i; |
845
|
|
|
|
|
|
STRLEN newsize, len; |
846
|
|
|
|
|
|
char *copy; |
847
|
|
|
|
|
|
const Char *p; |
848
|
|
|
|
|
|
|
849
|
|
|
|
|
|
#ifdef GLOB_DEBUG |
850
|
|
|
|
|
|
printf("Adding "); |
851
|
|
|
|
|
|
for (p = path; *p; p++) |
852
|
|
|
|
|
|
(void)printf("%c", CHAR(*p)); |
853
|
|
|
|
|
|
printf("\n"); |
854
|
|
|
|
|
|
#endif /* GLOB_DEBUG */ |
855
|
|
|
|
|
|
|
856
|
21648
|
|
|
|
|
newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); |
857
|
21648
|
|
|
|
|
if (pglob->gl_pathv) |
858
|
38900
|
|
|
|
|
pathv = Renew(pglob->gl_pathv,newsize,char*); |
859
|
|
|
|
|
|
else |
860
|
4396
|
|
|
|
|
Newx(pathv,newsize,char*); |
861
|
21648
|
|
|
|
|
if (pathv == NULL) { |
862
|
0
|
|
|
|
|
if (pglob->gl_pathv) { |
863
|
0
|
|
|
|
|
Safefree(pglob->gl_pathv); |
864
|
0
|
|
|
|
|
pglob->gl_pathv = NULL; |
865
|
|
|
|
|
|
} |
866
|
|
|
|
|
|
return(GLOB_NOSPACE); |
867
|
|
|
|
|
|
} |
868
|
|
|
|
|
|
|
869
|
21648
|
|
|
|
|
if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { |
870
|
|
|
|
|
|
/* first time around -- clear initial gl_offs items */ |
871
|
0
|
|
|
|
|
pathv += pglob->gl_offs; |
872
|
0
|
|
|
|
|
for (i = pglob->gl_offs; --i >= 0; ) |
873
|
0
|
|
|
|
|
*--pathv = NULL; |
874
|
|
|
|
|
|
} |
875
|
21648
|
|
|
|
|
pglob->gl_pathv = pathv; |
876
|
|
|
|
|
|
|
877
|
21648
|
|
|
|
|
for (p = path; *p++;) |
878
|
|
|
|
|
|
; |
879
|
21648
|
|
|
|
|
len = (STRLEN)(p - path); |
880
|
21648
|
|
|
|
|
*limitp += len; |
881
|
21648
|
|
|
|
|
Newx(copy, p-path, char); |
882
|
21648
|
|
|
|
|
if (copy != NULL) { |
883
|
21648
|
|
|
|
|
if (g_Ctoc(path, copy, len)) { |
884
|
0
|
|
|
|
|
Safefree(copy); |
885
|
0
|
|
|
|
|
return(GLOB_NOSPACE); |
886
|
|
|
|
|
|
} |
887
|
21648
|
|
|
|
|
pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; |
888
|
|
|
|
|
|
} |
889
|
21648
|
|
|
|
|
pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; |
890
|
|
|
|
|
|
|
891
|
21648
|
|
|
|
|
if ((pglob->gl_flags & GLOB_LIMIT) && |
892
|
0
|
|
|
|
|
newsize + *limitp >= ARG_MAX) { |
893
|
0
|
|
|
|
|
errno = 0; |
894
|
0
|
|
|
|
|
return(GLOB_NOSPACE); |
895
|
|
|
|
|
|
} |
896
|
|
|
|
|
|
|
897
|
21648
|
|
|
|
|
return(copy == NULL ? GLOB_NOSPACE : 0); |
898
|
|
|
|
|
|
} |
899
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
901
|
|
|
|
|
|
/* |
902
|
|
|
|
|
|
* pattern matching function for filenames. Each occurrence of the * |
903
|
|
|
|
|
|
* pattern causes a recursion level. |
904
|
|
|
|
|
|
*/ |
905
|
|
|
|
|
|
static int |
906
|
176614
|
|
|
|
|
match(Char *name, Char *pat, Char *patend, int nocase) |
907
|
|
|
|
|
|
{ |
908
|
|
|
|
|
|
int ok, negate_range; |
909
|
|
|
|
|
|
Char c, k; |
910
|
|
|
|
|
|
|
911
|
404938
|
|
|
|
|
while (pat < patend) { |
912
|
210576
|
|
|
|
|
c = *pat++; |
913
|
210576
|
|
|
|
|
switch (c & M_MASK) { |
914
|
|
|
|
|
|
case M_ALL: |
915
|
23206
|
|
|
|
|
if (pat == patend) |
916
|
|
|
|
|
|
return(1); |
917
|
|
|
|
|
|
do |
918
|
122454
|
|
|
|
|
if (match(name, pat, patend, nocase)) |
919
|
|
|
|
|
|
return(1); |
920
|
104694
|
|
|
|
|
while (*name++ != BG_EOS) |
921
|
104694
|
|
|
|
|
; |
922
|
|
|
|
|
|
return(0); |
923
|
|
|
|
|
|
case M_ONE: |
924
|
14
|
|
|
|
|
if (*name++ == BG_EOS) |
925
|
|
|
|
|
|
return(0); |
926
|
|
|
|
|
|
break; |
927
|
|
|
|
|
|
case M_SET: |
928
|
|
|
|
|
|
ok = 0; |
929
|
1028
|
|
|
|
|
if ((k = *name++) == BG_EOS) |
930
|
|
|
|
|
|
return(0); |
931
|
1028
|
|
|
|
|
if ((negate_range = ((*pat & M_MASK) == M_NOT)) != BG_EOS) |
932
|
0
|
|
|
|
|
++pat; |
933
|
11254
|
|
|
|
|
while (((c = *pat++) & M_MASK) != M_END) |
934
|
10226
|
|
|
|
|
if ((*pat & M_MASK) == M_RNG) { |
935
|
6
|
|
|
|
|
if (nocase) { |
936
|
0
|
|
|
|
|
if (tolower(c) <= tolower(k) && tolower(k) <= tolower(pat[1])) |
937
|
|
|
|
|
|
ok = 1; |
938
|
|
|
|
|
|
} else { |
939
|
6
|
|
|
|
|
if (c <= k && k <= pat[1]) |
940
|
|
|
|
|
|
ok = 1; |
941
|
|
|
|
|
|
} |
942
|
6
|
|
|
|
|
pat += 2; |
943
|
10220
|
|
|
|
|
} else if (nocase ? (tolower(c) == tolower(k)) : (c == k)) |
944
|
|
|
|
|
|
ok = 1; |
945
|
1028
|
|
|
|
|
if (ok == negate_range) |
946
|
|
|
|
|
|
return(0); |
947
|
|
|
|
|
|
break; |
948
|
|
|
|
|
|
default: |
949
|
186328
|
|
|
|
|
k = *name++; |
950
|
188344
|
|
|
|
|
if (nocase ? (tolower(k) != tolower(c)) : (k != c)) |
951
|
|
|
|
|
|
return(0); |
952
|
|
|
|
|
|
break; |
953
|
|
|
|
|
|
} |
954
|
|
|
|
|
|
} |
955
|
17748
|
|
|
|
|
return(*name == BG_EOS); |
956
|
|
|
|
|
|
} |
957
|
|
|
|
|
|
|
958
|
|
|
|
|
|
/* Free allocated data belonging to a glob_t structure. */ |
959
|
|
|
|
|
|
void |
960
|
2296
|
|
|
|
|
bsd_globfree(glob_t *pglob) |
961
|
|
|
|
|
|
{ |
962
|
|
|
|
|
|
int i; |
963
|
|
|
|
|
|
char **pp; |
964
|
|
|
|
|
|
|
965
|
2296
|
|
|
|
|
if (pglob->gl_pathv != NULL) { |
966
|
2198
|
|
|
|
|
pp = pglob->gl_pathv + pglob->gl_offs; |
967
|
23846
|
|
|
|
|
for (i = pglob->gl_pathc; i--; ++pp) |
968
|
21648
|
|
|
|
|
if (*pp) |
969
|
21648
|
|
|
|
|
Safefree(*pp); |
970
|
2198
|
|
|
|
|
Safefree(pglob->gl_pathv); |
971
|
2198
|
|
|
|
|
pglob->gl_pathv = NULL; |
972
|
|
|
|
|
|
} |
973
|
2296
|
|
|
|
|
} |
974
|
|
|
|
|
|
|
975
|
|
|
|
|
|
static DIR * |
976
|
0
|
|
|
|
|
g_opendir(Char *str, glob_t *pglob) |
977
|
|
|
|
|
|
{ |
978
|
|
|
|
|
|
char buf[MAXPATHLEN]; |
979
|
|
|
|
|
|
|
980
|
3012
|
|
|
|
|
if (!*str) { |
981
|
1202
|
|
|
|
|
my_strlcpy(buf, ".", sizeof(buf)); |
982
|
|
|
|
|
|
} else { |
983
|
1810
|
|
|
|
|
if (g_Ctoc(str, buf, sizeof(buf))) |
984
|
|
|
|
|
|
return(NULL); |
985
|
|
|
|
|
|
} |
986
|
|
|
|
|
|
|
987
|
3012
|
|
|
|
|
if (pglob->gl_flags & GLOB_ALTDIRFUNC) |
988
|
0
|
|
|
|
|
return((DIR*)(*pglob->gl_opendir)(buf)); |
989
|
|
|
|
|
|
|
990
|
3012
|
|
|
|
|
return(PerlDir_open(buf)); |
991
|
|
|
|
|
|
} |
992
|
|
|
|
|
|
|
993
|
|
|
|
|
|
static int |
994
|
21648
|
|
|
|
|
g_lstat(Char *fn, Stat_t *sb, glob_t *pglob) |
995
|
|
|
|
|
|
{ |
996
|
|
|
|
|
|
char buf[MAXPATHLEN]; |
997
|
|
|
|
|
|
|
998
|
21648
|
|
|
|
|
if (g_Ctoc(fn, buf, sizeof(buf))) |
999
|
|
|
|
|
|
return(-1); |
1000
|
21648
|
|
|
|
|
if (pglob->gl_flags & GLOB_ALTDIRFUNC) |
1001
|
0
|
|
|
|
|
return((*pglob->gl_lstat)(buf, sb)); |
1002
|
|
|
|
|
|
#ifdef HAS_LSTAT |
1003
|
0
|
|
|
|
|
return(PerlLIO_lstat(buf, sb)); |
1004
|
|
|
|
|
|
#else |
1005
|
|
|
|
|
|
return(PerlLIO_stat(buf, sb)); |
1006
|
|
|
|
|
|
#endif /* HAS_LSTAT */ |
1007
|
|
|
|
|
|
} |
1008
|
|
|
|
|
|
|
1009
|
|
|
|
|
|
static int |
1010
|
0
|
|
|
|
|
g_stat(Char *fn, Stat_t *sb, glob_t *pglob) |
1011
|
|
|
|
|
|
{ |
1012
|
|
|
|
|
|
char buf[MAXPATHLEN]; |
1013
|
|
|
|
|
|
|
1014
|
0
|
|
|
|
|
if (g_Ctoc(fn, buf, sizeof(buf))) |
1015
|
|
|
|
|
|
return(-1); |
1016
|
0
|
|
|
|
|
if (pglob->gl_flags & GLOB_ALTDIRFUNC) |
1017
|
0
|
|
|
|
|
return((*pglob->gl_stat)(buf, sb)); |
1018
|
0
|
|
|
|
|
return(PerlLIO_stat(buf, sb)); |
1019
|
|
|
|
|
|
} |
1020
|
|
|
|
|
|
|
1021
|
|
|
|
|
|
static Char * |
1022
|
|
|
|
|
|
g_strchr(Char *str, int ch) |
1023
|
|
|
|
|
|
{ |
1024
|
|
|
|
|
|
do { |
1025
|
37516
|
|
|
|
|
if (*str == ch) |
1026
|
|
|
|
|
|
return (str); |
1027
|
37198
|
|
|
|
|
} while (*str++); |
1028
|
|
|
|
|
|
return (NULL); |
1029
|
|
|
|
|
|
} |
1030
|
|
|
|
|
|
|
1031
|
|
|
|
|
|
static int |
1032
|
|
|
|
|
|
g_Ctoc(const Char *str, char *buf, STRLEN len) |
1033
|
|
|
|
|
|
{ |
1034
|
614336
|
|
|
|
|
while (len--) { |
1035
|
614336
|
|
|
|
|
if ((*buf++ = (char)*str++) == BG_EOS) |
1036
|
|
|
|
|
|
return (0); |
1037
|
|
|
|
|
|
} |
1038
|
|
|
|
|
|
return (1); |
1039
|
24268
|
|
|
|
|
} |
1040
|
|
|
|
|
|
|
1041
|
|
|
|
|
|
#ifdef GLOB_DEBUG |
1042
|
|
|
|
|
|
static void |
1043
|
|
|
|
|
|
qprintf(const char *str, Char *s) |
1044
|
|
|
|
|
|
{ |
1045
|
|
|
|
|
|
Char *p; |
1046
|
|
|
|
|
|
|
1047
|
|
|
|
|
|
(void)printf("%s:\n", str); |
1048
|
|
|
|
|
|
for (p = s; *p; p++) |
1049
|
|
|
|
|
|
(void)printf("%c", CHAR(*p)); |
1050
|
|
|
|
|
|
(void)printf("\n"); |
1051
|
|
|
|
|
|
for (p = s; *p; p++) |
1052
|
|
|
|
|
|
(void)printf("%c", *p & M_PROTECT ? '"' : ' '); |
1053
|
|
|
|
|
|
(void)printf("\n"); |
1054
|
|
|
|
|
|
for (p = s; *p; p++) |
1055
|
|
|
|
|
|
(void)printf("%c", ismeta(*p) ? '_' : ' '); |
1056
|
|
|
|
|
|
(void)printf("\n"); |
1057
|
|
|
|
|
|
} |
1058
|
|
|
|
|
|
#endif /* GLOB_DEBUG */ |