diff options
author | David Walter Seikel | 2012-04-22 09:19:23 +1000 |
---|---|---|
committer | David Walter Seikel | 2012-04-22 09:19:23 +1000 |
commit | c963d75dfdeec11f82e79e727062fbf89afa2c04 (patch) | |
tree | 895633dbf641110be46f117c29890c49b3ffc0bd /libraries/eina/src/lib/eina_file_win32.c | |
parent | Adding the new extantz viewer and grid manager. (diff) | |
download | SledjHamr-c963d75dfdeec11f82e79e727062fbf89afa2c04.zip SledjHamr-c963d75dfdeec11f82e79e727062fbf89afa2c04.tar.gz SledjHamr-c963d75dfdeec11f82e79e727062fbf89afa2c04.tar.bz2 SledjHamr-c963d75dfdeec11f82e79e727062fbf89afa2c04.tar.xz |
Update EFL to latest beta.
Diffstat (limited to '')
-rw-r--r-- | libraries/eina/src/lib/eina_file_win32.c | 2235 |
1 files changed, 1214 insertions, 1021 deletions
diff --git a/libraries/eina/src/lib/eina_file_win32.c b/libraries/eina/src/lib/eina_file_win32.c index 1cd8665..5c20fdd 100644 --- a/libraries/eina/src/lib/eina_file_win32.c +++ b/libraries/eina/src/lib/eina_file_win32.c | |||
@@ -1,1021 +1,1214 @@ | |||
1 | /* EINA - EFL data type library | 1 | /* EINA - EFL data type library |
2 | * Copyright (C) 2010 Vincent Torri | 2 | * Copyright (C) 2010 Vincent Torri |
3 | * | 3 | * |
4 | * This library is free software; you can redistribute it and/or | 4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser General Public | 5 | * modify it under the terms of the GNU Lesser General Public |
6 | * License as published by the Free Software Foundation; either | 6 | * License as published by the Free Software Foundation; either |
7 | * version 2.1 of the License, or (at your option) any later version. | 7 | * version 2.1 of the License, or (at your option) any later version. |
8 | * | 8 | * |
9 | * This library is distributed in the hope that it will be useful, | 9 | * This library is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Lesser General Public License for more details. | 12 | * Lesser General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU Lesser General Public | 14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with this library; | 15 | * License along with this library; |
16 | * if not, see <http://www.gnu.org/licenses/>. | 16 | * if not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #ifdef HAVE_CONFIG_H | 19 | #ifdef HAVE_CONFIG_H |
20 | # include "config.h" | 20 | # include "config.h" |
21 | #endif | 21 | #endif |
22 | 22 | ||
23 | #ifdef HAVE_ALLOCA_H | 23 | #ifdef HAVE_ALLOCA_H |
24 | # include <alloca.h> | 24 | # include <alloca.h> |
25 | #elif defined __GNUC__ | 25 | #elif defined __GNUC__ |
26 | # define alloca __builtin_alloca | 26 | # define alloca __builtin_alloca |
27 | #elif defined _AIX | 27 | #elif defined _AIX |
28 | # define alloca __alloca | 28 | # define alloca __alloca |
29 | #elif defined _MSC_VER | 29 | #elif defined _MSC_VER |
30 | # include <malloc.h> | 30 | # include <malloc.h> |
31 | # define alloca _alloca | 31 | # define alloca _alloca |
32 | #else | 32 | #else |
33 | # include <stddef.h> | 33 | # include <stddef.h> |
34 | # ifdef __cplusplus | 34 | # ifdef __cplusplus |
35 | extern "C" | 35 | extern "C" |
36 | # endif | 36 | # endif |
37 | void *alloca (size_t); | 37 | void *alloca (size_t); |
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | #define WIN32_LEAN_AND_MEAN | 40 | #include <sys/types.h> |
41 | #include <windows.h> | 41 | #include <sys/stat.h> |
42 | #undef WIN32_LEAN_AND_MEAN | 42 | |
43 | 43 | #define WIN32_LEAN_AND_MEAN | |
44 | //#include <Evil.h> | 44 | #include <windows.h> |
45 | 45 | #undef WIN32_LEAN_AND_MEAN | |
46 | #include "eina_config.h" | 46 | |
47 | #include "eina_private.h" | 47 | #include <Evil.h> |
48 | 48 | ||
49 | /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ | 49 | #include "eina_config.h" |
50 | #include "eina_safety_checks.h" | 50 | #include "eina_private.h" |
51 | #include "eina_file.h" | 51 | |
52 | #include "eina_stringshare.h" | 52 | /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ |
53 | #include "eina_hash.h" | 53 | #include "eina_safety_checks.h" |
54 | #include "eina_list.h" | 54 | #include "eina_file.h" |
55 | 55 | #include "eina_stringshare.h" | |
56 | /*============================================================================* | 56 | #include "eina_hash.h" |
57 | * Local * | 57 | #include "eina_list.h" |
58 | *============================================================================*/ | 58 | #include "eina_lock.h" |
59 | 59 | #include "eina_log.h" | |
60 | /** | 60 | |
61 | * @cond LOCAL | 61 | /*============================================================================* |
62 | */ | 62 | * Local * |
63 | 63 | *============================================================================*/ | |
64 | #ifndef EINA_LOG_COLOR_DEFAULT | 64 | |
65 | #define EINA_LOG_COLOR_DEFAULT EINA_COLOR_CYAN | 65 | /** |
66 | #endif | 66 | * @cond LOCAL |
67 | 67 | */ | |
68 | #ifdef ERR | 68 | |
69 | #undef ERR | 69 | #ifndef EINA_LOG_COLOR_DEFAULT |
70 | #endif | 70 | #define EINA_LOG_COLOR_DEFAULT EINA_COLOR_CYAN |
71 | #define ERR(...) EINA_LOG_DOM_ERR(_eina_file_log_dom, __VA_ARGS__) | 71 | #endif |
72 | 72 | ||
73 | #ifdef WRN | 73 | #ifdef ERR |
74 | #undef WRN | 74 | #undef ERR |
75 | #endif | 75 | #endif |
76 | #define WRN(...) EINA_LOG_DOM_WARN(_eina_file_log_dom, __VA_ARGS__) | 76 | #define ERR(...) EINA_LOG_DOM_ERR(_eina_file_log_dom, __VA_ARGS__) |
77 | 77 | ||
78 | #ifdef DBG | 78 | #ifdef WRN |
79 | #undef DBG | 79 | #undef WRN |
80 | #endif | 80 | #endif |
81 | #define DBG(...) EINA_LOG_DOM_DBG(_eina_file_log_dom, __VA_ARGS__) | 81 | #define WRN(...) EINA_LOG_DOM_WARN(_eina_file_log_dom, __VA_ARGS__) |
82 | 82 | ||
83 | #ifdef MAP_FAILED | 83 | #ifdef DBG |
84 | # undef MAP_FAILED | 84 | #undef DBG |
85 | #endif | 85 | #endif |
86 | #define MAP_FAILED ((void *)-1) | 86 | #define DBG(...) EINA_LOG_DOM_DBG(_eina_file_log_dom, __VA_ARGS__) |
87 | 87 | ||
88 | typedef struct _Eina_File_Iterator Eina_File_Iterator; | 88 | #ifdef MAP_FAILED |
89 | typedef struct _Eina_File_Direct_Iterator Eina_File_Direct_Iterator; | 89 | # undef MAP_FAILED |
90 | typedef struct _Eina_File_Map Eina_File_Map; | 90 | #endif |
91 | 91 | #define MAP_FAILED ((void *)-1) | |
92 | struct _Eina_File_Iterator | 92 | |
93 | { | 93 | typedef struct _Eina_File_Iterator Eina_File_Iterator; |
94 | Eina_Iterator iterator; | 94 | typedef struct _Eina_File_Direct_Iterator Eina_File_Direct_Iterator; |
95 | 95 | typedef struct _Eina_File_Map Eina_File_Map; | |
96 | WIN32_FIND_DATA data; | 96 | |
97 | HANDLE handle; | 97 | struct _Eina_File_Iterator |
98 | size_t length; | 98 | { |
99 | Eina_Bool is_last : 1; | 99 | Eina_Iterator iterator; |
100 | 100 | ||
101 | char dir[1]; | 101 | WIN32_FIND_DATA data; |
102 | }; | 102 | HANDLE handle; |
103 | 103 | size_t length; | |
104 | struct _Eina_File_Direct_Iterator | 104 | Eina_Bool is_last : 1; |
105 | { | 105 | |
106 | Eina_Iterator iterator; | 106 | char dir[1]; |
107 | 107 | }; | |
108 | WIN32_FIND_DATA data; | 108 | |
109 | HANDLE handle; | 109 | struct _Eina_File_Direct_Iterator |
110 | size_t length; | 110 | { |
111 | Eina_Bool is_last : 1; | 111 | Eina_Iterator iterator; |
112 | 112 | ||
113 | Eina_File_Direct_Info info; | 113 | WIN32_FIND_DATA data; |
114 | 114 | HANDLE handle; | |
115 | char dir[1]; | 115 | size_t length; |
116 | }; | 116 | Eina_Bool is_last : 1; |
117 | 117 | ||
118 | struct _Eina_File | 118 | Eina_File_Direct_Info info; |
119 | { | 119 | |
120 | const char *filename; | 120 | char dir[1]; |
121 | 121 | }; | |
122 | Eina_Hash *map; | 122 | |
123 | Eina_Hash *rmap; | 123 | struct _Eina_File |
124 | void *global_map; | 124 | { |
125 | 125 | const char *filename; | |
126 | ULONGLONG length; | 126 | |
127 | ULONGLONG mtime; | 127 | Eina_Hash *map; |
128 | 128 | Eina_Hash *rmap; | |
129 | int refcount; | 129 | void *global_map; |
130 | int global_refcount; | 130 | |
131 | 131 | Eina_Lock lock; | |
132 | HANDLE handle; | 132 | |
133 | HANDLE fm; | 133 | ULONGLONG length; |
134 | 134 | ULONGLONG mtime; | |
135 | Eina_Bool shared : 1; | 135 | |
136 | Eina_Bool delete_me : 1; | 136 | int refcount; |
137 | }; | 137 | int global_refcount; |
138 | 138 | ||
139 | struct _Eina_File_Map | 139 | HANDLE handle; |
140 | { | 140 | HANDLE fm; |
141 | void *map; | 141 | |
142 | 142 | Eina_Bool shared : 1; | |
143 | unsigned long int offset; | 143 | Eina_Bool delete_me : 1; |
144 | unsigned long int length; | 144 | }; |
145 | 145 | ||
146 | int refcount; | 146 | struct _Eina_File_Map |
147 | }; | 147 | { |
148 | 148 | void *map; | |
149 | static Eina_Hash *_eina_file_cache = NULL; | 149 | |
150 | static Eina_List *_eina_file_cache_lru = NULL; | 150 | unsigned long int offset; |
151 | static Eina_List *_eina_file_cache_delete = NULL; | 151 | unsigned long int length; |
152 | 152 | ||
153 | static int _eina_file_log_dom = -1; | 153 | int refcount; |
154 | 154 | }; | |
155 | static void | 155 | |
156 | _eina_file_win32_backslash_change(char *dir) | 156 | static Eina_Hash *_eina_file_cache = NULL; |
157 | { | 157 | static Eina_Lock _eina_file_lock_cache; |
158 | char *tmp; | 158 | |
159 | 159 | static int _eina_file_log_dom = -1; | |
160 | tmp = dir; | 160 | |
161 | while (*tmp) | 161 | static void |
162 | { | 162 | _eina_file_win32_backslash_change(char *dir) |
163 | if (*tmp == '/') *tmp = '\\'; | 163 | { |
164 | tmp++; | 164 | char *tmp; |
165 | } | 165 | |
166 | } | 166 | tmp = dir; |
167 | 167 | while (*tmp) | |
168 | static Eina_Bool | 168 | { |
169 | _eina_file_win32_is_dir(const char *dir) | 169 | if (*tmp == '/') *tmp = '\\'; |
170 | { | 170 | tmp++; |
171 | #ifdef UNICODE | 171 | } |
172 | wchar_t *wdir = NULL; | 172 | } |
173 | #endif | 173 | |
174 | DWORD attr; | 174 | static Eina_Bool |
175 | 175 | _eina_file_win32_is_dir(const char *dir) | |
176 | /* check if it's a directory */ | 176 | { |
177 | #ifdef UNICODE | 177 | #ifdef UNICODE |
178 | wdir = evil_char_to_wchar(dir); | 178 | wchar_t *wdir = NULL; |
179 | if (!wdir) | 179 | #endif |
180 | return EINA_FALSE; | 180 | DWORD attr; |
181 | 181 | ||
182 | attr = GetFileAttributes(wdir); | 182 | /* check if it's a directory */ |
183 | free(wdir); | 183 | #ifdef UNICODE |
184 | #else | 184 | wdir = evil_char_to_wchar(dir); |
185 | attr = GetFileAttributes(dir); | 185 | if (!wdir) |
186 | #endif | 186 | return EINA_FALSE; |
187 | 187 | ||
188 | if (attr == 0xFFFFFFFF) | 188 | attr = GetFileAttributes(wdir); |
189 | return EINA_FALSE; | 189 | free(wdir); |
190 | 190 | #else | |
191 | if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) | 191 | attr = GetFileAttributes(dir); |
192 | return EINA_FALSE; | 192 | #endif |
193 | 193 | ||
194 | return EINA_TRUE; | 194 | if (attr == 0xFFFFFFFF) |
195 | } | 195 | return EINA_FALSE; |
196 | 196 | ||
197 | static char * | 197 | if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) |
198 | _eina_file_win32_dir_new(const char *dir) | 198 | return EINA_FALSE; |
199 | { | 199 | |
200 | char *new_dir; | 200 | return EINA_TRUE; |
201 | size_t length; | 201 | } |
202 | 202 | ||
203 | length = strlen(dir); | 203 | static char * |
204 | 204 | _eina_file_win32_dir_new(const char *dir) | |
205 | new_dir = (char *)malloc(sizeof(char) * length + 5); | 205 | { |
206 | if (!new_dir) | 206 | char *new_dir; |
207 | return NULL; | 207 | size_t length; |
208 | 208 | ||
209 | memcpy(new_dir, dir, length); | 209 | length = strlen(dir); |
210 | memcpy(new_dir + length, "\\*.*", 5); | 210 | |
211 | _eina_file_win32_backslash_change(new_dir); | 211 | new_dir = (char *)malloc(sizeof(char) * length + 5); |
212 | 212 | if (!new_dir) | |
213 | return new_dir; | 213 | return NULL; |
214 | } | 214 | |
215 | 215 | memcpy(new_dir, dir, length); | |
216 | static HANDLE | 216 | memcpy(new_dir + length, "\\*.*", 5); |
217 | _eina_file_win32_first_file(const char *dir, WIN32_FIND_DATA *fd) | 217 | _eina_file_win32_backslash_change(new_dir); |
218 | { | 218 | |
219 | HANDLE h; | 219 | return new_dir; |
220 | #ifdef UNICODE | 220 | } |
221 | wchar_t *wdir = NULL; | 221 | |
222 | 222 | static HANDLE | |
223 | wdir = evil_char_to_wchar(dir); | 223 | _eina_file_win32_first_file(const char *dir, WIN32_FIND_DATA *fd) |
224 | if (!wdir) | 224 | { |
225 | return NULL; | 225 | HANDLE h; |
226 | 226 | #ifdef UNICODE | |
227 | h = FindFirstFile(wdir, fd); | 227 | wchar_t *wdir = NULL; |
228 | free(wdir); | 228 | |
229 | #else | 229 | wdir = evil_char_to_wchar(dir); |
230 | h = FindFirstFile(dir, fd); | 230 | if (!wdir) |
231 | #endif | 231 | return NULL; |
232 | 232 | ||
233 | if (!h) | 233 | h = FindFirstFile(wdir, fd); |
234 | return NULL; | 234 | free(wdir); |
235 | 235 | #else | |
236 | while ((fd->cFileName[0] == '.') && | 236 | h = FindFirstFile(dir, fd); |
237 | ((fd->cFileName[1] == '\0') || | 237 | #endif |
238 | ((fd->cFileName[1] == '.') && (fd->cFileName[2] == '\0')))) | 238 | |
239 | { | 239 | if (!h) |
240 | if (!FindNextFile(h, fd)) | 240 | return NULL; |
241 | return NULL; | 241 | |
242 | } | 242 | while ((fd->cFileName[0] == '.') && |
243 | 243 | ((fd->cFileName[1] == '\0') || | |
244 | return h; | 244 | ((fd->cFileName[1] == '.') && (fd->cFileName[2] == '\0')))) |
245 | } | 245 | { |
246 | 246 | if (!FindNextFile(h, fd)) | |
247 | static Eina_Bool | 247 | return NULL; |
248 | _eina_file_win32_ls_iterator_next(Eina_File_Iterator *it, void **data) | 248 | } |
249 | { | 249 | |
250 | #ifdef UNICODE | 250 | return h; |
251 | wchar_t *old_name; | 251 | } |
252 | #else | 252 | |
253 | char *old_name; | 253 | static Eina_Bool |
254 | #endif | 254 | _eina_file_win32_ls_iterator_next(Eina_File_Iterator *it, void **data) |
255 | char *name; | 255 | { |
256 | char *cname; | 256 | #ifdef UNICODE |
257 | size_t length; | 257 | wchar_t *old_name; |
258 | Eina_Bool is_last; | 258 | #else |
259 | Eina_Bool res = EINA_TRUE; | 259 | char *old_name; |
260 | 260 | #endif | |
261 | if (it->handle == INVALID_HANDLE_VALUE) | 261 | char *name; |
262 | return EINA_FALSE; | 262 | char *cname; |
263 | 263 | size_t length; | |
264 | is_last = it->is_last; | 264 | Eina_Bool is_last; |
265 | #ifdef UNICODE | 265 | Eina_Bool res = EINA_TRUE; |
266 | old_name = _wcsdup(it->data.cFileName); | 266 | |
267 | #else | 267 | if (it->handle == INVALID_HANDLE_VALUE) |
268 | old_name = _strdup(it->data.cFileName); | 268 | return EINA_FALSE; |
269 | #endif | 269 | |
270 | if (!old_name) | 270 | is_last = it->is_last; |
271 | return EINA_FALSE; | 271 | #ifdef UNICODE |
272 | 272 | old_name = _wcsdup(it->data.cFileName); | |
273 | do { | 273 | #else |
274 | if (!FindNextFile(it->handle, &it->data)) | 274 | old_name = _strdup(it->data.cFileName); |
275 | { | 275 | #endif |
276 | if (GetLastError() == ERROR_NO_MORE_FILES) | 276 | if (!old_name) |
277 | it->is_last = EINA_TRUE; | 277 | return EINA_FALSE; |
278 | else | 278 | |
279 | res = EINA_FALSE; | 279 | do { |
280 | } | 280 | if (!FindNextFile(it->handle, &it->data)) |
281 | } while ((it->data.cFileName[0] == '.') && | 281 | { |
282 | ((it->data.cFileName[1] == '\0') || | 282 | if (GetLastError() == ERROR_NO_MORE_FILES) |
283 | ((it->data.cFileName[1] == '.') && (it->data.cFileName[2] == '\0')))); /* FIXME: what about UNICODE ? */ | 283 | it->is_last = EINA_TRUE; |
284 | 284 | else | |
285 | #ifdef UNICODE | 285 | res = EINA_FALSE; |
286 | cname = evil_wchar_to_char(old_name); | 286 | } |
287 | if (!cname) | 287 | } while ((it->data.cFileName[0] == '.') && |
288 | return EINA_FALSE; | 288 | ((it->data.cFileName[1] == '\0') || |
289 | #else | 289 | ((it->data.cFileName[1] == '.') && (it->data.cFileName[2] == '\0')))); /* FIXME: what about UNICODE ? */ |
290 | cname = old_name; | 290 | |
291 | #endif | 291 | #ifdef UNICODE |
292 | 292 | cname = evil_wchar_to_char(old_name); | |
293 | length = strlen(cname); | 293 | if (!cname) |
294 | name = alloca(length + 2 + it->length); | 294 | return EINA_FALSE; |
295 | 295 | #else | |
296 | memcpy(name, it->dir, it->length); | 296 | cname = old_name; |
297 | memcpy(name + it->length, "\\", 1); | 297 | #endif |
298 | memcpy(name + it->length + 1, cname, length + 1); | 298 | |
299 | 299 | length = strlen(cname); | |
300 | *data = (char *)eina_stringshare_add(name); | 300 | name = alloca(length + 2 + it->length); |
301 | 301 | ||
302 | #ifdef UNICODE | 302 | memcpy(name, it->dir, it->length); |
303 | free(cname); | 303 | memcpy(name + it->length, "\\", 1); |
304 | #endif | 304 | memcpy(name + it->length + 1, cname, length + 1); |
305 | free(old_name); | 305 | |
306 | 306 | *data = (char *)eina_stringshare_add(name); | |
307 | if (is_last) | 307 | |
308 | res = EINA_FALSE; | 308 | #ifdef UNICODE |
309 | 309 | free(cname); | |
310 | return res; | 310 | #endif |
311 | } | 311 | free(old_name); |
312 | 312 | ||
313 | static HANDLE | 313 | if (is_last) |
314 | _eina_file_win32_ls_iterator_container(Eina_File_Iterator *it) | 314 | res = EINA_FALSE; |
315 | { | 315 | |
316 | return it->handle; | 316 | return res; |
317 | } | 317 | } |
318 | 318 | ||
319 | static void | 319 | static HANDLE |
320 | _eina_file_win32_ls_iterator_free(Eina_File_Iterator *it) | 320 | _eina_file_win32_ls_iterator_container(Eina_File_Iterator *it) |
321 | { | 321 | { |
322 | if (it->handle != INVALID_HANDLE_VALUE) | 322 | return it->handle; |
323 | FindClose(it->handle); | 323 | } |
324 | 324 | ||
325 | EINA_MAGIC_SET(&it->iterator, 0); | 325 | static void |
326 | free(it); | 326 | _eina_file_win32_ls_iterator_free(Eina_File_Iterator *it) |
327 | } | 327 | { |
328 | 328 | if (it->handle != INVALID_HANDLE_VALUE) | |
329 | static Eina_Bool | 329 | FindClose(it->handle); |
330 | _eina_file_win32_direct_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data) | 330 | |
331 | { | 331 | EINA_MAGIC_SET(&it->iterator, 0); |
332 | #ifdef UNICODE | 332 | free(it); |
333 | wchar_t *old_name; | 333 | } |
334 | #else | 334 | |
335 | char *old_name; | 335 | static Eina_Bool |
336 | #endif | 336 | _eina_file_win32_direct_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data) |
337 | char *cname; | 337 | { |
338 | size_t length; | 338 | #ifdef UNICODE |
339 | DWORD attr; | 339 | wchar_t *old_name; |
340 | Eina_Bool is_last; | 340 | #else |
341 | Eina_Bool res = EINA_TRUE; | 341 | char *old_name; |
342 | 342 | #endif | |
343 | if (it->handle == INVALID_HANDLE_VALUE) | 343 | char *cname; |
344 | return EINA_FALSE; | 344 | size_t length; |
345 | 345 | DWORD attr; | |
346 | attr = it->data.dwFileAttributes; | 346 | Eina_Bool is_last; |
347 | is_last = it->is_last; | 347 | Eina_Bool res = EINA_TRUE; |
348 | #ifdef UNICODE | 348 | |
349 | old_name = _wcsdup(it->data.cFileName); | 349 | if (it->handle == INVALID_HANDLE_VALUE) |
350 | #else | 350 | return EINA_FALSE; |
351 | old_name = _strdup(it->data.cFileName); | 351 | |
352 | #endif | 352 | attr = it->data.dwFileAttributes; |
353 | if (!old_name) | 353 | is_last = it->is_last; |
354 | return EINA_FALSE; | 354 | #ifdef UNICODE |
355 | 355 | old_name = _wcsdup(it->data.cFileName); | |
356 | do { | 356 | #else |
357 | if (!FindNextFile(it->handle, &it->data)) | 357 | old_name = _strdup(it->data.cFileName); |
358 | { | 358 | #endif |
359 | if (GetLastError() == ERROR_NO_MORE_FILES) | 359 | if (!old_name) |
360 | it->is_last = EINA_TRUE; | 360 | return EINA_FALSE; |
361 | else | 361 | |
362 | res = EINA_FALSE; | 362 | do { |
363 | } | 363 | if (!FindNextFile(it->handle, &it->data)) |
364 | 364 | { | |
365 | #ifdef UNICODE | 365 | if (GetLastError() == ERROR_NO_MORE_FILES) |
366 | length = wcslen(old_name); | 366 | it->is_last = EINA_TRUE; |
367 | #else | 367 | else |
368 | length = strlen(old_name); | 368 | res = EINA_FALSE; |
369 | #endif | 369 | } |
370 | if (it->info.name_start + length + 1 >= PATH_MAX) | 370 | |
371 | { | 371 | #ifdef UNICODE |
372 | free(old_name); | 372 | length = wcslen(old_name); |
373 | #ifdef UNICODE | 373 | #else |
374 | old_name = _wcsdup(it->data.cFileName); | 374 | length = strlen(old_name); |
375 | #else | 375 | #endif |
376 | old_name = _strdup(it->data.cFileName); | 376 | if (it->info.name_start + length + 1 >= PATH_MAX) |
377 | #endif | 377 | { |
378 | continue; | 378 | free(old_name); |
379 | } | 379 | #ifdef UNICODE |
380 | 380 | old_name = _wcsdup(it->data.cFileName); | |
381 | } while ((it->data.cFileName[0] == '.') && | 381 | #else |
382 | ((it->data.cFileName[1] == '\0') || | 382 | old_name = _strdup(it->data.cFileName); |
383 | ((it->data.cFileName[1] == '.') && (it->data.cFileName[2] == '\0')))); /* FIXME: what about UNICODE ? */ | 383 | #endif |
384 | 384 | continue; | |
385 | #ifdef UNICODE | 385 | } |
386 | cname = evil_wchar_to_char(old_name); | 386 | |
387 | if (!cname) | 387 | } while ((it->data.cFileName[0] == '.') && |
388 | return EINA_FALSE; | 388 | ((it->data.cFileName[1] == '\0') || |
389 | #else | 389 | ((it->data.cFileName[1] == '.') && (it->data.cFileName[2] == '\0')))); /* FIXME: what about UNICODE ? */ |
390 | cname = old_name; | 390 | |
391 | #endif | 391 | #ifdef UNICODE |
392 | 392 | cname = evil_wchar_to_char(old_name); | |
393 | memcpy(it->info.path + it->info.name_start, cname, length); | 393 | if (!cname) |
394 | it->info.name_length = length; | 394 | return EINA_FALSE; |
395 | it->info.path_length = it->info.name_start + length; | 395 | #else |
396 | it->info.path[it->info.path_length] = '\0'; | 396 | cname = old_name; |
397 | 397 | #endif | |
398 | if (attr & FILE_ATTRIBUTE_DIRECTORY) | 398 | |
399 | it->info.type = EINA_FILE_DIR; | 399 | memcpy(it->info.path + it->info.name_start, cname, length); |
400 | else if (attr & FILE_ATTRIBUTE_REPARSE_POINT) | 400 | it->info.name_length = length; |
401 | it->info.type = EINA_FILE_LNK; | 401 | it->info.path_length = it->info.name_start + length; |
402 | else if (attr & (FILE_ATTRIBUTE_ARCHIVE | | 402 | it->info.path[it->info.path_length] = '\0'; |
403 | FILE_ATTRIBUTE_COMPRESSED | | 403 | |
404 | FILE_ATTRIBUTE_COMPRESSED | | 404 | if (attr & FILE_ATTRIBUTE_DIRECTORY) |
405 | FILE_ATTRIBUTE_HIDDEN | | 405 | it->info.type = EINA_FILE_DIR; |
406 | FILE_ATTRIBUTE_NORMAL | | 406 | else if (attr & FILE_ATTRIBUTE_REPARSE_POINT) |
407 | FILE_ATTRIBUTE_SPARSE_FILE | | 407 | it->info.type = EINA_FILE_LNK; |
408 | FILE_ATTRIBUTE_TEMPORARY)) | 408 | else if (attr & (FILE_ATTRIBUTE_ARCHIVE | |
409 | it->info.type = EINA_FILE_REG; | 409 | FILE_ATTRIBUTE_COMPRESSED | |
410 | else | 410 | FILE_ATTRIBUTE_COMPRESSED | |
411 | it->info.type = EINA_FILE_UNKNOWN; | 411 | FILE_ATTRIBUTE_HIDDEN | |
412 | 412 | FILE_ATTRIBUTE_NORMAL | | |
413 | *data = &it->info; | 413 | FILE_ATTRIBUTE_SPARSE_FILE | |
414 | 414 | FILE_ATTRIBUTE_TEMPORARY)) | |
415 | #ifdef UNICODE | 415 | it->info.type = EINA_FILE_REG; |
416 | free(cname); | 416 | else |
417 | #endif | 417 | it->info.type = EINA_FILE_UNKNOWN; |
418 | 418 | ||
419 | free(old_name); | 419 | *data = &it->info; |
420 | 420 | ||
421 | if (is_last) | 421 | #ifdef UNICODE |
422 | res = EINA_FALSE; | 422 | free(cname); |
423 | 423 | #endif | |
424 | return res; | 424 | |
425 | } | 425 | free(old_name); |
426 | 426 | ||
427 | static HANDLE | 427 | if (is_last) |
428 | _eina_file_win32_direct_ls_iterator_container(Eina_File_Direct_Iterator *it) | 428 | res = EINA_FALSE; |
429 | { | 429 | |
430 | return it->handle; | 430 | return res; |
431 | } | 431 | } |
432 | 432 | ||
433 | static void | 433 | static HANDLE |
434 | _eina_file_win32_direct_ls_iterator_free(Eina_File_Direct_Iterator *it) | 434 | _eina_file_win32_direct_ls_iterator_container(Eina_File_Direct_Iterator *it) |
435 | { | 435 | { |
436 | if (it->handle != INVALID_HANDLE_VALUE) | 436 | return it->handle; |
437 | FindClose(it->handle); | 437 | } |
438 | 438 | ||
439 | EINA_MAGIC_SET(&it->iterator, 0); | 439 | static void |
440 | free(it); | 440 | _eina_file_win32_direct_ls_iterator_free(Eina_File_Direct_Iterator *it) |
441 | } | 441 | { |
442 | 442 | if (it->handle != INVALID_HANDLE_VALUE) | |
443 | static void | 443 | FindClose(it->handle); |
444 | _eina_file_real_close(Eina_File *file) | 444 | |
445 | { | 445 | EINA_MAGIC_SET(&it->iterator, 0); |
446 | eina_hash_free(file->rmap); | 446 | free(it); |
447 | eina_hash_free(file->map); | 447 | } |
448 | 448 | ||
449 | if (file->global_map != MAP_FAILED) | 449 | static void |
450 | UnmapViewOfFile(file->global_map); | 450 | _eina_file_real_close(Eina_File *file) |
451 | 451 | { | |
452 | CloseHandle(file->fm); | 452 | eina_hash_free(file->rmap); |
453 | CloseHandle(file->handle); | 453 | eina_hash_free(file->map); |
454 | 454 | ||
455 | eina_stringshare_del(file->filename); | 455 | if (file->global_map != MAP_FAILED) |
456 | 456 | UnmapViewOfFile(file->global_map); | |
457 | free(file); | 457 | |
458 | } | 458 | CloseHandle(file->fm); |
459 | 459 | CloseHandle(file->handle); | |
460 | static void | 460 | |
461 | _eina_file_map_close(Eina_File_Map *map) | 461 | free(file); |
462 | { | 462 | } |
463 | if (map->map != MAP_FAILED) | 463 | |
464 | UnmapViewOfFile(map->map); | 464 | static void |
465 | free(map); | 465 | _eina_file_map_close(Eina_File_Map *map) |
466 | } | 466 | { |
467 | 467 | if (map->map != MAP_FAILED) | |
468 | static unsigned int | 468 | UnmapViewOfFile(map->map); |
469 | _eina_file_map_key_length(const void *key __UNUSED__) | 469 | free(map); |
470 | { | 470 | } |
471 | return sizeof (unsigned long int) * 2; | 471 | |
472 | } | 472 | static unsigned int |
473 | 473 | _eina_file_map_key_length(const void *key __UNUSED__) | |
474 | static int | 474 | { |
475 | _eina_file_map_key_cmp(const unsigned long int *key1, int key1_length __UNUSED__, | 475 | return sizeof (unsigned long int) * 2; |
476 | const unsigned long int *key2, int key2_length __UNUSED__) | 476 | } |
477 | { | 477 | |
478 | if (key1[0] - key2[0] == 0) return key1[1] - key2[1]; | 478 | static int |
479 | return key1[0] - key2[0]; | 479 | _eina_file_map_key_cmp(const unsigned long int *key1, int key1_length __UNUSED__, |
480 | } | 480 | const unsigned long int *key2, int key2_length __UNUSED__) |
481 | 481 | { | |
482 | static int | 482 | if (key1[0] - key2[0] == 0) return key1[1] - key2[1]; |
483 | _eina_file_map_key_hash(const unsigned long int *key, int key_length __UNUSED__) | 483 | return key1[0] - key2[0]; |
484 | { | 484 | } |
485 | return eina_hash_int64(&key[0], sizeof (unsigned long int)) | 485 | |
486 | ^ eina_hash_int64(&key[1], sizeof (unsigned long int)); | 486 | static int |
487 | } | 487 | _eina_file_map_key_hash(const unsigned long int *key, int key_length __UNUSED__) |
488 | 488 | { | |
489 | Eina_Bool | 489 | return eina_hash_int64(&key[0], sizeof (unsigned long int)) |
490 | eina_file_init(void) | 490 | ^ eina_hash_int64(&key[1], sizeof (unsigned long int)); |
491 | { | 491 | } |
492 | _eina_file_log_dom = eina_log_domain_register("eina_file", | 492 | |
493 | EINA_LOG_COLOR_DEFAULT); | 493 | static char * |
494 | if (_eina_file_log_dom < 0) | 494 | _eina_file_win32_escape(const char *path, size_t *length) |
495 | { | 495 | { |
496 | EINA_LOG_ERR("Could not register log domain: eina_file"); | 496 | char *result = strdup(path ? path : ""); |
497 | return EINA_FALSE; | 497 | char *p = result; |
498 | } | 498 | char *q = result; |
499 | 499 | size_t len; | |
500 | _eina_file_cache = eina_hash_string_djb2_new(EINA_FREE_CB(_eina_file_real_close)); | 500 | |
501 | if (!_eina_file_cache) | 501 | if (!result) |
502 | { | 502 | return NULL; |
503 | ERR("Could not create cache."); | 503 | |
504 | eina_log_domain_unregister(_eina_file_log_dom); | 504 | if (length) len = *length; |
505 | _eina_file_log_dom = -1; | 505 | else len = strlen(result); |
506 | return EINA_FALSE; | 506 | |
507 | } | 507 | while ((p = strchr(p, '/'))) |
508 | 508 | { | |
509 | return EINA_TRUE; | 509 | // remove double `/' |
510 | } | 510 | if (p[1] == '/') |
511 | 511 | { | |
512 | Eina_Bool | 512 | memmove(p, p + 1, --len - (p - result)); |
513 | eina_file_shutdown(void) | 513 | result[len] = '\0'; |
514 | { | 514 | } |
515 | Eina_File *f; | 515 | else |
516 | Eina_List *l; | 516 | if (p[1] == '.' |
517 | 517 | && p[2] == '.') | |
518 | EINA_LIST_FREE(_eina_file_cache_delete, f) | 518 | { |
519 | _eina_file_real_close(f); | 519 | // remove `/../' |
520 | 520 | if (p[3] == '/') | |
521 | EINA_LIST_FOREACH(_eina_file_cache_lru, l, f) | 521 | { |
522 | eina_hash_del(_eina_file_cache, f->filename, f); | 522 | char tmp; |
523 | 523 | ||
524 | if (eina_hash_population(_eina_file_cache) > 0) | 524 | len -= p + 3 - q; |
525 | { | 525 | memmove(q, p + 3, len - (q - result)); |
526 | Eina_Iterator *it; | 526 | result[len] = '\0'; |
527 | const char *key; | 527 | p = q; |
528 | 528 | ||
529 | it = eina_hash_iterator_key_new(_eina_file_cache); | 529 | /* Update q correctly. */ |
530 | EINA_ITERATOR_FOREACH(it, key) | 530 | tmp = *p; |
531 | ERR("File [%s] still open !", key); | 531 | *p = '\0'; |
532 | eina_iterator_free(it); | 532 | q = strrchr(result, '/'); |
533 | } | 533 | if (!q) q = result; |
534 | 534 | *p = tmp; | |
535 | eina_hash_free(_eina_file_cache); | 535 | } |
536 | 536 | else | |
537 | eina_log_domain_unregister(_eina_file_log_dom); | 537 | // remove '/..$' |
538 | _eina_file_log_dom = -1; | 538 | if (p[3] == '\0') |
539 | return EINA_TRUE; | 539 | { |
540 | } | 540 | len -= p + 2 - q; |
541 | 541 | result[len] = '\0'; | |
542 | 542 | q = p; | |
543 | /** | 543 | ++p; |
544 | * @endcond | 544 | } |
545 | */ | 545 | else |
546 | 546 | { | |
547 | /*============================================================================* | 547 | q = p; |
548 | * Global * | 548 | ++p; |
549 | *============================================================================*/ | 549 | } |
550 | 550 | } | |
551 | /*============================================================================* | 551 | else |
552 | * API * | 552 | { |
553 | *============================================================================*/ | 553 | q = p; |
554 | 554 | ++p; | |
555 | EAPI Eina_Bool | 555 | } |
556 | eina_file_dir_list(const char *dir, | 556 | } |
557 | Eina_Bool recursive, | 557 | |
558 | Eina_File_Dir_List_Cb cb, | 558 | if (length) |
559 | void *data) | 559 | *length = len; |
560 | { | 560 | |
561 | WIN32_FIND_DATA file; | 561 | return result; |
562 | HANDLE h; | 562 | } |
563 | char *new_dir; | 563 | |
564 | 564 | ||
565 | EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE); | 565 | /** |
566 | EINA_SAFETY_ON_NULL_RETURN_VAL(dir, EINA_FALSE); | 566 | * @endcond |
567 | EINA_SAFETY_ON_TRUE_RETURN_VAL(dir[0] == '\0', EINA_FALSE); | 567 | */ |
568 | 568 | ||
569 | if (!_eina_file_win32_is_dir(dir)) | 569 | /*============================================================================* |
570 | return EINA_FALSE; | 570 | * Global * |
571 | 571 | *============================================================================*/ | |
572 | new_dir = _eina_file_win32_dir_new(dir); | 572 | |
573 | if (!new_dir) | 573 | Eina_Bool |
574 | return EINA_FALSE; | 574 | eina_file_init(void) |
575 | 575 | { | |
576 | h = _eina_file_win32_first_file(new_dir, &file); | 576 | _eina_file_log_dom = eina_log_domain_register("eina_file", |
577 | 577 | EINA_LOG_COLOR_DEFAULT); | |
578 | if (h == INVALID_HANDLE_VALUE) | 578 | if (_eina_file_log_dom < 0) |
579 | return EINA_FALSE; | 579 | { |
580 | 580 | EINA_LOG_ERR("Could not register log domain: eina_file"); | |
581 | do | 581 | return EINA_FALSE; |
582 | { | 582 | } |
583 | char *filename; | 583 | |
584 | 584 | _eina_file_cache = eina_hash_string_djb2_new(NULL); | |
585 | # ifdef UNICODE | 585 | if (!_eina_file_cache) |
586 | filename = evil_wchar_to_char(file.cFileName); | 586 | { |
587 | # else | 587 | ERR("Could not create cache."); |
588 | filename = file.cFileName; | 588 | eina_log_domain_unregister(_eina_file_log_dom); |
589 | # endif /* ! UNICODE */ | 589 | _eina_file_log_dom = -1; |
590 | if (!strcmp(filename, ".") || !strcmp(filename, "..")) | 590 | return EINA_FALSE; |
591 | continue; | 591 | } |
592 | 592 | ||
593 | cb(filename, dir, data); | 593 | eina_lock_new(&_eina_file_lock_cache); |
594 | 594 | ||
595 | if (recursive == EINA_TRUE) | 595 | return EINA_TRUE; |
596 | { | 596 | } |
597 | char *path; | 597 | |
598 | 598 | Eina_Bool | |
599 | path = alloca(strlen(dir) + strlen(filename) + 2); | 599 | eina_file_shutdown(void) |
600 | strcpy(path, dir); | 600 | { |
601 | strcat(path, "/"); | 601 | if (eina_hash_population(_eina_file_cache) > 0) |
602 | strcat(path, filename); | 602 | { |
603 | 603 | Eina_Iterator *it; | |
604 | if (!(file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) | 604 | const char *key; |
605 | continue; | 605 | |
606 | 606 | it = eina_hash_iterator_key_new(_eina_file_cache); | |
607 | eina_file_dir_list(path, recursive, cb, data); | 607 | EINA_ITERATOR_FOREACH(it, key) |
608 | } | 608 | ERR("File [%s] still open !", key); |
609 | 609 | eina_iterator_free(it); | |
610 | # ifdef UNICODE | 610 | } |
611 | free(filename); | 611 | |
612 | # endif /* UNICODE */ | 612 | eina_hash_free(_eina_file_cache); |
613 | 613 | ||
614 | } while (FindNextFile(h, &file)); | 614 | eina_lock_free(&_eina_file_lock_cache); |
615 | FindClose(h); | 615 | |
616 | 616 | eina_log_domain_unregister(_eina_file_log_dom); | |
617 | return EINA_TRUE; | 617 | _eina_file_log_dom = -1; |
618 | } | 618 | return EINA_TRUE; |
619 | 619 | } | |
620 | EAPI Eina_Array * | 620 | |
621 | eina_file_split(char *path) | 621 | /*============================================================================* |
622 | { | 622 | * API * |
623 | Eina_Array *ea; | 623 | *============================================================================*/ |
624 | char *current; | 624 | |
625 | size_t length; | 625 | |
626 | 626 | EAPI char * | |
627 | EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL); | 627 | eina_file_path_sanitize(const char *path) |
628 | 628 | { | |
629 | ea = eina_array_new(16); | 629 | char *result = NULL; |
630 | 630 | size_t len; | |
631 | if (!ea) | 631 | |
632 | return NULL; | 632 | if (!path) return NULL; |
633 | 633 | ||
634 | for (current = strchr(path, '\\'); | 634 | len = strlen(path); |
635 | current; | 635 | if (len < 3) return NULL; |
636 | path = current + 1, current = strchr(path, '\\')) | 636 | |
637 | { | 637 | if (!evil_path_is_absolute(path)) |
638 | length = current - path; | 638 | { |
639 | 639 | DWORD l; | |
640 | if (length <= 0) | 640 | |
641 | continue; | 641 | l = GetCurrentDirectory(0, NULL); |
642 | 642 | if (l > 0) | |
643 | eina_array_push(ea, path); | 643 | { |
644 | *current = '\0'; | 644 | char *cwd; |
645 | } | 645 | DWORD l2; |
646 | 646 | ||
647 | if (*path != '\0') | 647 | cwd = alloca(sizeof(char) * (l + 1)); |
648 | eina_array_push(ea, path); | 648 | l2 = GetCurrentDirectory(l + 1, cwd); |
649 | 649 | if (l2 == l) | |
650 | return ea; | 650 | { |
651 | } | 651 | char *tmp; |
652 | 652 | ||
653 | EAPI Eina_Iterator * | 653 | len += l + 2; |
654 | eina_file_ls(const char *dir) | 654 | tmp = alloca(sizeof (char) * len); |
655 | { | 655 | snprintf(tmp, len, "%s/%s", cwd, path); |
656 | Eina_File_Iterator *it; | 656 | tmp[len - 1] = '\0'; |
657 | char *new_dir; | 657 | result = tmp; |
658 | size_t length; | 658 | } |
659 | 659 | } | |
660 | if (!dir || !*dir) | 660 | } |
661 | return NULL; | 661 | |
662 | 662 | return _eina_file_win32_escape(result ? result : path, &len); | |
663 | if (!_eina_file_win32_is_dir(dir)) | 663 | } |
664 | return NULL; | 664 | |
665 | 665 | EAPI Eina_Bool | |
666 | length = strlen(dir); | 666 | eina_file_dir_list(const char *dir, |
667 | 667 | Eina_Bool recursive, | |
668 | it = calloc(1, sizeof (Eina_File_Iterator) + length); | 668 | Eina_File_Dir_List_Cb cb, |
669 | if (!it) | 669 | void *data) |
670 | return NULL; | 670 | { |
671 | 671 | WIN32_FIND_DATA file; | |
672 | EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); | 672 | HANDLE h; |
673 | 673 | char *new_dir; | |
674 | new_dir = _eina_file_win32_dir_new(dir); | 674 | |
675 | if (!new_dir) | 675 | EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE); |
676 | goto free_it; | 676 | EINA_SAFETY_ON_NULL_RETURN_VAL(dir, EINA_FALSE); |
677 | 677 | EINA_SAFETY_ON_TRUE_RETURN_VAL(dir[0] == '\0', EINA_FALSE); | |
678 | it->handle = _eina_file_win32_first_file(new_dir, &it->data); | 678 | |
679 | free(new_dir); | 679 | if (!_eina_file_win32_is_dir(dir)) |
680 | if (it->handle == INVALID_HANDLE_VALUE) | 680 | return EINA_FALSE; |
681 | goto free_it; | 681 | |
682 | 682 | new_dir = _eina_file_win32_dir_new(dir); | |
683 | memcpy(it->dir, dir, length + 1); | 683 | if (!new_dir) |
684 | if (dir[length - 1] != '\\') | 684 | return EINA_FALSE; |
685 | it->length = length; | 685 | |
686 | else | 686 | h = _eina_file_win32_first_file(new_dir, &file); |
687 | it->length = length - 1; | 687 | |
688 | _eina_file_win32_backslash_change(it->dir); | 688 | if (h == INVALID_HANDLE_VALUE) |
689 | 689 | return EINA_FALSE; | |
690 | it->iterator.version = EINA_ITERATOR_VERSION; | 690 | |
691 | it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_win32_ls_iterator_next); | 691 | do |
692 | it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_win32_ls_iterator_container); | 692 | { |
693 | it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_win32_ls_iterator_free); | 693 | char *filename; |
694 | 694 | ||
695 | return &it->iterator; | 695 | # ifdef UNICODE |
696 | 696 | filename = evil_wchar_to_char(file.cFileName); | |
697 | free_it: | 697 | # else |
698 | free(it); | 698 | filename = file.cFileName; |
699 | 699 | # endif /* ! UNICODE */ | |
700 | return NULL; | 700 | if (!strcmp(filename, ".") || !strcmp(filename, "..")) |
701 | } | 701 | continue; |
702 | 702 | ||
703 | EAPI Eina_Iterator * | 703 | cb(filename, dir, data); |
704 | eina_file_direct_ls(const char *dir) | 704 | |
705 | { | 705 | if (recursive == EINA_TRUE) |
706 | Eina_File_Direct_Iterator *it; | 706 | { |
707 | char *new_dir; | 707 | char *path; |
708 | size_t length; | 708 | |
709 | 709 | path = alloca(strlen(dir) + strlen(filename) + 2); | |
710 | if (!dir || !*dir) | 710 | strcpy(path, dir); |
711 | return NULL; | 711 | strcat(path, "/"); |
712 | 712 | strcat(path, filename); | |
713 | length = strlen(dir); | 713 | |
714 | 714 | if (!(file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) | |
715 | if (length + 12 + 2 >= MAX_PATH) | 715 | continue; |
716 | return NULL; | 716 | |
717 | 717 | eina_file_dir_list(path, recursive, cb, data); | |
718 | it = calloc(1, sizeof(Eina_File_Direct_Iterator) + length); | 718 | } |
719 | if (!it) | 719 | |
720 | return NULL; | 720 | # ifdef UNICODE |
721 | 721 | free(filename); | |
722 | EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); | 722 | # endif /* UNICODE */ |
723 | 723 | ||
724 | new_dir = _eina_file_win32_dir_new(dir); | 724 | } while (FindNextFile(h, &file)); |
725 | if (!new_dir) | 725 | FindClose(h); |
726 | goto free_it; | 726 | |
727 | 727 | return EINA_TRUE; | |
728 | it->handle = _eina_file_win32_first_file(new_dir, &it->data); | 728 | } |
729 | free(new_dir); | 729 | |
730 | if (it->handle == INVALID_HANDLE_VALUE) | 730 | EAPI Eina_Array * |
731 | goto free_it; | 731 | eina_file_split(char *path) |
732 | 732 | { | |
733 | memcpy(it->dir, dir, length + 1); | 733 | Eina_Array *ea; |
734 | it->length = length; | 734 | char *current; |
735 | _eina_file_win32_backslash_change(it->dir); | 735 | size_t length; |
736 | 736 | ||
737 | memcpy(it->info.path, dir, length); | 737 | EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL); |
738 | if (dir[length - 1] == '\\') | 738 | |
739 | it->info.name_start = length; | 739 | ea = eina_array_new(16); |
740 | else | 740 | |
741 | { | 741 | if (!ea) |
742 | it->info.path[length] = '\\'; | 742 | return NULL; |
743 | it->info.name_start = length + 1; | 743 | |
744 | } | 744 | for (current = strchr(path, '\\'); |
745 | _eina_file_win32_backslash_change(it->info.path); | 745 | current; |
746 | 746 | path = current + 1, current = strchr(path, '\\')) | |
747 | it->iterator.version = EINA_ITERATOR_VERSION; | 747 | { |
748 | it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_win32_direct_ls_iterator_next); | 748 | length = current - path; |
749 | it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_win32_direct_ls_iterator_container); | 749 | |
750 | it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_win32_direct_ls_iterator_free); | 750 | if (length <= 0) |
751 | 751 | continue; | |
752 | return &it->iterator; | 752 | |
753 | 753 | eina_array_push(ea, path); | |
754 | free_it: | 754 | *current = '\0'; |
755 | free(it); | 755 | } |
756 | 756 | ||
757 | return NULL; | 757 | if (*path != '\0') |
758 | } | 758 | eina_array_push(ea, path); |
759 | 759 | ||
760 | EAPI Eina_Iterator * | 760 | return ea; |
761 | eina_file_stat_ls(const char *dir) | 761 | } |
762 | { | 762 | |
763 | return eina_file_direct_ls(dir); | 763 | EAPI Eina_Iterator * |
764 | } | 764 | eina_file_ls(const char *dir) |
765 | 765 | { | |
766 | EAPI Eina_File * | 766 | Eina_File_Iterator *it; |
767 | eina_file_open(const char *filename, Eina_Bool shared) | 767 | char *new_dir; |
768 | { | 768 | size_t length; |
769 | Eina_File *file; | 769 | |
770 | Eina_File *n; | 770 | EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL); |
771 | HANDLE handle; | 771 | |
772 | HANDLE fm; | 772 | if (!dir || !*dir) |
773 | WIN32_FILE_ATTRIBUTE_DATA fad; | 773 | return NULL; |
774 | ULARGE_INTEGER length; | 774 | |
775 | ULARGE_INTEGER mtime; | 775 | if (!_eina_file_win32_is_dir(dir)) |
776 | Eina_Bool create = EINA_FALSE; | 776 | return NULL; |
777 | 777 | ||
778 | /* FIXME: always open absolute path (need to fix filename according to current | 778 | length = strlen(dir); |
779 | directory) */ | 779 | |
780 | 780 | it = calloc(1, sizeof (Eina_File_Iterator) + length); | |
781 | /* FIXME: how to emulate shm_open ? Just OpenFileMapping ? */ | 781 | if (!it) |
782 | #if 0 | 782 | return NULL; |
783 | if (shared) | 783 | |
784 | handle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, | 784 | EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); |
785 | NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, | 785 | |
786 | NULL); | 786 | new_dir = _eina_file_win32_dir_new(dir); |
787 | else | 787 | if (!new_dir) |
788 | #endif | 788 | goto free_it; |
789 | handle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, | 789 | |
790 | NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, | 790 | it->handle = _eina_file_win32_first_file(new_dir, &it->data); |
791 | NULL); | 791 | free(new_dir); |
792 | 792 | if (it->handle == INVALID_HANDLE_VALUE) | |
793 | if (handle == INVALID_HANDLE_VALUE) | 793 | goto free_it; |
794 | return NULL; | 794 | |
795 | 795 | memcpy(it->dir, dir, length + 1); | |
796 | fm = CreateFileMapping(handle, NULL, PAGE_READONLY, 0, 0, NULL); | 796 | if (dir[length - 1] != '\\') |
797 | if (!fm) | 797 | it->length = length; |
798 | goto close_handle; | 798 | else |
799 | 799 | it->length = length - 1; | |
800 | if (!GetFileAttributesEx(filename, GetFileExInfoStandard, &fad)) | 800 | _eina_file_win32_backslash_change(it->dir); |
801 | goto close_fm; | 801 | |
802 | 802 | it->iterator.version = EINA_ITERATOR_VERSION; | |
803 | length.u.LowPart = fad.nFileSizeLow; | 803 | it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_win32_ls_iterator_next); |
804 | length.u.HighPart = fad.nFileSizeHigh; | 804 | it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_win32_ls_iterator_container); |
805 | mtime.u.LowPart = fad.ftLastWriteTime.dwLowDateTime; | 805 | it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_win32_ls_iterator_free); |
806 | mtime.u.HighPart = fad.ftLastWriteTime.dwHighDateTime; | 806 | |
807 | 807 | return &it->iterator; | |
808 | file = eina_hash_find(_eina_file_cache, filename); | 808 | |
809 | if (file && | 809 | free_it: |
810 | (file->mtime != mtime.QuadPart || file->length != length.QuadPart)) | 810 | free(it); |
811 | { | 811 | |
812 | create = EINA_TRUE; | 812 | return NULL; |
813 | 813 | } | |
814 | if (file->refcount == 0) | 814 | |
815 | { | 815 | EAPI Eina_Iterator * |
816 | _eina_file_cache_lru = eina_list_prepend(_eina_file_cache_lru, file); | 816 | eina_file_direct_ls(const char *dir) |
817 | eina_hash_del(_eina_file_cache, file->filename, file); | 817 | { |
818 | 818 | Eina_File_Direct_Iterator *it; | |
819 | file = NULL; | 819 | char *new_dir; |
820 | } | 820 | size_t length; |
821 | else if (!file->delete_me) | 821 | |
822 | { | 822 | EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL); |
823 | file->delete_me = EINA_TRUE; | 823 | |
824 | _eina_file_cache_delete = eina_list_prepend(_eina_file_cache_delete, file); | 824 | if (!dir || !*dir) |
825 | } | 825 | return NULL; |
826 | } | 826 | |
827 | 827 | length = strlen(dir); | |
828 | if (!file || create) | 828 | |
829 | { | 829 | if (length + 12 + 2 >= MAX_PATH) |
830 | n = calloc(1, sizeof (Eina_File)); | 830 | return NULL; |
831 | if (!n) | 831 | |
832 | goto close_fm; | 832 | it = calloc(1, sizeof(Eina_File_Direct_Iterator) + length); |
833 | 833 | if (!it) | |
834 | n->filename = eina_stringshare_add(filename); | 834 | return NULL; |
835 | n->map = eina_hash_new(EINA_KEY_LENGTH(_eina_file_map_key_length), | 835 | |
836 | EINA_KEY_CMP(_eina_file_map_key_cmp), | 836 | EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); |
837 | EINA_KEY_HASH(_eina_file_map_key_hash), | 837 | |
838 | EINA_FREE_CB(_eina_file_map_close), | 838 | new_dir = _eina_file_win32_dir_new(dir); |
839 | 3); | 839 | if (!new_dir) |
840 | n->rmap = eina_hash_pointer_new(NULL); | 840 | goto free_it; |
841 | n->global_map = MAP_FAILED; | 841 | |
842 | n->length = length.QuadPart; | 842 | it->handle = _eina_file_win32_first_file(new_dir, &it->data); |
843 | n->mtime = mtime.QuadPart; | 843 | free(new_dir); |
844 | n->refcount = 0; | 844 | if (it->handle == INVALID_HANDLE_VALUE) |
845 | n->handle = handle; | 845 | goto free_it; |
846 | n->fm = fm; | 846 | |
847 | n->shared = shared; | 847 | memcpy(it->dir, dir, length + 1); |
848 | n->delete_me = EINA_FALSE; | 848 | it->length = length; |
849 | 849 | _eina_file_win32_backslash_change(it->dir); | |
850 | eina_hash_set(_eina_file_cache, filename, n); | 850 | |
851 | } | 851 | memcpy(it->info.path, dir, length); |
852 | else | 852 | if (dir[length - 1] == '\\') |
853 | { | 853 | it->info.name_start = length; |
854 | CloseHandle(fm); | 854 | else |
855 | CloseHandle(handle); | 855 | { |
856 | 856 | it->info.path[length] = '\\'; | |
857 | n = file; | 857 | it->info.name_start = length + 1; |
858 | 858 | } | |
859 | if (n->refcount == 0) | 859 | _eina_file_win32_backslash_change(it->info.path); |
860 | _eina_file_cache_lru = eina_list_remove(_eina_file_cache_lru, n); | 860 | |
861 | } | 861 | it->iterator.version = EINA_ITERATOR_VERSION; |
862 | 862 | it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_win32_direct_ls_iterator_next); | |
863 | n->refcount++; | 863 | it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_win32_direct_ls_iterator_container); |
864 | 864 | it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_win32_direct_ls_iterator_free); | |
865 | return n; | 865 | |
866 | 866 | return &it->iterator; | |
867 | close_fm: | 867 | |
868 | CloseHandle(fm); | 868 | free_it: |
869 | close_handle: | 869 | free(it); |
870 | CloseHandle(handle); | 870 | |
871 | 871 | return NULL; | |
872 | return NULL; | 872 | } |
873 | } | 873 | |
874 | 874 | EAPI Eina_Iterator * | |
875 | EAPI void | 875 | eina_file_stat_ls(const char *dir) |
876 | eina_file_close(Eina_File *file) | 876 | { |
877 | { | 877 | return eina_file_direct_ls(dir); |
878 | file->refcount--; | 878 | } |
879 | 879 | ||
880 | if (file->refcount != 0) return ; | 880 | EAPI Eina_File * |
881 | 881 | eina_file_open(const char *path, Eina_Bool shared) | |
882 | if (file->delete_me) | 882 | { |
883 | { | 883 | Eina_File *file; |
884 | _eina_file_cache_delete = eina_list_remove(_eina_file_cache_delete, file); | 884 | Eina_File *n; |
885 | _eina_file_real_close(file); | 885 | char *filename; |
886 | } | 886 | HANDLE handle; |
887 | else | 887 | HANDLE fm; |
888 | { | 888 | WIN32_FILE_ATTRIBUTE_DATA fad; |
889 | _eina_file_cache_lru = eina_list_prepend(_eina_file_cache_lru, file); | 889 | ULARGE_INTEGER length; |
890 | } | 890 | ULARGE_INTEGER mtime; |
891 | } | 891 | |
892 | 892 | EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL); | |
893 | EAPI size_t | 893 | |
894 | eina_file_size_get(Eina_File *file) | 894 | filename = eina_file_path_sanitize(path); |
895 | { | 895 | if (!filename) return NULL; |
896 | return file->length; | 896 | |
897 | } | 897 | /* FIXME: how to emulate shm_open ? Just OpenFileMapping ? */ |
898 | 898 | #if 0 | |
899 | EAPI time_t | 899 | if (shared) |
900 | eina_file_mtime_get(Eina_File *file) | 900 | handle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, |
901 | { | 901 | NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, |
902 | return file->mtime; | 902 | NULL); |
903 | } | 903 | else |
904 | 904 | #endif | |
905 | EAPI const char * | 905 | handle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, |
906 | eina_file_filename_get(Eina_File *file) | 906 | NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, |
907 | { | 907 | NULL); |
908 | return file->filename; | 908 | |
909 | } | 909 | if (handle == INVALID_HANDLE_VALUE) |
910 | 910 | return NULL; | |
911 | EAPI void * | 911 | |
912 | eina_file_map_all(Eina_File *file, Eina_File_Populate rule __UNUSED__) | 912 | fm = CreateFileMapping(handle, NULL, PAGE_READONLY, 0, 0, NULL); |
913 | { | 913 | if (!fm) |
914 | if (file->global_map == MAP_FAILED) | 914 | goto close_handle; |
915 | { | 915 | |
916 | void *data; | 916 | if (!GetFileAttributesEx(filename, GetFileExInfoStandard, &fad)) |
917 | 917 | goto close_fm; | |
918 | data = MapViewOfFile(file->fm, FILE_MAP_READ, | 918 | |
919 | 0, 0, file->length); | 919 | length.u.LowPart = fad.nFileSizeLow; |
920 | if (!data) | 920 | length.u.HighPart = fad.nFileSizeHigh; |
921 | file->global_map = MAP_FAILED; | 921 | mtime.u.LowPart = fad.ftLastWriteTime.dwLowDateTime; |
922 | else | 922 | mtime.u.HighPart = fad.ftLastWriteTime.dwHighDateTime; |
923 | file->global_map = data; | 923 | |
924 | } | 924 | eina_lock_take(&_eina_file_lock_cache); |
925 | 925 | ||
926 | if (file->global_map != MAP_FAILED) | 926 | file = eina_hash_find(_eina_file_cache, filename); |
927 | { | 927 | if (file && |
928 | file->global_refcount++; | 928 | (file->mtime != mtime.QuadPart || file->length != length.QuadPart)) |
929 | return file->global_map; | 929 | { |
930 | } | 930 | file->delete_me = EINA_TRUE; |
931 | 931 | eina_hash_del(_eina_file_cache, file->filename, file); | |
932 | return NULL; | 932 | _eina_file_real_close(file); |
933 | } | 933 | file = NULL; |
934 | 934 | } | |
935 | EAPI void * | 935 | |
936 | eina_file_map_new(Eina_File *file, Eina_File_Populate rule, | 936 | if (!file) |
937 | unsigned long int offset, unsigned long int length) | 937 | { |
938 | { | 938 | n = malloc(sizeof (Eina_File) + strlen(filename) + 1); |
939 | Eina_File_Map *map; | 939 | if (!n) |
940 | unsigned long int key[2]; | 940 | { |
941 | 941 | eina_lock_release(&_eina_file_lock_cache); | |
942 | if (offset > file->length) | 942 | goto close_fm; |
943 | return NULL; | 943 | } |
944 | if (offset + length > file->length) | 944 | |
945 | return NULL; | 945 | n->filename = (char*) (n + 1); |
946 | 946 | strcpy((char*) n->filename, filename); | |
947 | if (offset == 0 && length == file->length) | 947 | n->map = eina_hash_new(EINA_KEY_LENGTH(_eina_file_map_key_length), |
948 | return eina_file_map_all(file, rule); | 948 | EINA_KEY_CMP(_eina_file_map_key_cmp), |
949 | 949 | EINA_KEY_HASH(_eina_file_map_key_hash), | |
950 | key[0] = offset; | 950 | EINA_FREE_CB(_eina_file_map_close), |
951 | key[1] = length; | 951 | 3); |
952 | 952 | n->rmap = eina_hash_pointer_new(NULL); | |
953 | map = eina_hash_find(file->map, &key); | 953 | n->global_map = MAP_FAILED; |
954 | if (!map) | 954 | n->global_refcount = 0; |
955 | { | 955 | n->length = length.QuadPart; |
956 | void *data; | 956 | n->mtime = mtime.QuadPart; |
957 | 957 | n->refcount = 0; | |
958 | map = malloc(sizeof (Eina_File_Map)); | 958 | n->handle = handle; |
959 | if (!map) return NULL; | 959 | n->fm = fm; |
960 | 960 | n->shared = shared; | |
961 | data = MapViewOfFile(file->fm, FILE_MAP_READ, | 961 | n->delete_me = EINA_FALSE; |
962 | offset & 0xffff0000, | 962 | eina_lock_new(&n->lock); |
963 | offset & 0x0000ffff, | 963 | eina_hash_direct_add(_eina_file_cache, n->filename, n); |
964 | length); | 964 | } |
965 | if (!data) | 965 | else |
966 | map->map = MAP_FAILED; | 966 | { |
967 | else | 967 | CloseHandle(fm); |
968 | map->map = data; | 968 | CloseHandle(handle); |
969 | 969 | ||
970 | map->offset = offset; | 970 | n = file; |
971 | map->length = length; | 971 | } |
972 | map->refcount = 0; | 972 | eina_lock_take(&n->lock); |
973 | 973 | n->refcount++; | |
974 | if (map->map == MAP_FAILED) | 974 | eina_lock_release(&n->lock); |
975 | { | 975 | |
976 | free(map); | 976 | eina_lock_release(&_eina_file_lock_cache); |
977 | return NULL; | 977 | |
978 | } | 978 | free(filename); |
979 | 979 | ||
980 | eina_hash_add(file->map, &key, map); | 980 | return n; |
981 | eina_hash_direct_add(file->rmap, map->map, map); | 981 | |
982 | } | 982 | close_fm: |
983 | 983 | CloseHandle(fm); | |
984 | map->refcount++; | 984 | close_handle: |
985 | 985 | CloseHandle(handle); | |
986 | return map->map; | 986 | |
987 | } | 987 | return NULL; |
988 | 988 | } | |
989 | EAPI void | 989 | |
990 | eina_file_map_free(Eina_File *file, void *map) | 990 | EAPI void |
991 | { | 991 | eina_file_close(Eina_File *file) |
992 | if (file->global_map == map) | 992 | { |
993 | { | 993 | EINA_SAFETY_ON_NULL_RETURN(file); |
994 | file->global_refcount--; | 994 | |
995 | 995 | eina_lock_take(&file->lock); | |
996 | if (file->global_refcount > 0) return ; | 996 | file->refcount--; |
997 | 997 | eina_lock_release(&file->lock); | |
998 | /* FIXME: are we sure that file->global_map != MAP_FAILED ? */ | 998 | |
999 | if (file->global_map != MAP_FAILED) | 999 | if (file->refcount != 0) return ; |
1000 | UnmapViewOfFile(file->global_map); | 1000 | eina_lock_take(&_eina_file_lock_cache); |
1001 | file->global_map = MAP_FAILED; | 1001 | |
1002 | } | 1002 | eina_hash_del(_eina_file_cache, file->filename, file); |
1003 | else | 1003 | _eina_file_real_close(file); |
1004 | { | 1004 | |
1005 | Eina_File_Map *em; | 1005 | eina_lock_release(&_eina_file_lock_cache); |
1006 | unsigned long int key[2]; | 1006 | } |
1007 | 1007 | ||
1008 | em = eina_hash_find(file->rmap, &map); | 1008 | EAPI size_t |
1009 | if (!em) return ; | 1009 | eina_file_size_get(Eina_File *file) |
1010 | 1010 | { | |
1011 | em->refcount--; | 1011 | EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0); |
1012 | 1012 | return file->length; | |
1013 | if (em->refcount > 0) return ; | 1013 | } |
1014 | 1014 | ||
1015 | key[0] = em->offset; | 1015 | EAPI time_t |
1016 | key[1] = em->length; | 1016 | eina_file_mtime_get(Eina_File *file) |
1017 | 1017 | { | |
1018 | eina_hash_del(file->rmap, &map, em); | 1018 | EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0); |
1019 | eina_hash_del(file->map, &key, em); | 1019 | return file->mtime; |
1020 | } | 1020 | } |
1021 | } | 1021 | |
1022 | EAPI const char * | ||
1023 | eina_file_filename_get(Eina_File *file) | ||
1024 | { | ||
1025 | EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); | ||
1026 | return file->filename; | ||
1027 | } | ||
1028 | |||
1029 | EAPI Eina_Iterator *eina_file_xattr_get(Eina_File *file __UNUSED__) | ||
1030 | { | ||
1031 | return NULL; | ||
1032 | } | ||
1033 | |||
1034 | EAPI Eina_Iterator *eina_file_xattr_value_get(Eina_File *file __UNUSED__) | ||
1035 | { | ||
1036 | return NULL; | ||
1037 | } | ||
1038 | |||
1039 | EAPI void * | ||
1040 | eina_file_map_all(Eina_File *file, Eina_File_Populate rule __UNUSED__) | ||
1041 | { | ||
1042 | EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); | ||
1043 | |||
1044 | eina_lock_take(&file->lock); | ||
1045 | if (file->global_map == MAP_FAILED) | ||
1046 | { | ||
1047 | void *data; | ||
1048 | |||
1049 | data = MapViewOfFile(file->fm, FILE_MAP_READ, | ||
1050 | 0, 0, file->length); | ||
1051 | if (!data) | ||
1052 | file->global_map = MAP_FAILED; | ||
1053 | else | ||
1054 | file->global_map = data; | ||
1055 | } | ||
1056 | |||
1057 | if (file->global_map != MAP_FAILED) | ||
1058 | { | ||
1059 | file->global_refcount++; | ||
1060 | return file->global_map; | ||
1061 | } | ||
1062 | |||
1063 | eina_lock_release(&file->lock); | ||
1064 | return NULL; | ||
1065 | } | ||
1066 | |||
1067 | EAPI void * | ||
1068 | eina_file_map_new(Eina_File *file, Eina_File_Populate rule, | ||
1069 | unsigned long int offset, unsigned long int length) | ||
1070 | { | ||
1071 | Eina_File_Map *map; | ||
1072 | unsigned long int key[2]; | ||
1073 | |||
1074 | EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); | ||
1075 | |||
1076 | if (offset > file->length) | ||
1077 | return NULL; | ||
1078 | if (offset + length > file->length) | ||
1079 | return NULL; | ||
1080 | |||
1081 | if (offset == 0 && length == file->length) | ||
1082 | return eina_file_map_all(file, rule); | ||
1083 | |||
1084 | key[0] = offset; | ||
1085 | key[1] = length; | ||
1086 | |||
1087 | eina_lock_take(&file->lock); | ||
1088 | |||
1089 | map = eina_hash_find(file->map, &key); | ||
1090 | if (!map) | ||
1091 | { | ||
1092 | void *data; | ||
1093 | |||
1094 | map = malloc(sizeof (Eina_File_Map)); | ||
1095 | if (!map) | ||
1096 | { | ||
1097 | eina_lock_release(&file->lock); | ||
1098 | return NULL; | ||
1099 | } | ||
1100 | |||
1101 | data = MapViewOfFile(file->fm, FILE_MAP_READ, | ||
1102 | offset & 0xffff0000, | ||
1103 | offset & 0x0000ffff, | ||
1104 | length); | ||
1105 | if (!data) | ||
1106 | map->map = MAP_FAILED; | ||
1107 | else | ||
1108 | map->map = data; | ||
1109 | |||
1110 | map->offset = offset; | ||
1111 | map->length = length; | ||
1112 | map->refcount = 0; | ||
1113 | |||
1114 | if (map->map == MAP_FAILED) | ||
1115 | { | ||
1116 | free(map); | ||
1117 | eina_lock_release(&file->lock); | ||
1118 | return NULL; | ||
1119 | } | ||
1120 | |||
1121 | eina_hash_add(file->map, &key, map); | ||
1122 | eina_hash_direct_add(file->rmap, map->map, map); | ||
1123 | } | ||
1124 | |||
1125 | map->refcount++; | ||
1126 | |||
1127 | eina_lock_release(&file->lock); | ||
1128 | |||
1129 | return map->map; | ||
1130 | } | ||
1131 | |||
1132 | EAPI void | ||
1133 | eina_file_map_free(Eina_File *file, void *map) | ||
1134 | { | ||
1135 | EINA_SAFETY_ON_NULL_RETURN(file); | ||
1136 | |||
1137 | eina_lock_take(&file->lock); | ||
1138 | |||
1139 | if (file->global_map == map) | ||
1140 | { | ||
1141 | file->global_refcount--; | ||
1142 | |||
1143 | if (file->global_refcount > 0) goto on_exit; | ||
1144 | |||
1145 | UnmapViewOfFile(file->global_map); | ||
1146 | file->global_map = MAP_FAILED; | ||
1147 | } | ||
1148 | else | ||
1149 | { | ||
1150 | Eina_File_Map *em; | ||
1151 | unsigned long int key[2]; | ||
1152 | |||
1153 | em = eina_hash_find(file->rmap, &map); | ||
1154 | if (!em) goto on_exit; | ||
1155 | |||
1156 | em->refcount--; | ||
1157 | |||
1158 | if (em->refcount > 0) goto on_exit; | ||
1159 | |||
1160 | key[0] = em->offset; | ||
1161 | key[1] = em->length; | ||
1162 | |||
1163 | eina_hash_del(file->rmap, &map, em); | ||
1164 | eina_hash_del(file->map, &key, em); | ||
1165 | } | ||
1166 | |||
1167 | on_exit: | ||
1168 | eina_lock_release(&file->lock); | ||
1169 | } | ||
1170 | |||
1171 | EAPI int | ||
1172 | eina_file_statat(void *container __UNUSED__, Eina_File_Direct_Info *info, Eina_Stat *st) | ||
1173 | { | ||
1174 | struct __stat64 buf; | ||
1175 | |||
1176 | EINA_SAFETY_ON_NULL_RETURN_VAL(info, -1); | ||
1177 | EINA_SAFETY_ON_NULL_RETURN_VAL(st, -1); | ||
1178 | |||
1179 | if (stat64(info->path, &buf)) | ||
1180 | { | ||
1181 | if (info->type != EINA_FILE_LNK) | ||
1182 | info->type = EINA_FILE_UNKNOWN; | ||
1183 | return -1; | ||
1184 | } | ||
1185 | |||
1186 | if (info->type == EINA_FILE_UNKNOWN) | ||
1187 | { | ||
1188 | if (S_ISREG(buf.st_mode)) | ||
1189 | info->type = EINA_FILE_REG; | ||
1190 | else if (S_ISDIR(buf.st_mode)) | ||
1191 | info->type = EINA_FILE_DIR; | ||
1192 | else | ||
1193 | info->type = EINA_FILE_UNKNOWN; | ||
1194 | } | ||
1195 | |||
1196 | st->dev = buf.st_dev; | ||
1197 | st->ino = buf.st_ino; | ||
1198 | st->mode = buf.st_mode; | ||
1199 | st->nlink = buf.st_nlink; | ||
1200 | st->uid = buf.st_uid; | ||
1201 | st->gid = buf.st_gid; | ||
1202 | st->rdev = buf.st_rdev; | ||
1203 | st->size = buf.st_size; | ||
1204 | st->blksize = 0; | ||
1205 | st->blocks = 0; | ||
1206 | st->atime = buf.st_atime; | ||
1207 | st->mtime = buf.st_mtime; | ||
1208 | st->ctime = buf.st_ctime; | ||
1209 | st->atimensec = 0; | ||
1210 | st->mtimensec = 0; | ||
1211 | st->ctimensec = 0; | ||
1212 | |||
1213 | return 0; | ||
1214 | } | ||