1 /* EINA - EFL data type library
2 * Copyright (C) 2007-2008 Jorge Luis Zapata Muga, 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/>.
27 # include <sys/types.h>
28 # include <sys/stat.h>
32 # define WIN32_LEAN_AND_MEAN
34 # undef WIN32_LEAN_AND_MEAN
40 #elif defined __GNUC__
41 # define alloca __builtin_alloca
43 # define alloca __alloca
44 #elif defined _MSC_VER
46 # define alloca _alloca
52 void *alloca (size_t);
56 # define PATH_DELIM '/'
58 # define PATH_DELIM '\\'
61 #include "eina_file.h"
62 #include "eina_private.h"
63 #include "eina_safety_checks.h"
65 /*============================================================================*
67 *============================================================================*/
69 /*============================================================================*
71 *============================================================================*/
74 * @addtogroup Eina_Tools_Group Tools
80 * @addtogroup Eina_File_Group Memory File
82 * @brief Functions to traverse directories and split paths.
84 * @li eina_file_dir_list() list the content of a directory,
85 * recusrsively or not, and can call a callback function for eachfound
87 * @li eina_file_split() split a path into all the subdirectories that
88 * compose it, according to the separator of the file system.
90 * @warning eina_file_split() uses the @ref Eina_Array_Group module
91 * but does not initialize it. eina_array_init() and
92 * eina_array_shutdown() must be called if this function is used.
98 * @brief List all files on the directory calling the function for every file found.
100 * @param dir The directory name.
101 * @param recursive Iterate recursively in the directory.
102 * @param cb The callback to be called.
103 * @param data The data to pass to the callback.
104 * @return #EINA_TRUE on success, #EINA_FALSE oterwise.
106 * This function lists all the files in @p dir. To list also all the
107 * sub directoris recursively, @p recursive must be set to #EINA_TRUE,
108 * otherwise it must be set to #EINA_FALSE. For each found file, @p cb
109 * is called and @p data is passed to it.
111 * If @p cb or @p dir are @c NULL, or if @p dir is a string of size 0,
112 * or if @p dir can not be opened, this function returns #EINA_FALSE
113 * immediatly. otherwise, it returns #EINA_TRUE.
116 eina_file_dir_list(const char *dir, Eina_Bool recursive, Eina_File_Dir_List_Cb cb, void *data)
118 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE);
119 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, EINA_FALSE);
120 EINA_SAFETY_ON_TRUE_RETURN_VAL(dir[0] == '\0', EINA_FALSE);
127 if (!d) return EINA_FALSE;
129 while ((de = readdir(d)))
131 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
134 cb(de->d_name, dir, data);
135 /* d_type is only available on linux and bsd (_BSD_SOURCE) */
137 if (recursive == EINA_TRUE) {
140 path = alloca(strlen(dir) + strlen(de->d_name) + 2);
143 strcat(path, de->d_name);
145 if (de->d_type == DT_UNKNOWN) {
152 if (!S_ISDIR(st.st_mode))
155 } else if (de->d_type != DT_DIR) {
160 eina_file_dir_list(path, recursive, cb, data);
166 WIN32_FIND_DATA file;
172 length_dir = strlen(dir);
173 new_dir = (char *)alloca(length_dir + 5);
174 if (!new_dir) return EINA_FALSE;
176 memcpy(new_dir, dir, length_dir);
177 memcpy(new_dir + length_dir, "/*.*", 5);
180 tdir = evil_char_to_wchar(new_dir);
183 #endif /* ! UNICODE */
184 hSearch = FindFirstFile(tdir, &file);
189 if (hSearch == INVALID_HANDLE_VALUE) return EINA_FALSE;
196 filename = evil_wchar_to_char(file.cFileName);
198 filename = file.cFileName;
199 #endif /* ! UNICODE */
200 if (!strcmp(filename, ".") || !strcmp(filename, ".."))
203 cb(filename, dir, data);
205 if (recursive == EINA_TRUE) {
208 path = alloca(strlen(dir) + strlen(filename) + 2);
211 strcat(path, filename);
213 if (!(file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
216 eina_file_dir_list(path, recursive, cb, data);
222 } while (FindNextFile(hSearch, &file));
230 * @brief Split a path according to the delimiter of the filesystem.
232 * @param path The path to split.
233 * @return An array of the parts of the path to split.
235 * This function splits @p path according to the delimiter of the used
236 * filesystem. If @p path is @c NULL or if the array can not be
237 * created, @c NULL is returned, otherwise, an array with the
238 * different parts of @p path is returned.
240 * @warning This function uses the @ref Eina_Array_Group module but
241 * does not initialize it. eina_array_init() and eina_array_shutdown()
242 * must be called if this function is used.
245 eina_file_split(char *path)
251 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
253 ea = eina_array_new(16);
255 if (!ea) return NULL;
257 for (current = strchr(path, PATH_DELIM);
259 path = current + 1, current = strchr(path, PATH_DELIM))
261 length = current - path;
263 if (length <= 0) continue ;
265 eina_array_push(ea, path);
270 eina_array_push(ea, path);