1 /* EINA - EFL data type library
2 * Copyright (C) 2010 Vincent Torri
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.
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.
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/>.
25 #elif defined __GNUC__
26 # define alloca __builtin_alloca
28 # define alloca __alloca
29 #elif defined _MSC_VER
31 # define alloca _alloca
37 void *alloca (size_t);
40 #include <sys/types.h>
43 #define WIN32_LEAN_AND_MEAN
45 #undef WIN32_LEAN_AND_MEAN
49 #include "eina_config.h"
50 #include "eina_private.h"
52 /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
53 #include "eina_safety_checks.h"
54 #include "eina_file.h"
55 #include "eina_stringshare.h"
56 #include "eina_hash.h"
57 #include "eina_list.h"
58 #include "eina_lock.h"
61 /*============================================================================*
63 *============================================================================*/
69 #ifndef EINA_LOG_COLOR_DEFAULT
70 #define EINA_LOG_COLOR_DEFAULT EINA_COLOR_CYAN
76 #define ERR(...) EINA_LOG_DOM_ERR(_eina_file_log_dom, __VA_ARGS__)
81 #define WRN(...) EINA_LOG_DOM_WARN(_eina_file_log_dom, __VA_ARGS__)
86 #define DBG(...) EINA_LOG_DOM_DBG(_eina_file_log_dom, __VA_ARGS__)
91 #define MAP_FAILED ((void *)-1)
93 typedef struct _Eina_File_Iterator Eina_File_Iterator;
94 typedef struct _Eina_Lines_Iterator Eina_Lines_Iterator;
95 typedef struct _Eina_File_Direct_Iterator Eina_File_Direct_Iterator;
96 typedef struct _Eina_File_Map Eina_File_Map;
98 struct _Eina_File_Iterator
100 Eina_Iterator iterator;
102 WIN32_FIND_DATA data;
105 Eina_Bool is_last : 1;
110 struct _Eina_Lines_Iterator
112 Eina_Iterator iterator;
120 Eina_File_Line current;
123 struct _Eina_File_Direct_Iterator
125 Eina_Iterator iterator;
127 WIN32_FIND_DATA data;
130 Eina_Bool is_last : 1;
132 Eina_File_Direct_Info info;
139 const char *filename;
156 Eina_Bool shared : 1;
157 Eina_Bool delete_me : 1;
160 struct _Eina_File_Map
164 unsigned long int offset;
165 unsigned long int length;
170 static Eina_Hash *_eina_file_cache = NULL;
171 static Eina_Lock _eina_file_lock_cache;
173 static int _eina_file_log_dom = -1;
176 _eina_file_win32_is_dir(const char *dir)
179 wchar_t *wdir = NULL;
183 /* check if it's a directory */
185 wdir = evil_char_to_wchar(dir);
189 attr = GetFileAttributes(wdir);
192 attr = GetFileAttributes(dir);
195 if (attr == 0xFFFFFFFF)
198 if (!(attr & FILE_ATTRIBUTE_DIRECTORY))
205 _eina_file_win32_dir_new(const char *dir)
210 length = strlen(dir);
212 new_dir = (char *)malloc(sizeof(char) * length + 5);
216 memcpy(new_dir, dir, length);
217 memcpy(new_dir + length, "\\*.*", 5);
223 _eina_file_win32_first_file(const char *dir, WIN32_FIND_DATA *fd)
227 wchar_t *wdir = NULL;
229 wdir = evil_char_to_wchar(dir);
233 h = FindFirstFile(wdir, fd);
236 h = FindFirstFile(dir, fd);
242 while ((fd->cFileName[0] == '.') &&
243 ((fd->cFileName[1] == '\0') ||
244 ((fd->cFileName[1] == '.') && (fd->cFileName[2] == '\0'))))
246 if (!FindNextFile(h, fd))
254 _eina_file_win32_ls_iterator_next(Eina_File_Iterator *it, void **data)
265 Eina_Bool res = EINA_TRUE;
267 if (it->handle == INVALID_HANDLE_VALUE)
270 is_last = it->is_last;
272 old_name = _wcsdup(it->data.cFileName);
274 old_name = _strdup(it->data.cFileName);
280 if (!FindNextFile(it->handle, &it->data))
282 if (GetLastError() == ERROR_NO_MORE_FILES)
283 it->is_last = EINA_TRUE;
287 } while ((it->data.cFileName[0] == '.') &&
288 ((it->data.cFileName[1] == '\0') ||
289 ((it->data.cFileName[1] == '.') && (it->data.cFileName[2] == '\0')))); /* FIXME: what about UNICODE ? */
292 cname = evil_wchar_to_char(old_name);
299 length = strlen(cname);
300 name = alloca(length + 2 + it->length);
302 memcpy(name, it->dir, it->length);
303 memcpy(name + it->length, "\\", 1);
304 memcpy(name + it->length + 1, cname, length + 1);
306 *data = (char *)eina_stringshare_add(name);
320 _eina_file_win32_ls_iterator_container(Eina_File_Iterator *it)
326 _eina_file_win32_ls_iterator_free(Eina_File_Iterator *it)
328 if (it->handle != INVALID_HANDLE_VALUE)
329 FindClose(it->handle);
331 EINA_MAGIC_SET(&it->iterator, 0);
336 _eina_file_win32_direct_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data)
347 Eina_Bool res = EINA_TRUE;
349 if (it->handle == INVALID_HANDLE_VALUE)
352 attr = it->data.dwFileAttributes;
353 is_last = it->is_last;
355 old_name = _wcsdup(it->data.cFileName);
357 old_name = _strdup(it->data.cFileName);
363 if (!FindNextFile(it->handle, &it->data))
365 if (GetLastError() == ERROR_NO_MORE_FILES)
366 it->is_last = EINA_TRUE;
372 length = wcslen(old_name);
374 length = strlen(old_name);
376 if (it->info.name_start + length + 1 >= PATH_MAX)
380 old_name = _wcsdup(it->data.cFileName);
382 old_name = _strdup(it->data.cFileName);
387 } while ((it->data.cFileName[0] == '.') &&
388 ((it->data.cFileName[1] == '\0') ||
389 ((it->data.cFileName[1] == '.') && (it->data.cFileName[2] == '\0')))); /* FIXME: what about UNICODE ? */
392 cname = evil_wchar_to_char(old_name);
399 memcpy(it->info.path + it->info.name_start, cname, length);
400 it->info.name_length = length;
401 it->info.path_length = it->info.name_start + length;
402 it->info.path[it->info.path_length] = '\0';
404 if (attr & FILE_ATTRIBUTE_DIRECTORY)
405 it->info.type = EINA_FILE_DIR;
406 else if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
407 it->info.type = EINA_FILE_LNK;
408 else if (attr & (FILE_ATTRIBUTE_ARCHIVE |
409 FILE_ATTRIBUTE_COMPRESSED |
410 FILE_ATTRIBUTE_COMPRESSED |
411 FILE_ATTRIBUTE_HIDDEN |
412 FILE_ATTRIBUTE_NORMAL |
413 FILE_ATTRIBUTE_SPARSE_FILE |
414 FILE_ATTRIBUTE_TEMPORARY))
415 it->info.type = EINA_FILE_REG;
417 it->info.type = EINA_FILE_UNKNOWN;
434 _eina_file_win32_direct_ls_iterator_container(Eina_File_Direct_Iterator *it)
440 _eina_file_win32_direct_ls_iterator_free(Eina_File_Direct_Iterator *it)
442 if (it->handle != INVALID_HANDLE_VALUE)
443 FindClose(it->handle);
445 EINA_MAGIC_SET(&it->iterator, 0);
450 _eina_file_real_close(Eina_File *file)
452 eina_hash_free(file->rmap);
453 eina_hash_free(file->map);
455 if (file->global_map != MAP_FAILED)
456 UnmapViewOfFile(file->global_map);
458 CloseHandle(file->fm);
459 CloseHandle(file->handle);
465 _eina_file_map_close(Eina_File_Map *map)
467 if (map->map != MAP_FAILED)
468 UnmapViewOfFile(map->map);
473 _eina_file_map_key_length(const void *key __UNUSED__)
475 return sizeof (unsigned long int) * 2;
479 _eina_file_map_key_cmp(const unsigned long int *key1, int key1_length __UNUSED__,
480 const unsigned long int *key2, int key2_length __UNUSED__)
482 if (key1[0] - key2[0] == 0) return key1[1] - key2[1];
483 return key1[0] - key2[0];
487 _eina_file_map_key_hash(const unsigned long int *key, int key_length __UNUSED__)
489 return eina_hash_int64(&key[0], sizeof (unsigned long int))
490 ^ eina_hash_int64(&key[1], sizeof (unsigned long int));
494 _eina_file_win32_escape(const char *path, size_t *length)
501 result = strdup(path ? path : "");
508 if (*p == '\\') *p = '/';
517 if (length) len = *length;
518 else len = strlen(result);
520 while ((p = strchr(p, '/')))
525 memmove(p, p + 1, --len - (p - result));
538 memmove(q, p + 3, len - (q - result));
542 /* Update q correctly. */
545 q = strrchr(result, '/');
577 /* search '\r' and '\n' by preserving cache locality and page locality
578 in doing a search inside 4K boundary.
580 static inline const char *
581 _eina_fine_eol(const char *start, int boundary, const char *end)
585 unsigned long long chunk;
589 chunk = start + boundary < end ? boundary : end - start;
590 cr = memchr(start, '\r', chunk);
591 lf = memchr(start, '\n', chunk);
609 _eina_file_map_lines_iterator_next(Eina_Lines_Iterator *it, void **data)
614 if (it->current.end >= it->end)
617 match = *it->current.end;
618 while ((*it->current.end == '\n' || *it->current.end == '\r')
619 && it->current.end < it->end)
621 if (match == *it->current.end)
627 if (it->current.end == it->end)
630 eol = _eina_fine_eol(it->current.end,
633 it->boundary = (uintptr_t) eol & 0x3FF;
634 if (it->boundary == 0) it->boundary = 4096;
636 it->current.start = it->current.end;
638 it->current.end = eol;
639 it->current.length = eol - it->current.start - 1;
641 *data = &it->current;
646 _eina_file_map_lines_iterator_container(Eina_Lines_Iterator *it)
652 _eina_file_map_lines_iterator_free(Eina_Lines_Iterator *it)
654 eina_file_map_free(it->fp, (void*) it->map);
655 eina_file_close(it->fp);
657 EINA_MAGIC_SET(&it->iterator, 0);
666 /*============================================================================*
668 *============================================================================*/
673 _eina_file_log_dom = eina_log_domain_register("eina_file",
674 EINA_LOG_COLOR_DEFAULT);
675 if (_eina_file_log_dom < 0)
677 EINA_LOG_ERR("Could not register log domain: eina_file");
681 _eina_file_cache = eina_hash_string_djb2_new(NULL);
682 if (!_eina_file_cache)
684 ERR("Could not create cache.");
685 eina_log_domain_unregister(_eina_file_log_dom);
686 _eina_file_log_dom = -1;
690 eina_lock_new(&_eina_file_lock_cache);
696 eina_file_shutdown(void)
698 if (eina_hash_population(_eina_file_cache) > 0)
703 it = eina_hash_iterator_key_new(_eina_file_cache);
704 EINA_ITERATOR_FOREACH(it, key)
705 ERR("File [%s] still open !", key);
706 eina_iterator_free(it);
709 eina_hash_free(_eina_file_cache);
711 eina_lock_free(&_eina_file_lock_cache);
713 eina_log_domain_unregister(_eina_file_log_dom);
714 _eina_file_log_dom = -1;
718 /*============================================================================*
720 *============================================================================*/
724 eina_file_path_sanitize(const char *path)
729 if (!path) return NULL;
733 if (!evil_path_is_absolute(path))
737 l = GetCurrentDirectory(0, NULL);
743 cwd = alloca(sizeof(char) * (l + 1));
744 GetCurrentDirectory(l + 1, cwd);
746 tmp = alloca(sizeof (char) * len);
747 snprintf(tmp, len, "%s\\%s", cwd, path);
753 return _eina_file_win32_escape(result ? result : path, &len);
757 eina_file_dir_list(const char *dir,
759 Eina_File_Dir_List_Cb cb,
762 WIN32_FIND_DATA file;
766 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE);
767 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, EINA_FALSE);
768 EINA_SAFETY_ON_TRUE_RETURN_VAL(dir[0] == '\0', EINA_FALSE);
770 if (!_eina_file_win32_is_dir(dir))
773 new_dir = _eina_file_win32_dir_new(dir);
777 h = _eina_file_win32_first_file(new_dir, &file);
779 if (h == INVALID_HANDLE_VALUE)
787 filename = evil_wchar_to_char(file.cFileName);
789 filename = file.cFileName;
790 # endif /* ! UNICODE */
791 if (!strcmp(filename, ".") || !strcmp(filename, ".."))
794 cb(filename, dir, data);
796 if (recursive == EINA_TRUE)
800 path = alloca(strlen(dir) + strlen(filename) + 2);
803 strcat(path, filename);
805 if (!(file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
808 eina_file_dir_list(path, recursive, cb, data);
813 # endif /* UNICODE */
815 } while (FindNextFile(h, &file));
822 eina_file_split(char *path)
828 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
830 ea = eina_array_new(16);
838 if ((*current == '\\') || (*current == '/'))
840 if (((*current == '\\') && (current[1] == '\\')) ||
841 ((*current == '/') && (current[1] == '/')))
847 length = current - path;
851 eina_array_push(ea, path);
860 eina_array_push(ea, path);
866 eina_file_ls(const char *dir)
868 Eina_File_Iterator *it;
872 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
877 if (!_eina_file_win32_is_dir(dir))
880 length = strlen(dir);
882 it = calloc(1, sizeof (Eina_File_Iterator) + length);
886 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
888 new_dir = _eina_file_win32_dir_new(dir);
892 it->handle = _eina_file_win32_first_file(new_dir, &it->data);
894 if (it->handle == INVALID_HANDLE_VALUE)
897 memcpy(it->dir, dir, length + 1);
898 if ((dir[length - 1] != '\\') && (dir[length - 1] != '/'))
901 it->length = length - 1;
903 it->iterator.version = EINA_ITERATOR_VERSION;
904 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_win32_ls_iterator_next);
905 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_win32_ls_iterator_container);
906 it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_win32_ls_iterator_free);
908 return &it->iterator;
917 eina_file_direct_ls(const char *dir)
919 Eina_File_Direct_Iterator *it;
923 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
928 length = strlen(dir);
930 if (length + 12 + 2 >= MAX_PATH)
933 it = calloc(1, sizeof(Eina_File_Direct_Iterator) + length);
937 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
939 new_dir = _eina_file_win32_dir_new(dir);
943 it->handle = _eina_file_win32_first_file(new_dir, &it->data);
945 if (it->handle == INVALID_HANDLE_VALUE)
948 memcpy(it->dir, dir, length + 1);
951 memcpy(it->info.path, dir, length);
952 if ((dir[length - 1] == '\\') || (dir[length - 1] == '/'))
953 it->info.name_start = length;
956 it->info.path[length] = '\\';
957 it->info.name_start = length + 1;
960 it->iterator.version = EINA_ITERATOR_VERSION;
961 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_win32_direct_ls_iterator_next);
962 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_win32_direct_ls_iterator_container);
963 it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_win32_direct_ls_iterator_free);
965 return &it->iterator;
974 eina_file_stat_ls(const char *dir)
976 return eina_file_direct_ls(dir);
980 eina_file_open(const char *path, Eina_Bool shared)
987 WIN32_FILE_ATTRIBUTE_DATA fad;
988 ULARGE_INTEGER length;
989 ULARGE_INTEGER mtime;
991 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
993 filename = eina_file_path_sanitize(path);
994 if (!filename) return NULL;
996 /* FIXME: how to emulate shm_open ? Just OpenFileMapping ? */
999 handle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ,
1000 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY,
1004 handle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ,
1005 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY,
1008 if (handle == INVALID_HANDLE_VALUE)
1011 fm = CreateFileMapping(handle, NULL, PAGE_READONLY, 0, 0, NULL);
1015 if (!GetFileAttributesEx(filename, GetFileExInfoStandard, &fad))
1018 length.u.LowPart = fad.nFileSizeLow;
1019 length.u.HighPart = fad.nFileSizeHigh;
1020 mtime.u.LowPart = fad.ftLastWriteTime.dwLowDateTime;
1021 mtime.u.HighPart = fad.ftLastWriteTime.dwHighDateTime;
1023 eina_lock_take(&_eina_file_lock_cache);
1025 file = eina_hash_find(_eina_file_cache, filename);
1027 (file->mtime != mtime.QuadPart || file->length != length.QuadPart))
1029 file->delete_me = EINA_TRUE;
1030 eina_hash_del(_eina_file_cache, file->filename, file);
1031 _eina_file_real_close(file);
1037 n = malloc(sizeof(Eina_File) + strlen(filename) + 1);
1040 eina_lock_release(&_eina_file_lock_cache);
1044 memset(n, 0, sizeof(Eina_File));
1045 n->filename = (char*) (n + 1);
1046 strcpy((char*) n->filename, filename);
1047 n->map = eina_hash_new(EINA_KEY_LENGTH(_eina_file_map_key_length),
1048 EINA_KEY_CMP(_eina_file_map_key_cmp),
1049 EINA_KEY_HASH(_eina_file_map_key_hash),
1050 EINA_FREE_CB(_eina_file_map_close),
1052 n->rmap = eina_hash_pointer_new(NULL);
1053 n->global_map = MAP_FAILED;
1054 n->length = length.QuadPart;
1055 n->mtime = mtime.QuadPart;
1059 eina_lock_new(&n->lock);
1060 eina_hash_direct_add(_eina_file_cache, n->filename, n);
1065 CloseHandle(handle);
1069 eina_lock_take(&n->lock);
1071 eina_lock_release(&n->lock);
1073 eina_lock_release(&_eina_file_lock_cache);
1082 CloseHandle(handle);
1088 eina_file_close(Eina_File *file)
1090 EINA_SAFETY_ON_NULL_RETURN(file);
1092 eina_lock_take(&file->lock);
1094 eina_lock_release(&file->lock);
1096 if (file->refcount != 0) return ;
1097 eina_lock_take(&_eina_file_lock_cache);
1099 eina_hash_del(_eina_file_cache, file->filename, file);
1100 _eina_file_real_close(file);
1102 eina_lock_release(&_eina_file_lock_cache);
1106 eina_file_size_get(Eina_File *file)
1108 EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0);
1109 return file->length;
1113 eina_file_mtime_get(Eina_File *file)
1115 EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0);
1120 eina_file_filename_get(Eina_File *file)
1122 EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
1123 return file->filename;
1126 EAPI Eina_Iterator *eina_file_xattr_get(Eina_File *file __UNUSED__)
1131 EAPI Eina_Iterator *eina_file_xattr_value_get(Eina_File *file __UNUSED__)
1137 eina_file_map_all(Eina_File *file, Eina_File_Populate rule __UNUSED__)
1139 EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
1141 eina_lock_take(&file->lock);
1142 if (file->global_map == MAP_FAILED)
1146 data = MapViewOfFile(file->fm, FILE_MAP_READ,
1147 0, 0, file->length);
1149 file->global_map = MAP_FAILED;
1151 file->global_map = data;
1154 if (file->global_map != MAP_FAILED)
1156 file->global_refcount++;
1157 return file->global_map;
1160 eina_lock_release(&file->lock);
1164 EAPI Eina_Iterator *
1165 eina_file_map_lines(Eina_File *file)
1167 Eina_Lines_Iterator *it;
1169 EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
1171 if (file->length == 0) return NULL;
1173 it = calloc(1, sizeof (Eina_Lines_Iterator));
1174 if (!it) return NULL;
1176 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1178 it->map = eina_file_map_all(file, EINA_FILE_SEQUENTIAL);
1185 eina_lock_take(&file->lock);
1187 eina_lock_release(&file->lock);
1190 it->boundary = 4096;
1191 it->current.start = it->map;
1192 it->current.end = it->current.start;
1193 it->current.index = 0;
1194 it->current.length = 0;
1195 it->end = it->map + it->fp->length;
1197 it->iterator.version = EINA_ITERATOR_VERSION;
1198 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_map_lines_iterator_next);
1199 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_map_lines_iterator_container);
1200 it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_map_lines_iterator_free);
1202 return &it->iterator;
1206 eina_file_map_new(Eina_File *file, Eina_File_Populate rule,
1207 unsigned long int offset, unsigned long int length)
1210 unsigned long int key[2];
1212 EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
1214 if (offset > file->length)
1216 if (offset + length > file->length)
1219 if (offset == 0 && length == file->length)
1220 return eina_file_map_all(file, rule);
1225 eina_lock_take(&file->lock);
1227 map = eina_hash_find(file->map, &key);
1232 map = malloc(sizeof (Eina_File_Map));
1235 eina_lock_release(&file->lock);
1239 data = MapViewOfFile(file->fm, FILE_MAP_READ,
1240 offset & 0xffff0000,
1241 offset & 0x0000ffff,
1244 map->map = MAP_FAILED;
1248 map->offset = offset;
1249 map->length = length;
1252 if (map->map == MAP_FAILED)
1255 eina_lock_release(&file->lock);
1259 eina_hash_add(file->map, &key, map);
1260 eina_hash_direct_add(file->rmap, map->map, map);
1265 eina_lock_release(&file->lock);
1271 eina_file_map_free(Eina_File *file, void *map)
1273 EINA_SAFETY_ON_NULL_RETURN(file);
1275 eina_lock_take(&file->lock);
1277 if (file->global_map == map)
1279 file->global_refcount--;
1281 if (file->global_refcount > 0) goto on_exit;
1283 UnmapViewOfFile(file->global_map);
1284 file->global_map = MAP_FAILED;
1289 unsigned long int key[2];
1291 em = eina_hash_find(file->rmap, &map);
1292 if (!em) goto on_exit;
1296 if (em->refcount > 0) goto on_exit;
1298 key[0] = em->offset;
1299 key[1] = em->length;
1301 eina_hash_del(file->rmap, &map, em);
1302 eina_hash_del(file->map, &key, em);
1306 eina_lock_release(&file->lock);
1310 eina_file_map_faulted(Eina_File *file, void *map)
1314 * vc++ : http://msdn.microsoft.com/en-us/library/windows/desktop/aa366801%28v=vs.85%29.aspx
1317 * - 32 bits : there is a way to implement __try/__except/__final in C.
1318 * see excpt.h header for 32-bits
1319 * - 64 bits : some inline assembly required for it. See as example our
1320 * startup-code in WinMainCRTStartup() in crtexe.c :
1324 asm ("\t.l_startw:\n"
1325 "\t.seh_handler __C_specific_handler, @except\n"
1326 "\t.seh_handlerdata\n"
1328 "\t.rva .l_startw, .l_endw, _gnu_exception_handler ,.l_endw\n"
1333 __security_init_cookie ();
1334 ret = __tmainCRTStartup ();
1337 "\t.l_endw: nop\n");
1346 eina_file_statat(void *container __UNUSED__, Eina_File_Direct_Info *info, Eina_Stat *st)
1348 struct __stat64 buf;
1350 EINA_SAFETY_ON_NULL_RETURN_VAL(info, -1);
1351 EINA_SAFETY_ON_NULL_RETURN_VAL(st, -1);
1353 if (stat64(info->path, &buf))
1355 if (info->type != EINA_FILE_LNK)
1356 info->type = EINA_FILE_UNKNOWN;
1360 if (info->type == EINA_FILE_UNKNOWN)
1362 if (S_ISREG(buf.st_mode))
1363 info->type = EINA_FILE_REG;
1364 else if (S_ISDIR(buf.st_mode))
1365 info->type = EINA_FILE_DIR;
1367 info->type = EINA_FILE_UNKNOWN;
1370 st->dev = buf.st_dev;
1371 st->ino = buf.st_ino;
1372 st->mode = buf.st_mode;
1373 st->nlink = buf.st_nlink;
1374 st->uid = buf.st_uid;
1375 st->gid = buf.st_gid;
1376 st->rdev = buf.st_rdev;
1377 st->size = buf.st_size;
1380 st->atime = buf.st_atime;
1381 st->mtime = buf.st_mtime;
1382 st->ctime = buf.st_ctime;