diff options
author | Damien Miller <djm@mindrot.org> | 2010-10-07 21:39:17 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2010-10-07 21:39:17 +1100 |
commit | a6e121aaa0ab61965db2dcfe8e2ba5d719fbe1e6 (patch) | |
tree | 4583d2a94482493f21537611187bd119f496807c /openbsd-compat | |
parent | aa18063baf35e303832d9ec58204ffaab221de85 (diff) |
- djm@cvs.openbsd.org 2010/09/25 09:30:16
[sftp.c configure.ac openbsd-compat/glob.c openbsd-compat/glob.h]
make use of new glob(3) GLOB_KEEPSTAT extension to save extra server
rountrips to fetch per-file stat(2) information.
NB. update openbsd-compat/ glob(3) implementation from OpenBSD libc to
match.
Diffstat (limited to 'openbsd-compat')
-rw-r--r-- | openbsd-compat/charclass.h | 31 | ||||
-rw-r--r-- | openbsd-compat/glob.c | 232 | ||||
-rw-r--r-- | openbsd-compat/glob.h | 14 |
3 files changed, 210 insertions, 67 deletions
diff --git a/openbsd-compat/charclass.h b/openbsd-compat/charclass.h new file mode 100644 index 000000000..91f517447 --- /dev/null +++ b/openbsd-compat/charclass.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * Public domain, 2008, Todd C. Miller <Todd.Miller@courtesan.com> | ||
3 | * | ||
4 | * $OpenBSD: charclass.h,v 1.1 2008/10/01 23:04:13 millert Exp $ | ||
5 | */ | ||
6 | |||
7 | /* OPENBSD ORIGINAL: lib/libc/gen/charclass.h */ | ||
8 | |||
9 | /* | ||
10 | * POSIX character class support for fnmatch() and glob(). | ||
11 | */ | ||
12 | static struct cclass { | ||
13 | const char *name; | ||
14 | int (*isctype)(int); | ||
15 | } cclasses[] = { | ||
16 | { "alnum", isalnum }, | ||
17 | { "alpha", isalpha }, | ||
18 | { "blank", isblank }, | ||
19 | { "cntrl", iscntrl }, | ||
20 | { "digit", isdigit }, | ||
21 | { "graph", isgraph }, | ||
22 | { "lower", islower }, | ||
23 | { "print", isprint }, | ||
24 | { "punct", ispunct }, | ||
25 | { "space", isspace }, | ||
26 | { "upper", isupper }, | ||
27 | { "xdigit", isxdigit }, | ||
28 | { NULL, NULL } | ||
29 | }; | ||
30 | |||
31 | #define NCCLASSES (sizeof(cclasses) / sizeof(cclasses[0]) - 1) | ||
diff --git a/openbsd-compat/glob.c b/openbsd-compat/glob.c index 74b506403..7bbe6c71a 100644 --- a/openbsd-compat/glob.c +++ b/openbsd-compat/glob.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: glob.c,v 1.26 2005/11/28 17:50:12 deraadt Exp $ */ | 1 | /* $OpenBSD: glob.c,v 1.33 2010/09/26 22:15:39 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1989, 1993 | 3 | * Copyright (c) 1989, 1993 |
4 | * The Regents of the University of California. All rights reserved. | 4 | * The Regents of the University of California. All rights reserved. |
@@ -33,6 +33,31 @@ | |||
33 | 33 | ||
34 | /* OPENBSD ORIGINAL: lib/libc/gen/glob.c */ | 34 | /* OPENBSD ORIGINAL: lib/libc/gen/glob.c */ |
35 | 35 | ||
36 | /* | ||
37 | * glob(3) -- a superset of the one defined in POSIX 1003.2. | ||
38 | * | ||
39 | * The [!...] convention to negate a range is supported (SysV, Posix, ksh). | ||
40 | * | ||
41 | * Optional extra services, controlled by flags not defined by POSIX: | ||
42 | * | ||
43 | * GLOB_QUOTE: | ||
44 | * Escaping convention: \ inhibits any special meaning the following | ||
45 | * character might have (except \ at end of string is retained). | ||
46 | * GLOB_MAGCHAR: | ||
47 | * Set in gl_flags if pattern contained a globbing character. | ||
48 | * GLOB_NOMAGIC: | ||
49 | * Same as GLOB_NOCHECK, but it will only append pattern if it did | ||
50 | * not contain any magic characters. [Used in csh style globbing] | ||
51 | * GLOB_ALTDIRFUNC: | ||
52 | * Use alternately specified directory access functions. | ||
53 | * GLOB_TILDE: | ||
54 | * expand ~user/foo to the /home/dir/of/user/foo | ||
55 | * GLOB_BRACE: | ||
56 | * expand {1,2}{a,b} to 1a 1b 2a 2b | ||
57 | * gl_matchc: | ||
58 | * Number of matches in the current invocation of glob. | ||
59 | */ | ||
60 | |||
36 | #include "includes.h" | 61 | #include "includes.h" |
37 | 62 | ||
38 | #include <sys/types.h> | 63 | #include <sys/types.h> |
@@ -47,7 +72,7 @@ | |||
47 | #include <unistd.h> | 72 | #include <unistd.h> |
48 | 73 | ||
49 | #if !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || \ | 74 | #if !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || \ |
50 | !defined(GLOB_HAS_GL_MATCHC) || \ | 75 | !defined(GLOB_HAS_GL_MATCHC) || !defined(GLOB_HAS_GL_STATV) || \ |
51 | !defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \ | 76 | !defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \ |
52 | defined(BROKEN_GLOB) | 77 | defined(BROKEN_GLOB) |
53 | 78 | ||
@@ -63,31 +88,7 @@ get_arg_max(void) | |||
63 | #endif | 88 | #endif |
64 | } | 89 | } |
65 | 90 | ||
66 | /* | 91 | #include "charclass.h" |
67 | * glob(3) -- a superset of the one defined in POSIX 1003.2. | ||
68 | * | ||
69 | * The [!...] convention to negate a range is supported (SysV, Posix, ksh). | ||
70 | * | ||
71 | * Optional extra services, controlled by flags not defined by POSIX: | ||
72 | * | ||
73 | * GLOB_QUOTE: | ||
74 | * Escaping convention: \ inhibits any special meaning the following | ||
75 | * character might have (except \ at end of string is retained). | ||
76 | * GLOB_MAGCHAR: | ||
77 | * Set in gl_flags if pattern contained a globbing character. | ||
78 | * GLOB_NOMAGIC: | ||
79 | * Same as GLOB_NOCHECK, but it will only append pattern if it did | ||
80 | * not contain any magic characters. [Used in csh style globbing] | ||
81 | * GLOB_ALTDIRFUNC: | ||
82 | * Use alternately specified directory access functions. | ||
83 | * GLOB_TILDE: | ||
84 | * expand ~user/foo to the /home/dir/of/user/foo | ||
85 | * GLOB_BRACE: | ||
86 | * expand {1,2}{a,b} to 1a 1b 2a 2b | ||
87 | * gl_matchc: | ||
88 | * Number of matches in the current invocation of glob. | ||
89 | */ | ||
90 | |||
91 | 92 | ||
92 | #define DOLLAR '$' | 93 | #define DOLLAR '$' |
93 | #define DOT '.' | 94 | #define DOT '.' |
@@ -100,7 +101,6 @@ get_arg_max(void) | |||
100 | #define RBRACKET ']' | 101 | #define RBRACKET ']' |
101 | #define SEP '/' | 102 | #define SEP '/' |
102 | #define STAR '*' | 103 | #define STAR '*' |
103 | #undef TILDE /* Some platforms may already define it */ | ||
104 | #define TILDE '~' | 104 | #define TILDE '~' |
105 | #define UNDERSCORE '_' | 105 | #define UNDERSCORE '_' |
106 | #define LBRACE '{' | 106 | #define LBRACE '{' |
@@ -137,6 +137,7 @@ typedef char Char; | |||
137 | #define M_ONE META('?') | 137 | #define M_ONE META('?') |
138 | #define M_RNG META('-') | 138 | #define M_RNG META('-') |
139 | #define M_SET META('[') | 139 | #define M_SET META('[') |
140 | #define M_CLASS META(':') | ||
140 | #define ismeta(c) (((c)&M_QUOTE) != 0) | 141 | #define ismeta(c) (((c)&M_QUOTE) != 0) |
141 | 142 | ||
142 | 143 | ||
@@ -144,7 +145,8 @@ static int compare(const void *, const void *); | |||
144 | static int g_Ctoc(const Char *, char *, u_int); | 145 | static int g_Ctoc(const Char *, char *, u_int); |
145 | static int g_lstat(Char *, struct stat *, glob_t *); | 146 | static int g_lstat(Char *, struct stat *, glob_t *); |
146 | static DIR *g_opendir(Char *, glob_t *); | 147 | static DIR *g_opendir(Char *, glob_t *); |
147 | static Char *g_strchr(Char *, int); | 148 | static Char *g_strchr(const Char *, int); |
149 | static int g_strncmp(const Char *, const char *, size_t); | ||
148 | static int g_stat(Char *, struct stat *, glob_t *); | 150 | static int g_stat(Char *, struct stat *, glob_t *); |
149 | static int glob0(const Char *, glob_t *); | 151 | static int glob0(const Char *, glob_t *); |
150 | static int glob1(Char *, Char *, glob_t *, size_t *); | 152 | static int glob1(Char *, Char *, glob_t *, size_t *); |
@@ -152,11 +154,11 @@ static int glob2(Char *, Char *, Char *, Char *, Char *, Char *, | |||
152 | glob_t *, size_t *); | 154 | glob_t *, size_t *); |
153 | static int glob3(Char *, Char *, Char *, Char *, Char *, | 155 | static int glob3(Char *, Char *, Char *, Char *, Char *, |
154 | Char *, Char *, glob_t *, size_t *); | 156 | Char *, Char *, glob_t *, size_t *); |
155 | static int globextend(const Char *, glob_t *, size_t *); | 157 | static int globextend(const Char *, glob_t *, size_t *, struct stat *); |
156 | static const Char * | 158 | static const Char * |
157 | globtilde(const Char *, Char *, size_t, glob_t *); | 159 | globtilde(const Char *, Char *, size_t, glob_t *); |
158 | static int globexp1(const Char *, glob_t *); | 160 | static int globexp1(const Char *, glob_t *); |
159 | static int globexp2(const Char *, const Char *, glob_t *, int *); | 161 | static int globexp2(const Char *, const Char *, glob_t *); |
160 | static int match(Char *, Char *, Char *); | 162 | static int match(Char *, Char *, Char *); |
161 | #ifdef DEBUG | 163 | #ifdef DEBUG |
162 | static void qprintf(const char *, Char *); | 164 | static void qprintf(const char *, Char *); |
@@ -174,6 +176,7 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int), | |||
174 | if (!(flags & GLOB_APPEND)) { | 176 | if (!(flags & GLOB_APPEND)) { |
175 | pglob->gl_pathc = 0; | 177 | pglob->gl_pathc = 0; |
176 | pglob->gl_pathv = NULL; | 178 | pglob->gl_pathv = NULL; |
179 | pglob->gl_statv = NULL; | ||
177 | if (!(flags & GLOB_DOOFFS)) | 180 | if (!(flags & GLOB_DOOFFS)) |
178 | pglob->gl_offs = 0; | 181 | pglob->gl_offs = 0; |
179 | } | 182 | } |
@@ -215,15 +218,13 @@ static int | |||
215 | globexp1(const Char *pattern, glob_t *pglob) | 218 | globexp1(const Char *pattern, glob_t *pglob) |
216 | { | 219 | { |
217 | const Char* ptr = pattern; | 220 | const Char* ptr = pattern; |
218 | int rv; | ||
219 | 221 | ||
220 | /* Protect a single {}, for find(1), like csh */ | 222 | /* Protect a single {}, for find(1), like csh */ |
221 | if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) | 223 | if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) |
222 | return glob0(pattern, pglob); | 224 | return glob0(pattern, pglob); |
223 | 225 | ||
224 | while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL) | 226 | if ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL) |
225 | if (!globexp2(ptr, pattern, pglob, &rv)) | 227 | return globexp2(ptr, pattern, pglob); |
226 | return rv; | ||
227 | 228 | ||
228 | return glob0(pattern, pglob); | 229 | return glob0(pattern, pglob); |
229 | } | 230 | } |
@@ -235,9 +236,9 @@ globexp1(const Char *pattern, glob_t *pglob) | |||
235 | * If it fails then it tries to glob the rest of the pattern and returns. | 236 | * If it fails then it tries to glob the rest of the pattern and returns. |
236 | */ | 237 | */ |
237 | static int | 238 | static int |
238 | globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv) | 239 | globexp2(const Char *ptr, const Char *pattern, glob_t *pglob) |
239 | { | 240 | { |
240 | int i; | 241 | int i, rv; |
241 | Char *lm, *ls; | 242 | Char *lm, *ls; |
242 | const Char *pe, *pm, *pl; | 243 | const Char *pe, *pm, *pl; |
243 | Char patbuf[MAXPATHLEN]; | 244 | Char patbuf[MAXPATHLEN]; |
@@ -270,10 +271,8 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv) | |||
270 | } | 271 | } |
271 | 272 | ||
272 | /* Non matching braces; just glob the pattern */ | 273 | /* Non matching braces; just glob the pattern */ |
273 | if (i != 0 || *pe == EOS) { | 274 | if (i != 0 || *pe == EOS) |
274 | *rv = glob0(patbuf, pglob); | 275 | return glob0(patbuf, pglob); |
275 | return 0; | ||
276 | } | ||
277 | 276 | ||
278 | for (i = 0, pl = pm = ptr; pm <= pe; pm++) { | 277 | for (i = 0, pl = pm = ptr; pm <= pe; pm++) { |
279 | switch (*pm) { | 278 | switch (*pm) { |
@@ -319,7 +318,9 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv) | |||
319 | #ifdef DEBUG | 318 | #ifdef DEBUG |
320 | qprintf("globexp2:", patbuf); | 319 | qprintf("globexp2:", patbuf); |
321 | #endif | 320 | #endif |
322 | *rv = globexp1(patbuf, pglob); | 321 | rv = globexp1(patbuf, pglob); |
322 | if (rv && rv != GLOB_NOMATCH) | ||
323 | return rv; | ||
323 | 324 | ||
324 | /* move after the comma, to the next string */ | 325 | /* move after the comma, to the next string */ |
325 | pl = pm + 1; | 326 | pl = pm + 1; |
@@ -330,7 +331,6 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv) | |||
330 | break; | 331 | break; |
331 | } | 332 | } |
332 | } | 333 | } |
333 | *rv = 0; | ||
334 | return 0; | 334 | return 0; |
335 | } | 335 | } |
336 | 336 | ||
@@ -399,6 +399,47 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) | |||
399 | return patbuf; | 399 | return patbuf; |
400 | } | 400 | } |
401 | 401 | ||
402 | static int | ||
403 | g_strncmp(const Char *s1, const char *s2, size_t n) | ||
404 | { | ||
405 | int rv = 0; | ||
406 | |||
407 | while (n--) { | ||
408 | rv = *(Char *)s1 - *(const unsigned char *)s2++; | ||
409 | if (rv) | ||
410 | break; | ||
411 | if (*s1++ == '\0') | ||
412 | break; | ||
413 | } | ||
414 | return rv; | ||
415 | } | ||
416 | |||
417 | static int | ||
418 | g_charclass(const Char **patternp, Char **bufnextp) | ||
419 | { | ||
420 | const Char *pattern = *patternp + 1; | ||
421 | Char *bufnext = *bufnextp; | ||
422 | const Char *colon; | ||
423 | struct cclass *cc; | ||
424 | size_t len; | ||
425 | |||
426 | if ((colon = g_strchr(pattern, ':')) == NULL || colon[1] != ']') | ||
427 | return 1; /* not a character class */ | ||
428 | |||
429 | len = (size_t)(colon - pattern); | ||
430 | for (cc = cclasses; cc->name != NULL; cc++) { | ||
431 | if (!g_strncmp(pattern, cc->name, len) && cc->name[len] == '\0') | ||
432 | break; | ||
433 | } | ||
434 | if (cc->name == NULL) | ||
435 | return -1; /* invalid character class */ | ||
436 | *bufnext++ = M_CLASS; | ||
437 | *bufnext++ = (Char)(cc - &cclasses[0]); | ||
438 | *bufnextp = bufnext; | ||
439 | *patternp += len + 3; | ||
440 | |||
441 | return 0; | ||
442 | } | ||
402 | 443 | ||
403 | /* | 444 | /* |
404 | * The main glob() routine: compiles the pattern (optionally processing | 445 | * The main glob() routine: compiles the pattern (optionally processing |
@@ -427,7 +468,7 @@ glob0(const Char *pattern, glob_t *pglob) | |||
427 | if (c == NOT) | 468 | if (c == NOT) |
428 | ++qpatnext; | 469 | ++qpatnext; |
429 | if (*qpatnext == EOS || | 470 | if (*qpatnext == EOS || |
430 | g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) { | 471 | g_strchr(qpatnext+1, RBRACKET) == NULL) { |
431 | *bufnext++ = LBRACKET; | 472 | *bufnext++ = LBRACKET; |
432 | if (c == NOT) | 473 | if (c == NOT) |
433 | --qpatnext; | 474 | --qpatnext; |
@@ -438,6 +479,20 @@ glob0(const Char *pattern, glob_t *pglob) | |||
438 | *bufnext++ = M_NOT; | 479 | *bufnext++ = M_NOT; |
439 | c = *qpatnext++; | 480 | c = *qpatnext++; |
440 | do { | 481 | do { |
482 | if (c == LBRACKET && *qpatnext == ':') { | ||
483 | do { | ||
484 | err = g_charclass(&qpatnext, | ||
485 | &bufnext); | ||
486 | if (err) | ||
487 | break; | ||
488 | c = *qpatnext++; | ||
489 | } while (c == LBRACKET && *qpatnext == ':'); | ||
490 | if (err == -1 && | ||
491 | !(pglob->gl_flags & GLOB_NOCHECK)) | ||
492 | return GLOB_NOMATCH; | ||
493 | if (c == RBRACKET) | ||
494 | break; | ||
495 | } | ||
441 | *bufnext++ = CHAR(c); | 496 | *bufnext++ = CHAR(c); |
442 | if (*qpatnext == RANGE && | 497 | if (*qpatnext == RANGE && |
443 | (c = qpatnext[1]) != RBRACKET) { | 498 | (c = qpatnext[1]) != RBRACKET) { |
@@ -484,7 +539,7 @@ glob0(const Char *pattern, glob_t *pglob) | |||
484 | if ((pglob->gl_flags & GLOB_NOCHECK) || | 539 | if ((pglob->gl_flags & GLOB_NOCHECK) || |
485 | ((pglob->gl_flags & GLOB_NOMAGIC) && | 540 | ((pglob->gl_flags & GLOB_NOMAGIC) && |
486 | !(pglob->gl_flags & GLOB_MAGCHAR))) | 541 | !(pglob->gl_flags & GLOB_MAGCHAR))) |
487 | return(globextend(pattern, pglob, &limit)); | 542 | return(globextend(pattern, pglob, &limit, NULL)); |
488 | else | 543 | else |
489 | return(GLOB_NOMATCH); | 544 | return(GLOB_NOMATCH); |
490 | } | 545 | } |
@@ -547,7 +602,7 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | |||
547 | *pathend = EOS; | 602 | *pathend = EOS; |
548 | } | 603 | } |
549 | ++pglob->gl_matchc; | 604 | ++pglob->gl_matchc; |
550 | return(globextend(pathbuf, pglob, limitp)); | 605 | return(globextend(pathbuf, pglob, limitp, &sb)); |
551 | } | 606 | } |
552 | 607 | ||
553 | /* Find end of next segment, copy tentatively to pathend. */ | 608 | /* Find end of next segment, copy tentatively to pathend. */ |
@@ -670,25 +725,40 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | |||
670 | * gl_pathv points to (gl_offs + gl_pathc + 1) items. | 725 | * gl_pathv points to (gl_offs + gl_pathc + 1) items. |
671 | */ | 726 | */ |
672 | static int | 727 | static int |
673 | globextend(const Char *path, glob_t *pglob, size_t *limitp) | 728 | globextend(const Char *path, glob_t *pglob, size_t *limitp, struct stat *sb) |
674 | { | 729 | { |
675 | char **pathv; | 730 | char **pathv; |
676 | int i; | 731 | ssize_t i; |
677 | u_int newsize, len; | 732 | size_t newn, len; |
678 | char *copy; | 733 | char *copy = NULL; |
679 | const Char *p; | 734 | const Char *p; |
680 | 735 | struct stat **statv; | |
681 | newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); | 736 | |
682 | pathv = pglob->gl_pathv ? realloc((char *)pglob->gl_pathv, newsize) : | 737 | newn = 2 + pglob->gl_pathc + pglob->gl_offs; |
683 | malloc(newsize); | 738 | if (SIZE_MAX / sizeof(*pathv) <= newn || |
684 | if (pathv == NULL) { | 739 | SIZE_MAX / sizeof(*statv) <= newn) { |
740 | nospace: | ||
741 | for (i = pglob->gl_offs; i < newn - 2; i++) { | ||
742 | if (pglob->gl_pathv && pglob->gl_pathv[i]) | ||
743 | free(pglob->gl_pathv[i]); | ||
744 | if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 && | ||
745 | pglob->gl_pathv && pglob->gl_pathv[i]) | ||
746 | free(pglob->gl_statv[i]); | ||
747 | } | ||
685 | if (pglob->gl_pathv) { | 748 | if (pglob->gl_pathv) { |
686 | free(pglob->gl_pathv); | 749 | free(pglob->gl_pathv); |
687 | pglob->gl_pathv = NULL; | 750 | pglob->gl_pathv = NULL; |
688 | } | 751 | } |
752 | if (pglob->gl_statv) { | ||
753 | free(pglob->gl_statv); | ||
754 | pglob->gl_statv = NULL; | ||
755 | } | ||
689 | return(GLOB_NOSPACE); | 756 | return(GLOB_NOSPACE); |
690 | } | 757 | } |
691 | 758 | ||
759 | pathv = realloc(pglob->gl_pathv, newn * sizeof(*pathv)); | ||
760 | if (pathv == NULL) | ||
761 | goto nospace; | ||
692 | if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { | 762 | if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { |
693 | /* first time around -- clear initial gl_offs items */ | 763 | /* first time around -- clear initial gl_offs items */ |
694 | pathv += pglob->gl_offs; | 764 | pathv += pglob->gl_offs; |
@@ -697,6 +767,29 @@ globextend(const Char *path, glob_t *pglob, size_t *limitp) | |||
697 | } | 767 | } |
698 | pglob->gl_pathv = pathv; | 768 | pglob->gl_pathv = pathv; |
699 | 769 | ||
770 | if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0) { | ||
771 | statv = realloc(pglob->gl_statv, newn * sizeof(*statv)); | ||
772 | if (statv == NULL) | ||
773 | goto nospace; | ||
774 | if (pglob->gl_statv == NULL && pglob->gl_offs > 0) { | ||
775 | /* first time around -- clear initial gl_offs items */ | ||
776 | statv += pglob->gl_offs; | ||
777 | for (i = pglob->gl_offs; --i >= 0; ) | ||
778 | *--statv = NULL; | ||
779 | } | ||
780 | pglob->gl_statv = statv; | ||
781 | if (sb == NULL) | ||
782 | statv[pglob->gl_offs + pglob->gl_pathc] = NULL; | ||
783 | else { | ||
784 | if ((statv[pglob->gl_offs + pglob->gl_pathc] = | ||
785 | malloc(sizeof(**statv))) == NULL) | ||
786 | goto copy_error; | ||
787 | memcpy(statv[pglob->gl_offs + pglob->gl_pathc], sb, | ||
788 | sizeof(*sb)); | ||
789 | } | ||
790 | statv[pglob->gl_offs + pglob->gl_pathc + 1] = NULL; | ||
791 | } | ||
792 | |||
700 | for (p = path; *p++;) | 793 | for (p = path; *p++;) |
701 | ; | 794 | ; |
702 | len = (size_t)(p - path); | 795 | len = (size_t)(p - path); |
@@ -711,11 +804,11 @@ globextend(const Char *path, glob_t *pglob, size_t *limitp) | |||
711 | pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; | 804 | pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; |
712 | 805 | ||
713 | if ((pglob->gl_flags & GLOB_LIMIT) && | 806 | if ((pglob->gl_flags & GLOB_LIMIT) && |
714 | newsize + *limitp >= (u_int) get_arg_max()) { | 807 | (newn * sizeof(*pathv)) + *limitp >= ARG_MAX) { |
715 | errno = 0; | 808 | errno = 0; |
716 | return(GLOB_NOSPACE); | 809 | return(GLOB_NOSPACE); |
717 | } | 810 | } |
718 | 811 | copy_error: | |
719 | return(copy == NULL ? GLOB_NOSPACE : 0); | 812 | return(copy == NULL ? GLOB_NOSPACE : 0); |
720 | } | 813 | } |
721 | 814 | ||
@@ -751,13 +844,21 @@ match(Char *name, Char *pat, Char *patend) | |||
751 | return(0); | 844 | return(0); |
752 | if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) | 845 | if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) |
753 | ++pat; | 846 | ++pat; |
754 | while (((c = *pat++) & M_MASK) != M_END) | 847 | while (((c = *pat++) & M_MASK) != M_END) { |
848 | if ((c & M_MASK) == M_CLASS) { | ||
849 | int idx = *pat & M_MASK; | ||
850 | if (idx < NCCLASSES && | ||
851 | cclasses[idx].isctype(k)) | ||
852 | ok = 1; | ||
853 | ++pat; | ||
854 | } | ||
755 | if ((*pat & M_MASK) == M_RNG) { | 855 | if ((*pat & M_MASK) == M_RNG) { |
756 | if (c <= k && k <= pat[1]) | 856 | if (c <= k && k <= pat[1]) |
757 | ok = 1; | 857 | ok = 1; |
758 | pat += 2; | 858 | pat += 2; |
759 | } else if (c == k) | 859 | } else if (c == k) |
760 | ok = 1; | 860 | ok = 1; |
861 | } | ||
761 | if (ok == negate_range) | 862 | if (ok == negate_range) |
762 | return(0); | 863 | return(0); |
763 | break; | 864 | break; |
@@ -785,6 +886,14 @@ globfree(glob_t *pglob) | |||
785 | free(pglob->gl_pathv); | 886 | free(pglob->gl_pathv); |
786 | pglob->gl_pathv = NULL; | 887 | pglob->gl_pathv = NULL; |
787 | } | 888 | } |
889 | if (pglob->gl_statv != NULL) { | ||
890 | for (i = 0; i < pglob->gl_pathc; i++) { | ||
891 | if (pglob->gl_statv[i] != NULL) | ||
892 | free(pglob->gl_statv[i]); | ||
893 | } | ||
894 | free(pglob->gl_statv); | ||
895 | pglob->gl_statv = NULL; | ||
896 | } | ||
788 | } | 897 | } |
789 | 898 | ||
790 | static DIR * | 899 | static DIR * |
@@ -830,11 +939,11 @@ g_stat(Char *fn, struct stat *sb, glob_t *pglob) | |||
830 | } | 939 | } |
831 | 940 | ||
832 | static Char * | 941 | static Char * |
833 | g_strchr(Char *str, int ch) | 942 | g_strchr(const Char *str, int ch) |
834 | { | 943 | { |
835 | do { | 944 | do { |
836 | if (*str == ch) | 945 | if (*str == ch) |
837 | return (str); | 946 | return ((Char *)str); |
838 | } while (*str++); | 947 | } while (*str++); |
839 | return (NULL); | 948 | return (NULL); |
840 | } | 949 | } |
@@ -870,5 +979,4 @@ qprintf(const char *str, Char *s) | |||
870 | #endif | 979 | #endif |
871 | 980 | ||
872 | #endif /* !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || | 981 | #endif /* !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || |
873 | !defined(GLOB_HAS_GL_MATCHC) */ | 982 | !defined(GLOB_HAS_GL_MATCHC) || !defined(GLOB_HAS_GL_STATV) */ |
874 | |||
diff --git a/openbsd-compat/glob.h b/openbsd-compat/glob.h index a2b36f974..8ea391306 100644 --- a/openbsd-compat/glob.h +++ b/openbsd-compat/glob.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: glob.h,v 1.10 2005/12/13 00:35:22 millert Exp $ */ | 1 | /* $OpenBSD: glob.h,v 1.11 2010/09/24 13:32:55 djm Exp $ */ |
2 | /* $NetBSD: glob.h,v 1.5 1994/10/26 00:55:56 cgd Exp $ */ | 2 | /* $NetBSD: glob.h,v 1.5 1994/10/26 00:55:56 cgd Exp $ */ |
3 | 3 | ||
4 | /* | 4 | /* |
@@ -38,13 +38,16 @@ | |||
38 | /* OPENBSD ORIGINAL: include/glob.h */ | 38 | /* OPENBSD ORIGINAL: include/glob.h */ |
39 | 39 | ||
40 | #if !defined(HAVE_GLOB_H) || !defined(GLOB_HAS_ALTDIRFUNC) || \ | 40 | #if !defined(HAVE_GLOB_H) || !defined(GLOB_HAS_ALTDIRFUNC) || \ |
41 | !defined(GLOB_HAS_GL_MATCHC) || \ | 41 | !defined(GLOB_HAS_GL_MATCHC) || !define(GLOB_HAS_GL_STATV) \ |
42 | !defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \ | 42 | !defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \ |
43 | defined(BROKEN_GLOB) | 43 | defined(BROKEN_GLOB) |
44 | 44 | ||
45 | #ifndef _GLOB_H_ | 45 | #ifndef _GLOB_H_ |
46 | #define _GLOB_H_ | 46 | #define _GLOB_H_ |
47 | 47 | ||
48 | #include <sys/cdefs.h> | ||
49 | #include <sys/stat.h> | ||
50 | |||
48 | struct stat; | 51 | struct stat; |
49 | typedef struct { | 52 | typedef struct { |
50 | int gl_pathc; /* Count of total paths so far. */ | 53 | int gl_pathc; /* Count of total paths so far. */ |
@@ -52,6 +55,7 @@ typedef struct { | |||
52 | int gl_offs; /* Reserved at beginning of gl_pathv. */ | 55 | int gl_offs; /* Reserved at beginning of gl_pathv. */ |
53 | int gl_flags; /* Copy of flags parameter to glob. */ | 56 | int gl_flags; /* Copy of flags parameter to glob. */ |
54 | char **gl_pathv; /* List of paths matching pattern. */ | 57 | char **gl_pathv; /* List of paths matching pattern. */ |
58 | struct stat **gl_statv; /* Stat entries corresponding to gl_pathv */ | ||
55 | /* Copy of errfunc parameter to glob. */ | 59 | /* Copy of errfunc parameter to glob. */ |
56 | int (*gl_errfunc)(const char *, int); | 60 | int (*gl_errfunc)(const char *, int); |
57 | 61 | ||
@@ -75,12 +79,10 @@ typedef struct { | |||
75 | #define GLOB_NOSORT 0x0020 /* Don't sort. */ | 79 | #define GLOB_NOSORT 0x0020 /* Don't sort. */ |
76 | #define GLOB_NOESCAPE 0x1000 /* Disable backslash escaping. */ | 80 | #define GLOB_NOESCAPE 0x1000 /* Disable backslash escaping. */ |
77 | 81 | ||
78 | /* Error values returned by glob(3) */ | ||
79 | #define GLOB_NOSPACE (-1) /* Malloc call failed. */ | 82 | #define GLOB_NOSPACE (-1) /* Malloc call failed. */ |
80 | #define GLOB_ABORTED (-2) /* Unignored error. */ | 83 | #define GLOB_ABORTED (-2) /* Unignored error. */ |
81 | #define GLOB_NOMATCH (-3) /* No match and GLOB_NOCHECK not set. */ | 84 | #define GLOB_NOMATCH (-3) /* No match and GLOB_NOCHECK not set. */ |
82 | #define GLOB_NOSYS (-4) /* Function not supported. */ | 85 | #define GLOB_NOSYS (-4) /* Function not supported. */ |
83 | #define GLOB_ABEND GLOB_ABORTED | ||
84 | 86 | ||
85 | #define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */ | 87 | #define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */ |
86 | #define GLOB_BRACE 0x0080 /* Expand braces ala csh. */ | 88 | #define GLOB_BRACE 0x0080 /* Expand braces ala csh. */ |
@@ -89,6 +91,8 @@ typedef struct { | |||
89 | #define GLOB_QUOTE 0x0400 /* Quote special chars with \. */ | 91 | #define GLOB_QUOTE 0x0400 /* Quote special chars with \. */ |
90 | #define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */ | 92 | #define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */ |
91 | #define GLOB_LIMIT 0x2000 /* Limit pattern match output to ARG_MAX */ | 93 | #define GLOB_LIMIT 0x2000 /* Limit pattern match output to ARG_MAX */ |
94 | #define GLOB_KEEPSTAT 0x4000 /* Retain stat data for paths in gl_statv. */ | ||
95 | #define GLOB_ABEND GLOB_ABORTED /* backward compatibility */ | ||
92 | 96 | ||
93 | int glob(const char *, int, int (*)(const char *, int), glob_t *); | 97 | int glob(const char *, int, int (*)(const char *, int), glob_t *); |
94 | void globfree(glob_t *); | 98 | void globfree(glob_t *); |
@@ -96,5 +100,5 @@ void globfree(glob_t *); | |||
96 | #endif /* !_GLOB_H_ */ | 100 | #endif /* !_GLOB_H_ */ |
97 | 101 | ||
98 | #endif /* !defined(HAVE_GLOB_H) || !defined(GLOB_HAS_ALTDIRFUNC) || | 102 | #endif /* !defined(HAVE_GLOB_H) || !defined(GLOB_HAS_ALTDIRFUNC) || |
99 | !defined(GLOB_HAS_GL_MATCHC */ | 103 | !defined(GLOB_HAS_GL_MATCHC) || !defined(GLOH_HAS_GL_STATV) */ |
100 | 104 | ||