|
1 |
/*
|
|
2 |
* CDDL HEADER START
|
|
3 |
*
|
|
4 |
* The contents of this file are subject to the terms of the
|
|
5 |
* Common Development and Distribution License (the "License").
|
|
6 |
* You may not use this file except in compliance with the License.
|
|
7 |
*
|
|
8 |
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
9 |
* or http://www.opensolaris.org/os/licensing.
|
|
10 |
* See the License for the specific language governing permissions
|
|
11 |
* and limitations under the License.
|
|
12 |
*
|
|
13 |
* When distributing Covered Code, include this CDDL HEADER in each
|
|
14 |
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
15 |
* If applicable, add the following below this CDDL HEADER, with the
|
|
16 |
* fields enclosed by brackets "[]" replaced with your own identifying
|
|
17 |
* information: Portions Copyright [yyyy] [name of copyright owner]
|
|
18 |
*
|
|
19 |
* CDDL HEADER END
|
|
20 |
*/
|
|
21 |
|
|
22 |
/*
|
|
23 |
* Copyright (c) 2012 Gary Mills
|
|
24 |
*/
|
|
25 |
|
1 |
26 |
/* $OpenBSD: glob.c,v 1.39 2012/01/20 07:09:42 tedu Exp $ */
|
2 |
27 |
/*
|
3 |
28 |
* Copyright (c) 1989, 1993
|
... | ... | |
148 |
173 |
static Char *g_strchr(const Char *, int);
|
149 |
174 |
static int g_strncmp(const Char *, const char *, size_t);
|
150 |
175 |
static int g_stat(Char *, struct stat *, glob_t *);
|
151 |
|
static int glob0(const Char *, glob_t *, struct glob_lim *);
|
152 |
|
static int glob1(Char *, Char *, glob_t *, struct glob_lim *);
|
|
176 |
static int glob0(const Char *, glob_t *, struct glob_lim *,
|
|
177 |
int (*)(const char *, int));
|
|
178 |
static int glob1(Char *, Char *, glob_t *, struct glob_lim *,
|
|
179 |
int (*)(const char *, int));
|
153 |
180 |
static int glob2(Char *, Char *, Char *, Char *, Char *, Char *,
|
154 |
|
glob_t *, struct glob_lim *);
|
|
181 |
glob_t *, struct glob_lim *,
|
|
182 |
int (*)(const char *, int));
|
155 |
183 |
static int glob3(Char *, Char *, Char *, Char *, Char *,
|
156 |
|
Char *, Char *, glob_t *, struct glob_lim *);
|
|
184 |
Char *, Char *, glob_t *, struct glob_lim *,
|
|
185 |
int (*)(const char *, int));
|
157 |
186 |
static int globextend(const Char *, glob_t *, struct glob_lim *,
|
158 |
187 |
struct stat *);
|
159 |
188 |
static const Char *
|
160 |
189 |
globtilde(const Char *, Char *, size_t, glob_t *);
|
161 |
|
static int globexp1(const Char *, glob_t *, struct glob_lim *);
|
|
190 |
static int globexp1(const Char *, glob_t *, struct glob_lim *,
|
|
191 |
int (*)(const char *, int));
|
162 |
192 |
static int globexp2(const Char *, const Char *, glob_t *,
|
163 |
|
struct glob_lim *);
|
|
193 |
struct glob_lim *, int (*)(const char *, int));
|
164 |
194 |
static int match(Char *, Char *, Char *, int);
|
165 |
195 |
#ifdef DEBUG
|
166 |
196 |
static void qprintf(const char *, Char *);
|
... | ... | |
182 |
212 |
if (!(flags & GLOB_APPEND)) {
|
183 |
213 |
pglob->gl_pathc = 0;
|
184 |
214 |
pglob->gl_pathv = NULL;
|
185 |
|
pglob->gl_statv = NULL;
|
|
215 |
if ((flags & GLOB_KEEPSTAT) != 0)
|
|
216 |
pglob->gl_statv = NULL;
|
186 |
217 |
if (!(flags & GLOB_DOOFFS))
|
187 |
218 |
pglob->gl_offs = 0;
|
188 |
219 |
}
|
189 |
220 |
pglob->gl_flags = flags & ~GLOB_MAGCHAR;
|
190 |
|
pglob->gl_errfunc = errfunc;
|
191 |
221 |
pglob->gl_matchc = 0;
|
192 |
222 |
|
193 |
223 |
if (pglob->gl_offs < 0 || pglob->gl_pathc < 0 ||
|
... | ... | |
215 |
245 |
*bufnext = EOS;
|
216 |
246 |
|
217 |
247 |
if (flags & GLOB_BRACE)
|
218 |
|
return globexp1(patbuf, pglob, &limit);
|
|
248 |
return globexp1(patbuf, pglob, &limit, errfunc);
|
219 |
249 |
else
|
220 |
|
return glob0(patbuf, pglob, &limit);
|
|
250 |
return glob0(patbuf, pglob, &limit, errfunc);
|
221 |
251 |
}
|
222 |
252 |
|
223 |
253 |
/*
|
... | ... | |
226 |
256 |
* characters
|
227 |
257 |
*/
|
228 |
258 |
static int
|
229 |
|
globexp1(const Char *pattern, glob_t *pglob, struct glob_lim *limitp)
|
|
259 |
globexp1(const Char *pattern, glob_t *pglob, struct glob_lim *limitp,
|
|
260 |
int (*errfunc)(const char *, int))
|
230 |
261 |
{
|
231 |
262 |
const Char* ptr = pattern;
|
232 |
263 |
|
233 |
264 |
/* Protect a single {}, for find(1), like csh */
|
234 |
265 |
if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
|
235 |
|
return glob0(pattern, pglob, limitp);
|
|
266 |
return glob0(pattern, pglob, limitp, errfunc);
|
236 |
267 |
|
237 |
268 |
if ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL)
|
238 |
|
return globexp2(ptr, pattern, pglob, limitp);
|
|
269 |
return globexp2(ptr, pattern, pglob, limitp, errfunc);
|
239 |
270 |
|
240 |
|
return glob0(pattern, pglob, limitp);
|
|
271 |
return glob0(pattern, pglob, limitp, errfunc);
|
241 |
272 |
}
|
242 |
273 |
|
243 |
274 |
|
... | ... | |
248 |
279 |
*/
|
249 |
280 |
static int
|
250 |
281 |
globexp2(const Char *ptr, const Char *pattern, glob_t *pglob,
|
251 |
|
struct glob_lim *limitp)
|
|
282 |
struct glob_lim *limitp, int (*errfunc)(const char *, int))
|
252 |
283 |
{
|
253 |
284 |
int i, rv;
|
254 |
285 |
Char *lm, *ls;
|
... | ... | |
284 |
315 |
|
285 |
316 |
/* Non matching braces; just glob the pattern */
|
286 |
317 |
if (i != 0 || *pe == EOS)
|
287 |
|
return glob0(patbuf, pglob, limitp);
|
|
318 |
return glob0(patbuf, pglob, limitp, errfunc);
|
288 |
319 |
|
289 |
320 |
for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
|
290 |
321 |
switch (*pm) {
|
... | ... | |
330 |
361 |
#ifdef DEBUG
|
331 |
362 |
qprintf("globexp2:", patbuf);
|
332 |
363 |
#endif
|
333 |
|
rv = globexp1(patbuf, pglob, limitp);
|
|
364 |
rv = globexp1(patbuf, pglob, limitp, errfunc);
|
334 |
365 |
if (rv && rv != GLOB_NOMATCH)
|
335 |
366 |
return rv;
|
336 |
367 |
|
... | ... | |
458 |
489 |
* to find no matches.
|
459 |
490 |
*/
|
460 |
491 |
static int
|
461 |
|
glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp)
|
|
492 |
glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp,
|
|
493 |
int (*errfunc)(const char *, int))
|
462 |
494 |
{
|
463 |
495 |
const Char *qpatnext;
|
464 |
496 |
int c, err, oldpathc;
|
... | ... | |
534 |
566 |
qprintf("glob0:", patbuf);
|
535 |
567 |
#endif
|
536 |
568 |
|
537 |
|
if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, limitp)) != 0)
|
|
569 |
if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, limitp, errfunc))
|
|
570 |
!= 0)
|
538 |
571 |
return(err);
|
539 |
572 |
|
540 |
573 |
/*
|
... | ... | |
596 |
629 |
}
|
597 |
630 |
|
598 |
631 |
static int
|
599 |
|
glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp)
|
|
632 |
glob1(Char *pattern, Char *pattern_last, glob_t *pglob,
|
|
633 |
struct glob_lim *limitp, int (*errfunc)(const char *, int))
|
600 |
634 |
{
|
601 |
635 |
Char pathbuf[MAXPATHLEN];
|
602 |
636 |
|
... | ... | |
605 |
639 |
return(0);
|
606 |
640 |
return(glob2(pathbuf, pathbuf+MAXPATHLEN-1,
|
607 |
641 |
pathbuf, pathbuf+MAXPATHLEN-1,
|
608 |
|
pattern, pattern_last, pglob, limitp));
|
|
642 |
pattern, pattern_last, pglob, limitp, errfunc));
|
609 |
643 |
}
|
610 |
644 |
|
611 |
645 |
/*
|
... | ... | |
615 |
649 |
*/
|
616 |
650 |
static int
|
617 |
651 |
glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
|
618 |
|
Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp)
|
|
652 |
Char *pattern, Char *pattern_last, glob_t *pglob,
|
|
653 |
struct glob_lim *limitp, int (*errfunc)(const char *, int))
|
619 |
654 |
{
|
620 |
655 |
struct stat sb;
|
621 |
656 |
Char *p, *q;
|
... | ... | |
676 |
711 |
/* Need expansion, recurse. */
|
677 |
712 |
return(glob3(pathbuf, pathbuf_last, pathend,
|
678 |
713 |
pathend_last, pattern, p, pattern_last,
|
679 |
|
pglob, limitp));
|
|
714 |
pglob, limitp, errfunc));
|
680 |
715 |
}
|
681 |
716 |
/* NOTREACHED */
|
682 |
717 |
}
|
... | ... | |
684 |
719 |
static int
|
685 |
720 |
glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
|
686 |
721 |
Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob,
|
687 |
|
struct glob_lim *limitp)
|
|
722 |
struct glob_lim *limitp, int (*errfunc)(const char *, int))
|
688 |
723 |
{
|
689 |
724 |
struct dirent *dp;
|
690 |
725 |
DIR *dirp;
|
... | ... | |
706 |
741 |
|
707 |
742 |
if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
|
708 |
743 |
/* TODO: don't call for ENOENT or ENOTDIR? */
|
709 |
|
if (pglob->gl_errfunc) {
|
|
744 |
if (errfunc) {
|
710 |
745 |
if (g_Ctoc(pathbuf, buf, sizeof(buf)))
|
711 |
746 |
return(GLOB_ABORTED);
|
712 |
|
if (pglob->gl_errfunc(buf, errno) ||
|
|
747 |
if (errfunc(buf, errno) ||
|
713 |
748 |
pglob->gl_flags & GLOB_ERR)
|
714 |
749 |
return(GLOB_ABORTED);
|
715 |
750 |
}
|
... | ... | |
754 |
789 |
continue;
|
755 |
790 |
}
|
756 |
791 |
err = glob2(pathbuf, pathbuf_last, --dc, pathend_last,
|
757 |
|
restpattern, restpattern_last, pglob, limitp);
|
|
792 |
restpattern, restpattern_last, pglob, limitp,
|
|
793 |
errfunc);
|
758 |
794 |
if (err)
|
759 |
795 |
break;
|
760 |
796 |
}
|
... | ... | |
810 |
846 |
free(pglob->gl_pathv);
|
811 |
847 |
pglob->gl_pathv = NULL;
|
812 |
848 |
}
|
813 |
|
if (pglob->gl_statv) {
|
|
849 |
if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 &&
|
|
850 |
pglob->gl_statv) {
|
814 |
851 |
free(pglob->gl_statv);
|
815 |
852 |
pglob->gl_statv = NULL;
|
816 |
853 |
}
|
... | ... | |
959 |
996 |
free(pglob->gl_pathv);
|
960 |
997 |
pglob->gl_pathv = NULL;
|
961 |
998 |
}
|
962 |
|
if (pglob->gl_statv != NULL) {
|
|
999 |
if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 &&
|
|
1000 |
pglob->gl_statv != NULL) {
|
963 |
1001 |
for (i = 0; i < pglob->gl_pathc; i++) {
|
964 |
1002 |
if (pglob->gl_statv[i] != NULL)
|
965 |
1003 |
free(pglob->gl_statv[i]);
|