2008-08-06 11:15:24 -07:00
|
|
|
/* EINA - EFL data type library
|
2008-09-01 05:51:50 -07:00
|
|
|
* Copyright (C) 2007-2008 Jorge Luis Zapata Muga, Vincent Torri
|
2008-08-06 11:15:24 -07:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library;
|
|
|
|
* if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2008-08-28 00:46:42 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
2009-09-06 21:32:49 -07:00
|
|
|
# include "config.h"
|
2008-08-28 00:46:42 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_ALLOCA_H
|
|
|
|
# include <alloca.h>
|
|
|
|
#elif defined __GNUC__
|
|
|
|
# define alloca __builtin_alloca
|
|
|
|
#elif defined _AIX
|
|
|
|
# define alloca __alloca
|
|
|
|
#elif defined _MSC_VER
|
|
|
|
# include <malloc.h>
|
|
|
|
# define alloca _alloca
|
|
|
|
#else
|
|
|
|
# include <stddef.h>
|
|
|
|
# ifdef __cplusplus
|
|
|
|
extern "C"
|
|
|
|
# endif
|
|
|
|
void *alloca (size_t);
|
|
|
|
#endif
|
|
|
|
|
2009-08-23 02:18:14 -07:00
|
|
|
#include <string.h>
|
2010-10-28 02:59:27 -07:00
|
|
|
#include <stddef.h>
|
2010-07-11 04:52:43 -07:00
|
|
|
#include <dirent.h>
|
2009-08-23 02:18:14 -07:00
|
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
|
# include <sys/types.h>
|
|
|
|
# include <sys/stat.h>
|
|
|
|
# include <unistd.h>
|
|
|
|
#else
|
|
|
|
# include <Evil.h>
|
|
|
|
#endif /* _WIN2 */
|
|
|
|
|
2008-09-03 07:40:12 -07:00
|
|
|
#ifndef _WIN32
|
|
|
|
# define PATH_DELIM '/'
|
|
|
|
#else
|
|
|
|
# define PATH_DELIM '\\'
|
2010-07-11 04:52:43 -07:00
|
|
|
# define NAME_MAX MAX_PATH
|
2008-09-03 07:40:12 -07:00
|
|
|
#endif
|
2008-07-30 06:35:49 -07:00
|
|
|
|
2010-09-28 23:37:56 -07:00
|
|
|
#ifdef __sun
|
|
|
|
# ifndef NAME_MAX
|
|
|
|
# define NAME_MAX 255
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
2009-08-28 05:03:34 -07:00
|
|
|
#include "eina_config.h"
|
2008-07-30 05:46:55 -07:00
|
|
|
#include "eina_private.h"
|
2009-09-06 15:21:56 -07:00
|
|
|
|
|
|
|
/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
|
2008-12-26 10:31:14 -08:00
|
|
|
#include "eina_safety_checks.h"
|
2009-08-28 05:03:34 -07:00
|
|
|
#include "eina_file.h"
|
2010-07-02 10:23:05 -07:00
|
|
|
#include "eina_stringshare.h"
|
|
|
|
|
|
|
|
typedef struct _Eina_File_Iterator Eina_File_Iterator;
|
|
|
|
struct _Eina_File_Iterator
|
|
|
|
{
|
|
|
|
Eina_Iterator iterator;
|
|
|
|
|
|
|
|
DIR *dirp;
|
|
|
|
int length;
|
|
|
|
|
|
|
|
char dir[1];
|
|
|
|
};
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_eina_file_ls_iterator_next(Eina_File_Iterator *it, void **data)
|
|
|
|
{
|
|
|
|
struct dirent *dp;
|
|
|
|
char *name;
|
|
|
|
size_t length;
|
|
|
|
|
2010-10-28 02:59:27 -07:00
|
|
|
dp = alloca(offsetof(struct dirent, d_name) + pathconf(it->dir, _PC_NAME_MAX) + 1);
|
|
|
|
|
2010-07-02 10:23:05 -07:00
|
|
|
do
|
|
|
|
{
|
2010-10-28 02:59:27 -07:00
|
|
|
if (readdir_r(it->dirp, dp, &dp))
|
|
|
|
return EINA_FALSE;
|
|
|
|
if (dp == NULL)
|
|
|
|
return EINA_FALSE;
|
2010-07-02 10:23:05 -07:00
|
|
|
}
|
2010-07-06 08:45:12 -07:00
|
|
|
while ((dp->d_name[0] == '.') &&
|
2010-07-27 19:37:05 -07:00
|
|
|
((dp->d_name[1] == '\0') ||
|
|
|
|
((dp->d_name[1] == '.') && (dp->d_name[2] == '\0'))));
|
2010-07-02 10:23:05 -07:00
|
|
|
|
2010-10-29 22:48:07 -07:00
|
|
|
#ifdef _DIRENT_HAVE_D_NAMLEN
|
|
|
|
length = dp->d_namlen;
|
|
|
|
#else
|
2010-07-02 10:23:05 -07:00
|
|
|
length = strlen(dp->d_name);
|
2010-10-29 22:48:07 -07:00
|
|
|
#endif
|
2010-07-02 10:23:05 -07:00
|
|
|
name = alloca(length + 2 + it->length);
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
memcpy(name, it->dir, it->length);
|
|
|
|
memcpy(name + it->length, "/", 1);
|
2010-07-02 10:23:05 -07:00
|
|
|
memcpy(name + it->length + 1, dp->d_name, length + 1);
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
*data = (char *)eina_stringshare_add(name);
|
2010-07-02 10:23:05 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2010-10-25 05:25:24 -07:00
|
|
|
static DIR *
|
2010-07-02 10:23:05 -07:00
|
|
|
_eina_file_ls_iterator_container(Eina_File_Iterator *it)
|
|
|
|
{
|
2010-10-25 05:25:24 -07:00
|
|
|
return it->dirp;
|
2010-07-02 10:23:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eina_file_ls_iterator_free(Eina_File_Iterator *it)
|
|
|
|
{
|
|
|
|
closedir(it->dirp);
|
|
|
|
|
|
|
|
EINA_MAGIC_SET(&it->iterator, 0);
|
|
|
|
free(it);
|
|
|
|
}
|
2008-08-08 22:47:15 -07:00
|
|
|
|
2010-07-06 08:45:12 -07:00
|
|
|
typedef struct _Eina_File_Direct_Iterator Eina_File_Direct_Iterator;
|
|
|
|
struct _Eina_File_Direct_Iterator
|
|
|
|
{
|
|
|
|
Eina_Iterator iterator;
|
|
|
|
|
|
|
|
DIR *dirp;
|
|
|
|
int length;
|
|
|
|
|
|
|
|
Eina_File_Direct_Info info;
|
|
|
|
|
|
|
|
char dir[1];
|
|
|
|
};
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_eina_file_direct_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data)
|
|
|
|
{
|
|
|
|
struct dirent *dp;
|
|
|
|
size_t length;
|
2010-10-29 22:48:07 -07:00
|
|
|
#ifndef _DIRENT_HAVE_D_TYPE
|
|
|
|
struct stat st;
|
|
|
|
#endif
|
|
|
|
|
2010-10-28 02:59:27 -07:00
|
|
|
dp = alloca(offsetof(struct dirent, d_name) + pathconf(it->dir, _PC_NAME_MAX) + 1);
|
|
|
|
|
2010-07-06 08:45:12 -07:00
|
|
|
do
|
|
|
|
{
|
2010-10-28 02:59:27 -07:00
|
|
|
if (readdir_r(it->dirp, dp, &dp))
|
|
|
|
return EINA_FALSE;
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!dp)
|
|
|
|
return EINA_FALSE;
|
2010-07-06 08:45:12 -07:00
|
|
|
|
2010-10-29 22:48:07 -07:00
|
|
|
#ifdef _DIRENT_HAVE_D_NAMLEN
|
|
|
|
length = dp->d_namlen;
|
|
|
|
#else
|
2010-07-27 19:37:05 -07:00
|
|
|
length = strlen(dp->d_name);
|
2010-10-29 22:48:07 -07:00
|
|
|
#endif
|
2010-07-27 19:37:05 -07:00
|
|
|
if (it->info.name_start + length + 1 >= PATH_MAX)
|
|
|
|
continue;
|
2010-07-06 08:45:12 -07:00
|
|
|
}
|
|
|
|
while ((dp->d_name[0] == '.') &&
|
2010-07-27 19:37:05 -07:00
|
|
|
((dp->d_name[1] == '\0') ||
|
|
|
|
((dp->d_name[1] == '.') && (dp->d_name[2] == '\0'))));
|
2010-07-06 08:45:12 -07:00
|
|
|
|
|
|
|
memcpy(it->info.path + it->info.name_start, dp->d_name, length);
|
|
|
|
it->info.name_length = length;
|
|
|
|
it->info.path_length = it->info.name_start + length;
|
|
|
|
it->info.path[it->info.path_length] = '\0';
|
|
|
|
it->info.dirent = dp;
|
2010-10-29 22:48:07 -07:00
|
|
|
#ifdef _DIRENT_HAVE_D_TYPE
|
|
|
|
switch (dp->d_type)
|
|
|
|
{
|
|
|
|
case DT_FIFO:
|
|
|
|
it->info.type = EINA_FILE_FIFO;
|
|
|
|
break;
|
|
|
|
case DT_CHR:
|
|
|
|
it->info.type = EINA_FILE_CHR;
|
|
|
|
break;
|
|
|
|
case DT_DIR:
|
|
|
|
it->info.type = EINA_FILE_DIR;
|
|
|
|
break;
|
|
|
|
case DT_BLK:
|
|
|
|
it->info.type = EINA_FILE_BLK;
|
|
|
|
break;
|
|
|
|
case DT_REG:
|
|
|
|
it->info.type = EINA_FILE_REG;
|
|
|
|
break;
|
|
|
|
case DT_LNK:
|
|
|
|
it->info.type = EINA_FILE_LNK;
|
|
|
|
break;
|
|
|
|
case DT_SOCK:
|
|
|
|
it->info.type = EINA_FILE_SOCK;
|
|
|
|
break;
|
|
|
|
case DT_WHT:
|
|
|
|
it->info.type = EINA_FILE_WHT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
it->info.type = EINA_FILE_UNKNOWN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (stat(it->info.path, &st))
|
|
|
|
it->info.type = EINA_FILE_UNKNOWN;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (S_ISREG(st.st_mode))
|
|
|
|
it->info.type = EINA_FILE_REG;
|
|
|
|
else if (S_ISDIR(st.st_mode))
|
|
|
|
it->info.type = EINA_FILE_DIR;
|
|
|
|
else if (S_ISCHR(st.st_mode))
|
|
|
|
it->info.type = EINA_FILE_CHR;
|
|
|
|
else if (S_ISBLK(st.st_mode))
|
|
|
|
it->info.type = EINA_FILE_BLK;
|
|
|
|
else if (S_ISFIFO(st.st_mode))
|
|
|
|
it->info.type = EINA_FILE_FIFO;
|
|
|
|
else if (S_ISLNK(st.st_mode))
|
|
|
|
it->info.type = EINA_FILE_LNK;
|
|
|
|
else if (S_ISSOCK(st.st_mode))
|
|
|
|
it->info.type = EINA_FILE_SOCK;
|
|
|
|
else
|
|
|
|
it->info.type = EINA_FILE_UNKNOWN;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-07-06 08:45:12 -07:00
|
|
|
*data = &it->info;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2010-10-25 05:25:24 -07:00
|
|
|
static DIR *
|
2010-07-06 08:45:12 -07:00
|
|
|
_eina_file_direct_ls_iterator_container(Eina_File_Direct_Iterator *it)
|
|
|
|
{
|
2010-10-25 05:25:24 -07:00
|
|
|
return it->dirp;
|
2010-07-06 08:45:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eina_file_direct_ls_iterator_free(Eina_File_Direct_Iterator *it)
|
|
|
|
{
|
|
|
|
closedir(it->dirp);
|
|
|
|
|
|
|
|
EINA_MAGIC_SET(&it->iterator, 0);
|
|
|
|
free(it);
|
|
|
|
}
|
|
|
|
|
2008-08-28 00:46:42 -07:00
|
|
|
/*============================================================================*
|
2010-07-27 19:37:05 -07:00
|
|
|
* Global *
|
|
|
|
*============================================================================*/
|
2008-08-28 00:46:42 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
/*============================================================================*
|
2010-07-27 19:37:05 -07:00
|
|
|
* API *
|
|
|
|
*============================================================================*/
|
2008-08-08 22:47:15 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
/**
|
2009-06-22 13:03:58 -07:00
|
|
|
* @addtogroup Eina_File_Group File
|
2008-09-18 22:22:43 -07:00
|
|
|
*
|
2008-09-20 01:42:35 -07:00
|
|
|
* @brief Functions to traverse directories and split paths.
|
2008-09-18 22:22:43 -07:00
|
|
|
*
|
2008-09-20 01:42:35 -07:00
|
|
|
* @li eina_file_dir_list() list the content of a directory,
|
|
|
|
* recusrsively or not, and can call a callback function for eachfound
|
|
|
|
* file.
|
|
|
|
* @li eina_file_split() split a path into all the subdirectories that
|
|
|
|
* compose it, according to the separator of the file system.
|
|
|
|
*
|
2008-09-18 22:22:43 -07:00
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief List all files on the directory calling the function for every file found.
|
|
|
|
*
|
|
|
|
* @param dir The directory name.
|
|
|
|
* @param recursive Iterate recursively in the directory.
|
|
|
|
* @param cb The callback to be called.
|
|
|
|
* @param data The data to pass to the callback.
|
2010-02-11 09:38:24 -08:00
|
|
|
* @return #EINA_TRUE on success, #EINA_FALSE otherwise.
|
2008-09-18 22:22:43 -07:00
|
|
|
*
|
|
|
|
* This function lists all the files in @p dir. To list also all the
|
|
|
|
* sub directoris recursively, @p recursive must be set to #EINA_TRUE,
|
|
|
|
* otherwise it must be set to #EINA_FALSE. For each found file, @p cb
|
|
|
|
* is called and @p data is passed to it.
|
|
|
|
*
|
|
|
|
* If @p cb or @p dir are @c NULL, or if @p dir is a string of size 0,
|
|
|
|
* or if @p dir can not be opened, this function returns #EINA_FALSE
|
2010-09-07 20:21:16 -07:00
|
|
|
* immediately. otherwise, it returns #EINA_TRUE.
|
2008-07-30 05:46:55 -07:00
|
|
|
*/
|
2008-08-18 01:18:16 -07:00
|
|
|
EAPI Eina_Bool
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_file_dir_list(const char *dir,
|
|
|
|
Eina_Bool recursive,
|
|
|
|
Eina_File_Dir_List_Cb cb,
|
|
|
|
void *data)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
2008-08-31 07:05:17 -07:00
|
|
|
#ifndef _WIN32
|
2010-10-29 22:48:07 -07:00
|
|
|
int dlength;
|
2010-07-27 19:37:05 -07:00
|
|
|
struct dirent *de;
|
|
|
|
DIR *d;
|
2010-10-29 22:48:07 -07:00
|
|
|
#ifndef _DIRENT_HAVE_D_TYPE
|
|
|
|
struct stat st;
|
|
|
|
#endif
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE);
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(dir, EINA_FALSE);
|
|
|
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(dir[0] == '\0', EINA_FALSE);
|
2009-01-23 08:43:14 -08:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
d = opendir(dir);
|
|
|
|
if (!d)
|
|
|
|
return EINA_FALSE;
|
2008-07-30 05:46:55 -07:00
|
|
|
|
2010-10-29 22:48:07 -07:00
|
|
|
dlength = strlen(dir);
|
2010-10-28 02:59:27 -07:00
|
|
|
de = alloca(offsetof(struct dirent, d_name) + pathconf(dir, _PC_NAME_MAX) + 1);
|
2010-10-29 22:48:07 -07:00
|
|
|
|
2010-10-28 02:59:27 -07:00
|
|
|
while ((!readdir_r(d, de, &de) && de))
|
2010-07-27 19:37:05 -07:00
|
|
|
{
|
|
|
|
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
|
|
|
|
continue;
|
2008-08-18 01:18:16 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
cb(de->d_name, dir, data);
|
|
|
|
/* d_type is only available on linux and bsd (_BSD_SOURCE) */
|
2008-08-18 01:18:16 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (recursive == EINA_TRUE)
|
|
|
|
{
|
|
|
|
char *path;
|
2010-10-29 22:48:07 -07:00
|
|
|
int length;
|
|
|
|
|
|
|
|
#ifdef _DIRENT_HAVE_D_NAMLEN
|
|
|
|
length = de->d_namlen;
|
|
|
|
#else
|
|
|
|
length = strlen(de->d_name);
|
|
|
|
#endif
|
|
|
|
path = alloca(dlength + length + 2);
|
2010-07-27 19:37:05 -07:00
|
|
|
strcpy(path, dir);
|
|
|
|
strcat(path, "/");
|
|
|
|
strcat(path, de->d_name);
|
2010-10-29 22:48:07 -07:00
|
|
|
#ifdef _DIRENT_HAVE_D_TYPE
|
|
|
|
if (de->d_type != DT_DIR)
|
|
|
|
continue;
|
|
|
|
#else
|
2010-07-27 19:37:05 -07:00
|
|
|
if (stat(path, &st))
|
|
|
|
continue;
|
|
|
|
if (!S_ISDIR(st.st_mode))
|
|
|
|
continue;
|
2008-12-23 05:33:11 -08:00
|
|
|
#endif
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_file_dir_list(path, recursive, cb, data);
|
|
|
|
}
|
|
|
|
}
|
2008-08-18 01:18:16 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
closedir(d);
|
2008-08-31 07:05:17 -07:00
|
|
|
#else
|
2010-07-27 19:37:05 -07:00
|
|
|
WIN32_FIND_DATA file;
|
|
|
|
HANDLE hSearch;
|
|
|
|
char *new_dir;
|
|
|
|
TCHAR *tdir;
|
|
|
|
size_t length_dir;
|
2008-08-31 07:05:17 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE);
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(dir, EINA_FALSE);
|
|
|
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(dir[0] == '\0', EINA_FALSE);
|
2009-01-23 08:43:14 -08:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
length_dir = strlen(dir);
|
|
|
|
new_dir = (char *)alloca(length_dir + 5);
|
|
|
|
if (!new_dir)
|
|
|
|
return EINA_FALSE;
|
2008-08-31 07:05:17 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
memcpy(new_dir, dir, length_dir);
|
|
|
|
memcpy(new_dir + length_dir, "/*.*", 5);
|
2008-08-31 07:05:17 -07:00
|
|
|
|
|
|
|
#ifdef UNICODE
|
2010-07-27 19:37:05 -07:00
|
|
|
tdir = evil_char_to_wchar(new_dir);
|
2008-08-31 07:05:17 -07:00
|
|
|
#else
|
2010-07-27 19:37:05 -07:00
|
|
|
tdir = new_dir;
|
2008-08-31 07:05:17 -07:00
|
|
|
#endif /* ! UNICODE */
|
2010-07-27 19:37:05 -07:00
|
|
|
hSearch = FindFirstFile(tdir, &file);
|
2008-08-31 07:05:17 -07:00
|
|
|
#ifdef UNICODE
|
2010-07-27 19:37:05 -07:00
|
|
|
free(tdir);
|
2008-08-31 07:05:17 -07:00
|
|
|
#endif /* UNICODE */
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (hSearch == INVALID_HANDLE_VALUE)
|
|
|
|
return EINA_FALSE;
|
2008-08-31 07:05:17 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
do
|
|
|
|
{
|
|
|
|
char *filename;
|
2008-08-31 07:05:17 -07:00
|
|
|
|
|
|
|
#ifdef UNICODE
|
2010-07-27 19:37:05 -07:00
|
|
|
filename = evil_wchar_to_char(file.cFileName);
|
2008-08-31 07:05:17 -07:00
|
|
|
#else
|
2010-07-27 19:37:05 -07:00
|
|
|
filename = file.cFileName;
|
2008-08-31 07:05:17 -07:00
|
|
|
#endif /* ! UNICODE */
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!strcmp(filename, ".") || !strcmp(filename, ".."))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
cb(filename, dir, data);
|
2008-08-31 07:05:17 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (recursive == EINA_TRUE)
|
|
|
|
{
|
|
|
|
char *path;
|
2008-08-31 07:05:17 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
path = alloca(strlen(dir) + strlen(filename) + 2);
|
|
|
|
strcpy(path, dir);
|
|
|
|
strcat(path, "/");
|
|
|
|
strcat(path, filename);
|
2008-08-31 07:05:17 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!(file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
|
|
continue;
|
2008-08-31 07:05:17 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_file_dir_list(path, recursive, cb, data);
|
|
|
|
}
|
2008-08-31 07:05:17 -07:00
|
|
|
|
|
|
|
#ifdef UNICODE
|
2010-07-27 19:37:05 -07:00
|
|
|
free(filename);
|
2008-08-31 07:05:17 -07:00
|
|
|
#endif /* UNICODE */
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
} while (FindNextFile(hSearch, &file));
|
|
|
|
FindClose(hSearch);
|
2008-08-31 07:05:17 -07:00
|
|
|
#endif /* _WIN32 */
|
2008-07-30 05:46:55 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
return EINA_TRUE;
|
2008-08-18 01:18:16 -07:00
|
|
|
}
|
2008-09-01 05:51:50 -07:00
|
|
|
|
|
|
|
/**
|
2008-09-18 22:22:43 -07:00
|
|
|
* @brief Split a path according to the delimiter of the filesystem.
|
2008-09-01 05:51:50 -07:00
|
|
|
*
|
2008-09-18 22:22:43 -07:00
|
|
|
* @param path The path to split.
|
|
|
|
* @return An array of the parts of the path to split.
|
|
|
|
*
|
|
|
|
* This function splits @p path according to the delimiter of the used
|
|
|
|
* filesystem. If @p path is @c NULL or if the array can not be
|
|
|
|
* created, @c NULL is returned, otherwise, an array with the
|
|
|
|
* different parts of @p path is returned.
|
2008-09-01 05:51:50 -07:00
|
|
|
*/
|
2008-09-03 07:40:12 -07:00
|
|
|
EAPI Eina_Array *
|
|
|
|
eina_file_split(char *path)
|
2008-09-01 05:51:50 -07:00
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
Eina_Array *ea;
|
|
|
|
char *current;
|
|
|
|
size_t length;
|
2008-09-03 07:40:12 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
|
2008-09-03 07:40:12 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
ea = eina_array_new(16);
|
2008-09-03 07:40:12 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!ea)
|
|
|
|
return NULL;
|
2008-09-01 05:51:50 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
for (current = strchr(path, PATH_DELIM);
|
2010-08-21 06:52:25 -07:00
|
|
|
current;
|
2010-07-27 19:37:05 -07:00
|
|
|
path = current + 1, current = strchr(path, PATH_DELIM))
|
|
|
|
{
|
|
|
|
length = current - path;
|
2008-09-01 05:51:50 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (length <= 0)
|
|
|
|
continue;
|
2008-09-03 07:40:12 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_array_push(ea, path);
|
|
|
|
*current = '\0';
|
|
|
|
}
|
2008-09-01 05:51:50 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (*path != '\0')
|
|
|
|
eina_array_push(ea, path);
|
2008-09-03 07:40:12 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
return ea;
|
2008-09-03 07:40:12 -07:00
|
|
|
}
|
2008-09-18 22:22:43 -07:00
|
|
|
|
2010-07-02 10:23:05 -07:00
|
|
|
/**
|
2010-07-06 08:45:12 -07:00
|
|
|
* Get an iterator to list the content of a directory.
|
|
|
|
*
|
|
|
|
* Iterators are cheap to be created and allow interruption at any
|
|
|
|
* iteration. At each iteration, only the next directory entry is read
|
2010-10-28 02:59:27 -07:00
|
|
|
* from the filesystem with readdir_r().
|
2010-07-06 08:45:12 -07:00
|
|
|
*
|
|
|
|
* The iterator will handle the user a stringshared value with the
|
|
|
|
* full path. One must call eina_stringshare_del() on it after usage
|
|
|
|
* to not leak!
|
|
|
|
*
|
|
|
|
* The eina_file_direct_ls() function will provide a possibly faster
|
|
|
|
* alternative if you need to filter the results somehow, like
|
|
|
|
* checking extension.
|
|
|
|
*
|
2010-07-02 10:23:05 -07:00
|
|
|
* The iterator will walk over '.' and '..' without returning them.
|
2010-07-06 08:45:12 -07:00
|
|
|
*
|
2010-10-25 05:25:24 -07:00
|
|
|
* The iterator container is the DIR* corresponding to the current walk.
|
|
|
|
*
|
2010-07-02 10:23:05 -07:00
|
|
|
* @param dir The name of the directory to list
|
2010-07-06 08:45:12 -07:00
|
|
|
* @return Return an Eina_Iterator that will walk over the files and
|
|
|
|
* directory in the pointed directory. On failure it will
|
|
|
|
* return NULL. The iterator emits stringshared value with the
|
|
|
|
* full path and must be freed with eina_stringshare_del().
|
|
|
|
*
|
|
|
|
* @see eina_file_direct_ls()
|
2010-07-02 10:23:05 -07:00
|
|
|
*/
|
|
|
|
EAPI Eina_Iterator *
|
|
|
|
eina_file_ls(const char *dir)
|
|
|
|
{
|
|
|
|
Eina_File_Iterator *it;
|
|
|
|
size_t length;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!dir)
|
|
|
|
return NULL;
|
2010-07-02 10:23:05 -07:00
|
|
|
|
|
|
|
length = strlen(dir);
|
2010-07-27 19:37:05 -07:00
|
|
|
if (length < 1)
|
|
|
|
return NULL;
|
2010-07-02 10:23:05 -07:00
|
|
|
|
2010-08-19 05:02:28 -07:00
|
|
|
it = calloc(1, sizeof (Eina_File_Iterator) + length);
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!it)
|
|
|
|
return NULL;
|
2010-07-02 10:23:05 -07:00
|
|
|
|
|
|
|
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
|
|
|
|
|
|
|
|
it->dirp = opendir(dir);
|
|
|
|
if (!it->dirp)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
free(it);
|
|
|
|
return NULL;
|
2010-07-02 10:23:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(it->dir, dir, length + 1);
|
2010-07-06 08:45:12 -07:00
|
|
|
if (dir[length - 1] != '/')
|
2010-07-27 19:37:05 -07:00
|
|
|
it->length = length;
|
2010-07-06 08:45:12 -07:00
|
|
|
else
|
2010-07-27 19:37:05 -07:00
|
|
|
it->length = length - 1;
|
2010-07-02 10:23:05 -07:00
|
|
|
|
2010-08-19 05:02:28 -07:00
|
|
|
it->iterator.version = EINA_ITERATOR_VERSION;
|
2010-07-02 10:23:05 -07:00
|
|
|
it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_ls_iterator_next);
|
2010-07-27 19:37:05 -07:00
|
|
|
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
|
|
|
|
_eina_file_ls_iterator_container);
|
2010-07-02 10:23:05 -07:00
|
|
|
it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_ls_iterator_free);
|
|
|
|
|
|
|
|
return &it->iterator;
|
|
|
|
}
|
|
|
|
|
2010-07-06 08:45:12 -07:00
|
|
|
/**
|
|
|
|
* Get an iterator to list the content of a directory, with direct information.
|
|
|
|
*
|
|
|
|
* Iterators are cheap to be created and allow interruption at any
|
|
|
|
* iteration. At each iteration, only the next directory entry is read
|
2010-10-28 02:59:27 -07:00
|
|
|
* from the filesystem with readdir_r().
|
2010-07-06 08:45:12 -07:00
|
|
|
*
|
|
|
|
* The iterator returns the direct pointer to couple of useful information in
|
|
|
|
* #Eina_File_Direct_Info and that pointer should not be modified anyhow!
|
|
|
|
*
|
|
|
|
* The iterator will walk over '.' and '..' without returning them.
|
|
|
|
*
|
2010-10-25 05:25:24 -07:00
|
|
|
* The iterator container is the DIR* corresponding to the current walk.
|
|
|
|
*
|
2010-07-06 08:45:12 -07:00
|
|
|
* @param dir The name of the directory to list
|
|
|
|
|
|
|
|
* @return Return an Eina_Iterator that will walk over the files and
|
|
|
|
* directory in the pointed directory. On failure it will
|
|
|
|
* return NULL. The iterator emits #Eina_File_Direct_Info
|
|
|
|
* pointers that could be used but not modified. The lifetime
|
|
|
|
* of the returned pointer is until the next iteration and
|
|
|
|
* while the iterator is live, deleting the iterator
|
|
|
|
* invalidates the pointer.
|
|
|
|
*
|
|
|
|
* @see eina_file_ls()
|
|
|
|
*/
|
|
|
|
EAPI Eina_Iterator *
|
|
|
|
eina_file_direct_ls(const char *dir)
|
|
|
|
{
|
|
|
|
Eina_File_Direct_Iterator *it;
|
|
|
|
size_t length;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!dir)
|
|
|
|
return NULL;
|
2010-07-06 08:45:12 -07:00
|
|
|
|
|
|
|
length = strlen(dir);
|
2010-07-27 19:37:05 -07:00
|
|
|
if (length < 1)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (length + NAME_MAX + 2 >= PATH_MAX)
|
|
|
|
return NULL;
|
2010-07-06 08:45:12 -07:00
|
|
|
|
2010-08-19 05:02:28 -07:00
|
|
|
it = calloc(1, sizeof(Eina_File_Direct_Iterator) + length);
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!it)
|
|
|
|
return NULL;
|
2010-07-06 08:45:12 -07:00
|
|
|
|
|
|
|
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
|
|
|
|
|
|
|
|
it->dirp = opendir(dir);
|
|
|
|
if (!it->dirp)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
free(it);
|
|
|
|
return NULL;
|
2010-07-06 08:45:12 -07:00
|
|
|
}
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
memcpy(it->dir, dir, length + 1);
|
2010-07-06 08:45:12 -07:00
|
|
|
it->length = length;
|
|
|
|
|
|
|
|
memcpy(it->info.path, dir, length);
|
|
|
|
if (dir[length - 1] == '/')
|
2010-07-27 19:37:05 -07:00
|
|
|
it->info.name_start = length;
|
2010-07-06 08:45:12 -07:00
|
|
|
else
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
it->info.path[length] = '/';
|
|
|
|
it->info.name_start = length + 1;
|
2010-07-06 08:45:12 -07:00
|
|
|
}
|
|
|
|
|
2010-08-19 05:02:28 -07:00
|
|
|
it->iterator.version = EINA_ITERATOR_VERSION;
|
2010-07-06 08:45:12 -07:00
|
|
|
it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_direct_ls_iterator_next);
|
2010-07-27 19:37:05 -07:00
|
|
|
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
|
|
|
|
_eina_file_direct_ls_iterator_container);
|
2010-07-06 08:45:12 -07:00
|
|
|
it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_direct_ls_iterator_free);
|
|
|
|
|
|
|
|
return &it->iterator;
|
|
|
|
}
|
|
|
|
|
2008-09-18 22:22:43 -07:00
|
|
|
/**
|
|
|
|
* @}
|
|
|
|
*/
|