94 |
94 |
#include <stdlib.h>
|
95 |
95 |
#include <string.h>
|
96 |
96 |
#include <unistd.h>
|
|
97 |
#include <wchar.h>
|
97 |
98 |
|
98 |
99 |
#include "charclass.h"
|
99 |
100 |
|
... | ... | |
114 |
115 |
#define RBRACE '}'
|
115 |
116 |
#define SLASH '/'
|
116 |
117 |
#define COMMA ','
|
|
118 |
#define COLON ':'
|
117 |
119 |
|
118 |
|
#ifndef DEBUG
|
|
120 |
#define M_QUOTE 0x800000
|
|
121 |
#define M_PROTECT 0x400000
|
119 |
122 |
|
120 |
|
#define M_QUOTE 0x8000
|
121 |
|
#define M_PROTECT 0x4000
|
122 |
|
#define M_MASK 0xffff
|
123 |
|
#define M_ASCII 0x00ff
|
|
123 |
typedef struct Char_s {
|
|
124 |
wchar_t wc;
|
|
125 |
uint_t at;
|
|
126 |
} Char;
|
124 |
127 |
|
125 |
|
typedef ushort_t Char;
|
|
128 |
#define M_ALL '*' /* Plus M_QUOTE */
|
|
129 |
#define M_END ']' /* Plus M_QUOTE */
|
|
130 |
#define M_NOT '!' /* Plus M_QUOTE */
|
|
131 |
#define M_ONE '?' /* Plus M_QUOTE */
|
|
132 |
#define M_RNG '-' /* Plus M_QUOTE */
|
|
133 |
#define M_SET '[' /* Plus M_QUOTE */
|
|
134 |
#define M_CLASS ':' /* Plus M_QUOTE */
|
|
135 |
#define ismeta(c) (((c).at&M_QUOTE) != 0)
|
126 |
136 |
|
127 |
|
#else
|
128 |
|
|
129 |
|
#define M_QUOTE 0x80
|
130 |
|
#define M_PROTECT 0x40
|
131 |
|
#define M_MASK 0xff
|
132 |
|
#define M_ASCII 0x7f
|
133 |
|
|
134 |
|
typedef char Char;
|
135 |
|
|
136 |
|
#endif
|
137 |
|
|
138 |
|
|
139 |
|
#define CHAR(c) ((Char)((c)&M_ASCII))
|
140 |
|
#define META(c) ((Char)((c)|M_QUOTE))
|
141 |
|
#define M_ALL META('*')
|
142 |
|
#define M_END META(']')
|
143 |
|
#define M_NOT META('!')
|
144 |
|
#define M_ONE META('?')
|
145 |
|
#define M_RNG META('-')
|
146 |
|
#define M_SET META('[')
|
147 |
|
#define M_CLASS META(':')
|
148 |
|
#define ismeta(c) (((c)&M_QUOTE) != 0)
|
149 |
|
|
150 |
137 |
#define GLOB_LIMIT_MALLOC 65536
|
151 |
138 |
#define GLOB_LIMIT_STAT 2048
|
152 |
139 |
#define GLOB_LIMIT_READDIR 16384
|
... | ... | |
170 |
157 |
static int g_Ctoc(const Char *, char *, uint_t);
|
171 |
158 |
static int g_lstat(Char *, struct stat *, glob_t *);
|
172 |
159 |
static DIR *g_opendir(Char *, glob_t *);
|
173 |
|
static Char *g_strchr(const Char *, int);
|
174 |
|
static int g_strncmp(const Char *, const char *, size_t);
|
|
160 |
static Char *g_strchr(const Char *, wchar_t);
|
175 |
161 |
static int g_stat(Char *, struct stat *, glob_t *);
|
176 |
162 |
static int glob0(const Char *, glob_t *, struct glob_lim *,
|
177 |
163 |
int (*)(const char *, int));
|
... | ... | |
200 |
186 |
glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
|
201 |
187 |
glob_t *pglob)
|
202 |
188 |
{
|
203 |
|
const uchar_t *patnext;
|
204 |
|
int c;
|
|
189 |
const char *patnext;
|
|
190 |
size_t n;
|
|
191 |
wchar_t c;
|
205 |
192 |
Char *bufnext, *bufend, patbuf[MAXPATHLEN];
|
206 |
193 |
struct glob_lim limit = { 0, 0, 0 };
|
207 |
194 |
|
208 |
195 |
if (strnlen(pattern, PATH_MAX) == PATH_MAX)
|
209 |
196 |
return (GLOB_NOMATCH);
|
210 |
197 |
|
211 |
|
patnext = (uchar_t *)pattern;
|
|
198 |
patnext = pattern;
|
212 |
199 |
if (!(flags & GLOB_APPEND)) {
|
213 |
200 |
pglob->gl_pathc = 0;
|
214 |
201 |
pglob->gl_pathv = NULL;
|
... | ... | |
227 |
214 |
|
228 |
215 |
bufnext = patbuf;
|
229 |
216 |
bufend = bufnext + MAXPATHLEN - 1;
|
230 |
|
if (flags & GLOB_NOESCAPE)
|
231 |
|
while (bufnext < bufend && (c = *patnext++) != EOS)
|
232 |
|
*bufnext++ = c;
|
233 |
|
else {
|
|
217 |
if (flags & GLOB_NOESCAPE) {
|
|
218 |
while (bufnext < bufend) {
|
|
219 |
if ((n = mbtowc(&c, patnext, PATH_MAX)) > 0) {
|
|
220 |
patnext += n;
|
|
221 |
bufnext->at = 0;
|
|
222 |
(bufnext++)->wc = c;
|
|
223 |
} else if (n == 0) {
|
|
224 |
break;
|
|
225 |
} else {
|
|
226 |
return (GLOB_NOMATCH);
|
|
227 |
}
|
|
228 |
}
|
|
229 |
} else {
|
234 |
230 |
/* Protect the quoted characters. */
|
235 |
|
while (bufnext < bufend && (c = *patnext++) != EOS)
|
236 |
|
if (c == QUOTE) {
|
237 |
|
if ((c = *patnext++) == EOS) {
|
238 |
|
c = QUOTE;
|
239 |
|
--patnext;
|
|
231 |
while (bufnext < bufend) {
|
|
232 |
if ((n = mbtowc(&c, patnext, PATH_MAX)) > 0) {
|
|
233 |
patnext += n;
|
|
234 |
if (c == QUOTE) {
|
|
235 |
n = mbtowc(&c, patnext, PATH_MAX);
|
|
236 |
if (n < 0)
|
|
237 |
return (GLOB_NOMATCH);
|
|
238 |
if (n > 0)
|
|
239 |
patnext += n;
|
|
240 |
if (n == 0)
|
|
241 |
c = QUOTE;
|
|
242 |
bufnext->at = M_PROTECT;
|
|
243 |
(bufnext++)->wc = c;
|
|
244 |
} else {
|
|
245 |
bufnext->at = 0;
|
|
246 |
(bufnext++)->wc = c;
|
240 |
247 |
}
|
241 |
|
*bufnext++ = c | M_PROTECT;
|
242 |
|
} else
|
243 |
|
*bufnext++ = c;
|
|
248 |
} else if (n == 0) {
|
|
249 |
break;
|
|
250 |
} else {
|
|
251 |
return (GLOB_NOMATCH);
|
|
252 |
}
|
|
253 |
}
|
244 |
254 |
}
|
245 |
|
*bufnext = EOS;
|
|
255 |
bufnext->at = 0;
|
|
256 |
bufnext->wc = EOS;
|
246 |
257 |
|
247 |
258 |
if (flags & GLOB_BRACE)
|
248 |
259 |
return (globexp1(patbuf, pglob, &limit, errfunc));
|
... | ... | |
262 |
273 |
const Char* ptr = pattern;
|
263 |
274 |
|
264 |
275 |
/* Protect a single {}, for find(1), like csh */
|
265 |
|
if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
|
|
276 |
if (pattern[0].wc == LBRACE && pattern[1].wc == RBRACE &&
|
|
277 |
pattern[2].wc == EOS)
|
266 |
278 |
return (glob0(pattern, pglob, limitp, errfunc));
|
267 |
279 |
|
268 |
280 |
if ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL)
|
... | ... | |
289 |
301 |
/* copy part up to the brace */
|
290 |
302 |
for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
|
291 |
303 |
;
|
292 |
|
*lm = EOS;
|
|
304 |
lm->at = 0;
|
|
305 |
lm->wc = EOS;
|
293 |
306 |
ls = lm;
|
294 |
307 |
|
295 |
308 |
/* Find the balanced brace */
|
296 |
|
for (i = 0, pe = ++ptr; *pe; pe++)
|
297 |
|
if (*pe == LBRACKET) {
|
|
309 |
for (i = 0, pe = ++ptr; pe->wc != EOS; pe++)
|
|
310 |
if (pe->wc == LBRACKET) {
|
298 |
311 |
/* Ignore everything between [] */
|
299 |
|
for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
|
|
312 |
for (pm = pe++; pe->wc != RBRACKET &&
|
|
313 |
pe->wc != EOS; pe++)
|
300 |
314 |
;
|
301 |
|
if (*pe == EOS) {
|
|
315 |
if (pe->wc == EOS) {
|
302 |
316 |
/*
|
303 |
317 |
* We could not find a matching RBRACKET.
|
304 |
318 |
* Ignore and just look for RBRACE
|
305 |
319 |
*/
|
306 |
320 |
pe = pm;
|
307 |
321 |
}
|
308 |
|
} else if (*pe == LBRACE)
|
|
322 |
} else if (pe->wc == LBRACE) {
|
309 |
323 |
i++;
|
310 |
|
else if (*pe == RBRACE) {
|
|
324 |
} else if (pe->wc == RBRACE) {
|
311 |
325 |
if (i == 0)
|
312 |
326 |
break;
|
313 |
327 |
i--;
|
314 |
328 |
}
|
315 |
329 |
|
316 |
330 |
/* Non matching braces; just glob the pattern */
|
317 |
|
if (i != 0 || *pe == EOS)
|
|
331 |
if (i != 0 || pe->wc == EOS)
|
318 |
332 |
return (glob0(patbuf, pglob, limitp, errfunc));
|
319 |
333 |
|
320 |
334 |
for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
|
321 |
|
switch (*pm) {
|
|
335 |
switch (pm->wc) {
|
322 |
336 |
case LBRACKET:
|
323 |
337 |
/* Ignore everything between [] */
|
324 |
|
for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
|
|
338 |
for (pl = pm++; pm->wc != RBRACKET && pm->wc != EOS;
|
|
339 |
pm++)
|
325 |
340 |
;
|
326 |
|
if (*pm == EOS) {
|
|
341 |
if (pm->wc == EOS) {
|
327 |
342 |
/*
|
328 |
343 |
* We could not find a matching RBRACKET.
|
329 |
344 |
* Ignore and just look for RBRACE
|
... | ... | |
343 |
358 |
}
|
344 |
359 |
/* FALLTHROUGH */
|
345 |
360 |
case COMMA:
|
346 |
|
if (i && *pm == COMMA)
|
|
361 |
if (i && pm->wc == COMMA)
|
347 |
362 |
break;
|
348 |
363 |
else {
|
349 |
364 |
/* Append the current string */
|
... | ... | |
354 |
369 |
* Append the rest of the pattern after the
|
355 |
370 |
* closing brace
|
356 |
371 |
*/
|
357 |
|
for (pl = pe + 1; (*lm++ = *pl++) != EOS; )
|
|
372 |
for (pl = pe + 1;
|
|
373 |
(*lm++ = *pl++).wc != EOS; /* */)
|
358 |
374 |
;
|
359 |
375 |
|
360 |
376 |
/* Expand the current pattern */
|
361 |
|
#ifdef DEBUG
|
362 |
|
qprintf("globexp2:", patbuf);
|
363 |
|
#endif
|
364 |
377 |
rv = globexp1(patbuf, pglob, limitp, errfunc);
|
365 |
378 |
if (rv && rv != GLOB_NOMATCH)
|
366 |
379 |
return (rv);
|
... | ... | |
388 |
401 |
struct passwd *pwd;
|
389 |
402 |
char *h;
|
390 |
403 |
const Char *p;
|
391 |
|
Char *b, *eb;
|
|
404 |
Char *b, *eb, *q;
|
|
405 |
size_t n;
|
|
406 |
wchar_t c;
|
392 |
407 |
|
393 |
|
if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
|
|
408 |
if (pattern->wc != TILDE || !(pglob->gl_flags & GLOB_TILDE))
|
394 |
409 |
return (pattern);
|
395 |
410 |
|
396 |
411 |
/* Copy up to the end of the string or / */
|
397 |
412 |
eb = &patbuf[patbuf_len - 1];
|
398 |
|
for (p = pattern + 1, h = (char *)patbuf;
|
399 |
|
h < (char *)eb && *p && *p != SLASH; *h++ = *p++)
|
|
413 |
for (p = pattern + 1, q = patbuf;
|
|
414 |
q < eb && p->wc != EOS && p->wc != SLASH; *q++ = *p++)
|
400 |
415 |
;
|
401 |
416 |
|
402 |
|
*h = EOS;
|
|
417 |
q->at = 0;
|
|
418 |
q->wc = EOS;
|
403 |
419 |
|
404 |
|
#if 0
|
405 |
|
if (h == (char *)eb)
|
406 |
|
return (what);
|
407 |
|
#endif
|
|
420 |
/* What to do if patbuf is full? */
|
408 |
421 |
|
409 |
|
if (((char *)patbuf)[0] == EOS) {
|
|
422 |
if (patbuf[0].wc == EOS) {
|
410 |
423 |
/*
|
411 |
424 |
* handle a plain ~ or ~/ by expanding $HOME
|
412 |
425 |
* first and then trying the password file
|
... | ... | |
428 |
441 |
}
|
429 |
442 |
|
430 |
443 |
/* Copy the home directory */
|
431 |
|
for (b = patbuf; b < eb && *h; *b++ = *h++)
|
432 |
|
;
|
|
444 |
for (b = patbuf; b < eb && *h != EOS; b++) {
|
|
445 |
if ((n = mbtowc(&c, h, PATH_MAX)) > 0) {
|
|
446 |
h += n;
|
|
447 |
b->at = 0;
|
|
448 |
b->wc = c;
|
|
449 |
} else {
|
|
450 |
break;
|
|
451 |
}
|
|
452 |
}
|
433 |
453 |
|
434 |
454 |
/* Append the rest of the pattern */
|
435 |
|
while (b < eb && (*b++ = *p++) != EOS)
|
|
455 |
while (b < eb && (*b++ = *p++).wc != EOS)
|
436 |
456 |
;
|
437 |
|
*b = EOS;
|
|
457 |
b->at = 0;
|
|
458 |
b->wc = EOS;
|
438 |
459 |
|
439 |
460 |
return (patbuf);
|
440 |
461 |
}
|
441 |
462 |
|
442 |
463 |
static int
|
443 |
|
g_strncmp(const Char *s1, const char *s2, size_t n)
|
444 |
|
{
|
445 |
|
int rv = 0;
|
446 |
|
|
447 |
|
while (n--) {
|
448 |
|
rv = *(Char *)s1 - *(const unsigned char *)s2++;
|
449 |
|
if (rv)
|
450 |
|
break;
|
451 |
|
if (*s1++ == '\0')
|
452 |
|
break;
|
453 |
|
}
|
454 |
|
return (rv);
|
455 |
|
}
|
456 |
|
|
457 |
|
static int
|
458 |
464 |
g_charclass(const Char **patternp, Char **bufnextp)
|
459 |
465 |
{
|
460 |
466 |
const Char *pattern = *patternp + 1;
|
... | ... | |
463 |
469 |
struct cclass *cc;
|
464 |
470 |
size_t len;
|
465 |
471 |
|
466 |
|
if ((colon = g_strchr(pattern, ':')) == NULL || colon[1] != ']')
|
|
472 |
if ((colon = g_strchr(pattern, COLON)) == NULL ||
|
|
473 |
colon[1].wc != RBRACKET)
|
467 |
474 |
return (1); /* not a character class */
|
468 |
475 |
|
469 |
476 |
len = (size_t)(colon - pattern);
|
470 |
477 |
for (cc = cclasses; cc->name != NULL; cc++) {
|
471 |
|
if (!g_strncmp(pattern, cc->name, len) && cc->name[len] == '\0')
|
|
478 |
wchar_t w;
|
|
479 |
const Char *s1 = pattern;
|
|
480 |
const char *s2 = cc->name;
|
|
481 |
size_t n = len;
|
|
482 |
|
|
483 |
/* Are the strings the same? */
|
|
484 |
while (n > 0 && (w = (s1++)->wc) == *s2 && w != EOS) {
|
|
485 |
n--;
|
|
486 |
s2++;
|
|
487 |
}
|
|
488 |
if (n == 0 && *s2 == EOS)
|
472 |
489 |
break;
|
473 |
490 |
}
|
474 |
491 |
if (cc->name == NULL)
|
475 |
492 |
return (-1); /* invalid character class */
|
476 |
|
*bufnext++ = M_CLASS;
|
477 |
|
*bufnext++ = (Char)(cc - &cclasses[0]);
|
|
493 |
bufnext->at = M_QUOTE;
|
|
494 |
(bufnext++)->wc = M_CLASS;
|
|
495 |
bufnext->at = (cc - &cclasses[0]);
|
|
496 |
(bufnext++)->wc = COLON;
|
478 |
497 |
*bufnextp = bufnext;
|
479 |
498 |
*patternp += len + 3;
|
480 |
499 |
|
... | ... | |
493 |
512 |
int (*errfunc)(const char *, int))
|
494 |
513 |
{
|
495 |
514 |
const Char *qpatnext;
|
496 |
|
int c, err, oldpathc;
|
|
515 |
int err, oldpathc;
|
|
516 |
wchar_t c;
|
|
517 |
int a;
|
497 |
518 |
Char *bufnext, patbuf[MAXPATHLEN];
|
498 |
519 |
|
499 |
520 |
qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
|
... | ... | |
501 |
522 |
bufnext = patbuf;
|
502 |
523 |
|
503 |
524 |
/* We don't need to check for buffer overflow any more. */
|
504 |
|
while ((c = *qpatnext++) != EOS) {
|
|
525 |
while ((a = qpatnext->at), (c = (qpatnext++)->wc) != EOS) {
|
505 |
526 |
switch (c) {
|
506 |
527 |
case LBRACKET:
|
507 |
|
c = *qpatnext;
|
508 |
|
if (c == NOT)
|
|
528 |
if (a != 0) {
|
|
529 |
bufnext->at = a;
|
|
530 |
(bufnext++)->wc = c;
|
|
531 |
break;
|
|
532 |
}
|
|
533 |
a = qpatnext->at;
|
|
534 |
c = qpatnext->wc;
|
|
535 |
if (a == 0 && c == NOT)
|
509 |
536 |
++qpatnext;
|
510 |
|
if (*qpatnext == EOS ||
|
|
537 |
if (qpatnext->wc == EOS ||
|
511 |
538 |
g_strchr(qpatnext+1, RBRACKET) == NULL) {
|
512 |
|
*bufnext++ = LBRACKET;
|
513 |
|
if (c == NOT)
|
|
539 |
bufnext->at = 0;
|
|
540 |
(bufnext++)->wc = LBRACKET;
|
|
541 |
if (a == 0 && c == NOT)
|
514 |
542 |
--qpatnext;
|
515 |
543 |
break;
|
516 |
544 |
}
|
517 |
|
*bufnext++ = M_SET;
|
518 |
|
if (c == NOT)
|
519 |
|
*bufnext++ = M_NOT;
|
520 |
|
c = *qpatnext++;
|
|
545 |
bufnext->at = M_QUOTE;
|
|
546 |
(bufnext++)->wc = M_SET;
|
|
547 |
if (a == 0 && c == NOT) {
|
|
548 |
bufnext->at = M_QUOTE;
|
|
549 |
(bufnext++)->wc = M_NOT;
|
|
550 |
}
|
|
551 |
a = qpatnext->at;
|
|
552 |
c = (qpatnext++)->wc;
|
521 |
553 |
do {
|
522 |
|
if (c == LBRACKET && *qpatnext == ':') {
|
|
554 |
if (a == 0 && c == LBRACKET &&
|
|
555 |
qpatnext->wc == COLON) {
|
523 |
556 |
do {
|
524 |
557 |
err = g_charclass(&qpatnext,
|
525 |
558 |
&bufnext);
|
526 |
559 |
if (err)
|
527 |
560 |
break;
|
528 |
|
c = *qpatnext++;
|
529 |
|
} while (c == LBRACKET &&
|
530 |
|
*qpatnext == ':');
|
|
561 |
a = qpatnext->at;
|
|
562 |
c = (qpatnext++)->wc;
|
|
563 |
} while (a == 0 && c == LBRACKET &&
|
|
564 |
qpatnext->wc == COLON);
|
531 |
565 |
if (err == -1 &&
|
532 |
566 |
!(pglob->gl_flags & GLOB_NOCHECK))
|
533 |
567 |
return (GLOB_NOMATCH);
|
534 |
|
if (c == RBRACKET)
|
|
568 |
if (a == 0 && c == RBRACKET)
|
535 |
569 |
break;
|
536 |
570 |
}
|
537 |
|
*bufnext++ = CHAR(c);
|
538 |
|
if (*qpatnext == RANGE &&
|
539 |
|
(c = qpatnext[1]) != RBRACKET) {
|
540 |
|
*bufnext++ = M_RNG;
|
541 |
|
*bufnext++ = CHAR(c);
|
542 |
|
qpatnext += 2;
|
|
571 |
bufnext->at = a;
|
|
572 |
(bufnext++)->wc = c;
|
|
573 |
if (qpatnext->at == 0 &&
|
|
574 |
qpatnext->wc == RANGE) {
|
|
575 |
a = qpatnext[1].at;
|
|
576 |
c = qpatnext[1].wc;
|
|
577 |
if (qpatnext[1].at != 0 ||
|
|
578 |
qpatnext[1].wc != RBRACKET) {
|
|
579 |
bufnext->at = M_QUOTE;
|
|
580 |
(bufnext++)->wc = M_RNG;
|
|
581 |
bufnext->at = a;
|
|
582 |
(bufnext++)->wc = c;
|
|
583 |
qpatnext += 2;
|
|
584 |
}
|
543 |
585 |
}
|
544 |
|
} while ((c = *qpatnext++) != RBRACKET);
|
|
586 |
a = qpatnext->at;
|
|
587 |
c = (qpatnext++)->wc;
|
|
588 |
} while (a != 0 || c != RBRACKET);
|
545 |
589 |
pglob->gl_flags |= GLOB_MAGCHAR;
|
546 |
|
*bufnext++ = M_END;
|
|
590 |
bufnext->at = M_QUOTE;
|
|
591 |
(bufnext++)->wc = M_END;
|
547 |
592 |
break;
|
548 |
593 |
case QUESTION:
|
|
594 |
if (a != 0) {
|
|
595 |
bufnext->at = a;
|
|
596 |
(bufnext++)->wc = c;
|
|
597 |
break;
|
|
598 |
}
|
549 |
599 |
pglob->gl_flags |= GLOB_MAGCHAR;
|
550 |
|
*bufnext++ = M_ONE;
|
|
600 |
bufnext->at = M_QUOTE;
|
|
601 |
(bufnext++)->wc = M_ONE;
|
551 |
602 |
break;
|
552 |
603 |
case STAR:
|
|
604 |
if (a != 0) {
|
|
605 |
bufnext->at = a;
|
|
606 |
(bufnext++)->wc = c;
|
|
607 |
break;
|
|
608 |
}
|
553 |
609 |
pglob->gl_flags |= GLOB_MAGCHAR;
|
554 |
610 |
/*
|
555 |
611 |
* collapse adjacent stars to one,
|
556 |
612 |
* to avoid exponential behavior
|
557 |
613 |
*/
|
558 |
|
if (bufnext == patbuf || bufnext[-1] != M_ALL)
|
559 |
|
*bufnext++ = M_ALL;
|
|
614 |
if (bufnext == patbuf ||
|
|
615 |
bufnext[-1].at != M_QUOTE ||
|
|
616 |
bufnext[-1].wc != M_ALL) {
|
|
617 |
bufnext->at = M_QUOTE;
|
|
618 |
(bufnext++)->wc = M_ALL;
|
|
619 |
}
|
560 |
620 |
break;
|
561 |
621 |
default:
|
562 |
|
*bufnext++ = CHAR(c);
|
|
622 |
bufnext->at = a;
|
|
623 |
(bufnext++)->wc = c;
|
563 |
624 |
break;
|
564 |
625 |
}
|
565 |
626 |
}
|
566 |
|
*bufnext = EOS;
|
|
627 |
bufnext->at = 0;
|
|
628 |
bufnext->wc = EOS;
|
567 |
629 |
#ifdef DEBUG
|
568 |
|
qprintf("glob0:", patbuf);
|
|
630 |
qprintf("glob0:glob1:patbuf", patbuf);
|
569 |
631 |
#endif
|
570 |
632 |
|
571 |
633 |
if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, limitp, errfunc))
|
... | ... | |
638 |
700 |
Char pathbuf[MAXPATHLEN];
|
639 |
701 |
|
640 |
702 |
/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
|
641 |
|
if (*pattern == EOS)
|
|
703 |
if (pattern->wc == EOS)
|
642 |
704 |
return (0);
|
643 |
705 |
return (glob2(pathbuf, pathbuf+MAXPATHLEN-1,
|
644 |
706 |
pathbuf, pathbuf+MAXPATHLEN-1,
|
... | ... | |
664 |
726 |
* segment with meta character found.
|
665 |
727 |
*/
|
666 |
728 |
for (anymeta = 0; ; ) {
|
667 |
|
if (*pattern == EOS) { /* End of pattern? */
|
668 |
|
*pathend = EOS;
|
|
729 |
if (pattern->wc == EOS) { /* End of pattern? */
|
|
730 |
pathend->at = 0;
|
|
731 |
pathend->wc = EOS;
|
669 |
732 |
|
670 |
733 |
if ((pglob->gl_flags & GLOB_LIMIT) &&
|
671 |
734 |
limitp->glim_stat++ >= GLOB_LIMIT_STAT) {
|
672 |
735 |
errno = 0;
|
673 |
|
*pathend++ = SEP;
|
674 |
|
*pathend = EOS;
|
|
736 |
pathend->at = 0;
|
|
737 |
(pathend++)->wc = SEP;
|
|
738 |
pathend->at = 0;
|
|
739 |
pathend->wc = EOS;
|
675 |
740 |
return (GLOB_NOSPACE);
|
676 |
741 |
}
|
677 |
742 |
if (g_lstat(pathbuf, &sb, pglob))
|
678 |
743 |
return (0);
|
679 |
744 |
|
680 |
745 |
if (((pglob->gl_flags & GLOB_MARK) &&
|
681 |
|
pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) ||
|
|
746 |
(pathend[-1].at != 0 ||
|
|
747 |
pathend[-1].wc != SEP)) &&
|
|
748 |
(S_ISDIR(sb.st_mode) ||
|
682 |
749 |
(S_ISLNK(sb.st_mode) &&
|
683 |
750 |
(g_stat(pathbuf, &sb, pglob) == 0) &&
|
684 |
751 |
S_ISDIR(sb.st_mode)))) {
|
685 |
752 |
if (pathend+1 > pathend_last)
|
686 |
|
return (1);
|
687 |
|
*pathend++ = SEP;
|
688 |
|
*pathend = EOS;
|
|
753 |
return (GLOB_NOSPACE);
|
|
754 |
pathend->at = 0;
|
|
755 |
(pathend++)->wc = SEP;
|
|
756 |
pathend->at = 0;
|
|
757 |
pathend->wc = EOS;
|
689 |
758 |
}
|
690 |
759 |
++pglob->gl_matchc;
|
691 |
760 |
return (globextend(pathbuf, pglob, limitp, &sb));
|
... | ... | |
694 |
763 |
/* Find end of next segment, copy tentatively to pathend. */
|
695 |
764 |
q = pathend;
|
696 |
765 |
p = pattern;
|
697 |
|
while (*p != EOS && *p != SEP) {
|
|
766 |
while (p->wc != EOS && p->wc != SEP) {
|
698 |
767 |
if (ismeta(*p))
|
699 |
768 |
anymeta = 1;
|
700 |
769 |
if (q+1 > pathend_last)
|
701 |
|
return (1);
|
|
770 |
return (GLOB_NOSPACE);
|
702 |
771 |
*q++ = *p++;
|
703 |
772 |
}
|
704 |
773 |
|
705 |
774 |
if (!anymeta) { /* No expansion, do next segment. */
|
706 |
775 |
pathend = q;
|
707 |
776 |
pattern = p;
|
708 |
|
while (*pattern == SEP) {
|
|
777 |
while (pattern->wc == SEP) {
|
709 |
778 |
if (pathend+1 > pathend_last)
|
710 |
|
return (1);
|
|
779 |
return (GLOB_NOSPACE);
|
711 |
780 |
*pathend++ = *pattern++;
|
712 |
781 |
}
|
713 |
|
} else
|
|
782 |
} else {
|
714 |
783 |
/* Need expansion, recurse. */
|
715 |
784 |
return (glob3(pathbuf, pathbuf_last, pathend,
|
716 |
785 |
pathend_last, pattern, p, pattern_last,
|
717 |
786 |
pglob, limitp, errfunc));
|
|
787 |
}
|
718 |
788 |
}
|
719 |
789 |
/* NOTREACHED */
|
720 |
790 |
}
|
... | ... | |
738 |
808 |
struct dirent *(*readdirfunc)(void *);
|
739 |
809 |
|
740 |
810 |
if (pathend > pathend_last)
|
741 |
|
return (1);
|
742 |
|
*pathend = EOS;
|
|
811 |
return (GLOB_NOSPACE);
|
|
812 |
pathend->at = 0;
|
|
813 |
pathend->wc = EOS;
|
743 |
814 |
errno = 0;
|
744 |
815 |
|
745 |
816 |
if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
|
... | ... | |
762 |
833 |
else
|
763 |
834 |
readdirfunc = (struct dirent *(*)(void *))readdir;
|
764 |
835 |
while ((dp = (*readdirfunc)(dirp))) {
|
765 |
|
uchar_t *sc;
|
|
836 |
char *sc;
|
766 |
837 |
Char *dc;
|
|
838 |
size_t n;
|
|
839 |
wchar_t w;
|
767 |
840 |
|
768 |
841 |
if ((pglob->gl_flags & GLOB_LIMIT) &&
|
769 |
842 |
limitp->glim_readdir++ >= GLOB_LIMIT_READDIR) {
|
770 |
843 |
errno = 0;
|
771 |
|
*pathend++ = SEP;
|
772 |
|
*pathend = EOS;
|
|
844 |
pathend->at = 0;
|
|
845 |
(pathend++)->wc = SEP;
|
|
846 |
pathend->at = 0;
|
|
847 |
pathend->wc = EOS;
|
773 |
848 |
err = GLOB_NOSPACE;
|
774 |
849 |
break;
|
775 |
850 |
}
|
776 |
851 |
|
777 |
852 |
/* Initial DOT must be matched literally. */
|
778 |
|
if (dp->d_name[0] == DOT && *pattern != DOT)
|
|
853 |
if (dp->d_name[0] == DOT && pattern->wc != DOT)
|
779 |
854 |
continue;
|
780 |
855 |
dc = pathend;
|
781 |
|
sc = (uchar_t *)dp->d_name;
|
782 |
|
while (dc < pathend_last && (*dc++ = *sc++) != EOS)
|
783 |
|
;
|
|
856 |
sc = dp->d_name;
|
|
857 |
while (dc < pathend_last) {
|
|
858 |
if ((n = mbtowc(&w, sc, MB_LEN_MAX)) <= 0) {
|
|
859 |
sc += 1;
|
|
860 |
dc->at = 0;
|
|
861 |
dc->wc = EOS;
|
|
862 |
} else {
|
|
863 |
sc += n;
|
|
864 |
dc->at = 0;
|
|
865 |
dc->wc = w;
|
|
866 |
}
|
|
867 |
dc++;
|
|
868 |
if (n <= 0)
|
|
869 |
break;
|
|
870 |
}
|
784 |
871 |
if (dc >= pathend_last) {
|
785 |
|
*dc = EOS;
|
786 |
|
err = 1;
|
|
872 |
dc->at = 0;
|
|
873 |
dc->wc = EOS;
|
|
874 |
err = GLOB_NOSPACE;
|
787 |
875 |
break;
|
788 |
876 |
}
|
|
877 |
if (n < 0) {
|
|
878 |
dc->at = 0;
|
|
879 |
dc->wc = EOS;
|
|
880 |
continue;
|
|
881 |
}
|
789 |
882 |
|
790 |
883 |
if (!match(pathend, pattern, restpattern, GLOB_LIMIT_RECUR)) {
|
791 |
|
*pathend = EOS;
|
|
884 |
pathend->at = 0;
|
|
885 |
pathend->wc = EOS;
|
792 |
886 |
continue;
|
793 |
887 |
}
|
794 |
888 |
err = glob2(pathbuf, pathbuf_last, --dc, pathend_last,
|
... | ... | |
830 |
924 |
char *copy = NULL;
|
831 |
925 |
const Char *p;
|
832 |
926 |
struct stat **statv;
|
|
927 |
char junk[MB_LEN_MAX];
|
|
928 |
int n;
|
833 |
929 |
|
834 |
930 |
newn = 2 + pglob->gl_pathc + pglob->gl_offs;
|
835 |
931 |
if (pglob->gl_offs >= INT_MAX ||
|
... | ... | |
897 |
993 |
statv[pglob->gl_offs + pglob->gl_pathc + 1] = NULL;
|
898 |
994 |
}
|
899 |
995 |
|
900 |
|
for (p = path; *p++; )
|
901 |
|
;
|
902 |
|
len = (size_t)(p - path);
|
|
996 |
len = MB_LEN_MAX;
|
|
997 |
p = path;
|
|
998 |
while ((n = wctomb(junk, p->wc)) > 0) {
|
|
999 |
len += n;
|
|
1000 |
if ((p++)->wc == EOS)
|
|
1001 |
break;
|
|
1002 |
}
|
|
1003 |
|
903 |
1004 |
limitp->glim_malloc += len;
|
904 |
1005 |
if ((copy = malloc(len)) != NULL) {
|
905 |
1006 |
if (g_Ctoc(path, copy, len)) {
|
... | ... | |
932 |
1033 |
Char c, k;
|
933 |
1034 |
|
934 |
1035 |
if (recur-- == 0)
|
935 |
|
return (GLOB_NOSPACE);
|
|
1036 |
return (1);
|
936 |
1037 |
|
937 |
1038 |
while (pat < patend) {
|
938 |
1039 |
c = *pat++;
|
939 |
|
switch (c & M_MASK) {
|
|
1040 |
switch (c.wc) {
|
940 |
1041 |
case M_ALL:
|
941 |
|
while (pat < patend && (*pat & M_MASK) == M_ALL)
|
|
1042 |
if (c.at != M_QUOTE) {
|
|
1043 |
k = *name++;
|
|
1044 |
if (k.at != c.at || k.wc != c.wc)
|
|
1045 |
return (0);
|
|
1046 |
break;
|
|
1047 |
}
|
|
1048 |
while (pat < patend && pat->at == M_QUOTE &&
|
|
1049 |
pat->wc == M_ALL)
|
942 |
1050 |
pat++; /* eat consecutive '*' */
|
943 |
1051 |
if (pat == patend)
|
944 |
1052 |
return (1);
|
945 |
1053 |
do {
|
946 |
1054 |
if (match(name, pat, patend, recur))
|
947 |
1055 |
return (1);
|
948 |
|
} while (*name++ != EOS);
|
|
1056 |
} while ((name++)->wc != EOS);
|
949 |
1057 |
return (0);
|
950 |
1058 |
case M_ONE:
|
951 |
|
if (*name++ == EOS)
|
|
1059 |
if (c.at != M_QUOTE) {
|
|
1060 |
k = *name++;
|
|
1061 |
if (k.at != c.at || k.wc != c.wc)
|
|
1062 |
return (0);
|
|
1063 |
break;
|
|
1064 |
}
|
|
1065 |
if ((name++)->wc == EOS)
|
952 |
1066 |
return (0);
|
953 |
1067 |
break;
|
954 |
1068 |
case M_SET:
|
|
1069 |
if (c.at != M_QUOTE) {
|
|
1070 |
k = *name++;
|
|
1071 |
if (k.at != c.at || k.wc != c.wc)
|
|
1072 |
return (0);
|
|
1073 |
break;
|
|
1074 |
}
|
955 |
1075 |
ok = 0;
|
956 |
|
if ((k = *name++) == EOS)
|
|
1076 |
if ((k = *name++).wc == EOS)
|
957 |
1077 |
return (0);
|
958 |
|
if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
|
|
1078 |
if ((negate_range = (pat->at == M_QUOTE &&
|
|
1079 |
pat->wc == M_NOT)) != 0)
|
959 |
1080 |
++pat;
|
960 |
|
while (((c = *pat++) & M_MASK) != M_END) {
|
961 |
|
if ((c & M_MASK) == M_CLASS) {
|
962 |
|
Char idx = *pat & M_MASK;
|
963 |
|
if (idx < NCCLASSES &&
|
964 |
|
cclasses[idx].isctype(k))
|
|
1081 |
while (((c = *pat++).at != M_QUOTE) || c.wc != M_END) {
|
|
1082 |
if (c.at == M_QUOTE && c.wc == M_CLASS) {
|
|
1083 |
Char idx;
|
|
1084 |
|
|
1085 |
idx.at = pat->at;
|
|
1086 |
idx.wc = pat->wc;
|
|
1087 |
if (idx.at < NCCLASSES &&
|
|
1088 |
cclasses[idx.at].isctype(k.wc))
|
965 |
1089 |
ok = 1;
|
966 |
1090 |
++pat;
|
967 |
1091 |
}
|
968 |
|
if ((*pat & M_MASK) == M_RNG) {
|
969 |
|
if (c <= k && k <= pat[1])
|
|
1092 |
if (pat->at == M_QUOTE && pat->wc == M_RNG) {
|
|
1093 |
if (c.wc <= k.wc && k.wc <= pat[1].wc)
|
970 |
1094 |
ok = 1;
|
971 |
1095 |
pat += 2;
|
972 |
|
} else if (c == k)
|
|
1096 |
} else if (c.wc == k.wc)
|
973 |
1097 |
ok = 1;
|
974 |
1098 |
}
|
975 |
1099 |
if (ok == negate_range)
|
976 |
1100 |
return (0);
|
977 |
1101 |
break;
|
978 |
1102 |
default:
|
979 |
|
if (*name++ != c)
|
|
1103 |
k = *name++;
|
|
1104 |
if (k.at != c.at || k.wc != c.wc)
|
980 |
1105 |
return (0);
|
981 |
1106 |
break;
|
982 |
1107 |
}
|
983 |
1108 |
}
|
984 |
|
return (*name == EOS);
|
|
1109 |
return (name->wc == EOS);
|
985 |
1110 |
}
|
986 |
1111 |
|
987 |
1112 |
/* Free allocated data belonging to a glob_t structure. */
|
... | ... | |
1015 |
1140 |
{
|
1016 |
1141 |
char buf[MAXPATHLEN];
|
1017 |
1142 |
|
1018 |
|
if (!*str)
|
|
1143 |
if (str->wc == EOS)
|
1019 |
1144 |
strlcpy(buf, ".", sizeof (buf));
|
1020 |
1145 |
else {
|
1021 |
1146 |
if (g_Ctoc(str, buf, sizeof (buf)))
|
... | ... | |
1053 |
1178 |
}
|
1054 |
1179 |
|
1055 |
1180 |
static Char *
|
1056 |
|
g_strchr(const Char *str, int ch)
|
|
1181 |
g_strchr(const Char *str, wchar_t ch)
|
1057 |
1182 |
{
|
1058 |
1183 |
do {
|
1059 |
|
if (*str == ch)
|
|
1184 |
if (str->at == 0 && str->wc == ch)
|
1060 |
1185 |
return ((Char *)str);
|
1061 |
|
} while (*str++);
|
|
1186 |
} while ((str++)->wc != EOS);
|
1062 |
1187 |
return (NULL);
|
1063 |
1188 |
}
|
1064 |
1189 |
|
1065 |
1190 |
static int
|
1066 |
1191 |
g_Ctoc(const Char *str, char *buf, uint_t len)
|
1067 |
1192 |
{
|
|
1193 |
int n;
|
|
1194 |
wchar_t w;
|
1068 |
1195 |
|
1069 |
|
while (len--) {
|
1070 |
|
if ((*buf++ = *str++) == EOS)
|
|
1196 |
while (len >= MB_LEN_MAX) {
|
|
1197 |
w = (str++)->wc;
|
|
1198 |
if ((n = wctomb(buf, w)) > 0) {
|
|
1199 |
len -= n;
|
|
1200 |
buf += n;
|
|
1201 |
}
|
|
1202 |
if (n < 0)
|
|
1203 |
break;
|
|
1204 |
if (w == EOS)
|
1071 |
1205 |
return (0);
|
1072 |
1206 |
}
|
1073 |
1207 |
return (1);
|
... | ... | |
1080 |
1214 |
Char *p;
|
1081 |
1215 |
|
1082 |
1216 |
(void) printf("%s:\n", str);
|
1083 |
|
for (p = s; *p; p++)
|
1084 |
|
(void) printf("%c", CHAR(*p));
|
|
1217 |
for (p = s; p->wc != EOS; p++)
|
|
1218 |
(void) printf("%wc", p->wc);
|
1085 |
1219 |
(void) printf("\n");
|
1086 |
|
for (p = s; *p; p++)
|
1087 |
|
(void) printf("%c", *p & M_PROTECT ? '"' : ' ');
|
|
1220 |
for (p = s; p->wc != EOS; p++)
|
|
1221 |
(void) printf("%c", p->at & M_PROTECT ? '"' : ' ');
|
1088 |
1222 |
(void) printf("\n");
|
1089 |
|
for (p = s; *p; p++)
|
|
1223 |
for (p = s; p->wc != EOS; p++)
|
1090 |
1224 |
(void) printf("%c", ismeta(*p) ? '_' : ' ');
|
1091 |
1225 |
(void) printf("\n");
|
1092 |
1226 |
}
|