1: #line 635 "./lpsrc/flx_glob.pak"
2:
3:
4:
5:
6:
7:
8:
9:
10: /* Error codes */
11:
12:
13:
14:
15:
16:
17: /* Flags */
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28: /* #define GLOB_ALTDIRFUNC 0x00000200 */ /*!< \brief Use gl_opendir et al functions. Not currently supported in this implementation. */
29: /* #define GLOB_BRACE 0x00000400 */ /*!< \brief Expand "{a,b}" to "a" "b". Not currently supported in this implementation. */
30:
31:
32:
33:
34:
35:
36:
37:
38: typedef struct
39: {
40: int gl_pathc; /*!< count of total paths so far */
41: int gl_matchc; /*!< count of paths matching pattern */
42: int gl_offs; /*!< reserved at beginning of gl_pathv */
43: int gl_flags; /*!< returned flags */
44: char **gl_pathv; /*!< list of paths matching pattern */
45: } glob_t;
46:
47: int GLOB_EXTERN glob( char const *pattern
48: , int flags
49: , int (*errfunc)(char const *, int)
50: , glob_t *pglob);
51:
52: void GLOB_EXTERN globfree(glob_t *pglob);
53:
54:
55:
56:
1: #line 692 "./lpsrc/flx_glob.pak"
2:
3:
4:
5:
6:
7:
8:
9:
10: static char const *strrpbrk(char const *string, char const *strCharSet)
11: {
12: char const *part = NULL;
13: char const *pch;
14:
15: for(pch = strCharSet; *pch; ++pch)
16: {
17: char const *p = strrchr(string, *pch);
18:
19: if(NULL != p)
20: {
21: if(NULL == part)
22: {
23: part = p;
24: }
25: else
26: {
27: if(part < p)
28: {
29: part = p;
30: }
31: }
32: }
33: }
34:
35: return part;
36: }
37:
38: int glob( char const *pattern
39: , int flags
40: , int (*errfunc)(char const *, int)
41: , glob_t *pglob)
42: {
43: int result;
44: char szRelative[1 + _MAX_PATH];
45: char const *file_part;
46: WIN32_FIND_DATAA find_data;
47: HANDLE hFind;
48: char *buffer;
49: char szPattern2[1 + _MAX_PATH];
50: char szPattern3[1 + _MAX_PATH];
51: char const *effectivePattern = pattern;
52: char const *leafMost;
53: const int bMagic = (NULL != strpbrk(pattern, "?*"));
54: int bNoMagic = 0;
55: int bMagic0;
56: size_t maxMatches = ~(size_t)(0);
57:
58: if(flags & GLOB_NOMAGIC)
59: {
60: bNoMagic = !bMagic;
61: }
62:
63: if(flags & GLOB_LIMIT)
64: {
65: maxMatches = (size_t)pglob->gl_matchc;
66: }
67:
68: if(flags & GLOB_TILDE)
69: {
70: if( '~' == pattern[0] &&
71: ( '\0' == pattern[1] ||
72: '/' == pattern[1] ||
73: '\\' == pattern[1]))
74: {
75: DWORD dw;
76:
77: (void)lstrcpyA(&szPattern2[0], "%HOMEDRIVE%%HOMEPATH%");
78:
79: dw = ExpandEnvironmentStringsA(&szPattern2[0], &szPattern3[0], UNIXEM_NUM_ELEMENTS(szPattern3) - 1);
80:
81: if(0 != dw)
82: {
83: (void)lstrcpynA(&szPattern3[0] + dw - 1, &pattern[1], (int)(UNIXEM_NUM_ELEMENTS(szPattern3) - dw));
84: szPattern3[UNIXEM_NUM_ELEMENTS(szPattern3) - 1] = '\0';
85:
86: effectivePattern = szPattern3;
87: }
88: }
89: }
90:
91: file_part = strrpbrk(effectivePattern, "\\/");
92:
93: if(NULL != file_part)
94: {
95: leafMost = ++file_part;
96:
97: (void)lstrcpyA(szRelative, effectivePattern);
98: szRelative[file_part - effectivePattern] = '\0';
99: }
100: else
101: {
102: szRelative[0] = '\0';
103: leafMost = effectivePattern;
104: }
105:
106: bMagic0 = (leafMost == strpbrk(leafMost, "?*"));
107:
108: hFind = FindFirstFileA(effectivePattern, &find_data);
109: buffer = NULL;
110:
111: pglob->gl_pathc = 0;
112: pglob->gl_pathv = NULL;
113:
114: if(0 == (flags & GLOB_DOOFFS))
115: {
116: pglob->gl_offs = 0;
117: }
118:
119: if(hFind == INVALID_HANDLE_VALUE)
120: {
121: if(NULL != errfunc)
122: {
123: (void)errfunc(effectivePattern, (int)GetLastError());
124: }
125:
126: result = GLOB_NOMATCH;
127: }
128: else
129: {
130: int cbCurr = 0;
131: size_t cbAlloc = 0;
132: size_t cMatches = 0;
133:
134: result = 0;
135:
136: do
137: {
138: int cch;
139: size_t new_cbAlloc;
140:
141: if( bMagic0 &&
142: 0 == (flags & GLOB_PERIOD))
143: {
144: if('.' == find_data.cFileName[0])
145: {
146: continue;
147: }
148: }
149:
150: if(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
151: {
152: #ifdef GLOB_ONLYFILE
153: if(flags & GLOB_ONLYFILE)
154: {
155: continue;
156: }
157: #endif /* GLOB_ONLYFILE */
158:
159: if( bMagic0 &&
160: GLOB_NODOTSDIRS == (flags & GLOB_NODOTSDIRS))
161: {
162: /* Pattern must begin with '.' to match either dots directory */
163: if( 0 == lstrcmpA(".", find_data.cFileName) ||
164: 0 == lstrcmpA("..", find_data.cFileName))
165: {
166: continue;
167: }
168: }
169:
170: if(flags & GLOB_MARK)
171: {
172: #if 0
173: if(find_data.cFileName[0] >= 'A' && find_data.cFileName[0] <= 'M')
174: #endif /* 0 */
175: (void)lstrcatA(find_data.cFileName, "/");
176: }
177: }
178: else
179: {
180: if(flags & GLOB_ONLYDIR)
181: {
182: /* Skip all further actions, and get the next entry */
183: #if 0
184: if(find_data.cFileName[0] >= 'A' && find_data.cFileName[0] <= 'M')
185: #endif /* 0 */
186: continue;
187: }
188: }
189:
190: cch = lstrlenA(find_data.cFileName);
191: if(NULL != file_part)
192: {
193: cch += file_part - effectivePattern;
194: }
195:
196: new_cbAlloc = (size_t)cbCurr + cch + 1;
197: if(new_cbAlloc > cbAlloc)
198: {
199: char *new_buffer;
200:
201: new_cbAlloc *= 2;
202:
203: new_cbAlloc = (new_cbAlloc + 31) & ~(31);
204:
205: new_buffer = (char*)realloc(buffer, new_cbAlloc);
206:
207: if(new_buffer == NULL)
208: {
209: result = GLOB_NOSPACE;
210: free(buffer);
211: buffer = NULL;
212: break;
213: }
214:
215: buffer = new_buffer;
216: cbAlloc = new_cbAlloc;
217: }
218:
219: (void)lstrcpynA(buffer + cbCurr, szRelative, 1 + (file_part - effectivePattern));
220: (void)lstrcatA(buffer + cbCurr, find_data.cFileName);
221: cbCurr += cch + 1;
222:
223: ++cMatches;
224: }
225: while(FindNextFile(hFind, &find_data) && cMatches != maxMatches);
226:
227: (void)FindClose(hFind);
228:
229: if(result == 0)
230: {
231: /* Now expand the buffer, to fit in all the pointers. */
232: size_t cbPointers = (1 + cMatches + pglob->gl_offs) * sizeof(char*);
233: char *new_buffer = (char*)realloc(buffer, cbAlloc + cbPointers);
234:
235: if(new_buffer == NULL)
236: {
237: result = GLOB_NOSPACE;
238: free(buffer);
239: }
240: else
241: {
242: char **pp;
243: char **begin;
244: char **end;
245: char *next_str;
246:
247: buffer = new_buffer;
248:
249: (void)memmove(new_buffer + cbPointers, new_buffer, cbAlloc);
250:
251: /* Handle the offsets. */
252: begin = (char**)new_buffer;
253: end = begin + pglob->gl_offs;
254:
255: for(; begin != end; ++begin)
256: {
257: *begin = NULL;
258: }
259:
260: /* Sort, or no sort. */
261: pp = (char**)new_buffer + pglob->gl_offs;
262: begin = pp;
263: end = begin + cMatches;
264:
265: if(flags & GLOB_NOSORT)
266: {
267: /* The way we need in order to test the removal of dots in the findfile_sequence. */
268: *end = NULL;
269: for(begin = pp, next_str = buffer + cbPointers; begin != end; --end)
270: {
271: *(end - 1) = next_str;
272:
273: /* Find the next string. */
274: next_str += 1 + lstrlenA(next_str);
275: }
276: }
277: else
278: {
279: /* The normal way. */
280: for(begin = pp, next_str = buffer + cbPointers; begin != end; ++begin)
281: {
282: *begin = next_str;
283:
284: /* Find the next string. */
285: next_str += 1 + lstrlenA(next_str);
286: }
287: *begin = NULL;
288: }
289:
290: /* Return results to caller. */
291: pglob->gl_pathc = (int)cMatches;
292: pglob->gl_matchc= (int)cMatches;
293: pglob->gl_flags = 0;
294: if(bMagic)
295: {
296: pglob->gl_flags |= GLOB_MAGCHAR;
297: }
298: pglob->gl_pathv = (char**)new_buffer;
299: }
300: }
301:
302: if(0 == cMatches)
303: {
304: result = GLOB_NOMATCH;
305: }
306: }
307:
308: if(GLOB_NOMATCH == result)
309: {
310: if( (flags & GLOB_TILDE_CHECK) &&
311: effectivePattern == szPattern3)
312: {
313: result = GLOB_NOMATCH;
314: }
315: else if(bNoMagic ||
316: (flags & GLOB_NOCHECK))
317: {
318: size_t cbNeeded = ((2 + pglob->gl_offs) * sizeof(char*)) + (1 + strlen(effectivePattern));
319: char **pp = (char**)realloc(buffer, cbNeeded);
320:
321: if(NULL == pp)
322: {
323: result = GLOB_NOSPACE;
324: free(buffer);
325: }
326: else
327: {
328: /* Handle the offsets. */
329: char **begin = pp;
330: char **end = pp + pglob->gl_offs;
331:
332: for(; begin != end; ++begin)
333: {
334: *begin = NULL;
335: }
336:
337: /* Synthesis the pattern result. */
338: pp[0 + pglob->gl_offs] = strcpy((char*)(pp + 2 + pglob->gl_offs), effectivePattern);
339: pp[1 + pglob->gl_offs] = NULL;
340:
341: /* Return results to caller. */
342: pglob->gl_pathc = 1;
343: pglob->gl_matchc= 1;
344: pglob->gl_flags = 0;
345: if(bMagic)
346: {
347: pglob->gl_flags |= GLOB_MAGCHAR;
348: }
349: pglob->gl_pathv = pp;
350:
351: result = 0;
352: }
353: }
354: }
355: else if(0 == result)
356: {
357: if((size_t)pglob->gl_matchc == maxMatches)
358: {
359: result = GLOB_NOSPACE;
360: }
361: }
362:
363: return result;
364: }
365:
366: void globfree(glob_t *pglob)
367: {
368: if(pglob != NULL)
369: {
370: free(pglob->gl_pathv);
371: pglob->gl_pathc = 0;
372: pglob->gl_pathv = NULL;
373: }
374: }
375: