4 * MinGW implementation of (approximately) POSIX conforming glob() and
5 * globfree() API functions.
9 * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
10 * Copyright (C) 2011-2014, 2017, MinGW.org Project.
13 * Permission is hereby granted, free of charge, to any person obtaining a
14 * copy of this software and associated documentation files (the "Software"),
15 * to deal in the Software without restriction, including without limitation
16 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 * and/or sell copies of the Software, and to permit persons to whom the
18 * Software is furnished to do so, subject to the following conditions:
20 * The above copyright notice, this permission notice, and the following
21 * disclaimer shall be included in all copies or substantial portions of
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
30 * DEALINGS IN THE SOFTWARE.
37 #include <sys/types.h>
43 /* Extend the flags offset enumeration, beyond the user visible
44 * high water mark, to accommodate some additional flags which are
45 * required for private use by the implementation.
47 __GLOB_DIRONLY_OFFSET = __GLOB_FLAG_OFFSET_HIGH_WATER_MARK,
48 __GLOB_PERIOD_PRIVATE_OFFSET,
50 * For congruency, set a new high water mark above the private data
51 * range, (which we don't otherwise use).
53 __GLOB_PRIVATE_FLAGS_HIGH_WATER_MARK
56 #define GLOB_DIRONLY __GLOB_FLAG__(DIRONLY)
58 # define GLOB_PERIOD __GLOB_FLAG__(PERIOD_PRIVATE)
62 # define GLOB_INLINE static __inline__ __attribute__((__always_inline__))
65 #if defined _WIN32 || defined __MS_DOS__
67 * For the Microsoft platforms, we treat '\' and '/' interchangeably
68 * as directory separator characters...
70 #define GLOB_DIRSEP ('\\')
71 # define glob_is_dirsep( c ) (((c) == ('/')) || ((c) == GLOB_DIRSEP))
73 * ...and we substitute whatever may have been predefined as the
74 * manifest constant __CRT_GLOB_ESCAPE_CHAR__, (nominally ASCII DEL,
75 * a.k.a. RUBOUT), as an alternative escape character.
77 # ifdef __CRT_GLOB_ESCAPE_CHAR__
78 # define GLOB_HARD_ESC __CRT_GLOB_ESCAPE_CHAR__
80 # define GLOB_HARD_ESC ((char)(127))
83 static int glob_escape_char = GLOB_HARD_ESC;
85 GLOB_INLINE char *glob_strdup( const char *pattern )
87 /* An inline wrapper around the standard strdup() function;
88 * this strips instances of the GLOB_HARD_ESC character, which
89 * have not themselves been escaped, from the strdup()ed copy.
91 char buf[1 + strlen( pattern )];
92 char *copy = buf; const char *origin = pattern;
93 do { if( *origin == GLOB_HARD_ESC ) ++origin;
100 /* Otherwise, we assume only the POSIX standard '/'...
102 #define GLOB_DIRSEP ('/')
103 # define glob_is_dirsep( c ) ((c) == GLOB_DIRSEP)
105 * ...and we interpret '\', as specified by POSIX, as
106 * the escape character.
108 static int glob_escape_char = '\\';
110 #define glob_strdup strdup
113 static int is_glob_pattern( const char *pattern, int flags )
115 /* Check if "pattern" represents a globbing pattern
116 * with included wild card characters.
118 register const char *p;
121 /* Proceed only if specified pattern is not NULL...
123 if( (p = pattern) != NULL )
125 /* ...initially, with no bracketted character set open;
126 * (none can be, because we haven't yet had any opportunity
127 * to see the opening bracket).
131 /* Check each character in "pattern" in turn...
133 while( (c = *p++) != '\0' )
135 /* ...proceeding since we have not yet reached the NUL terminator.
137 if( ((flags & GLOB_NOESCAPE) == 0)
138 && (c == glob_escape_char) && (*p++ == '\0') )
140 * We found an escape character, (and the escape mechanism has
141 * not been disabled), but there is no following character to
142 * escape; it may be malformed, but this certainly doesn't look
143 * like a candidate globbing pattern.
147 else if( bracket == 0 )
149 /* Still outside of any bracketted character set...
151 if( (c == '*') || (c == '?') )
153 * ...either of these makes "pattern" an explicit
154 * globbing pattern...
160 * ...while this marks the start of a bracketted
166 else if( (bracket > 1) && (c == ']') )
168 * Within a bracketted character set, where it is not
169 * the first character, ']' marks the end of the set,
170 * making "pattern" a globbing pattern.
176 * Also within a bracketted character set, '!' is special
177 * when the first character, and shouldn't be counted; note
178 * that it should be counted when not the first character,
179 * but the short count resulting from ignoring it doesn't
180 * affect our desired outcome.
186 /* If we get to here, then we ran off the end of "pattern" without
187 * identifying it as a globbing pattern.
192 static const char *glob_set_adjusted( const char *pattern, int flags )
194 /* Adjust the globbing pattern pointer, to make it refer to the
195 * next character (if any) following a character set specification;
196 * this adjustment is required when pattern matching is to resume
197 * after matching a set specification, irrespective of whether the
198 * match was successful or not; (a failed match is the desired
199 * outcome for an excluded character set).
201 register const char *p = pattern;
203 /* We need to move the pointer forward, until we find the ']'
204 * which marks the end of the set specification.
208 /* We haven't found it yet; advance by one character...
210 if( (*p == glob_escape_char) && ((flags & GLOB_NOESCAPE) == 0) )
212 * ...or maybe even two, when we identify a need to
213 * step over any character which has been escaped...
219 * ...but if we find a NUL on the way, then the pattern
220 * is malformed, so we return NULL to report a bad match.
224 /* We found the expected ']'; return a pointer to the NEXT
225 * character, (which may be ANYTHING; even NUL is okay).
230 GLOB_INLINE int glob_case_match( int flags, int check, int match )
232 /* Local helper function, used to facilitate the case insensitive
233 * glob character matching appropriate for MS-Windows systems.
235 return (flags & GLOB_CASEMATCH) ? check - match
236 : tolower( check ) - tolower( match );
239 static const char *glob_in_set( const char *set, int test, int flags )
241 /* Check if the single character "test" is present in the set
242 * of characters represented by "set", (a specification of the
243 * form "[SET]", or "[!SET]" in the case of an excluded set).
245 * On entry, "set" always points to the first character in the
246 * set to be tested, i.e. the character FOLLOWING the '[' which
247 * opens an inclusive set, or FOLLOWING the initial '!' which
248 * marks the set as exclusive.
250 * Matching is ALWAYS performed as if checking an inclusive set;
251 * return value is a pointer to the globbing pattern character
252 * following the closing ']' of "set", when "test" IS in "set",
253 * or NULL when it is not. Caller performing an inclusive match
254 * should handle NULL as a failed match, and non-NULL as success.
255 * Caller performing an exclusive match should handle non-NULL as
256 * a failed match, with NULL indicating success, and should call
257 * glob_set_adjusted() before resuming pattern matching in the
258 * case of a successful match.
260 register int c, lastc;
261 if( ((lastc = *set) == ']') || (lastc == '-') )
263 /* This is the special case of matching ']' or '-' as the
264 * first character in the set, where it must match literally...
268 * ...which it does, so immediately report it so.
270 return glob_set_adjusted( ++set, flags );
272 /* ...otherwise we didn't match this special case of ']' or '-',
273 * so we simply ignore this special set entry, thus handling it
274 * as an implicitly escaped literal which has not been matched.
278 while( (c = *set++) != ']' )
280 /* We are still scanning the set, and have not yet reached the
281 * closing ']' sentinel character.
283 if( (c == '-') && (*set != ']') && ((c = *set++) != '\0') )
285 /* Since the current character is a '-', and is not immediately
286 * followed by the set's closing sentinel, nor is it at the end
287 * of the (malformed) pattern, it specifies a character range,
288 * running from the last character scanned...
292 /* ...in incremental collating sequence order, to the next
293 * character following the '-'...
295 if( glob_case_match( flags, lastc++, test ) == 0 )
297 * ...returning immediately on a successful match...
299 return glob_set_adjusted( set, flags );
303 /* ...or failing that, consider the possibility that the
304 * range may have been specified in decrementing collating
307 if( glob_case_match( flags, lastc--, test ) == 0 )
309 * ...once again, return immediately on a successful match.
311 return glob_set_adjusted( set, flags );
317 * This is a malformed set; (not closed before the end of
320 || glob_is_dirsep( c ) )
322 * ...or it attempts to explicitly match a directory separator,
323 * which is invalid in this context. We MUST fail it, in either
324 * case, reporting a mismatch.
328 if( glob_case_match( flags, c, test ) == 0 )
330 * We found the test character within the set; adjust the pattern
331 * reference, to resume after the end of the set, and return the
334 return glob_set_adjusted( set, flags );
336 /* If we get to here, we haven't yet found the test character within
337 * this set; remember the character within the set which we just tried
338 * to match, as it may represent the start of a character range, then
339 * continue the scan, until we exhaust the set.
343 /* Having exhausted the set, without finding a match, we return NULL
344 * to indicate that the test character was NOT found in the set.
349 static int glob_strcmp( const char *pattern, const char *text, int flags )
351 /* Compare "text" to a specified globbing "pattern" using semantics
352 * comparable to "strcmp()"; returns zero for a complete match, else
353 * non-zero for a mismatch.
356 * '?' matches any one character in "text" (except '\0')
357 * '*' matches any sequence of zero or more characters in "text"
358 * [SET] matches any one character in "text" which is also in "SET"
359 * [!SET] matches any one character in "text" which is NOT in "SET"
361 register const char *p = pattern, *t = text;
364 if( (*t == '.') && (*p != '.') && ((flags & GLOB_PERIOD) == 0) )
366 * The special GNU extension allowing wild cards to match a period
367 * as first character is NOT in effect; "text" DOES have an initial
368 * period character AND "pattern" DOES NOT match it EXPLICITLY, so
369 * this comparison must report a MISMATCH.
373 /* Attempt to match "pattern", character by character...
375 while( (c = *p++) != '\0' )
377 /* ...so long as we haven't exhausted it...
382 /* Match any one character...
385 /* ...but when there isn't one left to be matched,
386 * then we must report a mismatch.
392 /* Match any sequence of zero or more characters...
396 * ...ignoring any repeated '*' in the pattern...
400 /* ...and if we've exhausted the pattern...
404 * ...then we simply match all remaining characters,
405 * to the end of "text", so we may return immediately,
406 * reporting a successful match.
410 /* When we haven't exhausted the pattern, then we may
411 * attempt to recursively match the remainder of the
412 * pattern to some terminal substring of "text"; we do
413 * this iteratively, stepping over as many characters
414 * of "text" as necessary, (and which thus match the '*'
415 * in "pattern"), until we either find the start of this
416 * matching substring, or we exhaust "text" without any
419 do { c = glob_strcmp( p, t, flags | GLOB_PERIOD );
420 } while( (c != 0) && (*t++ != '\0') );
422 * ...and ultimately, we return the result of this
423 * recursive attempt to find a match.
428 /* Here we need to match (or not match) exactly one
429 * character from the candidate text with any one of
430 * a set of characters in the pattern...
432 if( (c = *t++) == '\0' )
434 * ...but, we must return a mismatch if there is no
435 * candidate character left to match.
441 /* Match any one character which is NOT in the SET
442 * specified by [!SET].
444 if( glob_in_set( ++p, c, flags ) == NULL )
448 p = glob_set_adjusted( p, flags );
452 { /* Match any one character which IS in the SET
453 * specified by [SET].
455 p = glob_in_set( p, c, flags );
459 * The character under test didn't satisfy the SET
460 * matching criterion; return as unmatched.
466 /* The escape character cannot be handled as a regular
467 * switch case, because the escape character is specified
468 * as a variable, (to better support Microsoft nuisances).
469 * The escape mechanism may have been disabled within the
472 if( ((flags & GLOB_NOESCAPE) == 0)
474 * ...but when it is active, and we find an escape
475 * character without exhausting the pattern...
477 && (c == glob_escape_char) && ((c = *p) != 0) )
479 * ...then we handle the escaped character here, as
480 * a literal, and step over it, within the pattern.
484 /* When we get to here, a successful match requires that
485 * the current pattern character "c" is an exact literal
486 * match for the next available character "t", if any,
487 * in the candidate text string...
489 if( (*t == '\0') || (glob_case_match( flags, c, *t ) != 0) )
491 * ...otherwise we return a mismatch.
495 /* No mismatch yet; proceed to test the following character
496 * within the candidate text string.
501 /* When we've exhausted the pattern, then this final check will return
502 * a match if we've simultaneously exhausted the candidate text string,
503 * or a mismatch otherwise.
510 * When this is defined, we assume that we can safely interrogate
511 * the d_type member of a globbed dirent structure, to determine if
512 * the referenced directory entry is itself a subdirectory entry.
514 # define GLOB_ISDIR( ent ) ((ent)->d_type == DT_DIR)
517 /* We can't simply check for (ent)->d_type == DT_DIR, so we must
518 * use stat() to identify subdirectory entries.
520 # include <sys/stat.h>
523 int GLOB_ISDIR( const struct *dirent ent )
526 if( stat( ent->d_name, &entinfo ) == 0 )
527 return S_ISDIR( entinfo.st_mode );
532 #if _DIRENT_HAVE_D_NAMLEN
534 * Our DIRENT implementation provides a direct indication
535 * of the length of the file system entity name returned by
536 * the last readdir operation...
538 # define D_NAMLEN( entry ) ((entry)->d_namlen)
541 * ...otherwise, we have to scan for it.
543 # define D_NAMLEN( entry ) (strlen( (entry)->d_name ))
546 static int glob_initialise( glob_t *gl_data )
548 /* Helper routine to initialise a glob_t structure
549 * for first time use.
551 if( gl_data != NULL )
553 /* Caller gave us a valid pointer to what we assume has been
554 * defined as a glob_t structure; allocate space on the heap,
555 * for storage of the globbed paths vector...
557 int entries = gl_data->gl_offs + 1;
558 if( (gl_data->gl_pathv = malloc( entries * sizeof( char ** ) )) == NULL )
560 * ...bailing out, if insufficient free heap memory.
564 /* On successful allocation, clear the initial path count...
566 gl_data->gl_pathc = 0;
569 * ...and place a NULL pointer in each allocated slot...
571 gl_data->gl_pathv[--entries] = NULL;
573 /* ...ultimately returning a successful initialisation status.
578 GLOB_INLINE int glob_expand( glob_t *gl_buf )
580 /* Inline helper to compute the new size allocation required
581 * for buf->gl_pathv, prior to adding a new glob result.
583 return ((2 + gl_buf->gl_pathc + gl_buf->gl_offs) * sizeof( char ** ));
586 static int glob_store_entry( char *path, glob_t *gl_buf )
588 /* Local helper routine to add a single path name entity
589 * to the globbed path vector, after first expanding the
590 * allocated memory space to accommodate it.
593 if( (path != NULL) && (gl_buf != NULL)
594 && ((pathv = realloc( gl_buf->gl_pathv, glob_expand( gl_buf ))) != NULL) )
596 /* Memory expansion was successful; store the new path name
597 * in place of the former NULL pointer at the end of the old
600 gl_buf->gl_pathv = pathv;
601 gl_buf->gl_pathv[gl_buf->gl_offs + gl_buf->gl_pathc++] = path;
603 * ...then place a further NULL pointer into the newly allocated
604 * slot, to mark the new end of the vector...
606 gl_buf->gl_pathv[gl_buf->gl_offs + gl_buf->gl_pathc] = NULL;
608 * ...before returning a successful completion status.
612 /* If we get to here, then we were unsuccessful.
619 /* A private data structure, used to keep an ordered collection
620 * of globbed path names in collated sequence within a (possibly
621 * unbalanced) binary tree.
623 struct glob_collator *prev;
624 struct glob_collator *next;
628 GLOB_INLINE struct glob_collator
629 *glob_collate_entry( struct glob_collator *collator, char *entry, int flags )
631 /* Inline helper function to construct a binary tree representation
632 * of a collated collection of globbed path name entities.
635 struct glob_collator *ref = collator;
636 struct glob_collator *lastref = collator;
639 /* Walk the tree, to find the leaf node representing the insertion
640 * point, in correctly collated sequence order, for the new entry,
641 * noting whether we must insert the new entry before or after the
642 * original entry at that leaf.
645 if( flags & GLOB_CASEMATCH )
646 seq = strcoll( entry, ref->entry );
648 seq = stricoll( entry, ref->entry );
649 ref = (seq > 0) ? ref->next : ref->prev;
651 /* Allocate storage for a new leaf node, and if successful...
653 if( (ref = malloc( sizeof( struct glob_collator ))) != NULL )
655 /* ...place the new entry on this new leaf...
658 ref->prev = ref->next = NULL;
660 /* ...and attach it to the tree...
662 if( lastref != NULL )
677 /* ...the original leaf,as appropriate. */
680 /* When done, return a pointer to the root node of the resultant tree.
682 return (collator == NULL) ? ref : collator;
686 glob_store_collated_entries( struct glob_collator *collator, glob_t *gl_buf )
688 /* A local helper routine to store a collated collection of globbed
689 * path name entities into the path vector within a glob_t structure;
690 * it performs a recursive inorder traversal of a glob_collator tree,
691 * deleting it leaf by leaf, branch by branch, as it stores the path
692 * data contained thereon.
694 if( collator->prev != NULL )
696 * Recurse into the sub-tree of entries which collate before the
697 * root of the current (sub-)tree.
699 glob_store_collated_entries( collator->prev, gl_buf );
701 /* Store the path name entry at the root of the current (sub-)tree.
703 glob_store_entry( collator->entry, gl_buf );
705 if( collator->next != NULL )
707 * Recurse into the sub-tree of entries which collate after the
708 * root of the current (sub-)tree.
710 glob_store_collated_entries( collator->next, gl_buf );
712 /* Finally, delete the root node of the current (sub-)tree; since
713 * recursion visits every node of the tree, ultimately considering
714 * each leaf as a sub-tree of only one node, unwinding recursion
715 * will cause this to delete the entire tree.
721 accept_glob_nocheck_match( const char *pattern, int flags )
723 /* Helper to check whether a pattern may be stored into gl_pathv as is,
724 * without attempting to find any file system match; (this is permitted
725 * only when the caller has set the GLOB_NOCHECK flag, and the pattern
726 * is devoid of any globbing token).
728 return (flags & GLOB_NOCHECK) && (is_glob_pattern( pattern, flags ) == 0);
732 glob_match( const char *pattern, int flags, int (*errfn)(), glob_t *gl_buf )
734 /* Local helper function; it provides the backbone of the glob()
735 * implementation, recursively decomposing the pattern into separate
736 * globbable path components, to collect the union of all possible
737 * matches to the pattern, in all possible matching directories.
740 int status = GLOB_SUCCESS;
742 /* Begin by separating out any path prefix from the glob pattern.
744 char dirbuf[1 + strlen( pattern )];
745 const char *dir = dirname( memcpy( dirbuf, pattern, sizeof( dirbuf )) );
746 char **dirp, preferred_dirsep = GLOB_DIRSEP;
748 /* Initialise a temporary local glob_t structure, to capture the
749 * intermediate results at the current level of recursion...
751 local_gl_buf.gl_offs = 0;
752 if( (status = glob_initialise( &local_gl_buf )) != GLOB_SUCCESS )
754 * ...bailing out if unsuccessful.
758 /* Check if there are any globbing tokens in the path prefix...
760 if( is_glob_pattern( dir, flags ) )
762 * ...and recurse to identify all possible matching prefixes,
763 * as may be necessary...
765 status = glob_match( dir, flags | GLOB_DIRONLY, errfn, &local_gl_buf );
768 /* ...or simply store the current prefix, if not.
770 status = glob_store_entry( glob_strdup( dir ), &local_gl_buf );
772 /* Check nothing has gone wrong, so far...
774 if( status != GLOB_SUCCESS )
776 * ...and bail out if necessary.
780 /* The original "pattern" argument may have included a path name
781 * prefix, which we used "dirname()" to isolate. If there was no
782 * such prefix, then "dirname()" would have reported an effective
783 * prefix which is identically equal to "."; however, this would
784 * also be the case if the prefix was "./" (or ".\\" in the case
785 * of a WIN32 host). Thus, we may deduce that...
787 if( glob_is_dirsep( pattern[1] ) || (strcmp( dir, "." ) != 0) )
789 /* ...when the prefix is not reported as ".", or even if it is
790 * but the original pattern had "./" (or ".\\") as the prefix,
791 * then we must adjust to identify the effective pattern with
792 * its original prefix stripped away...
794 const char *tail = pattern + strlen( dir );
795 while( (tail > pattern) && ! glob_is_dirsep( *tail ) )
797 while( glob_is_dirsep( *tail ) )
798 preferred_dirsep = *tail++;
803 /* ...otherwise, we simply note that there was no prefix.
807 /* We now have a globbed list of prefix directories, returned from
808 * recursive processing, in local_gl_buf.gl_pathv, and we also have
809 * a separate pattern which we may attempt to match in each of them;
810 * at the outset, we have yet to match this pattern to anything.
812 status = GLOB_NOMATCH;
814 /* When the caller has enabled the GLOB_NOCHECK option, then in the
815 * case of any pattern with no prefix, and which contains no explicit
818 if( (dir == NULL) && accept_glob_nocheck_match( pattern, flags ) )
820 /* ...we prefer to store it as is, without any attempt to find
821 * a glob match, (which could also induce a case transliteration
822 * on MS-Windows' case-insensitive file system)...
824 glob_store_entry( glob_strdup( pattern ), gl_buf );
825 status = GLOB_SUCCESS;
827 /* ...otherwise we initiate glob matching, to find all possible
828 * file system matches for the designated pattern, within each of
829 * the identified prefix directory paths.
831 else for( dirp = local_gl_buf.gl_pathv; *dirp != NULL; free( *dirp++ ) )
833 /* Provided an earlier cycle hasn't scheduled an abort...
835 if( status != GLOB_ABORTED )
837 /* ...take each candidate directory in turn, and prepare
838 * to collate any matched entities within it...
840 struct glob_collator *collator = NULL;
842 /* ...attempt to open the current candidate directory...
845 if( (dp = opendir( *dirp )) != NULL )
847 /* ...and when successful, instantiate a dirent structure...
849 struct dirent *entry;
850 size_t dirlen = (dir == NULL) ? 0 : strlen( *dirp );
851 while( (entry = readdir( dp )) != NULL )
853 /* ...into which we read each entry from the candidate
854 * directory, in turn, then...
856 if( (((flags & GLOB_DIRONLY) == 0) || GLOB_ISDIR( entry ))
858 * ...provided we don't require it to be a subdirectory,
859 * or it actually is one...
861 && (glob_strcmp( pattern, entry->d_name, flags ) == 0) )
863 /* ...and it is a globbed match for the pattern, then
864 * we allocate a temporary local buffer of sufficient
865 * size to assemble the matching path name...
869 size_t matchlen = D_NAMLEN( entry );
870 char matchpath[2 + dirlen + matchlen];
871 if( (prefix = dirlen) > 0 )
873 /* ...first copying the prefix, if any,
874 * followed by a directory name separator...
876 memcpy( matchpath, *dirp, dirlen );
877 if( ! glob_is_dirsep( matchpath[prefix - 1] ) )
878 matchpath[prefix++] = preferred_dirsep;
880 /* ...and append the matching dirent entry.
882 memcpy( matchpath + prefix, entry->d_name, matchlen + 1 );
884 /* Duplicate the content of the temporary buffer to
885 * the heap, for assignment into gl_buf->gl_pathv...
887 if( (found = glob_strdup( matchpath )) == NULL )
889 * ...setting the appropriate error code, in the
890 * event that the heap memory has been exhausted.
892 status = GLOB_NOSPACE;
895 { /* This glob match has been successfully recorded on
896 * the heap, ready for assignment to gl_buf->gl_pathv;
897 * if this is the first match assigned to this gl_buf,
898 * and we haven't trapped any prior error...
900 if( status == GLOB_NOMATCH )
902 * ...then record this successful match.
904 status = GLOB_SUCCESS;
906 if( (flags & GLOB_NOSORT) == 0 )
908 /* The results of this glob are to be sorted in
909 * collating sequence order; divert the current
910 * match into the collator.
912 collator = glob_collate_entry( collator, found, flags );
915 { /* Sorting has been suppressed for this glob;
916 * just add the current match directly into the
917 * result vector at gl_buf->gl_pathv.
919 glob_store_entry( found, gl_buf );
924 /* When we've processed all of the entries in the current
925 * prefix directory, we may close it.
929 /* In the event of failure to open the candidate prefix directory...
931 else if( (flags & GLOB_ERR) || ((errfn != NULL) && errfn( *dirp, errno )) )
933 * ...and when the caller has set the GLOB_ERR flag, or has provided
934 * an error handler which returns non-zero for the failure condition,
935 * then we schedule an abort.
937 status = GLOB_ABORTED;
939 /* When we diverted the glob results for collation...
941 if( collator != NULL )
943 * ...then we redirect them to gl_buf->gl_pathv now, before we
944 * begin a new cycle, to process any further prefix directories
945 * which may have been identified; note that we do this even if
946 * we scheduled an abort, so that we may return any results we
947 * may have already collected before the error occurred.
949 glob_store_collated_entries( collator, gl_buf );
952 /* Finally, free the memory block allocated for the results vector
953 * in the internal glob buffer, to avoid leaking memory, before we
954 * return the resultant status code.
956 free( local_gl_buf.gl_pathv );
960 #define GLOB_INIT (0x100 << 0)
961 #define GLOB_FREE (0x100 << 1)
963 GLOB_INLINE int glob_signed( const char *check, const char *magic )
965 /* Inline helper function, used exclusively by the glob_registry()
966 * function, to confirm that the gl_magic field within a glob_t data
967 * structure has been set, to indicate a properly initialised state.
969 * FIXME: we'd like to be able to verify the content at "check"
970 * against the signature at "magic", but "check" is likely to be
971 * an uninitialised pointer, and MS-Windows lamely crashes when the
972 * memory it might appear to address cannot be read. There may be a
973 * way we could trap, and effectively handle, the resulting access
974 * violation, (likely restricted to WinXP and later); in the absence
975 * of a suitable handler, we must restrict our check to require that
976 * "check" is a strict alias for "magic". This will lose, if we have
977 * multiple copies of "glob" loaded via distinct DLLs, and we pass a
978 * "glob_t" entity which has been initialised in one DLL across the
979 * boundary of another; for now, however, checking for strict pointer
980 * aliasing seems to be the only reliably safe option available.
982 return (check == magic) ? 0 : 1;
985 static glob_t *glob_registry( int request, glob_t *gl_data )
987 /* Helper function to verify proper registration (initialisation)
988 * of a glob_t data structure, prior to first use; it also provides
989 * the core implementation for the globfree() function.
991 static const char *glob_magic = "glob-1.0-mingw32";
993 /* We must be prepared to handle either of...
997 /* ...a registration (initialisation) request...
1000 if( glob_signed( gl_data->gl_magic, glob_magic ) != 0 )
1002 /* The gl_magic field doesn't (yet) indicate that the
1003 * data structure has been initialised; assume that this
1004 * is first use, and initialise it now.
1006 glob_initialise( gl_data );
1007 gl_data->gl_magic = (void *)(glob_magic);
1011 /* ...or a de-registration (globfree()) request; here we
1012 * perform a sanity check, to ensure that the passed glob_t
1013 * structure is a valid, previously initialised structure,
1014 * before we attempt to free it.
1017 if( glob_signed( gl_data->gl_magic, glob_magic ) == 0 )
1019 /* On passing the sanity check, we may proceed to free
1020 * all dynamically (strdup) allocated string buffers in
1021 * the gl_pathv list, and the reference pointer table
1022 * itself, thus completing the globfree() activity.
1024 int base = gl_data->gl_offs;
1025 int argc = gl_data->gl_pathc;
1027 free( gl_data->gl_pathv[base++] );
1028 free( gl_data->gl_pathv );
1031 /* In either case, we return the original glob_t data pointer.
1037 __mingw_glob( const char *pattern, int flags, int (*errfn)(), glob_t *gl_data )
1039 /* Module entry point for the glob() function.
1043 /* First, consult the glob "registry", to ensure that the
1044 * glob data structure passed by the caller, has been properly
1045 * initialised. (Note that this implementation gratuitously uses
1046 * gl_data->gl_offs, irrespective of specification of GLOB_DOOFFS
1047 * in the flags; while the user must accept responsibility for the
1048 * initialisation of gl_data->gl_offs when specifying GLOB_DOOFFS,
1049 * this is not the case when GLOB_DOOFFS is not specified; in the
1050 * latter case, WE must assume the responsibility, ensuring that
1051 * the required zero value is assigned BEFORE registration).
1053 if( (gl_data != NULL) && ((flags & GLOB_DOOFFS) == 0) )
1054 gl_data->gl_offs = 0;
1056 /* With this pre-registration requirement satisfied, we may now
1057 * proceed to register the provided gl_data structure.
1059 gl_data = glob_registry( GLOB_INIT, gl_data );
1061 /* The actual globbing function is performed by glob_match()...
1063 status = glob_match( pattern, flags, errfn, gl_data );
1064 if( (status == GLOB_NOMATCH) && ((flags & GLOB_NOCHECK) != 0) )
1066 * ...ultimately delegating to glob_strdup() and glob_store_entry()
1067 * to handle any unmatched globbing pattern which the user specified
1068 * options may require to be stored anyway.
1070 glob_store_entry( glob_strdup( pattern ), gl_data );
1072 /* We always return the status reported by glob_match().
1078 __mingw_globfree( glob_t *gl_data )
1080 /* Module entry point for globfree() function; the activity is
1081 * entirely delegated to the glob "registry" helper function.
1083 glob_registry( GLOB_FREE, gl_data );
1086 /* $RCSfile$: end of file */