]>
git.proxmox.com Git - mirror_edk2.git/blob - StdLib/PosixLib/Glob/glob.c
2 * glob(3) -- a superset of the one defined in POSIX 1003.2.
4 * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
6 * Optional extra services, controlled by flags not defined by POSIX:
9 * Set in gl_flags if pattern contained a globbing character.
11 * Same as GLOB_NOCHECK, but it will only append pattern if it did
12 * not contain any magic characters. [Used in csh style globbing]
14 * Use alternately specified directory access functions.
16 * expand ~user/foo to the /home/dir/of/user/foo
18 * expand {1,2}{a,b} to 1a 1b 2a 2b
20 * allow metacharacters to match leading dots in filenames.
22 * . and .. are hidden from wildcards, even if GLOB_PERIOD is set.
24 * Number of matches in the current invocation of glob.
26 Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
27 This program and the accompanying materials are licensed and made available under
28 the terms and conditions of the BSD License that accompanies this distribution.
29 The full text of the license may be found at
30 http://opensource.org/licenses/bsd-license.
32 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
33 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
35 * Copyright (c) 1989, 1993
36 * The Regents of the University of California. All rights reserved.
38 * This code is derived from software contributed to Berkeley by
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 glob.c 8.3 (Berkeley) 10/13/93
66 NetBSD: glob.c,v 1.23.4.1 2010/07/19 18:14:08 riz Exp
69 #pragma warning ( disable : 4244 )
70 #pragma warning ( disable : 4018 )
73 #include <LibConfig.h>
75 #include <sys/cdefs.h>
77 #include <sys/param.h>
91 #include <sys/fcntl.h>
93 #ifdef HAVE_NBTOOL_CONFIG_H
97 #define GLOB_LIMIT_MALLOC 65536
98 #define GLOB_LIMIT_STAT 128
99 #define GLOB_LIMIT_READDIR 16384
101 #define GLOB_INDEX_MALLOC 0
102 #define GLOB_INDEX_STAT 1
103 #define GLOB_INDEX_READDIR 2
106 * XXX: For NetBSD 1.4.x compatibility. (kill me l8r)
109 #define _DIAGASSERT(a)
124 #define UNDERSCORE '_'
130 #ifndef USE_8BIT_CHARS
132 #define M_QUOTE 0x8000
133 #define M_PROTECT 0x4000
134 #define M_MASK 0xffff
135 #define M_ASCII 0x00ff
137 typedef u_short Char
;
141 #define M_QUOTE (Char)0x80
142 #define M_PROTECT (Char)0x40
143 #define M_MASK (Char)0xff
144 #define M_ASCII (Char)0x7f
151 #define CHAR(c) ((Char)((c)&M_ASCII))
152 #define META(c) ((Char)((c)|M_QUOTE))
153 #define M_ALL META('*')
154 #define M_END META(']')
155 #define M_NOT META('!')
156 #define M_ONE META('?')
157 #define M_RNG META('-')
158 #define M_SET META('[')
159 #define ismeta(c) (((c)&M_QUOTE) != 0)
161 static int compare(const void *, const void *);
162 static int g_Ctoc(const Char
*, char *, size_t);
163 static int g_lstat(Char
*, __gl_stat_t
*, glob_t
*);
164 static DIR *g_opendir(Char
*, glob_t
*);
165 static Char
*g_strchr(const Char
*, int);
166 static int g_stat(Char
*, __gl_stat_t
*, glob_t
*);
167 static int glob0(const Char
*, glob_t
*, size_t *);
168 static int glob1(Char
*, glob_t
*, size_t *);
169 static int glob2(Char
*, Char
*, Char
*, Char
*, glob_t
*, size_t *);
170 static int glob3(Char
*, Char
*, Char
*, Char
*, Char
*, glob_t
*, size_t *);
171 static int globextend(const Char
*, glob_t
*, size_t *);
172 static const Char
*globtilde(const Char
*, Char
*, size_t, glob_t
*);
173 static int globexp1(const Char
*, glob_t
*, size_t *);
174 static int globexp2(const Char
*, const Char
*, glob_t
*, int *, size_t *);
175 static int match(Char
*, Char
*, Char
*);
177 static void qprintf(const char *, Char
*);
184 int (*errfunc
)(const char *, int),
188 const u_char
*patnext
;
190 Char
*bufnext
, *bufend
, patbuf
[MAXPATHLEN
+1];
191 /* 0 = malloc(), 1 = stat(), 2 = readdir() */
192 size_t limit
[] = { 0, 0, 0 };
194 _DIAGASSERT(pattern
!= NULL
);
196 patnext
= (const u_char
*) pattern
;
197 if (!(flags
& GLOB_APPEND
)) {
199 pglob
->gl_pathv
= NULL
;
200 if (!(flags
& GLOB_DOOFFS
))
203 pglob
->gl_flags
= flags
& ~GLOB_MAGCHAR
;
204 pglob
->gl_errfunc
= errfunc
;
205 pglob
->gl_matchc
= 0;
208 bufend
= bufnext
+ MAXPATHLEN
;
209 if (flags
& GLOB_NOESCAPE
) {
210 while (bufnext
< bufend
&& (c
= *patnext
++) != EOS
)
213 /* Protect the quoted characters. */
214 while (bufnext
< bufend
&& (c
= *patnext
++) != EOS
)
216 if ((c
= *patnext
++) == EOS
) {
220 *bufnext
++ = c
| M_PROTECT
;
227 if (flags
& GLOB_BRACE
)
228 return globexp1(patbuf
, pglob
, limit
);
230 return glob0(patbuf
, pglob
, limit
);
234 * Expand recursively a glob {} pattern. When there is no more expansion
235 * invoke the standard globbing routine to glob the rest of the magic
239 globexp1(const Char
*pattern
, glob_t
*pglob
, size_t *limit
)
241 const Char
* ptr
= pattern
;
244 _DIAGASSERT(pattern
!= NULL
);
245 _DIAGASSERT(pglob
!= NULL
);
247 /* Protect a single {}, for find(1), like csh */
248 if (pattern
[0] == LBRACE
&& pattern
[1] == RBRACE
&& pattern
[2] == EOS
)
249 return glob0(pattern
, pglob
, limit
);
251 while ((ptr
= (const Char
*) g_strchr(ptr
, LBRACE
)) != NULL
)
252 if (!globexp2(ptr
, pattern
, pglob
, &rv
, limit
))
255 return glob0(pattern
, pglob
, limit
);
260 * Recursive brace globbing helper. Tries to expand a single brace.
261 * If it succeeds then it invokes globexp1 with the new pattern.
262 * If it fails then it tries to glob the rest of the pattern and returns.
265 globexp2(const Char
*ptr
, const Char
*pattern
, glob_t
*pglob
, int *rv
,
270 const Char
*pe
, *pm
, *pl
;
271 Char patbuf
[MAXPATHLEN
+ 1];
273 _DIAGASSERT(ptr
!= NULL
);
274 _DIAGASSERT(pattern
!= NULL
);
275 _DIAGASSERT(pglob
!= NULL
);
276 _DIAGASSERT(rv
!= NULL
);
278 /* copy part up to the brace */
279 for (lm
= patbuf
, pm
= pattern
; pm
!= ptr
; *lm
++ = *pm
++)
283 /* Find the balanced brace */
284 for (i
= 0, pe
= ++ptr
; *pe
; pe
++)
285 if (*pe
== LBRACKET
) {
286 /* Ignore everything between [] */
287 for (pm
= pe
++; *pe
!= RBRACKET
&& *pe
!= EOS
; pe
++)
291 * We could not find a matching RBRACKET.
292 * Ignore and just look for RBRACE
297 else if (*pe
== LBRACE
)
299 else if (*pe
== RBRACE
) {
305 /* Non matching braces; just glob the pattern */
306 if (i
!= 0 || *pe
== EOS
) {
308 * we use `pattern', not `patbuf' here so that that
309 * unbalanced braces are passed to the match
311 *rv
= glob0(pattern
, pglob
, limit
);
315 for (i
= 0, pl
= pm
= ptr
; pm
<= pe
; pm
++) {
318 /* Ignore everything between [] */
319 for (pl
= pm
++; *pm
!= RBRACKET
&& *pm
!= EOS
; pm
++)
323 * We could not find a matching RBRACKET.
324 * Ignore and just look for RBRACE
341 if (i
&& *pm
== COMMA
)
344 /* Append the current string */
345 for (lm
= ls
; (pl
< pm
); *lm
++ = *pl
++)
348 * Append the rest of the pattern after the
351 for (pl
= pe
+ 1; (*lm
++ = *pl
++) != EOS
;)
354 /* Expand the current pattern */
356 qprintf("globexp2:", patbuf
);
358 *rv
= globexp1(patbuf
, pglob
, limit
);
360 /* move after the comma, to the next string */
376 * expand tilde from the passwd file.
379 globtilde(const Char
*pattern
, Char
*patbuf
, size_t patsize
, glob_t
*pglob
)
385 Char
*pend
= &patbuf
[patsize
/ sizeof(Char
)];
389 _DIAGASSERT(pattern
!= NULL
);
390 _DIAGASSERT(patbuf
!= NULL
);
391 _DIAGASSERT(pglob
!= NULL
);
393 if (*pattern
!= TILDE
|| !(pglob
->gl_flags
& GLOB_TILDE
))
396 /* Copy up to the end of the string or / */
397 for (p
= pattern
+ 1, d
= (char *)(void *)patbuf
;
398 d
< (char *)(void *)pend
&& *p
&& *p
!= SLASH
;
402 if (d
== (char *)(void *)pend
)
406 d
= (char *)(void *)patbuf
;
410 * handle a plain ~ or ~/ by expanding $HOME
411 * first and then trying the password file
413 if ((h
= getenv("HOME")) == NULL
) {
424 /* Copy the home directory */
425 for (b
= patbuf
; b
< pend
&& *h
; *b
++ = *h
++)
431 /* Append the rest of the pattern */
432 while (b
< pend
&& (*b
++ = *p
++) != EOS
)
443 * The main glob() routine: compiles the pattern (optionally processing
444 * quotes), calls glob1() to do the real pattern matching, and finally
445 * sorts the list (unless unsorted operation is requested). Returns 0
446 * if things went well, nonzero if errors occurred. It is not an error
447 * to find no matches.
450 glob0(const Char
*pattern
, glob_t
*pglob
, size_t *limit
)
452 const Char
*qpatnext
;
454 __gl_size_t oldpathc
;
455 Char
*bufnext
, patbuf
[MAXPATHLEN
+1];
457 _DIAGASSERT(pattern
!= NULL
);
458 _DIAGASSERT(pglob
!= NULL
);
460 if ((qpatnext
= globtilde(pattern
, patbuf
, sizeof(patbuf
),
463 oldpathc
= pglob
->gl_pathc
;
466 /* We don't need to check for buffer overflow any more. */
467 while ((c
= *qpatnext
++) != EOS
) {
473 if (*qpatnext
== EOS
||
474 g_strchr(qpatnext
+1, RBRACKET
) == NULL
) {
475 *bufnext
++ = LBRACKET
;
485 *bufnext
++ = CHAR(c
);
486 if (*qpatnext
== RANGE
&&
487 (c
= qpatnext
[1]) != RBRACKET
) {
489 *bufnext
++ = CHAR(c
);
492 } while ((c
= *qpatnext
++) != RBRACKET
);
493 pglob
->gl_flags
|= GLOB_MAGCHAR
;
497 pglob
->gl_flags
|= GLOB_MAGCHAR
;
501 pglob
->gl_flags
|= GLOB_MAGCHAR
;
502 /* collapse adjacent stars to one,
503 * to avoid exponential behavior
505 if (bufnext
== patbuf
|| bufnext
[-1] != M_ALL
)
509 *bufnext
++ = CHAR(c
);
515 qprintf("glob0:", patbuf
);
518 if ((error
= glob1(patbuf
, pglob
, limit
)) != 0)
521 if (pglob
->gl_pathc
== oldpathc
) {
523 * If there was no match we are going to append the pattern
524 * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was
525 * specified and the pattern did not contain any magic
526 * characters GLOB_NOMAGIC is there just for compatibility
529 if ((pglob
->gl_flags
& GLOB_NOCHECK
) ||
530 ((pglob
->gl_flags
& (GLOB_NOMAGIC
|GLOB_MAGCHAR
))
532 return globextend(pattern
, pglob
, limit
);
536 } else if (!(pglob
->gl_flags
& GLOB_NOSORT
)) {
537 qsort(pglob
->gl_pathv
+ pglob
->gl_offs
+ oldpathc
,
538 (size_t)pglob
->gl_pathc
- oldpathc
, sizeof(char *),
546 compare(const void *p
, const void *q
)
549 _DIAGASSERT(p
!= NULL
);
550 _DIAGASSERT(q
!= NULL
);
552 return strcoll(*(const char * const *)p
, *(const char * const *)q
);
556 glob1(Char
*pattern
, glob_t
*pglob
, size_t *limit
)
558 Char pathbuf
[MAXPATHLEN
+1];
560 _DIAGASSERT(pattern
!= NULL
);
561 _DIAGASSERT(pglob
!= NULL
);
563 /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
567 * we save one character so that we can use ptr >= limit,
568 * in the general case when we are appending non nul chars only.
570 return glob2(pathbuf
, pathbuf
,
571 pathbuf
+ (sizeof(pathbuf
) / sizeof(*pathbuf
)) - 1, pattern
,
576 * The functions glob2 and glob3 are mutually recursive; there is one level
577 * of recursion for each segment in the pattern that contains one or more
581 glob2(Char
*pathbuf
, Char
*pathend
, Char
*pathlim
, Char
*pattern
, glob_t
*pglob
,
590 _DIAGASSERT(pathbuf
!= NULL
);
591 _DIAGASSERT(pathend
!= NULL
);
592 _DIAGASSERT(pattern
!= NULL
);
593 _DIAGASSERT(pglob
!= NULL
);
596 * Loop over pattern segments until end of pattern or until
597 * segment with meta character found.
599 for (anymeta
= 0;;) {
600 if (*pattern
== EOS
) { /* End of pattern? */
602 if (g_lstat(pathbuf
, &sb
, pglob
))
605 if ((pglob
->gl_flags
& GLOB_LIMIT
) &&
606 limit
[GLOB_INDEX_STAT
]++ >= GLOB_LIMIT_STAT
) {
612 if (((pglob
->gl_flags
& GLOB_MARK
) &&
613 pathend
[-1] != SEP
) && (S_ISDIR(sb
.st_mode
) ||
614 // (S_ISLNK(sb.st_mode) &&
616 (g_stat(pathbuf
, &sb
, pglob
) == 0) &&
617 S_ISDIR(sb
.st_mode
)))) {
618 if (pathend
>= pathlim
)
624 return globextend(pathbuf
, pglob
, limit
);
627 /* Find end of next segment, copy tentatively to pathend. */
630 while (*p
!= EOS
&& *p
!= SEP
) {
639 * No expansion, or path ends in slash-dot shash-dot-dot,
642 if (pglob
->gl_flags
& GLOB_PERIOD
) {
643 for (pend
= pathend
; pend
> pathbuf
&& pend
[-1] == '/';
646 diff
= pend
- pathbuf
;
654 ((pglob
->gl_flags
& GLOB_PERIOD
) &&
655 (diff
>= 1 && pend
[-1] == DOT
) &&
656 (diff
>= 2 && (pend
[-2] == SLASH
|| pend
[-2] == DOT
)) &&
657 (diff
< 3 || pend
[-3] == SLASH
))) {
660 while (*pattern
== SEP
) {
661 if (pathend
>= pathlim
)
663 *pathend
++ = *pattern
++;
665 } else /* Need expansion, recurse. */
666 return glob3(pathbuf
, pathend
, pathlim
, pattern
, p
,
673 glob3(Char
*pathbuf
, Char
*pathend
, Char
*pathlim
, Char
*pattern
,
674 Char
*restpattern
, glob_t
*pglob
, size_t *limit
)
679 char buf
[MAXPATHLEN
];
682 * The readdirfunc declaration can't be prototyped, because it is
683 * assigned, below, to two functions which are prototyped in glob.h
684 * and dirent.h as taking pointers to differently typed opaque
687 struct dirent
*(*readdirfunc
)(void *);
689 _DIAGASSERT(pathbuf
!= NULL
);
690 _DIAGASSERT(pathend
!= NULL
);
691 _DIAGASSERT(pattern
!= NULL
);
692 _DIAGASSERT(restpattern
!= NULL
);
693 _DIAGASSERT(pglob
!= NULL
);
698 if ((dirp
= g_opendir(pathbuf
, pglob
)) == NULL
) {
699 if (pglob
->gl_errfunc
) {
700 if (g_Ctoc(pathbuf
, buf
, sizeof(buf
)))
702 if (pglob
->gl_errfunc(buf
, errno
) ||
703 pglob
->gl_flags
& GLOB_ERR
)
707 * Posix/XOpen: glob should return when it encounters a
708 * directory that it cannot open or read
709 * XXX: Should we ignore ENOTDIR and ENOENT though?
710 * I think that Posix had in mind EPERM...
712 if (pglob
->gl_flags
& GLOB_ERR
)
720 /* Search directory for matching names. */
721 if (pglob
->gl_flags
& GLOB_ALTDIRFUNC
)
722 readdirfunc
= pglob
->gl_readdir
;
724 readdirfunc
= (struct dirent
*(*)(void *)) readdir
;
725 while ((dp
= (*readdirfunc
)(dirp
)) != NULL
) {
729 if ((pglob
->gl_flags
& GLOB_LIMIT
) &&
730 limit
[GLOB_INDEX_READDIR
]++ >= GLOB_LIMIT_READDIR
) {
738 * Initial DOT must be matched literally, unless we have
741 if ((pglob
->gl_flags
& GLOB_PERIOD
) == 0)
742 if (dp
->FileName
[0] == DOT
&& *pattern
!= DOT
)
745 * If GLOB_NO_DOTDIRS is set, . and .. vanish.
747 if ((pglob
->gl_flags
& GLOB_NO_DOTDIRS
) &&
748 (dp
->FileName
[0] == DOT
) &&
749 ((dp
->FileName
[1] == EOS
) ||
750 ((dp
->FileName
[1] == DOT
) && (dp
->FileName
[2] == EOS
))))
753 * The resulting string contains EOS, so we can
754 * use the pathlim character, if it is the nul
756 for (sc
= (u_char
*) dp
->FileName
, dc
= pathend
;
757 dc
<= pathlim
&& (*dc
++ = *sc
++) != EOS
;)
761 * Have we filled the buffer without seeing EOS?
763 if (dc
> pathlim
&& *pathlim
!= EOS
) {
765 * Abort when requested by caller, otherwise
766 * reset pathend back to last SEP and continue
767 * with next dir entry.
769 if (pglob
->gl_flags
& GLOB_ERR
) {
770 error
= GLOB_ABORTED
;
779 if (!match(pathend
, pattern
, restpattern
)) {
783 error
= glob2(pathbuf
, --dc
, pathlim
, restpattern
, pglob
,
789 if (pglob
->gl_flags
& GLOB_ALTDIRFUNC
)
790 (*pglob
->gl_closedir
)(dirp
);
795 * Again Posix X/Open issue with regards to error handling.
797 if ((error
|| errno
) && (pglob
->gl_flags
& GLOB_ERR
))
805 * Extend the gl_pathv member of a glob_t structure to accommodate a new item,
806 * add the new item, and update gl_pathc.
808 * This assumes the BSD realloc, which only copies the block when its size
809 * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
812 * Return 0 if new item added, error code if memory couldn't be allocated.
814 * Invariant of the glob_t structure:
815 * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
816 * gl_pathv points to (gl_offs + gl_pathc + 1) items.
819 globextend(const Char
*path
, glob_t
*pglob
, size_t *limit
)
822 size_t i
, newsize
, len
;
826 _DIAGASSERT(path
!= NULL
);
827 _DIAGASSERT(pglob
!= NULL
);
829 newsize
= sizeof(*pathv
) * (2 + pglob
->gl_pathc
+ pglob
->gl_offs
);
830 pathv
= pglob
->gl_pathv
? realloc(pglob
->gl_pathv
, newsize
) :
835 if (pglob
->gl_pathv
== NULL
&& pglob
->gl_offs
> 0) {
836 /* first time around -- clear initial gl_offs items */
837 pathv
+= pglob
->gl_offs
;
838 for (i
= pglob
->gl_offs
+ 1; --i
> 0; )
841 pglob
->gl_pathv
= pathv
;
843 for (p
= path
; *p
++;)
845 len
= (size_t)(p
- path
);
846 limit
[GLOB_INDEX_MALLOC
] += len
;
847 if ((copy
= malloc(len
)) != NULL
) {
848 if (g_Ctoc(path
, copy
, len
)) {
852 pathv
[pglob
->gl_offs
+ pglob
->gl_pathc
++] = copy
;
854 pathv
[pglob
->gl_offs
+ pglob
->gl_pathc
] = NULL
;
856 if ((pglob
->gl_flags
& GLOB_LIMIT
) &&
857 (newsize
+ limit
[GLOB_INDEX_MALLOC
]) >= GLOB_LIMIT_MALLOC
) {
862 return copy
== NULL
? GLOB_NOSPACE
: 0;
867 * pattern matching function for filenames. Each occurrence of the *
868 * pattern causes a recursion level.
871 match(Char
*name
, Char
*pat
, Char
*patend
)
873 int ok
, negate_range
;
876 _DIAGASSERT(name
!= NULL
);
877 _DIAGASSERT(pat
!= NULL
);
878 _DIAGASSERT(patend
!= NULL
);
880 while (pat
< patend
) {
882 switch (c
& M_MASK
) {
887 if (match(name
, pat
, patend
))
889 while (*name
++ != EOS
);
897 if ((k
= *name
++) == EOS
)
899 if ((negate_range
= ((*pat
& M_MASK
) == M_NOT
)) != EOS
)
901 while (((c
= *pat
++) & M_MASK
) != M_END
)
902 if ((*pat
& M_MASK
) == M_RNG
) {
903 if (c
<= k
&& k
<= pat
[1])
908 if (ok
== negate_range
)
920 /* Free allocated data belonging to a glob_t structure. */
922 globfree(glob_t
*pglob
)
927 _DIAGASSERT(pglob
!= NULL
);
929 if (pglob
->gl_pathv
!= NULL
) {
930 pp
= pglob
->gl_pathv
+ pglob
->gl_offs
;
931 for (i
= pglob
->gl_pathc
; i
--; ++pp
)
934 free(pglob
->gl_pathv
);
935 pglob
->gl_pathv
= NULL
;
941 g_opendir(Char
*str
, glob_t
*pglob
)
943 char buf
[MAXPATHLEN
];
945 _DIAGASSERT(str
!= NULL
);
946 _DIAGASSERT(pglob
!= NULL
);
949 (void)strlcpy(buf
, ".", sizeof(buf
));
951 if (g_Ctoc(str
, buf
, sizeof(buf
)))
955 if (pglob
->gl_flags
& GLOB_ALTDIRFUNC
)
956 return (*pglob
->gl_opendir
)(buf
);
962 g_lstat(Char
*fn
, __gl_stat_t
*sb
, glob_t
*pglob
)
964 char buf
[MAXPATHLEN
];
966 _DIAGASSERT(fn
!= NULL
);
967 _DIAGASSERT(sb
!= NULL
);
968 _DIAGASSERT(pglob
!= NULL
);
970 if (g_Ctoc(fn
, buf
, sizeof(buf
)))
972 if (pglob
->gl_flags
& GLOB_ALTDIRFUNC
)
973 return (*pglob
->gl_lstat
)(buf
, sb
);
974 return lstat(buf
, sb
);
978 g_stat(Char
*fn
, __gl_stat_t
*sb
, glob_t
*pglob
)
980 char buf
[MAXPATHLEN
];
982 _DIAGASSERT(fn
!= NULL
);
983 _DIAGASSERT(sb
!= NULL
);
984 _DIAGASSERT(pglob
!= NULL
);
986 if (g_Ctoc(fn
, buf
, sizeof(buf
)))
988 if (pglob
->gl_flags
& GLOB_ALTDIRFUNC
)
989 return (*pglob
->gl_stat
)(buf
, sb
);
990 return stat(buf
, sb
);
994 g_strchr(const Char
*str
, int ch
)
997 _DIAGASSERT(str
!= NULL
);
1001 return __UNCONST(str
);
1007 g_Ctoc(const Char
*str
, char *buf
, size_t len
)
1011 _DIAGASSERT(str
!= NULL
);
1012 _DIAGASSERT(buf
!= NULL
);
1017 for (dc
= buf
; len
&& (*dc
++ = *str
++) != EOS
; len
--)
1025 qprintf(const char *str
, Char
*s
)
1029 _DIAGASSERT(str
!= NULL
);
1030 _DIAGASSERT(s
!= NULL
);
1032 (void)printf("%s:\n", str
);
1033 for (p
= s
; *p
; p
++)
1034 (void)printf("%c", CHAR(*p
));
1036 for (p
= s
; *p
; p
++)
1037 (void)printf("%c", *p
& M_PROTECT
? '"' : ' ');
1039 for (p
= s
; *p
; p
++)
1040 (void)printf("%c", ismeta(*p
) ? '_' : ' ');