99
99
gs_memory_t *memory;
101
gs_private_st_ptrs1(st_file_enum, struct file_enum_s, "file_enum",
102
file_enum_enum_ptrs, file_enum_reloc_ptrs, pattern);
100
struct directory_enum_s *previous;
102
gs_private_st_ptrs2(st_directory_enum, struct directory_enum_s, "directory_enum",
103
directory_enum_enum_ptrs, directory_enum_reloc_ptrs, pattern, previous);
105
typedef struct directory_enum_s directory_enum;
108
struct directory_enum_s *current;
110
gs_private_st_ptrs1(st_file_enum, struct file_enum_s, "directory_enum",
111
file_enum_enum_ptrs, file_enum_reloc_ptrs, current);
113
static int enumerate_directory_init(gs_memory_t *mem, directory_enum *pden, const char *directory, int dir_size, char *filename, const char *pattern, int pat_size)
115
int length = dir_size + pat_size;
118
length += strlen(filename);
120
length = length * 2 + 3;
122
/* pattern could be allocated as a string, */
123
/* but it's simpler for GC and freeing to allocate it as bytes. */
124
pden->pattern = (char *)gs_alloc_bytes(mem, length,
125
"gp_enumerate_files(pattern)");
126
if (pden->pattern == 0)
129
memcpy(pden->pattern, directory, dir_size);
130
if (directory[dir_size - 1] != '/') {
131
pden->pattern[dir_size++] = '/';
134
memcpy(&pden->pattern[dir_size], filename, strlen(filename));
135
dir_size += strlen(filename);
136
pden->pattern[dir_size++] = '/';
139
memcpy(&(pden->pattern[dir_size]), pattern, pat_size);
140
pden->pattern[dir_size + pat_size] = 0;
142
pden->head_size = dir_size;
143
pden->patlen = dir_size + pat_size;
144
pden->pat_size = length;
146
pden->first_time = 1;
147
memset(&pden->find_data, 0, sizeof(pden->find_data));
148
pden->find_handle = INVALID_HANDLE_VALUE;
104
153
/* Initialize an enumeration. Note that * and ? in a directory */
105
154
/* don't work with the OS call currently used. The '\' escape */
108
157
gp_enumerate_files_init(const char *pat, uint patlen, gs_memory_t * mem)
110
file_enum *pfen = gs_alloc_struct(mem, file_enum, &st_file_enum, "gp_enumerate_files");
159
directory_enum *pden;
111
161
int pat_size = 2 * patlen + 1;
118
/* pattern could be allocated as a string, */
119
/* but it's simpler for GC and freeing to allocate it as bytes. */
120
pattern = (char *)gs_alloc_bytes(mem, pat_size,
121
"gp_enumerate_files(pattern)");
124
/* translate the template into a pattern discarding the escape */
125
/* char '\' (not needed by the OS Find...File logic). Note that */
126
/* a final '\' in the string is also discarded. */
127
for (i = 0, j=0; i < patlen; i++) {
128
if (pat[i] == '\\') {
131
break; /* '\' at end ignored */
166
pden = gs_alloc_struct(mem, directory_enum, &st_directory_enum, "gp_enumerate_files");
169
pfen = gs_alloc_struct(mem, file_enum, &st_file_enum, "gp_enumerate_files");
171
gs_free_object(mem, pden, "free directory enumerator on error");
174
pfen->current = pden;
135
176
/* Scan for last path separator to determine 'head_size' (directory part) */
136
for (i = 0; i < j; i++) {
137
if(pattern[i] == '/' || pattern[i] == '\\' || pattern[i] == ':')
141
pfen->pattern = pattern;
143
pfen->pat_size = pat_size;
144
pfen->head_size = hsize;
146
pfen->first_time = 1;
147
memset(&pfen->find_data, 0, sizeof(pfen->find_data));
148
pfen->find_handle = INVALID_HANDLE_VALUE;
177
for (i = 0; i < patlen; i++) {
178
if(pat[i] == '/' || pat[i] == '\\' || pat[i] == ':')
182
if (enumerate_directory_init(mem, pden, pat, hsize, NULL, &pat[hsize], patlen - hsize) < 0)
184
gs_free_object(mem, pden, "free directory enumerator on error");
185
gs_free_object(mem, pfen, "free file enumerator on error");
154
194
gp_enumerate_files_next(file_enum * pfen, char *ptr, uint maxlen)
196
directory_enum *new_denum = NULL, *pden = pfen->current;
158
#ifdef WINDOWS_NO_UNICODE
161
char outfname[(sizeof(pfen->find_data.cFileName)*3+1)/2];
202
char outfname[(sizeof(pden->find_data.cFileName)*3+1)/2];
164
if (pfen->first_time) {
165
#ifdef WINDOWS_NO_UNICODE
166
pfen->find_handle = FindFirstFile(pfen->pattern, &(pfen->find_data));
205
if (pden->first_time) {
207
pden->find_handle = FindFirstFile(pden->pattern, &(pden->find_data));
169
pat = malloc(utf8_to_wchar(NULL, pfen->pattern)*sizeof(wchar_t));
210
pat = malloc(utf8_to_wchar(NULL, pden->pattern)*sizeof(wchar_t));
170
211
if (pat == NULL) {
174
utf8_to_wchar(pat, pfen->pattern);
175
pfen->find_handle = FindFirstFileW(pat, &(pfen->find_data));
215
utf8_to_wchar(pat, pden->pattern);
217
pden->find_handle = FindFirstFileExW(pat, FindExInfoStandard, &(pden->find_data), FindExSearchNameMatch, NULL, 0);
219
pden->find_handle = FindFirstFileW(pat, &(pden->find_data));
178
if (pfen->find_handle == INVALID_HANDLE_VALUE) {
223
if (pden->find_handle == INVALID_HANDLE_VALUE) {
224
if (pden->previous) {
225
FindClose(pden->find_handle);
226
gs_free_object(pden->memory, pden->pattern,
227
"gp_enumerate_files_close(pattern)");
228
new_denum = pden->previous;
229
gs_free_object(pden->memory, pden, "gp_enumerate_files_close");
231
pfen->current = pden;
182
pfen->first_time = 0;
238
pden->first_time = 0;
184
#ifdef WINDOWS_NO_UNICODE
185
if (!FindNextFile(pfen->find_handle, &(pfen->find_data))) {
241
if (!FindNextFile(pden->find_handle, &(pden->find_data))) {
187
if (!FindNextFileW(pfen->find_handle, &(pfen->find_data))) {
243
if (!FindNextFileW(pden->find_handle, &(pden->find_data))) {
245
if (pden->previous) {
246
FindClose(pden->find_handle);
247
gs_free_object(pden->memory, pden->pattern,
248
"gp_enumerate_files_close(pattern)");
249
new_denum = pden->previous;
250
gs_free_object(pden->memory, pden, "gp_enumerate_files_close");
252
pfen->current = pden;
193
#ifdef WINDOWS_NO_UNICODE
194
if ( strcmp(".", pfen->find_data.cFileName)
195
&& strcmp("..", pfen->find_data.cFileName)
196
&& (pfen->find_data.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY))
261
if ( strcmp(".", pden->find_data.cFileName)
262
&& strcmp("..", pden->find_data.cFileName)) {
263
if (pden->find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
264
new_denum = gs_alloc_struct(pden->memory, directory_enum, &st_directory_enum, "gp_enumerate_files");
265
if (new_denum != 0) {
266
if (enumerate_directory_init(pden->memory, new_denum, pden->pattern, pden->head_size,
267
pden->find_data.cFileName, &pden->pattern[pden->head_size], pden->pat_size - pden->head_size) < 0)
269
gs_free_object(pden->memory, new_denum, "free directory enumerator on error");
271
new_denum->previous = pden;
273
pfen->current = pden;
199
if ( wcscmp(L".", pfen->find_data.cFileName)
200
&& wcscmp(L"..", pfen->find_data.cFileName)
201
&& (pfen->find_data.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY))
280
if ( wcscmp(L".", pden->find_data.cFileName)
281
&& wcscmp(L"..", pden->find_data.cFileName)) {
282
if (pden->find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
283
new_denum = gs_alloc_struct(pden->memory, directory_enum, &st_directory_enum, "gp_enumerate_files");
284
if (new_denum != 0) {
286
fname = gs_alloc_bytes(pden->memory, wchar_to_utf8(NULL, pden->find_data.cFileName)*sizeof(wchar_t), "temporary wchar buffer");
288
gs_free_object(pden->memory, new_denum, "free directory enumerator on error");
290
wchar_to_utf8(fname, pden->find_data.cFileName);
291
if (enumerate_directory_init(pden->memory, new_denum, pden->pattern, pden->head_size,
292
fname, &pden->pattern[pden->head_size], pden->pat_size - pden->head_size) < 0)
294
gs_free_object(pden->memory, new_denum, "free directory enumerator on error");
296
gs_free_object(pden->memory, fname, "free temporary wchar buffer");
297
new_denum->previous = pden;
299
pfen->current = pden;
207
310
gp_enumerate_files_close(pfen);
208
311
return ~(uint) 0;
210
#ifdef WINDOWS_NO_UNICODE
211
outfname = pfen->find_data.cFileName;
314
outfname = pden->find_data.cFileName;
213
wchar_to_utf8(outfname, pfen->find_data.cFileName);
316
wchar_to_utf8(outfname, pden->find_data.cFileName);
215
318
len = strlen(outfname);
217
if (pfen->head_size + len < maxlen) {
218
memcpy(ptr, pfen->pattern, pfen->head_size);
219
strcpy(ptr + pfen->head_size, outfname);
220
return pfen->head_size + len;
320
if (pden->head_size + len < maxlen) {
321
memcpy(ptr, pden->pattern, pden->head_size);
322
strcpy(ptr + pden->head_size, outfname);
323
return pden->head_size + len;
222
if (pfen->head_size >= maxlen)
325
if (pden->head_size >= maxlen)
223
326
return 0; /* no hope at all */
225
memcpy(ptr, pfen->pattern, pfen->head_size);
226
strncpy(ptr + pfen->head_size, outfname, maxlen - pfen->head_size - 1);
328
memcpy(ptr, pden->pattern, pden->head_size);
329
strncpy(ptr + pden->head_size, outfname, maxlen - pden->head_size - 1);
232
335
gp_enumerate_files_close(file_enum * pfen)
234
gs_memory_t *mem = pfen->memory;
337
directory_enum *ptenum, *pden = pfen->current;
338
gs_memory_t *mem = pden->memory;
236
if (pfen->find_handle != INVALID_HANDLE_VALUE)
237
FindClose(pfen->find_handle);
238
gs_free_object(mem, pfen->pattern,
341
if (pden->find_handle != INVALID_HANDLE_VALUE)
342
FindClose(pden->find_handle);
343
gs_free_object(mem, pden->pattern,
239
344
"gp_enumerate_files_close(pattern)");
345
ptenum = pden->previous;
346
gs_free_object(mem, pden, "gp_enumerate_files_close");
240
349
gs_free_object(mem, pfen, "gp_enumerate_files_close");