diff options
Diffstat (limited to 'openbsd-compat/glob.c')
-rw-r--r-- | openbsd-compat/glob.c | 69 |
1 files changed, 60 insertions, 9 deletions
diff --git a/openbsd-compat/glob.c b/openbsd-compat/glob.c index 0341225cd..742b4b954 100644 --- a/openbsd-compat/glob.c +++ b/openbsd-compat/glob.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: glob.c,v 1.35 2011/01/12 01:53:14 djm Exp $ */ | 1 | /* $OpenBSD: glob.c,v 1.38 2011/09/22 06:27:29 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. |
@@ -66,6 +66,7 @@ | |||
66 | #include <dirent.h> | 66 | #include <dirent.h> |
67 | #include <ctype.h> | 67 | #include <ctype.h> |
68 | #include <errno.h> | 68 | #include <errno.h> |
69 | #include <limits.h> | ||
69 | #include <pwd.h> | 70 | #include <pwd.h> |
70 | #include <stdlib.h> | 71 | #include <stdlib.h> |
71 | #include <string.h> | 72 | #include <string.h> |
@@ -132,13 +133,22 @@ typedef char Char; | |||
132 | #define GLOB_LIMIT_STAT 128 | 133 | #define GLOB_LIMIT_STAT 128 |
133 | #define GLOB_LIMIT_READDIR 16384 | 134 | #define GLOB_LIMIT_READDIR 16384 |
134 | 135 | ||
136 | /* Limit of recursion during matching attempts. */ | ||
137 | #define GLOB_LIMIT_RECUR 64 | ||
138 | |||
135 | struct glob_lim { | 139 | struct glob_lim { |
136 | size_t glim_malloc; | 140 | size_t glim_malloc; |
137 | size_t glim_stat; | 141 | size_t glim_stat; |
138 | size_t glim_readdir; | 142 | size_t glim_readdir; |
139 | }; | 143 | }; |
140 | 144 | ||
145 | struct glob_path_stat { | ||
146 | char *gps_path; | ||
147 | struct stat *gps_stat; | ||
148 | }; | ||
149 | |||
141 | static int compare(const void *, const void *); | 150 | static int compare(const void *, const void *); |
151 | static int compare_gps(const void *, const void *); | ||
142 | static int g_Ctoc(const Char *, char *, u_int); | 152 | static int g_Ctoc(const Char *, char *, u_int); |
143 | static int g_lstat(Char *, struct stat *, glob_t *); | 153 | static int g_lstat(Char *, struct stat *, glob_t *); |
144 | static DIR *g_opendir(Char *, glob_t *); | 154 | static DIR *g_opendir(Char *, glob_t *); |
@@ -158,7 +168,7 @@ static const Char * | |||
158 | static int globexp1(const Char *, glob_t *, struct glob_lim *); | 168 | static int globexp1(const Char *, glob_t *, struct glob_lim *); |
159 | static int globexp2(const Char *, const Char *, glob_t *, | 169 | static int globexp2(const Char *, const Char *, glob_t *, |
160 | struct glob_lim *); | 170 | struct glob_lim *); |
161 | static int match(Char *, Char *, Char *); | 171 | static int match(Char *, Char *, Char *, int); |
162 | #ifdef DEBUG | 172 | #ifdef DEBUG |
163 | static void qprintf(const char *, Char *); | 173 | static void qprintf(const char *, Char *); |
164 | #endif | 174 | #endif |
@@ -172,6 +182,9 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int), | |||
172 | Char *bufnext, *bufend, patbuf[MAXPATHLEN]; | 182 | Char *bufnext, *bufend, patbuf[MAXPATHLEN]; |
173 | struct glob_lim limit = { 0, 0, 0 }; | 183 | struct glob_lim limit = { 0, 0, 0 }; |
174 | 184 | ||
185 | if (strnlen(pattern, PATH_MAX) == PATH_MAX) | ||
186 | return(GLOB_NOMATCH); | ||
187 | |||
175 | patnext = (u_char *) pattern; | 188 | patnext = (u_char *) pattern; |
176 | if (!(flags & GLOB_APPEND)) { | 189 | if (!(flags & GLOB_APPEND)) { |
177 | pglob->gl_pathc = 0; | 190 | pglob->gl_pathc = 0; |
@@ -548,9 +561,32 @@ glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) | |||
548 | else | 561 | else |
549 | return(GLOB_NOMATCH); | 562 | return(GLOB_NOMATCH); |
550 | } | 563 | } |
551 | if (!(pglob->gl_flags & GLOB_NOSORT)) | 564 | if (!(pglob->gl_flags & GLOB_NOSORT)) { |
552 | qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, | 565 | if ((pglob->gl_flags & GLOB_KEEPSTAT)) { |
553 | pglob->gl_pathc - oldpathc, sizeof(char *), compare); | 566 | /* Keep the paths and stat info synced during sort */ |
567 | struct glob_path_stat *path_stat; | ||
568 | int i; | ||
569 | int n = pglob->gl_pathc - oldpathc; | ||
570 | int o = pglob->gl_offs + oldpathc; | ||
571 | |||
572 | if ((path_stat = calloc(n, sizeof(*path_stat))) == NULL) | ||
573 | return GLOB_NOSPACE; | ||
574 | for (i = 0; i < n; i++) { | ||
575 | path_stat[i].gps_path = pglob->gl_pathv[o + i]; | ||
576 | path_stat[i].gps_stat = pglob->gl_statv[o + i]; | ||
577 | } | ||
578 | qsort(path_stat, n, sizeof(*path_stat), compare_gps); | ||
579 | for (i = 0; i < n; i++) { | ||
580 | pglob->gl_pathv[o + i] = path_stat[i].gps_path; | ||
581 | pglob->gl_statv[o + i] = path_stat[i].gps_stat; | ||
582 | } | ||
583 | free(path_stat); | ||
584 | } else { | ||
585 | qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, | ||
586 | pglob->gl_pathc - oldpathc, sizeof(char *), | ||
587 | compare); | ||
588 | } | ||
589 | } | ||
554 | return(0); | 590 | return(0); |
555 | } | 591 | } |
556 | 592 | ||
@@ -561,6 +597,15 @@ compare(const void *p, const void *q) | |||
561 | } | 597 | } |
562 | 598 | ||
563 | static int | 599 | static int |
600 | compare_gps(const void *_p, const void *_q) | ||
601 | { | ||
602 | const struct glob_path_stat *p = (const struct glob_path_stat *)_p; | ||
603 | const struct glob_path_stat *q = (const struct glob_path_stat *)_q; | ||
604 | |||
605 | return(strcmp(p->gps_path, q->gps_path)); | ||
606 | } | ||
607 | |||
608 | static int | ||
564 | glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) | 609 | glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) |
565 | { | 610 | { |
566 | Char pathbuf[MAXPATHLEN]; | 611 | Char pathbuf[MAXPATHLEN]; |
@@ -697,7 +742,8 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | |||
697 | errno = 0; | 742 | errno = 0; |
698 | *pathend++ = SEP; | 743 | *pathend++ = SEP; |
699 | *pathend = EOS; | 744 | *pathend = EOS; |
700 | return(GLOB_NOSPACE); | 745 | err = GLOB_NOSPACE; |
746 | break; | ||
701 | } | 747 | } |
702 | 748 | ||
703 | /* Initial DOT must be matched literally. */ | 749 | /* Initial DOT must be matched literally. */ |
@@ -713,7 +759,7 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | |||
713 | break; | 759 | break; |
714 | } | 760 | } |
715 | 761 | ||
716 | if (!match(pathend, pattern, restpattern)) { | 762 | if (!match(pathend, pattern, restpattern, GLOB_LIMIT_RECUR)) { |
717 | *pathend = EOS; | 763 | *pathend = EOS; |
718 | continue; | 764 | continue; |
719 | } | 765 | } |
@@ -850,19 +896,24 @@ globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp, | |||
850 | * pattern causes a recursion level. | 896 | * pattern causes a recursion level. |
851 | */ | 897 | */ |
852 | static int | 898 | static int |
853 | match(Char *name, Char *pat, Char *patend) | 899 | match(Char *name, Char *pat, Char *patend, int recur) |
854 | { | 900 | { |
855 | int ok, negate_range; | 901 | int ok, negate_range; |
856 | Char c, k; | 902 | Char c, k; |
857 | 903 | ||
904 | if (recur-- == 0) | ||
905 | return(GLOB_NOSPACE); | ||
906 | |||
858 | while (pat < patend) { | 907 | while (pat < patend) { |
859 | c = *pat++; | 908 | c = *pat++; |
860 | switch (c & M_MASK) { | 909 | switch (c & M_MASK) { |
861 | case M_ALL: | 910 | case M_ALL: |
911 | while (pat < patend && (*pat & M_MASK) == M_ALL) | ||
912 | pat++; /* eat consecutive '*' */ | ||
862 | if (pat == patend) | 913 | if (pat == patend) |
863 | return(1); | 914 | return(1); |
864 | do { | 915 | do { |
865 | if (match(name, pat, patend)) | 916 | if (match(name, pat, patend, recur)) |
866 | return(1); | 917 | return(1); |
867 | } while (*name++ != EOS); | 918 | } while (*name++ != EOS); |
868 | return(0); | 919 | return(0); |