aaagh. dirent... bad! too many things in dirent that are not portable

- d_type for example... so put that into the direct_info struct and
handle the compat in eina.



SVN revision: 54015
This commit is contained in:
Carsten Haitzler 2010-10-30 05:48:07 +00:00
parent 3d6e44bd91
commit a08524ea65
2 changed files with 104 additions and 21 deletions

View File

@ -50,6 +50,22 @@ typedef struct _Eina_File_Direct_Info Eina_File_Direct_Info;
*/ */
typedef void (*Eina_File_Dir_List_Cb)(const char *name, const char *path, void *data); typedef void (*Eina_File_Dir_List_Cb)(const char *name, const char *path, void *data);
/**
* @typedef Eina_File_Type
* file type in Eina_File_Direct_Info.
*/
typedef enum {
EINA_FILE_UNKNOWN,
EINA_FILE_FIFO,
EINA_FILE_CHR,
EINA_FILE_DIR,
EINA_FILE_BLK,
EINA_FILE_REG,
EINA_FILE_LNK,
EINA_FILE_SOCK,
EINA_FILE_WHT
} Eina_File_Type;
/** /**
* @struct _Eina_File_Direct_Info * @struct _Eina_File_Direct_Info
* A structure to store informations of a path. * A structure to store informations of a path.
@ -60,7 +76,8 @@ struct _Eina_File_Direct_Info
size_t name_length; /**< size of the filename/basename component */ size_t name_length; /**< size of the filename/basename component */
size_t name_start; /**< where the filename/basename component starts */ size_t name_start; /**< where the filename/basename component starts */
char path[PATH_MAX]; /**< the path */ char path[PATH_MAX]; /**< the path */
const struct dirent *dirent; /**< the dirent structure of the path */ const struct dirent *dirent; /**< the dirent structure of the path - don't use this if you want compatibility */
Eina_File_Type type; /**< file type */
}; };
/** /**

View File

@ -101,7 +101,11 @@ _eina_file_ls_iterator_next(Eina_File_Iterator *it, void **data)
((dp->d_name[1] == '\0') || ((dp->d_name[1] == '\0') ||
((dp->d_name[1] == '.') && (dp->d_name[2] == '\0')))); ((dp->d_name[1] == '.') && (dp->d_name[2] == '\0'))));
#ifdef _DIRENT_HAVE_D_NAMLEN
length = dp->d_namlen;
#else
length = strlen(dp->d_name); length = strlen(dp->d_name);
#endif
name = alloca(length + 2 + it->length); name = alloca(length + 2 + it->length);
memcpy(name, it->dir, it->length); memcpy(name, it->dir, it->length);
@ -145,7 +149,10 @@ _eina_file_direct_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data)
{ {
struct dirent *dp; struct dirent *dp;
size_t length; size_t length;
#ifndef _DIRENT_HAVE_D_TYPE
struct stat st;
#endif
dp = alloca(offsetof(struct dirent, d_name) + pathconf(it->dir, _PC_NAME_MAX) + 1); dp = alloca(offsetof(struct dirent, d_name) + pathconf(it->dir, _PC_NAME_MAX) + 1);
do do
@ -155,7 +162,11 @@ _eina_file_direct_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data)
if (!dp) if (!dp)
return EINA_FALSE; return EINA_FALSE;
#ifdef _DIRENT_HAVE_D_NAMLEN
length = dp->d_namlen;
#else
length = strlen(dp->d_name); length = strlen(dp->d_name);
#endif
if (it->info.name_start + length + 1 >= PATH_MAX) if (it->info.name_start + length + 1 >= PATH_MAX)
continue; continue;
} }
@ -168,7 +179,61 @@ _eina_file_direct_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data)
it->info.path_length = it->info.name_start + length; it->info.path_length = it->info.name_start + length;
it->info.path[it->info.path_length] = '\0'; it->info.path[it->info.path_length] = '\0';
it->info.dirent = dp; it->info.dirent = dp;
#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
*data = &it->info; *data = &it->info;
return EINA_TRUE; return EINA_TRUE;
} }
@ -235,9 +300,13 @@ eina_file_dir_list(const char *dir,
void *data) void *data)
{ {
#ifndef _WIN32 #ifndef _WIN32
int dlength;
struct dirent *de; struct dirent *de;
DIR *d; DIR *d;
#ifndef _DIRENT_HAVE_D_TYPE
struct stat st;
#endif
EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(dir, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(dir, EINA_FALSE);
EINA_SAFETY_ON_TRUE_RETURN_VAL(dir[0] == '\0', EINA_FALSE); EINA_SAFETY_ON_TRUE_RETURN_VAL(dir[0] == '\0', EINA_FALSE);
@ -246,8 +315,9 @@ eina_file_dir_list(const char *dir,
if (!d) if (!d)
return EINA_FALSE; return EINA_FALSE;
dlength = strlen(dir);
de = alloca(offsetof(struct dirent, d_name) + pathconf(dir, _PC_NAME_MAX) + 1); de = alloca(offsetof(struct dirent, d_name) + pathconf(dir, _PC_NAME_MAX) + 1);
while ((!readdir_r(d, de, &de) && de)) while ((!readdir_r(d, de, &de) && de))
{ {
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
@ -259,30 +329,26 @@ eina_file_dir_list(const char *dir,
if (recursive == EINA_TRUE) if (recursive == EINA_TRUE)
{ {
char *path; char *path;
int length;
path = alloca(strlen(dir) + strlen(de->d_name) + 2);
#ifdef _DIRENT_HAVE_D_NAMLEN
length = de->d_namlen;
#else
length = strlen(de->d_name);
#endif
path = alloca(dlength + length + 2);
strcpy(path, dir); strcpy(path, dir);
strcat(path, "/"); strcat(path, "/");
strcat(path, de->d_name); strcat(path, de->d_name);
#ifndef sun #ifdef _DIRENT_HAVE_D_TYPE
if (de->d_type == DT_UNKNOWN) if (de->d_type != DT_DIR)
{ continue;
#endif #else
struct stat st;
if (stat(path, &st)) if (stat(path, &st))
continue; continue;
if (!S_ISDIR(st.st_mode)) if (!S_ISDIR(st.st_mode))
continue; continue;
#ifndef sun
}
else if (de->d_type != DT_DIR)
continue;
#endif #endif
eina_file_dir_list(path, recursive, cb, data); eina_file_dir_list(path, recursive, cb, data);
} }
} }