summaryrefslogtreecommitdiff
path: root/legacy
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2010-11-06 21:01:36 +0000
committerVincent Torri <vincent.torri@gmail.com>2010-11-06 21:01:36 +0000
commitb4571378c2d0461774a56b2ab27274865c634e1b (patch)
treef39d2f5f68373ce450bbe16fc1195447f6042bff /legacy
parent899983412bb173a0a8eb7f2a312322aac4b434e2 (diff)
and add file
SVN revision: 54251
Diffstat (limited to 'legacy')
-rw-r--r--legacy/eina/src/lib/eina_file_win32.c575
1 files changed, 575 insertions, 0 deletions
diff --git a/legacy/eina/src/lib/eina_file_win32.c b/legacy/eina/src/lib/eina_file_win32.c
new file mode 100644
index 0000000000..1027b94977
--- /dev/null
+++ b/legacy/eina/src/lib/eina_file_win32.c
@@ -0,0 +1,575 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2010 Vincent Torri
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H
20# include "config.h"
21#endif
22
23#ifdef HAVE_ALLOCA_H
24# include <alloca.h>
25#elif defined __GNUC__
26# define alloca __builtin_alloca
27#elif defined _AIX
28# define alloca __alloca
29#elif defined _MSC_VER
30# include <malloc.h>
31# define alloca _alloca
32#else
33# include <stddef.h>
34# ifdef __cplusplus
35extern "C"
36# endif
37void *alloca (size_t);
38#endif
39
40#define WIN32_LEAN_AND_MEAN
41#include <windows.h>
42#undef WIN32_LEAN_AND_MEAN
43
44#include "eina_config.h"
45#include "eina_private.h"
46
47/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
48#include "eina_safety_checks.h"
49#include "eina_file.h"
50#include "eina_stringshare.h"
51
52/*============================================================================*
53 * Local *
54 *============================================================================*/
55
56/**
57 * @cond LOCAL
58 */
59
60typedef struct _Eina_File_Iterator Eina_File_Iterator;
61typedef struct _Eina_File_Direct_Iterator Eina_File_Direct_Iterator;
62
63struct _Eina_File_Iterator
64{
65 Eina_Iterator iterator;
66
67 WIN32_FIND_DATA data;
68 HANDLE handle;
69 int length;
70 Eina_Bool is_last : 1;
71
72 char dir[1];
73};
74
75struct _Eina_File_Direct_Iterator
76{
77 Eina_Iterator iterator;
78
79 WIN32_FIND_DATA data;
80 HANDLE handle;
81 int length;
82 Eina_Bool is_last : 1;
83
84 Eina_File_Direct_Info info;
85
86 char dir[1];
87};
88
89static void
90_eina_file_win32_backslash_change(char *dir)
91{
92 char *tmp;
93
94 tmp = dir;
95 while (*tmp)
96 {
97 if (*tmp == '/') *tmp = '\\';
98 tmp++;
99 }
100}
101
102static Eina_Bool
103_eina_file_win32_is_dir(const char *dir)
104{
105#ifdef UNICODE
106 wchar_t *wdir = NULL;
107#endif
108 DWORD attr;
109
110 /* check if it's a directory */
111#ifdef UNICODE
112 wdir = evil_char_to_wchar(dir);
113 if (!wdir)
114 return EINA_FALSE;
115
116 attr = GetFileAttributes(wdir);
117 free(wdir);
118#else
119 attr = GetFileAttributes(dir);
120#endif
121
122 if (attr == 0xFFFFFFFF)
123 return EINA_FALSE;
124
125 if (!(attr & FILE_ATTRIBUTE_DIRECTORY))
126 return EINA_FALSE;
127
128 return EINA_TRUE;
129}
130
131static char *
132_eina_file_win32_dir_new(const char *dir)
133{
134 char *new_dir;
135 size_t length;
136
137 length = strlen(dir);
138
139 new_dir = (char *)malloc(sizeof(char) * length + 5);
140 if (!new_dir)
141 return NULL;
142
143 memcpy(new_dir, dir, length);
144 memcpy(new_dir + length, "\\*.*", 5);
145 _eina_file_win32_backslash_change(new_dir);
146
147 return new_dir;
148}
149
150static HANDLE
151_eina_file_win32_first_file(const char *dir, WIN32_FIND_DATA *fd)
152{
153 HANDLE h;
154#ifdef UNICODE
155 wchar_t *wdir = NULL;
156
157 wdir = evil_char_to_wchar(dir);
158 if (!wdir)
159 return NULL;
160
161 h = FindFirstFile(wdir, fd);
162 free(wdir);
163#else
164 h = FindFirstFile(dir, fd);
165#endif
166
167 if (!h)
168 return NULL;
169
170 while ((fd->cFileName[0] == '.') &&
171 ((fd->cFileName[1] == '\0') ||
172 ((fd->cFileName[1] == '.') && (fd->cFileName[2] == '\0'))))
173 {
174 if (!FindNextFile(h, fd))
175 return NULL;
176 }
177
178 return h;
179}
180
181static Eina_Bool
182_eina_file_win32_ls_iterator_next(Eina_File_Iterator *it, void **data)
183{
184 char *old_name;
185 char *name;
186 char *cname;
187 size_t length;
188 Eina_Bool is_last;
189 Eina_Bool res = EINA_TRUE;
190
191 if (it->handle == INVALID_HANDLE_VALUE)
192 return EINA_FALSE;
193
194 is_last = it->is_last;
195 old_name = strdup(it->data.cFileName);
196 if (!old_name)
197 return EINA_FALSE;
198
199 do {
200 if (!FindNextFile(it->handle, &it->data))
201 {
202 if (GetLastError() == ERROR_NO_MORE_FILES)
203 it->is_last = EINA_TRUE;
204 else
205 res = EINA_FALSE;
206 }
207 } while ((it->data.cFileName[0] == '.') &&
208 ((it->data.cFileName[1] == '\0') ||
209 ((it->data.cFileName[1] == '.') && (it->data.cFileName[2] == '\0'))));
210
211#ifdef UNICODE
212 cname = evil_wchar_to_char(old_name);
213 if (!cname)
214 return EINA_FALSE;
215#else
216 cname = old_name;
217#endif
218
219 length = strlen(cname);
220 name = alloca(length + 2 + it->length);
221
222 memcpy(name, it->dir, it->length);
223 memcpy(name + it->length, "\\", 1);
224 memcpy(name + it->length + 1, cname, length + 1);
225
226 *data = (char *)eina_stringshare_add(name);
227
228#ifdef UNICODE
229 free(cname);
230#endif
231 free(old_name);
232
233 if (is_last)
234 res = EINA_FALSE;
235
236 return res;
237}
238
239static HANDLE
240_eina_file_win32_ls_iterator_container(Eina_File_Iterator *it)
241{
242 return it->handle;
243}
244
245static void
246_eina_file_win32_ls_iterator_free(Eina_File_Iterator *it)
247{
248 if (it->handle != INVALID_HANDLE_VALUE)
249 FindClose(it->handle);
250
251 EINA_MAGIC_SET(&it->iterator, 0);
252 free(it);
253}
254
255static Eina_Bool
256_eina_file_win32_direct_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data)
257{
258 char *old_name;
259 char *cname;
260 size_t length;
261 DWORD attr;
262 Eina_Bool is_last;
263 Eina_Bool res = EINA_TRUE;
264
265 if (it->handle == INVALID_HANDLE_VALUE)
266 return EINA_FALSE;
267
268 attr = it->data.dwFileAttributes;
269 is_last = it->is_last;
270 old_name = strdup(it->data.cFileName);
271 if (!old_name)
272 return EINA_FALSE;
273
274 do {
275 if (!FindNextFile(it->handle, &it->data))
276 {
277 if (GetLastError() == ERROR_NO_MORE_FILES)
278 it->is_last = EINA_TRUE;
279 else
280 res = EINA_FALSE;
281 }
282
283 length = strlen(old_name);
284 if (it->info.name_start + length + 1 >= PATH_MAX)
285 {
286 free(old_name);
287 old_name = strdup(it->data.cFileName);
288 continue;
289 }
290
291 } while ((it->data.cFileName[0] == '.') &&
292 ((it->data.cFileName[1] == '\0') ||
293 ((it->data.cFileName[1] == '.') && (it->data.cFileName[2] == '\0'))));
294
295#ifdef UNICODE
296 cname = evil_wchar_to_char(old_name);
297 if (!cname)
298 return EINA_FALSE;
299#else
300 cname = old_name;
301#endif
302
303 memcpy(it->info.path + it->info.name_start, cname, length);
304 it->info.name_length = length;
305 it->info.path_length = it->info.name_start + length;
306 it->info.path[it->info.path_length] = '\0';
307
308 if (attr & FILE_ATTRIBUTE_DIRECTORY)
309 it->info.type = EINA_FILE_DIR;
310 else if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
311 it->info.type = EINA_FILE_LNK;
312 else if (attr & (FILE_ATTRIBUTE_ARCHIVE |
313 FILE_ATTRIBUTE_COMPRESSED |
314 FILE_ATTRIBUTE_COMPRESSED |
315 FILE_ATTRIBUTE_HIDDEN |
316 FILE_ATTRIBUTE_NORMAL |
317 FILE_ATTRIBUTE_SPARSE_FILE |
318 FILE_ATTRIBUTE_TEMPORARY))
319 it->info.type = EINA_FILE_REG;
320 else
321 it->info.type = EINA_FILE_UNKNOWN;
322
323 *data = &it->info;
324
325#ifdef UNICODE
326 free(cname);
327#endif
328
329 free(old_name);
330
331 if (is_last)
332 res = EINA_FALSE;
333
334 return res;
335}
336
337static HANDLE
338_eina_file_win32_direct_ls_iterator_container(Eina_File_Direct_Iterator *it)
339{
340 return it->handle;
341}
342
343static void
344_eina_file_win32_direct_ls_iterator_free(Eina_File_Direct_Iterator *it)
345{
346 if (it->handle != INVALID_HANDLE_VALUE)
347 FindClose(it->handle);
348
349 EINA_MAGIC_SET(&it->iterator, 0);
350 free(it);
351}
352
353
354/**
355 * @endcond
356 */
357
358/*============================================================================*
359 * Global *
360 *============================================================================*/
361
362/*============================================================================*
363 * API *
364 *============================================================================*/
365
366EAPI Eina_Bool
367eina_file_dir_list(const char *dir,
368 Eina_Bool recursive,
369 Eina_File_Dir_List_Cb cb,
370 void *data)
371{
372 WIN32_FIND_DATA file;
373 HANDLE h;
374 char *new_dir;
375
376 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE);
377 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, EINA_FALSE);
378 EINA_SAFETY_ON_TRUE_RETURN_VAL(dir[0] == '\0', EINA_FALSE);
379
380 if (!_eina_file_win32_is_dir(dir))
381 return EINA_FALSE;
382
383 new_dir = _eina_file_win32_dir_new(dir);
384 if (!new_dir)
385 return EINA_FALSE;
386
387 h = _eina_file_win32_first_file(new_dir, &file);
388
389 if (h == INVALID_HANDLE_VALUE)
390 return EINA_FALSE;
391
392 do
393 {
394 char *filename;
395
396# ifdef UNICODE
397 filename = evil_wchar_to_char(file.cFileName);
398# else
399 filename = file.cFileName;
400# endif /* ! UNICODE */
401 if (!strcmp(filename, ".") || !strcmp(filename, ".."))
402 continue;
403
404 cb(filename, dir, data);
405
406 if (recursive == EINA_TRUE)
407 {
408 char *path;
409
410 path = alloca(strlen(dir) + strlen(filename) + 2);
411 strcpy(path, dir);
412 strcat(path, "/");
413 strcat(path, filename);
414
415 if (!(file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
416 continue;
417
418 eina_file_dir_list(path, recursive, cb, data);
419 }
420
421# ifdef UNICODE
422 free(filename);
423# endif /* UNICODE */
424
425 } while (FindNextFile(h, &file));
426 FindClose(h);
427
428 return EINA_TRUE;
429}
430
431EAPI Eina_Array *
432eina_file_split(char *path)
433{
434 Eina_Array *ea;
435 char *current;
436 size_t length;
437
438 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
439
440 ea = eina_array_new(16);
441
442 if (!ea)
443 return NULL;
444
445 for (current = strchr(path, '\\');
446 current;
447 path = current + 1, current = strchr(path, '\\'))
448 {
449 length = current - path;
450
451 if (length <= 0)
452 continue;
453
454 eina_array_push(ea, path);
455 *current = '\0';
456 }
457
458 if (*path != '\0')
459 eina_array_push(ea, path);
460
461 return ea;
462}
463
464EAPI Eina_Iterator *
465eina_file_ls(const char *dir)
466{
467 Eina_File_Iterator *it;
468 char *new_dir;
469 size_t length;
470
471 if (!dir || !*dir)
472 return NULL;
473
474 if (!_eina_file_win32_is_dir(dir))
475 return NULL;
476
477 length = strlen(dir);
478
479 it = calloc(1, sizeof (Eina_File_Iterator) + length);
480 if (!it)
481 return NULL;
482
483 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
484
485 new_dir = _eina_file_win32_dir_new(dir);
486 if (!new_dir)
487 goto free_it;
488
489 it->handle = _eina_file_win32_first_file(new_dir, &it->data);
490 free(new_dir);
491 if (it->handle == INVALID_HANDLE_VALUE)
492 goto free_it;
493
494 memcpy(it->dir, dir, length + 1);
495 if (dir[length - 1] != '\\')
496 it->length = length;
497 else
498 it->length = length - 1;
499 _eina_file_win32_backslash_change(it->dir);
500
501 it->iterator.version = EINA_ITERATOR_VERSION;
502 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_win32_ls_iterator_next);
503 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_win32_ls_iterator_container);
504 it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_win32_ls_iterator_free);
505
506 return &it->iterator;
507
508 free_it:
509 free(it);
510
511 return NULL;
512}
513
514EAPI Eina_Iterator *
515eina_file_direct_ls(const char *dir)
516{
517 Eina_File_Direct_Iterator *it;
518 char *new_dir;
519 size_t length;
520
521 if (!dir || !*dir)
522 return NULL;
523
524 length = strlen(dir);
525
526 if (length + 12 + 2 >= MAX_PATH)
527 return NULL;
528
529 it = calloc(1, sizeof(Eina_File_Direct_Iterator) + length);
530 if (!it)
531 return NULL;
532
533 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
534
535 new_dir = _eina_file_win32_dir_new(dir);
536 if (!new_dir)
537 goto free_it;
538
539 it->handle = _eina_file_win32_first_file(new_dir, &it->data);
540 free(new_dir);
541 if (it->handle == INVALID_HANDLE_VALUE)
542 goto free_it;
543
544 memcpy(it->dir, dir, length + 1);
545 it->length = length;
546 _eina_file_win32_backslash_change(it->dir);
547
548 memcpy(it->info.path, dir, length);
549 if (dir[length - 1] == '\\')
550 it->info.name_start = length;
551 else
552 {
553 it->info.path[length] = '\\';
554 it->info.name_start = length + 1;
555 }
556 _eina_file_win32_backslash_change(it->info.path);
557
558 it->iterator.version = EINA_ITERATOR_VERSION;
559 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_win32_direct_ls_iterator_next);
560 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_win32_direct_ls_iterator_container);
561 it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_win32_direct_ls_iterator_free);
562
563 return &it->iterator;
564
565 free_it:
566 free(it);
567
568 return NULL;
569}
570
571EAPI Eina_Iterator *
572eina_file_stat_ls(const char *dir)
573{
574 return eina_file_direct_ls(dir);
575}