and add file
authorcaro <caro>
Sat, 6 Nov 2010 21:01:36 +0000 (21:01 +0000)
committercaro <caro@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Sat, 6 Nov 2010 21:01:36 +0000 (21:01 +0000)
git-svn-id: http://svn.enlightenment.org/svn/e/trunk/eina@54251 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/eina_file_win32.c [new file with mode: 0644]

diff --git a/src/lib/eina_file_win32.c b/src/lib/eina_file_win32.c
new file mode 100644 (file)
index 0000000..1027b94
--- /dev/null
@@ -0,0 +1,575 @@
+/* EINA - EFL data type library\r
+ * Copyright (C) 2010 Vincent Torri\r
+ *\r
+ * This library is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU Lesser General Public\r
+ * License as published by the Free Software Foundation; either\r
+ * version 2.1 of the License, or (at your option) any later version.\r
+ *\r
+ * This library is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+ * Lesser General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU Lesser General Public\r
+ * License along with this library;\r
+ * if not, see <http://www.gnu.org/licenses/>.\r
+ */\r
+\r
+#ifdef HAVE_CONFIG_H\r
+# include "config.h"\r
+#endif\r
+\r
+#ifdef HAVE_ALLOCA_H\r
+# include <alloca.h>\r
+#elif defined __GNUC__\r
+# define alloca __builtin_alloca\r
+#elif defined _AIX\r
+# define alloca __alloca\r
+#elif defined _MSC_VER\r
+# include <malloc.h>\r
+# define alloca _alloca\r
+#else\r
+# include <stddef.h>\r
+# ifdef  __cplusplus\r
+extern "C"\r
+# endif\r
+void *alloca (size_t);\r
+#endif\r
+\r
+#define WIN32_LEAN_AND_MEAN\r
+#include <windows.h>\r
+#undef WIN32_LEAN_AND_MEAN\r
+\r
+#include "eina_config.h"\r
+#include "eina_private.h"\r
+\r
+/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */\r
+#include "eina_safety_checks.h"\r
+#include "eina_file.h"\r
+#include "eina_stringshare.h"\r
+\r
+/*============================================================================*\r
+ *                                  Local                                     *\r
+ *============================================================================*/\r
+\r
+/**\r
+ * @cond LOCAL\r
+ */\r
+\r
+typedef struct _Eina_File_Iterator        Eina_File_Iterator;\r
+typedef struct _Eina_File_Direct_Iterator Eina_File_Direct_Iterator;\r
+\r
+struct _Eina_File_Iterator\r
+{\r
+   Eina_Iterator   iterator;\r
+\r
+   WIN32_FIND_DATA data;\r
+   HANDLE          handle;\r
+   int             length;\r
+   Eina_Bool       is_last : 1;\r
+\r
+   char            dir[1];\r
+};\r
+\r
+struct _Eina_File_Direct_Iterator\r
+{\r
+   Eina_Iterator         iterator;\r
+\r
+   WIN32_FIND_DATA       data;\r
+   HANDLE                handle;\r
+   int                   length;\r
+   Eina_Bool             is_last : 1;\r
+\r
+   Eina_File_Direct_Info info;\r
+\r
+   char                  dir[1];\r
+};\r
+\r
+static void\r
+_eina_file_win32_backslash_change(char *dir)\r
+{\r
+   char *tmp;\r
+\r
+   tmp = dir;\r
+   while (*tmp)\r
+     {\r
+        if (*tmp == '/') *tmp = '\\';\r
+        tmp++;\r
+     }\r
+}\r
+\r
+static Eina_Bool\r
+_eina_file_win32_is_dir(const char *dir)\r
+{\r
+#ifdef UNICODE\r
+   wchar_t *wdir = NULL;\r
+#endif\r
+   DWORD    attr;\r
+\r
+   /* check if it's a directory */\r
+#ifdef UNICODE\r
+   wdir = evil_char_to_wchar(dir);\r
+   if (!wdir)\r
+     return EINA_FALSE;\r
+\r
+   attr = GetFileAttributes(wdir);\r
+   free(wdir);\r
+#else\r
+   attr = GetFileAttributes(dir);\r
+#endif\r
+\r
+   if (attr == 0xFFFFFFFF)\r
+     return EINA_FALSE;\r
+\r
+   if (!(attr & FILE_ATTRIBUTE_DIRECTORY))\r
+     return EINA_FALSE;\r
+\r
+   return EINA_TRUE;\r
+}\r
+\r
+static char *\r
+_eina_file_win32_dir_new(const char *dir)\r
+{\r
+   char *new_dir;\r
+   size_t length;\r
+\r
+   length = strlen(dir);\r
+\r
+   new_dir = (char *)malloc(sizeof(char) * length + 5);\r
+   if (!new_dir)\r
+     return NULL;\r
+\r
+   memcpy(new_dir, dir, length);\r
+   memcpy(new_dir + length, "\\*.*", 5);\r
+   _eina_file_win32_backslash_change(new_dir);\r
+\r
+   return new_dir;\r
+}\r
+\r
+static HANDLE\r
+_eina_file_win32_first_file(const char *dir, WIN32_FIND_DATA *fd)\r
+{\r
+  HANDLE h;\r
+#ifdef UNICODE\r
+   wchar_t *wdir = NULL;\r
+\r
+   wdir = evil_char_to_wchar(dir);\r
+   if (!wdir)\r
+     return NULL;\r
+\r
+   h = FindFirstFile(wdir, fd);\r
+   free(wdir);\r
+#else\r
+   h = FindFirstFile(dir, fd);\r
+#endif\r
+\r
+   if (!h)\r
+     return NULL;\r
+\r
+   while ((fd->cFileName[0] == '.') &&\r
+          ((fd->cFileName[1] == '\0') ||\r
+           ((fd->cFileName[1] == '.') && (fd->cFileName[2] == '\0'))))\r
+     {\r
+        if (!FindNextFile(h, fd))\r
+          return NULL;\r
+     }\r
+\r
+   return h;\r
+}\r
+\r
+static Eina_Bool\r
+_eina_file_win32_ls_iterator_next(Eina_File_Iterator *it, void **data)\r
+{\r
+   char     *old_name;\r
+   char     *name;\r
+   char     *cname;\r
+   size_t    length;\r
+   Eina_Bool is_last;\r
+   Eina_Bool res = EINA_TRUE;\r
+\r
+   if (it->handle == INVALID_HANDLE_VALUE)\r
+     return EINA_FALSE;\r
+\r
+   is_last = it->is_last;\r
+   old_name = strdup(it->data.cFileName);\r
+   if (!old_name)\r
+     return EINA_FALSE;\r
+\r
+   do {\r
+      if (!FindNextFile(it->handle, &it->data))\r
+        {\r
+           if (GetLastError() == ERROR_NO_MORE_FILES)\r
+             it->is_last = EINA_TRUE;\r
+           else\r
+             res = EINA_FALSE;\r
+        }\r
+   } while ((it->data.cFileName[0] == '.') &&\r
+            ((it->data.cFileName[1] == '\0') ||\r
+             ((it->data.cFileName[1] == '.') && (it->data.cFileName[2] == '\0'))));\r
+\r
+#ifdef UNICODE\r
+   cname = evil_wchar_to_char(old_name);\r
+   if (!cname)\r
+     return EINA_FALSE;\r
+#else\r
+     cname = old_name;\r
+#endif\r
+\r
+   length = strlen(cname);\r
+   name = alloca(length + 2 + it->length);\r
+\r
+   memcpy(name,                  it->dir, it->length);\r
+   memcpy(name + it->length,     "\\",    1);\r
+   memcpy(name + it->length + 1, cname,   length + 1);\r
+\r
+   *data = (char *)eina_stringshare_add(name);\r
+\r
+#ifdef UNICODE\r
+   free(cname);\r
+#endif\r
+   free(old_name);\r
+\r
+   if (is_last)\r
+     res = EINA_FALSE;\r
+\r
+   return res;\r
+}\r
+\r
+static HANDLE\r
+_eina_file_win32_ls_iterator_container(Eina_File_Iterator *it)\r
+{\r
+   return it->handle;\r
+}\r
+\r
+static void\r
+_eina_file_win32_ls_iterator_free(Eina_File_Iterator *it)\r
+{\r
+   if (it->handle != INVALID_HANDLE_VALUE)\r
+     FindClose(it->handle);\r
+\r
+   EINA_MAGIC_SET(&it->iterator, 0);\r
+   free(it);\r
+}\r
+\r
+static Eina_Bool\r
+_eina_file_win32_direct_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data)\r
+{\r
+   char     *old_name;\r
+   char     *cname;\r
+   size_t    length;\r
+   DWORD     attr;\r
+   Eina_Bool is_last;\r
+   Eina_Bool res = EINA_TRUE;\r
+\r
+   if (it->handle == INVALID_HANDLE_VALUE)\r
+     return EINA_FALSE;\r
+\r
+   attr = it->data.dwFileAttributes;\r
+   is_last = it->is_last;\r
+   old_name = strdup(it->data.cFileName);\r
+   if (!old_name)\r
+     return EINA_FALSE;\r
+\r
+   do {\r
+      if (!FindNextFile(it->handle, &it->data))\r
+        {\r
+           if (GetLastError() == ERROR_NO_MORE_FILES)\r
+             it->is_last = EINA_TRUE;\r
+           else\r
+             res = EINA_FALSE;\r
+        }\r
+\r
+     length = strlen(old_name);\r
+     if (it->info.name_start + length + 1 >= PATH_MAX)\r
+       {\r
+          free(old_name);\r
+          old_name = strdup(it->data.cFileName);\r
+          continue;\r
+       }\r
+\r
+   } while ((it->data.cFileName[0] == '.') &&\r
+            ((it->data.cFileName[1] == '\0') ||\r
+             ((it->data.cFileName[1] == '.') && (it->data.cFileName[2] == '\0'))));\r
+\r
+#ifdef UNICODE\r
+   cname = evil_wchar_to_char(old_name);\r
+   if (!cname)\r
+     return EINA_FALSE;\r
+#else\r
+     cname = old_name;\r
+#endif\r
+\r
+   memcpy(it->info.path + it->info.name_start, cname, length);\r
+   it->info.name_length = length;\r
+   it->info.path_length = it->info.name_start + length;\r
+   it->info.path[it->info.path_length] = '\0';\r
+\r
+   if (attr & FILE_ATTRIBUTE_DIRECTORY)\r
+     it->info.type = EINA_FILE_DIR;\r
+   else if (attr & FILE_ATTRIBUTE_REPARSE_POINT)\r
+     it->info.type = EINA_FILE_LNK;\r
+   else if (attr & (FILE_ATTRIBUTE_ARCHIVE |\r
+                    FILE_ATTRIBUTE_COMPRESSED |\r
+                    FILE_ATTRIBUTE_COMPRESSED |\r
+                    FILE_ATTRIBUTE_HIDDEN |\r
+                    FILE_ATTRIBUTE_NORMAL |\r
+                    FILE_ATTRIBUTE_SPARSE_FILE |\r
+                    FILE_ATTRIBUTE_TEMPORARY))\r
+     it->info.type = EINA_FILE_REG;\r
+   else\r
+     it->info.type = EINA_FILE_UNKNOWN;\r
+\r
+   *data = &it->info;\r
+\r
+#ifdef UNICODE\r
+   free(cname);\r
+#endif\r
+\r
+   free(old_name);\r
+\r
+   if (is_last)\r
+     res = EINA_FALSE;\r
+\r
+   return res;\r
+}\r
+\r
+static HANDLE\r
+_eina_file_win32_direct_ls_iterator_container(Eina_File_Direct_Iterator *it)\r
+{\r
+   return it->handle;\r
+}\r
+\r
+static void\r
+_eina_file_win32_direct_ls_iterator_free(Eina_File_Direct_Iterator *it)\r
+{\r
+   if (it->handle != INVALID_HANDLE_VALUE)\r
+     FindClose(it->handle);\r
+\r
+   EINA_MAGIC_SET(&it->iterator, 0);\r
+   free(it);\r
+}\r
+\r
+\r
+/**\r
+ * @endcond\r
+ */\r
+\r
+/*============================================================================*\r
+ *                                 Global                                     *\r
+ *============================================================================*/\r
+\r
+/*============================================================================*\r
+ *                                   API                                      *\r
+ *============================================================================*/\r
+\r
+EAPI Eina_Bool\r
+eina_file_dir_list(const char *dir,\r
+                   Eina_Bool recursive,\r
+                   Eina_File_Dir_List_Cb cb,\r
+                   void *data)\r
+{\r
+   WIN32_FIND_DATA file;\r
+   HANDLE h;\r
+   char *new_dir;\r
+\r
+   EINA_SAFETY_ON_NULL_RETURN_VAL(cb,  EINA_FALSE);\r
+   EINA_SAFETY_ON_NULL_RETURN_VAL(dir, EINA_FALSE);\r
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(dir[0] == '\0', EINA_FALSE);\r
+\r
+   if (!_eina_file_win32_is_dir(dir))\r
+     return EINA_FALSE;\r
+\r
+   new_dir = _eina_file_win32_dir_new(dir);\r
+   if (!new_dir)\r
+      return EINA_FALSE;\r
+\r
+   h = _eina_file_win32_first_file(new_dir, &file);\r
+\r
+   if (h == INVALID_HANDLE_VALUE)\r
+      return EINA_FALSE;\r
+\r
+   do\r
+     {\r
+        char *filename;\r
+\r
+# ifdef UNICODE\r
+        filename = evil_wchar_to_char(file.cFileName);\r
+# else\r
+        filename = file.cFileName;\r
+# endif /* ! UNICODE */\r
+        if (!strcmp(filename, ".") || !strcmp(filename, ".."))\r
+           continue;\r
+\r
+        cb(filename, dir, data);\r
+\r
+        if (recursive == EINA_TRUE)\r
+          {\r
+             char *path;\r
+\r
+             path = alloca(strlen(dir) + strlen(filename) + 2);\r
+             strcpy(path, dir);\r
+             strcat(path, "/");\r
+             strcat(path, filename);\r
+\r
+             if (!(file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))\r
+                continue;\r
+\r
+             eina_file_dir_list(path, recursive, cb, data);\r
+          }\r
+\r
+# ifdef UNICODE\r
+        free(filename);\r
+# endif /* UNICODE */\r
+\r
+     } while (FindNextFile(h, &file));\r
+   FindClose(h);\r
+\r
+   return EINA_TRUE;\r
+}\r
+\r
+EAPI Eina_Array *\r
+eina_file_split(char *path)\r
+{\r
+   Eina_Array *ea;\r
+   char *current;\r
+   size_t length;\r
+\r
+   EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);\r
+\r
+   ea = eina_array_new(16);\r
+\r
+   if (!ea)\r
+      return NULL;\r
+\r
+   for (current = strchr(path, '\\');\r
+        current;\r
+        path = current + 1, current = strchr(path, '\\'))\r
+     {\r
+        length = current - path;\r
+\r
+        if (length <= 0)\r
+           continue;\r
+\r
+        eina_array_push(ea, path);\r
+        *current = '\0';\r
+     }\r
+\r
+   if (*path != '\0')\r
+        eina_array_push(ea, path);\r
+\r
+   return ea;\r
+}\r
+\r
+EAPI Eina_Iterator *\r
+eina_file_ls(const char *dir)\r
+{\r
+   Eina_File_Iterator *it;\r
+   char               *new_dir;\r
+   size_t              length;\r
+\r
+   if (!dir || !*dir)\r
+      return NULL;\r
+\r
+   if (!_eina_file_win32_is_dir(dir))\r
+     return NULL;\r
+\r
+   length = strlen(dir);\r
+\r
+   it = calloc(1, sizeof (Eina_File_Iterator) + length);\r
+   if (!it)\r
+      return NULL;\r
+\r
+   EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);\r
+\r
+   new_dir = _eina_file_win32_dir_new(dir);\r
+   if (!new_dir)\r
+      goto free_it;\r
+\r
+   it->handle = _eina_file_win32_first_file(new_dir, &it->data);\r
+   free(new_dir);\r
+   if (it->handle == INVALID_HANDLE_VALUE)\r
+     goto free_it;\r
+\r
+   memcpy(it->dir, dir, length + 1);\r
+   if (dir[length - 1] != '\\')\r
+      it->length = length;\r
+   else\r
+      it->length = length - 1;\r
+   _eina_file_win32_backslash_change(it->dir);\r
+\r
+   it->iterator.version = EINA_ITERATOR_VERSION;\r
+   it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_win32_ls_iterator_next);\r
+   it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_win32_ls_iterator_container);\r
+   it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_win32_ls_iterator_free);\r
+\r
+   return &it->iterator;\r
+\r
+ free_it:\r
+   free(it);\r
+\r
+   return NULL;\r
+}\r
+\r
+EAPI Eina_Iterator *\r
+eina_file_direct_ls(const char *dir)\r
+{\r
+   Eina_File_Direct_Iterator *it;\r
+   char                      *new_dir;\r
+   size_t                     length;\r
+\r
+   if (!dir || !*dir)\r
+      return NULL;\r
+\r
+   length = strlen(dir);\r
+\r
+   if (length + 12 + 2 >= MAX_PATH)\r
+      return NULL;\r
+\r
+   it = calloc(1, sizeof(Eina_File_Direct_Iterator) + length);\r
+   if (!it)\r
+      return NULL;\r
+\r
+   EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);\r
+\r
+   new_dir = _eina_file_win32_dir_new(dir);\r
+   if (!new_dir)\r
+      goto free_it;\r
+\r
+   it->handle = _eina_file_win32_first_file(new_dir, &it->data);\r
+   free(new_dir);\r
+   if (it->handle == INVALID_HANDLE_VALUE)\r
+     goto free_it;\r
+\r
+   memcpy(it->dir, dir, length + 1);\r
+   it->length = length;\r
+   _eina_file_win32_backslash_change(it->dir);\r
+\r
+   memcpy(it->info.path, dir, length);\r
+   if (dir[length - 1] == '\\')\r
+      it->info.name_start = length;\r
+   else\r
+     {\r
+        it->info.path[length] = '\\';\r
+        it->info.name_start = length + 1;\r
+     }\r
+   _eina_file_win32_backslash_change(it->info.path);\r
+\r
+   it->iterator.version = EINA_ITERATOR_VERSION;\r
+   it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_win32_direct_ls_iterator_next);\r
+   it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_win32_direct_ls_iterator_container);\r
+   it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_win32_direct_ls_iterator_free);\r
+\r
+   return &it->iterator;\r
+\r
+ free_it:\r
+   free(it);\r
+\r
+   return NULL;\r
+}\r
+\r
+EAPI Eina_Iterator *\r
+eina_file_stat_ls(const char *dir)\r
+{\r
+   return eina_file_direct_ls(dir);\r
+}\r