forked from enlightenment/efl
parent
49a33976cc
commit
c6cb315e35
|
@ -156,6 +156,13 @@ EAPI Eio_File *eio_file_stat_ls(const char *dir,
|
||||||
Eio_Error_Cb error_cb,
|
Eio_Error_Cb error_cb,
|
||||||
const void *data);
|
const void *data);
|
||||||
|
|
||||||
|
EAPI Eio_File *eio_dir_stat_ls(const char *dir,
|
||||||
|
Eio_Filter_Direct_Cb filter_cb,
|
||||||
|
Eio_Main_Direct_Cb main_cb,
|
||||||
|
Eio_Done_Cb done_cb,
|
||||||
|
Eio_Error_Cb error_cb,
|
||||||
|
const void *data);
|
||||||
|
|
||||||
EAPI Eio_File *eio_file_direct_stat(const char *path,
|
EAPI Eio_File *eio_file_direct_stat(const char *path,
|
||||||
Eio_Stat_Cb done_cb,
|
Eio_Stat_Cb done_cb,
|
||||||
Eio_Error_Cb error_cb,
|
Eio_Error_Cb error_cb,
|
||||||
|
|
|
@ -97,6 +97,87 @@
|
||||||
* @endcode
|
* @endcode
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page tutorial_dir_stat_ls eio_dir_stat_ls() tutorial
|
||||||
|
*
|
||||||
|
* @li The filter callback, which allow or not a file to be seen
|
||||||
|
* by the main loop handler. This callback run in a separated thread.
|
||||||
|
* @li The main callback, which receive in the main loop all the file
|
||||||
|
* that are allowed by the filter. If you are updating a user interface
|
||||||
|
* it make sense to delay the insertion a little, so you get a chance
|
||||||
|
* to update the canvas for a bunch of file instead of one by one.
|
||||||
|
* @li The end callback, which is called in the main loop when the
|
||||||
|
* content of the directory has been correctly scanned and all the
|
||||||
|
* file notified to the main loop.
|
||||||
|
* @li The error callback, which is called if an error occured or
|
||||||
|
* if the listing was cancelled during it's run. You can then retrieve
|
||||||
|
* the error type as an errno error.
|
||||||
|
*
|
||||||
|
* Here is a simple example that implement a stupidly simple replacement for find:
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* #include <Ecore.h>
|
||||||
|
* #include <Eio.h>
|
||||||
|
*
|
||||||
|
* static Eina_Bool
|
||||||
|
* _test_filter_cb(void *data, Eio_File *handler, const Eina_File_Direct_Info *info)
|
||||||
|
* {
|
||||||
|
* fprintf(stderr, "ACCEPTING: %s\n", info->path);
|
||||||
|
* return EINA_TRUE;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* static void
|
||||||
|
* _test_main_cb(void *data, Eio_File *handler, const Eina_File_Direct_Info *info)
|
||||||
|
* {
|
||||||
|
* fprintf(stderr, "PROCESS: %s\n", info->path);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* static void
|
||||||
|
* _test_done_cb(void *data, Eio_File *handler)
|
||||||
|
* {
|
||||||
|
* printf("ls done\n");
|
||||||
|
* ecore_main_loop_quit();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* static void
|
||||||
|
* _test_error_cb(void *data, Eio_File *handler, int error)
|
||||||
|
* {
|
||||||
|
* fprintf(stderr, "error: [%s]\n", strerror(error));
|
||||||
|
* ecore_main_loop_quit();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* int
|
||||||
|
* main(int argc, char **argv)
|
||||||
|
* {
|
||||||
|
* Eio_File *cp;
|
||||||
|
*
|
||||||
|
* if (argc != 2)
|
||||||
|
* {
|
||||||
|
* fprintf(stderr, "eio_ls directory\n");
|
||||||
|
* return -1;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* ecore_init();
|
||||||
|
* eio_init();
|
||||||
|
*
|
||||||
|
* cp = eio_dir_stat_ls(argv[1],
|
||||||
|
* _test_filter_cb,
|
||||||
|
* _test_main_cb,
|
||||||
|
* _test_done_cb,
|
||||||
|
* _test_error_cb,
|
||||||
|
* NULL);
|
||||||
|
*
|
||||||
|
* ecore_main_loop_begin();
|
||||||
|
*
|
||||||
|
* eio_shutdown();
|
||||||
|
* ecore_shutdown();
|
||||||
|
*
|
||||||
|
* return 0;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
|
||||||
#include "eio_private.h"
|
#include "eio_private.h"
|
||||||
#include "Eio.h"
|
#include "Eio.h"
|
||||||
|
|
||||||
|
@ -113,64 +194,84 @@ eio_strcmp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return strcmp(a, b);
|
return strcmp(a, b);
|
||||||
}
|
}
|
||||||
|
static Eina_Bool
|
||||||
|
_eio_dir_recursive_progress(Eio_Dir_Copy *copy, Eio_File *handler, const Eina_File_Direct_Info *info)
|
||||||
|
{
|
||||||
|
switch (info->type)
|
||||||
|
{
|
||||||
|
case EINA_FILE_UNKNOWN:
|
||||||
|
eio_file_thread_error(©->progress.common, handler->thread);
|
||||||
|
return EINA_FALSE;
|
||||||
|
case EINA_FILE_LNK:
|
||||||
|
copy->links = eina_list_append(copy->links, eina_stringshare_add(info->path));
|
||||||
|
break;
|
||||||
|
case EINA_FILE_DIR:
|
||||||
|
copy->dirs = eina_list_append(copy->dirs, eina_stringshare_add(info->path));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
copy->files = eina_list_append(copy->files, eina_stringshare_add(info->path));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static Eina_Bool
|
static Eina_Bool
|
||||||
_eio_dir_recursiv_ls(Ecore_Thread *thread, Eio_Dir_Copy *copy, const char *target)
|
_eio_file_recursiv_ls(Ecore_Thread *thread,
|
||||||
|
Eio_File *common,
|
||||||
|
Eio_Filter_Direct_Cb filter_cb,
|
||||||
|
void *data,
|
||||||
|
const char *target)
|
||||||
{
|
{
|
||||||
const Eina_File_Direct_Info *info;
|
Eina_File_Direct_Info *info;
|
||||||
Eina_Iterator *it;
|
Eina_Iterator *it = NULL;
|
||||||
Eina_List *dirs = NULL;
|
|
||||||
Eina_List *l;
|
Eina_List *l;
|
||||||
|
Eina_List *dirs = NULL;
|
||||||
const char *dir;
|
const char *dir;
|
||||||
struct stat buffer;
|
|
||||||
|
|
||||||
it = eina_file_stat_ls(target);
|
it = eina_file_stat_ls(target);
|
||||||
if (!it)
|
if (!it)
|
||||||
{
|
{
|
||||||
eio_file_thread_error(©->progress.common, thread);
|
eio_file_thread_error(common, thread);
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
EINA_ITERATOR_FOREACH(it, info)
|
EINA_ITERATOR_FOREACH(it, info)
|
||||||
{
|
{
|
||||||
|
Eina_Bool filter = EINA_TRUE;
|
||||||
|
struct stat buffer;
|
||||||
|
|
||||||
switch (info->type)
|
switch (info->type)
|
||||||
{
|
{
|
||||||
case EINA_FILE_UNKNOWN:
|
|
||||||
eio_file_thread_error(©->progress.common, thread);
|
|
||||||
goto on_error;
|
|
||||||
case EINA_FILE_DIR:
|
case EINA_FILE_DIR:
|
||||||
if (lstat(info->path, &buffer) != 0)
|
if (lstat(info->path, &buffer) != 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
if (S_ISDIR(buffer.st_mode))
|
if (S_ISLNK(buffer.st_mode))
|
||||||
dirs = eina_list_append(dirs, eina_stringshare_add(info->path));
|
info->type = EINA_FILE_LNK;
|
||||||
else /* It's a link we should not forget about it */
|
|
||||||
copy->links = eina_list_append(copy->links, eina_stringshare_add(info->path));
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
copy->files = eina_list_append(copy->files, eina_stringshare_add(info->path));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filter = filter_cb(data, common, info);
|
||||||
|
if (filter && info->type == EINA_FILE_DIR)
|
||||||
|
dirs = eina_list_append(dirs, eina_stringshare_add(info->path));
|
||||||
|
|
||||||
if (ecore_thread_check(thread))
|
if (ecore_thread_check(thread))
|
||||||
goto on_error;
|
goto on_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
eina_iterator_free(it);
|
eina_iterator_free(it);
|
||||||
|
it = NULL;
|
||||||
|
|
||||||
EINA_LIST_FOREACH(dirs, l, dir)
|
EINA_LIST_FOREACH(dirs, l, dir)
|
||||||
if (!_eio_dir_recursiv_ls(thread, copy, dir))
|
if (!_eio_file_recursiv_ls(thread, common, filter_cb, data, dir))
|
||||||
{
|
goto on_error;
|
||||||
EINA_LIST_FREE(dirs, dir)
|
|
||||||
eina_stringshare_del(dir);
|
|
||||||
return EINA_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
copy->dirs = eina_list_merge(copy->dirs, dirs);
|
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
|
|
||||||
on_error:
|
on_error:
|
||||||
eina_iterator_free(it);
|
if (it) eina_iterator_free(it);
|
||||||
|
|
||||||
EINA_LIST_FREE(dirs, dir)
|
EINA_LIST_FREE(dirs, dir)
|
||||||
eina_stringshare_del(dir);
|
eina_stringshare_del(dir);
|
||||||
|
@ -178,6 +279,18 @@ _eio_dir_recursiv_ls(Ecore_Thread *thread, Eio_Dir_Copy *copy, const char *targe
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_eio_dir_recursiv_ls(Ecore_Thread *thread, Eio_Dir_Copy *copy, const char *target)
|
||||||
|
{
|
||||||
|
if (!_eio_file_recursiv_ls(thread, ©->progress.common,
|
||||||
|
(Eio_Filter_Direct_Cb) _eio_dir_recursive_progress,
|
||||||
|
copy, target))
|
||||||
|
return EINA_FALSE;
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static Eina_Bool
|
static Eina_Bool
|
||||||
_eio_dir_init(Ecore_Thread *thread,
|
_eio_dir_init(Ecore_Thread *thread,
|
||||||
off_t *step, off_t *count,
|
off_t *step, off_t *count,
|
||||||
|
@ -314,7 +427,7 @@ _eio_dir_link(Ecore_Thread *thread, Eio_Dir_Copy *order,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create the link */
|
/* create the link */
|
||||||
if (symlink(oldpath, newpath) != 0)
|
if (symlink(newpath, oldpath) != 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
/* inform main thread */
|
/* inform main thread */
|
||||||
|
@ -698,6 +811,78 @@ _eio_dir_rmrf_heavy(void *data, Ecore_Thread *thread)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_eio_dir_stat_find_forward(Eio_File_Direct_Ls *async,
|
||||||
|
Eio_File *handler,
|
||||||
|
const Eina_File_Direct_Info *info)
|
||||||
|
{
|
||||||
|
Eina_Bool filter = EINA_TRUE;
|
||||||
|
|
||||||
|
if (async->filter_cb)
|
||||||
|
{
|
||||||
|
filter = async->filter_cb((void*) async->ls.common.data, &async->ls.common, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter)
|
||||||
|
{
|
||||||
|
Eina_File_Direct_Info *send;
|
||||||
|
|
||||||
|
send = eio_direct_info_malloc();
|
||||||
|
if (!send) return EINA_FALSE;
|
||||||
|
|
||||||
|
memcpy(send, info, sizeof (Eina_File_Direct_Info));
|
||||||
|
|
||||||
|
ecore_thread_feedback(handler->thread, send);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_eio_dir_stat_find_heavy(void *data, Ecore_Thread *thread)
|
||||||
|
{
|
||||||
|
Eio_File_Direct_Ls *async = data;
|
||||||
|
|
||||||
|
async->ls.common.thread = thread;
|
||||||
|
|
||||||
|
_eio_file_recursiv_ls(thread, &async->ls.common,
|
||||||
|
(Eio_Filter_Direct_Cb) _eio_dir_stat_find_forward,
|
||||||
|
async, async->ls.directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_eio_dir_stat_find_notify(void *data, Ecore_Thread *thread __UNUSED__, void *msg_data)
|
||||||
|
{
|
||||||
|
Eio_File_Direct_Ls *async = data;
|
||||||
|
Eina_File_Direct_Info *info = msg_data;
|
||||||
|
|
||||||
|
async->main_cb((void*) async->ls.common.data, &async->ls.common, info);
|
||||||
|
|
||||||
|
eio_direct_info_free(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_eio_dir_stat_done(void *data, Ecore_Thread *thread __UNUSED__)
|
||||||
|
{
|
||||||
|
Eio_File_Ls *async = data;
|
||||||
|
|
||||||
|
async->common.done_cb((void*) async->common.data, &async->common);
|
||||||
|
|
||||||
|
eina_stringshare_del(async->directory);
|
||||||
|
free(async);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_eio_dir_stat_error(void *data, Ecore_Thread *thread __UNUSED__)
|
||||||
|
{
|
||||||
|
Eio_File_Ls *async = data;
|
||||||
|
|
||||||
|
eio_file_error(&async->common);
|
||||||
|
|
||||||
|
eina_stringshare_del(async->directory);
|
||||||
|
free(async);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @endcond
|
* @endcond
|
||||||
*/
|
*/
|
||||||
|
@ -873,6 +1058,54 @@ eio_dir_unlink(const char *path,
|
||||||
return &rmrf->progress.common;
|
return &rmrf->progress.common;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief List the content of a directory and all it's sub-content asynchronously
|
||||||
|
* @param dir The directory to list.
|
||||||
|
* @param filter_cb Callback called from another thread.
|
||||||
|
* @param main_cb Callback called from the main loop for each accepted file.
|
||||||
|
* @param done_cb Callback called from the main loop when the content of the directory has been listed.
|
||||||
|
* @param error_cb Callback called from the main loop when the directory could not be opened or listing content has been canceled.
|
||||||
|
* @param data Data passed to callback and not modified at all by eio_dir_stat_find.
|
||||||
|
* @return A reference to the IO operation.
|
||||||
|
*
|
||||||
|
* eio_dir_stat_find() run eina_file_stat_ls() recursivly in a separated thread using
|
||||||
|
* ecore_thread_feedback_run. This prevent any lock in your apps.
|
||||||
|
*/
|
||||||
|
EAPI Eio_File *
|
||||||
|
eio_dir_stat_ls(const char *dir,
|
||||||
|
Eio_Filter_Direct_Cb filter_cb,
|
||||||
|
Eio_Main_Direct_Cb main_cb,
|
||||||
|
Eio_Done_Cb done_cb,
|
||||||
|
Eio_Error_Cb error_cb,
|
||||||
|
const void *data)
|
||||||
|
{
|
||||||
|
Eio_File_Direct_Ls *async;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(main_cb, NULL);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
|
||||||
|
|
||||||
|
async = malloc(sizeof(Eio_File_Direct_Ls));
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(async, NULL);
|
||||||
|
|
||||||
|
async->filter_cb = filter_cb;
|
||||||
|
async->main_cb = main_cb;
|
||||||
|
async->ls.directory = eina_stringshare_add(dir);
|
||||||
|
|
||||||
|
if (!eio_long_file_set(&async->ls.common,
|
||||||
|
done_cb,
|
||||||
|
error_cb,
|
||||||
|
data,
|
||||||
|
_eio_dir_stat_find_heavy,
|
||||||
|
_eio_dir_stat_find_notify,
|
||||||
|
_eio_dir_stat_done,
|
||||||
|
_eio_dir_stat_error))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &async->ls.common;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -727,7 +727,7 @@ eio_file_direct_ls(const char *dir,
|
||||||
* @param main_cb Callback called from the main loop for each accepted file.
|
* @param main_cb Callback called from the main loop for each accepted file.
|
||||||
* @param done_cb Callback called from the main loop when the content of the directory has been listed.
|
* @param done_cb Callback called from the main loop when the content of the directory has been listed.
|
||||||
* @param error_cb Callback called from the main loop when the directory could not be opened or listing content has been canceled.
|
* @param error_cb Callback called from the main loop when the directory could not be opened or listing content has been canceled.
|
||||||
* @param data Data passed to callback and not modified at all by eio_file_direct_ls.
|
* @param data Data passed to callback and not modified at all by eio_file_stat_ls.
|
||||||
* @return A reference to the IO operation.
|
* @return A reference to the IO operation.
|
||||||
*
|
*
|
||||||
* eio_file_stat_ls() run eina_file_stat_ls() in a separated thread using
|
* eio_file_stat_ls() run eina_file_stat_ls() in a separated thread using
|
||||||
|
|
Loading…
Reference in New Issue