]>
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>
94 #ifdef HAVE_NBTOOL_CONFIG_H
98 #define GLOB_LIMIT_MALLOC 65536
99 #define GLOB_LIMIT_STAT 128
100 #define GLOB_LIMIT_READDIR 16384
102 #define GLOB_INDEX_MALLOC 0
103 #define GLOB_INDEX_STAT 1
104 #define GLOB_INDEX_READDIR 2
107 * XXX: For NetBSD 1.4.x compatibility. (kill me l8r)
110 #define _DIAGASSERT(a)
125 #define UNDERSCORE '_'
131 #ifndef USE_8BIT_CHARS
133 #define M_QUOTE 0x8000
134 #define M_PROTECT 0x4000
135 #define M_MASK 0xffff
136 #define M_ASCII 0x00ff
138 typedef u_short Char
;
142 #define M_QUOTE (Char)0x80
143 #define M_PROTECT (Char)0x40
144 #define M_MASK (Char)0xff
145 #define M_ASCII (Char)0x7f
152 #define CHAR(c) ((Char)((c)&M_ASCII))
153 #define META(c) ((Char)((c)|M_QUOTE))
154 #define M_ALL META('*')
155 #define M_END META(']')
156 #define M_NOT META('!')
157 #define M_ONE META('?')
158 #define M_RNG META('-')
159 #define M_SET META('[')
160 #define ismeta(c) (((c)&M_QUOTE) != 0)
162 static int compare(const void *, const void *);
163 static int g_Ctoc(const Char
*, char *, size_t);
164 static int g_lstat(Char
*, __gl_stat_t
*, glob_t
*);
165 static DIR *g_opendir(Char
*, glob_t
*);
166 static Char
*g_strchr(const Char
*, int);
167 static int g_stat(Char
*, __gl_stat_t
*, glob_t
*);
168 static int glob0(const Char
*, glob_t
*, size_t *);
169 static int glob1(Char
*, glob_t
*, size_t *);
170 static int glob2(Char
*, Char
*, Char
*, Char
*, glob_t
*, size_t *);
171 static int glob3(Char
*, Char
*, Char
*, Char
*, Char
*, glob_t
*, size_t *);
172 static int globextend(const Char
*, glob_t
*, size_t *);
173 static const Char
*globtilde(const Char
*, Char
*, size_t, glob_t
*);
174 static int globexp1(const Char
*, glob_t
*, size_t *);
175 static int globexp2(const Char
*, const Char
*, glob_t
*, int *, size_t *);
176 static int match(Char
*, Char
*, Char
*);
178 static void qprintf(const char *, Char
*);
185 int (*errfunc
)(const char *, int),
189 const u_char
*patnext
;
191 Char
*bufnext
, *bufend
, patbuf
[MAXPATHLEN
+1];
192 /* 0 = malloc(), 1 = stat(), 2 = readdir() */
193 size_t limit
[] = { 0, 0, 0 };
195 _DIAGASSERT(pattern
!= NULL
);
197 patnext
= (const u_char
*) pattern
;
198 if (!(flags
& GLOB_APPEND
)) {
200 pglob
->gl_pathv
= NULL
;
201 if (!(flags
& GLOB_DOOFFS
))
204 pglob
->gl_flags
= flags
& ~GLOB_MAGCHAR
;
205 pglob
->gl_errfunc
= errfunc
;
206 pglob
->gl_matchc
= 0;
209 bufend
= bufnext
+ MAXPATHLEN
;
210 if (flags
& GLOB_NOESCAPE
) {
211 while (bufnext
< bufend
&& (c
= *patnext
++) != EOS
)
214 /* Protect the quoted characters. */
215 while (bufnext
< bufend
&& (c
= *patnext
++) != EOS
)
217 if ((c
= *patnext
++) == EOS
) {
221 *bufnext
++ = c
| M_PROTECT
;
228 if (flags
& GLOB_BRACE
)
229 return globexp1(patbuf
, pglob
, limit
);
231 return glob0(patbuf
, pglob
, limit
);
235 * Expand recursively a glob {} pattern. When there is no more expansion
236 * invoke the standard globbing routine to glob the rest of the magic
240 globexp1(const Char
*pattern
, glob_t
*pglob
, size_t *limit
)
242 const Char
* ptr
= pattern
;
245 _DIAGASSERT(pattern
!= NULL
);
246 _DIAGASSERT(pglob
!= NULL
);
248 /* Protect a single {}, for find(1), like csh */
249 if (pattern
[0] == LBRACE
&& pattern
[1] == RBRACE
&& pattern
[2] == EOS
)
250 return glob0(pattern
, pglob
, limit
);
252 while ((ptr
= (const Char
*) g_strchr(ptr
, LBRACE
)) != NULL
)
253 if (!globexp2(ptr
, pattern
, pglob
, &rv
, limit
))
256 return glob0(pattern
, pglob
, limit
);
261 * Recursive brace globbing helper. Tries to expand a single brace.
262 * If it succeeds then it invokes globexp1 with the new pattern.
263 * If it fails then it tries to glob the rest of the pattern and returns.
266 globexp2(const Char
*ptr
, const Char
*pattern
, glob_t
*pglob
, int *rv
,
271 const Char
*pe
, *pm
, *pl
;
272 Char patbuf
[MAXPATHLEN
+ 1];
274 _DIAGASSERT(ptr
!= NULL
);
275 _DIAGASSERT(pattern
!= NULL
);
276 _DIAGASSERT(pglob
!= NULL
);
277 _DIAGASSERT(rv
!= NULL
);
279 /* copy part up to the brace */
280 for (lm
= patbuf
, pm
= pattern
; pm
!= ptr
; *lm
++ = *pm
++)
284 /* Find the balanced brace */
285 for (i
= 0, pe
= ++ptr
; *pe
; pe
++)
286 if (*pe
== LBRACKET
) {
287 /* Ignore everything between [] */
288 for (pm
= pe
++; *pe
!= RBRACKET
&& *pe
!= EOS
; pe
++)
292 * We could not find a matching RBRACKET.
293 * Ignore and just look for RBRACE
298 else if (*pe
== LBRACE
)
300 else if (*pe
== RBRACE
) {
306 /* Non matching braces; just glob the pattern */
307 if (i
!= 0 || *pe
== EOS
) {
309 * we use `pattern', not `patbuf' here so that that
310 * unbalanced braces are passed to the match
312 *rv
= glob0(pattern
, pglob
, limit
);
316 for (i
= 0, pl
= pm
= ptr
; pm
<= pe
; pm
++) {
319 /* Ignore everything between [] */
320 for (pl
= pm
++; *pm
!= RBRACKET
&& *pm
!= EOS
; pm
++)
324 * We could not find a matching RBRACKET.
325 * Ignore and just look for RBRACE
342 if (i
&& *pm
== COMMA
)
345 /* Append the current string */
346 for (lm
= ls
; (pl
< pm
); *lm
++ = *pl
++)
349 * Append the rest of the pattern after the
352 for (pl
= pe
+ 1; (*lm
++ = *pl
++) != EOS
;)
355 /* Expand the current pattern */
357 qprintf("globexp2:", patbuf
);
359 *rv
= globexp1(patbuf
, pglob
, limit
);
361 /* move after the comma, to the next string */
377 * expand tilde from the passwd file.
380 globtilde(const Char
*pattern
, Char
*patbuf
, size_t patsize
, glob_t
*pglob
)
386 Char
*pend
= &patbuf
[patsize
/ sizeof(Char
)];
390 _DIAGASSERT(pattern
!= NULL
);
391 _DIAGASSERT(patbuf
!= NULL
);
392 _DIAGASSERT(pglob
!= NULL
);
394 if (*pattern
!= TILDE
|| !(pglob
->gl_flags
& GLOB_TILDE
))
397 /* Copy up to the end of the string or / */
398 for (p
= pattern
+ 1, d
= (char *)(void *)patbuf
;
399 d
< (char *)(void *)pend
&& *p
&& *p
!= SLASH
;
403 if (d
== (char *)(void *)pend
)
407 d
= (char *)(void *)patbuf
;
411 * handle a plain ~ or ~/ by expanding $HOME
412 * first and then trying the password file
414 if ((h
= getenv("HOME")) == NULL
) {
425 /* Copy the home directory */
426 for (b
= patbuf
; b
< pend
&& *h
; *b
++ = *h
++)
432 /* Append the rest of the pattern */
433 while (b
< pend
&& (*b
++ = *p
++) != EOS
)
444 * The main glob() routine: compiles the pattern (optionally processing
445 * quotes), calls glob1() to do the real pattern matching, and finally
446 * sorts the list (unless unsorted operation is requested). Returns 0
447 * if things went well, nonzero if errors occurred. It is not an error
448 * to find no matches.
451 glob0(const Char
*pattern
, glob_t
*pglob
, size_t *limit
)
453 const Char
*qpatnext
;
455 __gl_size_t oldpathc
;
456 Char
*bufnext
, patbuf
[MAXPATHLEN
+1];
458 _DIAGASSERT(pattern
!= NULL
);
459 _DIAGASSERT(pglob
!= NULL
);
461 if ((qpatnext
= globtilde(pattern
, patbuf
, sizeof(patbuf
),
464 oldpathc
= pglob
->gl_pathc
;
467 /* We don't need to check for buffer overflow any more. */
468 while ((c
= *qpatnext
++) != EOS
) {
474 if (*qpatnext
== EOS
||
475 g_strchr(qpatnext
+1, RBRACKET
) == NULL
) {
476 *bufnext
++ = LBRACKET
;
486 *bufnext
++ = CHAR(c
);
487 if (*qpatnext
== RANGE
&&
488 (c
= qpatnext
[1]) != RBRACKET
) {
490 *bufnext
++ = CHAR(c
);
493 } while ((c
= *qpatnext
++) != RBRACKET
);
494 pglob
->gl_flags
|= GLOB_MAGCHAR
;
498 pglob
->gl_flags
|= GLOB_MAGCHAR
;
502 pglob
->gl_flags
|= GLOB_MAGCHAR
;
503 /* collapse adjacent stars to one,
504 * to avoid exponential behavior
506 if (bufnext
== patbuf
|| bufnext
[-1] != M_ALL
)
510 *bufnext
++ = CHAR(c
);
516 qprintf("glob0:", patbuf
);
519 if ((error
= glob1(patbuf
, pglob
, limit
)) != 0)
522 if (pglob
->gl_pathc
== oldpathc
) {
524 * If there was no match we are going to append the pattern
525 * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was
526 * specified and the pattern did not contain any magic
527 * characters GLOB_NOMAGIC is there just for compatibility
530 if ((pglob
->gl_flags
& GLOB_NOCHECK
) ||
531 ((pglob
->gl_flags
& (GLOB_NOMAGIC
|GLOB_MAGCHAR
))
533 return globextend(pattern
, pglob
, limit
);
537 } else if (!(pglob
->gl_flags
& GLOB_NOSORT
)) {
538 qsort(pglob
->gl_pathv
+ pglob
->gl_offs
+ oldpathc
,
539 (size_t)pglob
->gl_pathc
- oldpathc
, sizeof(char *),
547 compare(const void *p
, const void *q
)
550 _DIAGASSERT(p
!= NULL
);
551 _DIAGASSERT(q
!= NULL
);
553 return strcoll(*(const char * const *)p
, *(const char * const *)q
);
557 glob1(Char
*pattern
, glob_t
*pglob
, size_t *limit
)
559 Char pathbuf
[MAXPATHLEN
+1];
561 _DIAGASSERT(pattern
!= NULL
);
562 _DIAGASSERT(pglob
!= NULL
);
564 /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
568 * we save one character so that we can use ptr >= limit,
569 * in the general case when we are appending non nul chars only.
571 return glob2(pathbuf
, pathbuf
,
572 pathbuf
+ (sizeof(pathbuf
) / sizeof(*pathbuf
)) - 1, pattern
,
577 * The functions glob2 and glob3 are mutually recursive; there is one level
578 * of recursion for each segment in the pattern that contains one or more
582 glob2(Char
*pathbuf
, Char
*pathend
, Char
*pathlim
, Char
*pattern
, glob_t
*pglob
,
591 _DIAGASSERT(pathbuf
!= NULL
);
592 _DIAGASSERT(pathend
!= NULL
);
593 _DIAGASSERT(pattern
!= NULL
);
594 _DIAGASSERT(pglob
!= NULL
);
597 * Loop over pattern segments until end of pattern or until
598 * segment with meta character found.
600 for (anymeta
= 0;;) {
601 if (*pattern
== EOS
) { /* End of pattern? */
603 if (g_lstat(pathbuf
, &sb
, pglob
))
606 if ((pglob
->gl_flags
& GLOB_LIMIT
) &&
607 limit
[GLOB_INDEX_STAT
]++ >= GLOB_LIMIT_STAT
) {
613 if (((pglob
->gl_flags
& GLOB_MARK
) &&
614 pathend
[-1] != SEP
) && (S_ISDIR(sb
.st_mode
) ||
615 // (S_ISLNK(sb.st_mode) &&
617 (g_stat(pathbuf
, &sb
, pglob
) == 0) &&
618 S_ISDIR(sb
.st_mode
)))) {
619 if (pathend
>= pathlim
)
625 return globextend(pathbuf
, pglob
, limit
);
628 /* Find end of next segment, copy tentatively to pathend. */
631 while (*p
!= EOS
&& *p
!= SEP
) {
640 * No expansion, or path ends in slash-dot shash-dot-dot,
643 if (pglob
->gl_flags
& GLOB_PERIOD
) {
644 for (pend
= pathend
; pend
> pathbuf
&& pend
[-1] == '/';
647 diff
= pend
- pathbuf
;
655 ((pglob
->gl_flags
& GLOB_PERIOD
) &&
656 (diff
>= 1 && pend
[-1] == DOT
) &&
657 (diff
>= 2 && (pend
[-2] == SLASH
|| pend
[-2] == DOT
)) &&
658 (diff
< 3 || pend
[-3] == SLASH
))) {
661 while (*pattern
== SEP
) {
662 if (pathend
>= pathlim
)
664 *pathend
++ = *pattern
++;
666 } else /* Need expansion, recurse. */
667 return glob3(pathbuf
, pathend
, pathlim
, pattern
, p
,
674 glob3(Char
*pathbuf
, Char
*pathend
, Char
*pathlim
, Char
*pattern
,
675 Char
*restpattern
, glob_t
*pglob
, size_t *limit
)
680 char buf
[MAXPATHLEN
];
683 * The readdirfunc declaration can't be prototyped, because it is
684 * assigned, below, to two functions which are prototyped in glob.h
685 * and dirent.h as taking pointers to differently typed opaque
688 struct dirent
*(*readdirfunc
)(void *);
690 _DIAGASSERT(pathbuf
!= NULL
);
691 _DIAGASSERT(pathend
!= NULL
);
692 _DIAGASSERT(pattern
!= NULL
);
693 _DIAGASSERT(restpattern
!= NULL
);
694 _DIAGASSERT(pglob
!= NULL
);
699 if ((dirp
= g_opendir(pathbuf
, pglob
)) == NULL
) {
700 if (pglob
->gl_errfunc
) {
701 if (g_Ctoc(pathbuf
, buf
, sizeof(buf
)))
703 if (pglob
->gl_errfunc(buf
, errno
) ||
704 pglob
->gl_flags
& GLOB_ERR
)
708 * Posix/XOpen: glob should return when it encounters a
709 * directory that it cannot open or read
710 * XXX: Should we ignore ENOTDIR and ENOENT though?
711 * I think that Posix had in mind EPERM...
713 if (pglob
->gl_flags
& GLOB_ERR
)
721 /* Search directory for matching names. */
722 if (pglob
->gl_flags
& GLOB_ALTDIRFUNC
)
723 readdirfunc
= pglob
->gl_readdir
;
725 readdirfunc
= (struct dirent
*(*)(void *)) readdir
;
726 while ((dp
= (*readdirfunc
)(dirp
)) != NULL
) {
730 if ((pglob
->gl_flags
& GLOB_LIMIT
) &&
731 limit
[GLOB_INDEX_READDIR
]++ >= GLOB_LIMIT_READDIR
) {
739 * Initial DOT must be matched literally, unless we have
742 if ((pglob
->gl_flags
& GLOB_PERIOD
) == 0)
743 if (dp
->FileName
[0] == DOT
&& *pattern
!= DOT
)
746 * If GLOB_NO_DOTDIRS is set, . and .. vanish.
748 if ((pglob
->gl_flags
& GLOB_NO_DOTDIRS
) &&
749 (dp
->FileName
[0] == DOT
) &&
750 ((dp
->FileName
[1] == EOS
) ||
751 ((dp
->FileName
[1] == DOT
) && (dp
->FileName
[2] == EOS
))))
754 * The resulting string contains EOS, so we can
755 * use the pathlim character, if it is the nul
757 for (sc
= (u_char
*) dp
->FileName
, dc
= pathend
;
758 dc
<= pathlim
&& (*dc
++ = *sc
++) != EOS
;)
762 * Have we filled the buffer without seeing EOS?
764 if (dc
> pathlim
&& *pathlim
!= EOS
) {
766 * Abort when requested by caller, otherwise
767 * reset pathend back to last SEP and continue
768 * with next dir entry.
770 if (pglob
->gl_flags
& GLOB_ERR
) {
771 error
= GLOB_ABORTED
;
780 if (!match(pathend
, pattern
, restpattern
)) {
784 error
= glob2(pathbuf
, --dc
, pathlim
, restpattern
, pglob
,
790 if (pglob
->gl_flags
& GLOB_ALTDIRFUNC
)
791 (*pglob
->gl_closedir
)(dirp
);
796 * Again Posix X/Open issue with regards to error handling.
798 if ((error
|| errno
) && (pglob
->gl_flags
& GLOB_ERR
))
806 * Extend the gl_pathv member of a glob_t structure to accommodate a new item,
807 * add the new item, and update gl_pathc.
809 * This assumes the BSD realloc, which only copies the block when its size
810 * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
813 * Return 0 if new item added, error code if memory couldn't be allocated.
815 * Invariant of the glob_t structure:
816 * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
817 * gl_pathv points to (gl_offs + gl_pathc + 1) items.
820 globextend(const Char
*path
, glob_t
*pglob
, size_t *limit
)
823 size_t i
, newsize
, len
;
827 _DIAGASSERT(path
!= NULL
);
828 _DIAGASSERT(pglob
!= NULL
);
830 newsize
= sizeof(*pathv
) * (2 + pglob
->gl_pathc
+ pglob
->gl_offs
);
831 pathv
= pglob
->gl_pathv
? realloc(pglob
->gl_pathv
, newsize
) :
836 if (pglob
->gl_pathv
== NULL
&& pglob
->gl_offs
> 0) {
837 /* first time around -- clear initial gl_offs items */
838 pathv
+= pglob
->gl_offs
;
839 for (i
= pglob
->gl_offs
+ 1; --i
> 0; )
842 pglob
->gl_pathv
= pathv
;
844 for (p
= path
; *p
++;)
846 len
= (size_t)(p
- path
);
847 limit
[GLOB_INDEX_MALLOC
] += len
;
848 if ((copy
= malloc(len
)) != NULL
) {
849 if (g_Ctoc(path
, copy
, len
)) {
853 pathv
[pglob
->gl_offs
+ pglob
->gl_pathc
++] = copy
;
855 pathv
[pglob
->gl_offs
+ pglob
->gl_pathc
] = NULL
;
857 if ((pglob
->gl_flags
& GLOB_LIMIT
) &&
858 (newsize
+ limit
[GLOB_INDEX_MALLOC
]) >= GLOB_LIMIT_MALLOC
) {
863 return copy
== NULL
? GLOB_NOSPACE
: 0;
868 * pattern matching function for filenames. Each occurrence of the *
869 * pattern causes a recursion level.
872 match(Char
*name
, Char
*pat
, Char
*patend
)
874 int ok
, negate_range
;
877 _DIAGASSERT(name
!= NULL
);
878 _DIAGASSERT(pat
!= NULL
);
879 _DIAGASSERT(patend
!= NULL
);
881 while (pat
< patend
) {
883 switch (c
& M_MASK
) {
888 if (match(name
, pat
, patend
))
890 while (*name
++ != EOS
);
898 if ((k
= *name
++) == EOS
)
900 if ((negate_range
= ((*pat
& M_MASK
) == M_NOT
)) != EOS
)
902 while (((c
= *pat
++) & M_MASK
) != M_END
)
903 if ((*pat
& M_MASK
) == M_RNG
) {
904 if (c
<= k
&& k
<= pat
[1])
909 if (ok
== negate_range
)
921 /* Free allocated data belonging to a glob_t structure. */
923 globfree(glob_t
*pglob
)
928 _DIAGASSERT(pglob
!= NULL
);
930 if (pglob
->gl_pathv
!= NULL
) {
931 pp
= pglob
->gl_pathv
+ pglob
->gl_offs
;
932 for (i
= pglob
->gl_pathc
; i
--; ++pp
)
935 free(pglob
->gl_pathv
);
936 pglob
->gl_pathv
= NULL
;
942 g_opendir(Char
*str
, glob_t
*pglob
)
944 char buf
[MAXPATHLEN
];
946 _DIAGASSERT(str
!= NULL
);
947 _DIAGASSERT(pglob
!= NULL
);
950 (void)strlcpy(buf
, ".", sizeof(buf
));
952 if (g_Ctoc(str
, buf
, sizeof(buf
)))
956 if (pglob
->gl_flags
& GLOB_ALTDIRFUNC
)
957 return (*pglob
->gl_opendir
)(buf
);
963 g_lstat(Char
*fn
, __gl_stat_t
*sb
, glob_t
*pglob
)
965 char buf
[MAXPATHLEN
];
967 _DIAGASSERT(fn
!= NULL
);
968 _DIAGASSERT(sb
!= NULL
);
969 _DIAGASSERT(pglob
!= NULL
);
971 if (g_Ctoc(fn
, buf
, sizeof(buf
)))
973 if (pglob
->gl_flags
& GLOB_ALTDIRFUNC
)
974 return (*pglob
->gl_lstat
)(buf
, sb
);
975 return lstat(buf
, sb
);
979 g_stat(Char
*fn
, __gl_stat_t
*sb
, glob_t
*pglob
)
981 char buf
[MAXPATHLEN
];
983 _DIAGASSERT(fn
!= NULL
);
984 _DIAGASSERT(sb
!= NULL
);
985 _DIAGASSERT(pglob
!= NULL
);
987 if (g_Ctoc(fn
, buf
, sizeof(buf
)))
989 if (pglob
->gl_flags
& GLOB_ALTDIRFUNC
)
990 return (*pglob
->gl_stat
)(buf
, sb
);
991 return stat(buf
, sb
);
995 g_strchr(const Char
*str
, int ch
)
998 _DIAGASSERT(str
!= NULL
);
1002 return __UNCONST(str
);
1008 g_Ctoc(const Char
*str
, char *buf
, size_t len
)
1012 _DIAGASSERT(str
!= NULL
);
1013 _DIAGASSERT(buf
!= NULL
);
1018 for (dc
= buf
; len
&& (*dc
++ = *str
++) != EOS
; len
--)
1026 qprintf(const char *str
, Char
*s
)
1030 _DIAGASSERT(str
!= NULL
);
1031 _DIAGASSERT(s
!= NULL
);
1033 (void)printf("%s:\n", str
);
1034 for (p
= s
; *p
; p
++)
1035 (void)printf("%c", CHAR(*p
));
1037 for (p
= s
; *p
; p
++)
1038 (void)printf("%c", *p
& M_PROTECT
? '"' : ' ');
1040 for (p
= s
; *p
; p
++)
1041 (void)printf("%c", ismeta(*p
) ? '_' : ' ');