forked from enlightenment/efl
Inotify monitoring almost works now. Since inotify seems to be the
future, I changed the interface of monitoring to be more like inotify. SVN revision: 13984
This commit is contained in:
parent
78939419b3
commit
40ec35d38d
|
@ -738,14 +738,16 @@ else
|
||||||
AM_CONDITIONAL(BUILD_ECORE_CONFIG, false)
|
AM_CONDITIONAL(BUILD_ECORE_CONFIG, false)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_MSG_CHECKING(wheter ecore_file module is to be built)
|
|
||||||
|
|
||||||
have_ecore_file="no"
|
have_ecore_file="no"
|
||||||
ecore_file_libs=""
|
ecore_file_libs=""
|
||||||
|
use_fam="no"
|
||||||
|
use_inotify="no"
|
||||||
|
use_poll="no"
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(wheter ecore_file module is to be built)
|
||||||
AC_ARG_ENABLE(ecore-file,
|
AC_ARG_ENABLE(ecore-file,
|
||||||
[ --disable-ecore-file disable the ecore_file module], [
|
[ --disable-ecore-file disable the ecore_file module], [
|
||||||
if [ test "$enableval" = "yes" ]; then
|
if test "$enableval" = "yes"; then
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
have_ecore_file="yes"
|
have_ecore_file="yes"
|
||||||
else
|
else
|
||||||
|
@ -757,13 +759,49 @@ AC_ARG_ENABLE(ecore-file,
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(wheter inotify is to be used for filemonitoring)
|
||||||
|
AC_ARG_ENABLE(inotify,
|
||||||
|
[ --disable-inotify disable inotify in the ecore_file module], [
|
||||||
|
if test "$enableval" = "yes"; then
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
use_inotify="yes"
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
fi
|
||||||
|
], [
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
use_inotify="yes"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
if test "x$use_inotify" = "xyes"; then
|
||||||
|
AC_CHECK_HEADER(linux/inotify.h,
|
||||||
|
[
|
||||||
|
AC_DEFINE(HAVE_INOTIFY, 1, [ File monitoring with Inotify ])
|
||||||
|
use_inotify="yes"
|
||||||
|
], [
|
||||||
|
use_inotify="no"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
#AC_MSG_CHECKING(wheter FAM is to be used for filemonitoring)
|
||||||
|
#AC_ARG_ENABLE(fam,
|
||||||
|
#[ --disable-fam disable fam in the ecore_file module], [
|
||||||
|
# if test "$enableval" = "yes"; then
|
||||||
|
# AC_MSG_RESULT(yes)
|
||||||
|
# use_fam="yes"
|
||||||
|
# else
|
||||||
|
# AC_MSG_RESULT(no)
|
||||||
|
# fi
|
||||||
|
#], [
|
||||||
|
# AC_MSG_RESULT(yes)
|
||||||
|
# use_fam="yes"
|
||||||
|
#]
|
||||||
|
#)
|
||||||
|
|
||||||
fam_libs=""
|
fam_libs=""
|
||||||
if [ test "x$have_ecore_file" = "xyes" ]; then
|
#if test "x$use_fam" = "xyes"; then
|
||||||
AM_CONDITIONAL(BUILD_ECORE_FILE, true)
|
|
||||||
ecore_file_libs="-lecore_file"
|
|
||||||
AC_DEFINE(HAVE_POLL, 1, [ File monitoring with polling ])
|
|
||||||
# I'm to stupid to get fam working right :)
|
|
||||||
# PKG_CHECK_MODULES(FAM, gamin >= 0.0.23,
|
|
||||||
# AC_CHECK_LIB(fam, FAMOpen,
|
# AC_CHECK_LIB(fam, FAMOpen,
|
||||||
# [
|
# [
|
||||||
# AC_DEFINE(HAVE_FAM, 1, [ File monitoring with FAM ])
|
# AC_DEFINE(HAVE_FAM, 1, [ File monitoring with FAM ])
|
||||||
|
@ -773,6 +811,31 @@ if [ test "x$have_ecore_file" = "xyes" ]; then
|
||||||
# use_fam="no"
|
# use_fam="no"
|
||||||
# ]
|
# ]
|
||||||
# )
|
# )
|
||||||
|
#fi
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(wheter polling is to be used for filemonitoring)
|
||||||
|
AC_ARG_ENABLE(poll,
|
||||||
|
[ --disable-poll disable poll in the ecore_file module], [
|
||||||
|
if test "$enableval" = "yes"; then
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
use_poll="yes"
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
fi
|
||||||
|
], [
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
use_poll="yes"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
if test "x$use_poll" = "xyes"; then
|
||||||
|
AC_DEFINE(HAVE_POLL, 1, [ File monitoring with polling ])
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$have_ecore_file" = "xyes"; then
|
||||||
|
AM_CONDITIONAL(BUILD_ECORE_FILE, true)
|
||||||
|
ecore_file_libs="-lecore_file"
|
||||||
|
AC_DEFINE(HAVE_POLL, 1, [ File monitoring with polling ])
|
||||||
else
|
else
|
||||||
AM_CONDITIONAL(BUILD_ECORE_FILE, false)
|
AM_CONDITIONAL(BUILD_ECORE_FILE, false)
|
||||||
fi
|
fi
|
||||||
|
@ -884,7 +947,8 @@ echo " Ecore_Evas FB Support...: $have_ecore_evas_fb"
|
||||||
echo " Ecore_Buffer............: $have_ecore_evas_buffer"
|
echo " Ecore_Buffer............: $have_ecore_evas_buffer"
|
||||||
echo " Ecore_Ipc...............: $have_ecore_ipc (OpenSSL: $use_openssl)"
|
echo " Ecore_Ipc...............: $have_ecore_ipc (OpenSSL: $use_openssl)"
|
||||||
echo " Ecore_Config............: $have_ecore_config"
|
echo " Ecore_Config............: $have_ecore_config"
|
||||||
echo " Ecore_File..............: $have_ecore_file (FAM: $use_fam)"
|
#echo " Ecore_File..............: $have_ecore_file (Inotify: $use_inotify) (FAM: $use_fam) (Poll: $use_poll)"
|
||||||
|
echo " Ecore_File..............: $have_ecore_file (Inotify: $use_inotify) (Poll: $use_poll)"
|
||||||
echo
|
echo
|
||||||
echo "Now type 'make' ('gmake' on some systems) to compile $PACKAGE."
|
echo "Now type 'make' ('gmake' on some systems) to compile $PACKAGE."
|
||||||
echo
|
echo
|
||||||
|
|
|
@ -48,54 +48,24 @@ EAPI Evas_List *ecore_file_ls (const char *dir);
|
||||||
typedef struct _Ecore_File_Monitor Ecore_File_Monitor;
|
typedef struct _Ecore_File_Monitor Ecore_File_Monitor;
|
||||||
typedef struct _Ecore_File_Monitor_Event Ecore_File_Monitor_Event;
|
typedef struct _Ecore_File_Monitor_Event Ecore_File_Monitor_Event;
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
ECORE_FILE_TYPE_NONE,
|
|
||||||
ECORE_FILE_TYPE_FILE,
|
|
||||||
ECORE_FILE_TYPE_DIRECTORY
|
|
||||||
} Ecore_File_Type;
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ECORE_FILE_EVENT_NONE,
|
ECORE_FILE_EVENT_NONE,
|
||||||
ECORE_FILE_EVENT_EXISTS,
|
ECORE_FILE_EVENT_CREATED_FILE,
|
||||||
ECORE_FILE_EVENT_CREATED,
|
ECORE_FILE_EVENT_CREATED_DIRECTORY,
|
||||||
ECORE_FILE_EVENT_DELETED,
|
ECORE_FILE_EVENT_DELETED_FILE,
|
||||||
ECORE_FILE_EVENT_CHANGED
|
ECORE_FILE_EVENT_DELETED_DIRECTORY,
|
||||||
|
ECORE_FILE_EVENT_DELETED_SELF,
|
||||||
|
ECORE_FILE_EVENT_MODIFIED
|
||||||
} Ecore_File_Event;
|
} Ecore_File_Event;
|
||||||
|
|
||||||
#if 0
|
|
||||||
struct _Ecore_File_Monitor {
|
|
||||||
void (*func) (void *data,
|
|
||||||
Ecore_File_Monitor *ecore_file_monitor,
|
|
||||||
Ecore_File_Type type,
|
|
||||||
Ecore_File_Event event,
|
|
||||||
const char *path);
|
|
||||||
|
|
||||||
char *path;
|
|
||||||
Ecore_File_Type type;
|
|
||||||
void *data;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
struct _Ecore_File_Monitor_Event {
|
|
||||||
Ecore_File_Monitor *ecore_file_monitor;
|
|
||||||
Ecore_File_Type type;
|
|
||||||
Ecore_File_Event event;
|
|
||||||
char *path;
|
|
||||||
void *data;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ECORE_FILE_MONITOR(x) ((Ecore_File_Monitor *)(x))
|
|
||||||
|
|
||||||
EAPI Ecore_File_Monitor *ecore_file_monitor_add(const char *path,
|
EAPI Ecore_File_Monitor *ecore_file_monitor_add(const char *path,
|
||||||
void (*func) (void *data,
|
void (*func) (void *data,
|
||||||
Ecore_File_Monitor *ecore_file_monitor,
|
Ecore_File_Monitor *ecore_file_monitor,
|
||||||
Ecore_File_Type type,
|
|
||||||
Ecore_File_Event event,
|
Ecore_File_Event event,
|
||||||
const char *path),
|
const char *path),
|
||||||
void *data);
|
void *data);
|
||||||
EAPI void ecore_file_monitor_del(Ecore_File_Monitor *ecore_file_monitor);
|
EAPI void ecore_file_monitor_del(Ecore_File_Monitor *ecore_file_monitor);
|
||||||
EAPI Ecore_File_Type ecore_file_monitor_type_get(Ecore_File_Monitor *ecore_file_monitor);
|
EAPI const char *ecore_file_monitor_path_get(Ecore_File_Monitor *ecore_file_monitor);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,7 +19,6 @@ ecore_file_private.h \
|
||||||
ecore_file_monitor.c \
|
ecore_file_monitor.c \
|
||||||
ecore_file_monitor_fam.c \
|
ecore_file_monitor_fam.c \
|
||||||
ecore_file_monitor_inotify.c \
|
ecore_file_monitor_inotify.c \
|
||||||
ecore_file_monitor_dnotify.c \
|
|
||||||
ecore_file_monitor_poll.c
|
ecore_file_monitor_poll.c
|
||||||
|
|
||||||
libecore_file_la_LIBADD = \
|
libecore_file_la_LIBADD = \
|
||||||
|
@ -35,6 +34,5 @@ ecore_file_private.h \
|
||||||
ecore_file_monitor.c \
|
ecore_file_monitor.c \
|
||||||
ecore_file_monitor_fam.c \
|
ecore_file_monitor_fam.c \
|
||||||
ecore_file_monitor_inotify.c \
|
ecore_file_monitor_inotify.c \
|
||||||
ecore_file_monitor_dnotify.c \
|
|
||||||
ecore_file_monitor_poll.c
|
ecore_file_monitor_poll.c
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,124 @@
|
||||||
*/
|
*/
|
||||||
#include "ecore_file_private.h"
|
#include "ecore_file_private.h"
|
||||||
|
|
||||||
Ecore_File_Type
|
typedef enum {
|
||||||
ecore_file_monitor_type_get(Ecore_File_Monitor *em)
|
ECORE_FILE_MONITOR_TYPE_NONE,
|
||||||
|
#ifdef HAVE_INOTIFY
|
||||||
|
ECORE_FILE_MONITOR_TYPE_INOTIFY,
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FAM
|
||||||
|
ECORE_FILE_MONITOR_TYPE_FAM,
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_POLL
|
||||||
|
ECORE_FILE_MONITOR_TYPE_POLL
|
||||||
|
#endif
|
||||||
|
} Ecore_File_Monitor_Type;
|
||||||
|
|
||||||
|
static Ecore_File_Monitor_Type monitor_type = ECORE_FILE_MONITOR_TYPE_NONE;
|
||||||
|
|
||||||
|
int
|
||||||
|
ecore_file_monitor_init(void)
|
||||||
{
|
{
|
||||||
return em->type;
|
#ifdef HAVE_INOTIFY
|
||||||
|
#if 0
|
||||||
|
monitor_type = ECORE_FILE_MONITOR_TYPE_INOTIFY;
|
||||||
|
if (ecore_file_monitor_inotify_init())
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FAM
|
||||||
|
#if 0
|
||||||
|
monitor_type = ECORE_FILE_MONITOR_TYPE_FAM;
|
||||||
|
if (ecore_file_monitor_fam_init())
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_POLL
|
||||||
|
monitor_type = ECORE_FILE_MONITOR_TYPE_POLL;
|
||||||
|
if (ecore_file_monitor_poll_init())
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
monitor_type = ECORE_FILE_MONITOR_TYPE_NONE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ecore_file_monitor_shutdown(void)
|
||||||
|
{
|
||||||
|
switch (monitor_type)
|
||||||
|
{
|
||||||
|
case ECORE_FILE_MONITOR_TYPE_NONE:
|
||||||
|
return 1;
|
||||||
|
#ifdef HAVE_INOTIFY
|
||||||
|
case ECORE_FILE_MONITOR_TYPE_INOTIFY:
|
||||||
|
return ecore_file_monitor_inotify_shutdown();
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FAM
|
||||||
|
case ECORE_FILE_MONITOR_TYPE_FAM:
|
||||||
|
return ecore_file_monitor_fam_shutdown();
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_POLL
|
||||||
|
case ECORE_FILE_MONITOR_TYPE_POLL:
|
||||||
|
return ecore_file_monitor_poll_shutdown();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ecore_File_Monitor *
|
||||||
|
ecore_file_monitor_add(const char *path,
|
||||||
|
void (*func) (void *data, Ecore_File_Monitor *em,
|
||||||
|
Ecore_File_Event event,
|
||||||
|
const char *path),
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
switch (monitor_type)
|
||||||
|
{
|
||||||
|
case ECORE_FILE_MONITOR_TYPE_NONE:
|
||||||
|
return NULL;
|
||||||
|
#ifdef HAVE_INOTIFY
|
||||||
|
case ECORE_FILE_MONITOR_TYPE_INOTIFY:
|
||||||
|
return ecore_file_monitor_inotify_add(path, func, data);
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FAM
|
||||||
|
case ECORE_FILE_MONITOR_TYPE_FAM:
|
||||||
|
return ecore_file_monitor_fam_add(path, func, data);
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_POLL
|
||||||
|
case ECORE_FILE_MONITOR_TYPE_POLL:
|
||||||
|
return ecore_file_monitor_poll_add(path, func, data);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ecore_file_monitor_del(Ecore_File_Monitor *em)
|
||||||
|
{
|
||||||
|
switch (monitor_type)
|
||||||
|
{
|
||||||
|
case ECORE_FILE_MONITOR_TYPE_NONE:
|
||||||
|
break;
|
||||||
|
#ifdef HAVE_INOTIFY
|
||||||
|
case ECORE_FILE_MONITOR_TYPE_INOTIFY:
|
||||||
|
ecore_file_monitor_inotify_del(em);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FAM
|
||||||
|
case ECORE_FILE_MONITOR_TYPE_FAM:
|
||||||
|
ecore_file_monitor_fam_del(em);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_POLL
|
||||||
|
case ECORE_FILE_MONITOR_TYPE_POLL:
|
||||||
|
ecore_file_monitor_poll_del(em);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
ecore_file_monitor_path_get(Ecore_File_Monitor *em)
|
||||||
|
{
|
||||||
|
return em->path;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,322 +0,0 @@
|
||||||
/*
|
|
||||||
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
|
|
||||||
*/
|
|
||||||
#include "ecore_file_private.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO:
|
|
||||||
* - Check the return value from fcntl.
|
|
||||||
* - Try different realtime numbers if one fail.
|
|
||||||
* - Doesn't work right!
|
|
||||||
* - Misses fileupdates
|
|
||||||
* - Misses filedeletions
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_DNOTIFY
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
typedef struct _Ecore_File_Monitor_Dnotify Ecore_File_Monitor_Dnotify;
|
|
||||||
typedef struct _Ecore_File Ecore_File;
|
|
||||||
|
|
||||||
#define ECORE_FILE_MONITOR_DNOTIFY(x) ((Ecore_File_Monitor_Dnotify *)(x))
|
|
||||||
|
|
||||||
struct _Ecore_File_Monitor_Dnotify
|
|
||||||
{
|
|
||||||
Ecore_File_Monitor monitor;
|
|
||||||
int fd;
|
|
||||||
Evas_List *files;
|
|
||||||
unsigned char deleted;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Ecore_File
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
int mtime;
|
|
||||||
Ecore_File_Type type;
|
|
||||||
};
|
|
||||||
|
|
||||||
static Ecore_Event_Handler *_eh;
|
|
||||||
static Evas_List *_monitors = NULL;
|
|
||||||
static int _lock = 0;
|
|
||||||
|
|
||||||
static int _ecore_file_monitor_handler(void *data, int type, void *event);
|
|
||||||
static void _ecore_file_monitor_check(Ecore_File_Monitor *em);
|
|
||||||
static int _ecore_file_monitor_checking(Ecore_File_Monitor *em, char *path);
|
|
||||||
|
|
||||||
int
|
|
||||||
ecore_file_monitor_init(void)
|
|
||||||
{
|
|
||||||
_eh = ecore_event_handler_add(ECORE_EVENT_SIGNAL_REALTIME, _ecore_file_monitor_handler, NULL);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ecore_file_monitor_shutdown(void)
|
|
||||||
{
|
|
||||||
Evas_List *l;
|
|
||||||
|
|
||||||
if (_eh) ecore_event_handler_del(_eh);
|
|
||||||
for (l = _monitors; l;)
|
|
||||||
{
|
|
||||||
Ecore_File_Monitor *em;
|
|
||||||
|
|
||||||
em = l->data;
|
|
||||||
l = l->next;
|
|
||||||
ecore_file_monitor_del(em);
|
|
||||||
}
|
|
||||||
evas_list_free(_monitors);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ecore_File_Monitor *
|
|
||||||
ecore_file_monitor_add(const char *path,
|
|
||||||
void (*func) (void *data, Ecore_File_Monitor *em,
|
|
||||||
Ecore_File_Type type,
|
|
||||||
Ecore_File_Event event,
|
|
||||||
const char *path),
|
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
Ecore_File_Monitor *em;
|
|
||||||
Ecore_File_Monitor_Dnotify *emd;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
if (!path) return NULL;
|
|
||||||
if (!func) return NULL;
|
|
||||||
|
|
||||||
emd = calloc(1, sizeof(Ecore_File_Monitor_Dnotify));
|
|
||||||
em = ECORE_FILE_MONITOR(emd);
|
|
||||||
if (!em) return NULL;
|
|
||||||
|
|
||||||
em->func = func;
|
|
||||||
em->data = data;
|
|
||||||
|
|
||||||
em->path = strdup(path);
|
|
||||||
len = strlen(em->path);
|
|
||||||
if (em->path[len - 1] == '/')
|
|
||||||
em->path[len - 1] = '\0';
|
|
||||||
|
|
||||||
if (ecore_file_exists(em->path))
|
|
||||||
{
|
|
||||||
em->type = ecore_file_is_dir(em->path) ?
|
|
||||||
ECORE_FILE_TYPE_DIRECTORY :
|
|
||||||
ECORE_FILE_TYPE_FILE;
|
|
||||||
|
|
||||||
if (em->type == ECORE_FILE_TYPE_DIRECTORY)
|
|
||||||
{
|
|
||||||
/* Check for subdirs */
|
|
||||||
Evas_List *files, *l;
|
|
||||||
|
|
||||||
files = ecore_file_ls(em->path);
|
|
||||||
for (l = files; l; l = l->next)
|
|
||||||
{
|
|
||||||
Ecore_File *f;
|
|
||||||
char *file;
|
|
||||||
char buf[PATH_MAX];
|
|
||||||
|
|
||||||
file = l->data;
|
|
||||||
f = calloc(1, sizeof(Ecore_File));
|
|
||||||
if (!f)
|
|
||||||
{
|
|
||||||
free(file);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", em->path, file);
|
|
||||||
f->name = file;
|
|
||||||
f->mtime = ecore_file_mod_time(buf);
|
|
||||||
f->type = ecore_file_is_dir(buf) ?
|
|
||||||
ECORE_FILE_TYPE_DIRECTORY :
|
|
||||||
ECORE_FILE_TYPE_FILE;
|
|
||||||
em->func(em->data, em, f->type, ECORE_FILE_EVENT_EXISTS, buf);
|
|
||||||
emd->files = evas_list_append(emd->files, f);
|
|
||||||
}
|
|
||||||
evas_list_free(files);
|
|
||||||
|
|
||||||
emd->fd = open(em->path, O_RDONLY);
|
|
||||||
if (fcntl(emd->fd, F_SETSIG, SIGRTMIN + 1))
|
|
||||||
printf("ERROR: F_SETSIG\n");
|
|
||||||
if (fcntl(emd->fd, F_NOTIFY, DN_ACCESS|DN_MODIFY|DN_CREATE|DN_DELETE|DN_MULTISHOT))
|
|
||||||
printf("ERROR: F_NOTIFY\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* TODO: We do not support monitoring files! */
|
|
||||||
free(em);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
em->type = ECORE_FILE_TYPE_NONE;
|
|
||||||
em->func(em->data, em, em->type, ECORE_FILE_EVENT_DELETED, em->path);
|
|
||||||
}
|
|
||||||
|
|
||||||
_monitors = evas_list_append(_monitors, em);
|
|
||||||
|
|
||||||
return em;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ecore_file_monitor_del(Ecore_File_Monitor *em)
|
|
||||||
{
|
|
||||||
Ecore_File_Monitor_Dnotify *emd;
|
|
||||||
Evas_List *l;
|
|
||||||
|
|
||||||
emd = ECORE_FILE_MONITOR_DNOTIFY(em);
|
|
||||||
if (_lock)
|
|
||||||
{
|
|
||||||
emd->deleted = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
close(emd->fd);
|
|
||||||
/* Remove files */
|
|
||||||
for (l = emd->files; l; l = l->next)
|
|
||||||
{
|
|
||||||
Ecore_File *f;
|
|
||||||
f = l->data;
|
|
||||||
free(f->name);
|
|
||||||
free(f);
|
|
||||||
}
|
|
||||||
evas_list_free(emd->files);
|
|
||||||
|
|
||||||
_monitors = evas_list_remove(_monitors, em);
|
|
||||||
free(em->path);
|
|
||||||
free(em);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
_ecore_file_monitor_handler(void *data, int type, void *event)
|
|
||||||
{
|
|
||||||
Ecore_Event_Signal_Realtime *ev;
|
|
||||||
Evas_List *monitor;
|
|
||||||
|
|
||||||
ev = event;
|
|
||||||
_lock = 1;
|
|
||||||
for (monitor = _monitors; monitor;)
|
|
||||||
{
|
|
||||||
Ecore_File_Monitor *em;
|
|
||||||
Ecore_File_Monitor_Dnotify *emd;
|
|
||||||
|
|
||||||
em = monitor->data;
|
|
||||||
emd = ECORE_FILE_MONITOR_DNOTIFY(em);
|
|
||||||
monitor = monitor->next;
|
|
||||||
|
|
||||||
if (emd->fd == ev->data.si_fd)
|
|
||||||
_ecore_file_monitor_check(em);
|
|
||||||
}
|
|
||||||
_lock = 0;
|
|
||||||
for (monitor = _monitors; monitor;)
|
|
||||||
{
|
|
||||||
Ecore_File_Monitor *em;
|
|
||||||
Ecore_File_Monitor_Dnotify *emd;
|
|
||||||
|
|
||||||
em = monitor->data;
|
|
||||||
emd = ECORE_FILE_MONITOR_DNOTIFY(em);
|
|
||||||
monitor = monitor->next;
|
|
||||||
|
|
||||||
if (emd->deleted)
|
|
||||||
ecore_file_monitor_del(em);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
static Ecore_File_Monitor_Request *
|
|
||||||
_ecore_file_monitor_request_find(Ecore_File_Monitor *em, char *path)
|
|
||||||
{
|
|
||||||
Evas_List *l;
|
|
||||||
|
|
||||||
for (l = em->requests; l; l = l->next)
|
|
||||||
{
|
|
||||||
Ecore_File_Monitor_Request *er;
|
|
||||||
|
|
||||||
er = l->data;
|
|
||||||
if (!strcmp(er->path, path))
|
|
||||||
return er;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
|
||||||
_ecore_file_monitor_check(Ecore_File_Monitor *em)
|
|
||||||
{
|
|
||||||
Ecore_File_Monitor_Dnotify *emd;
|
|
||||||
Evas_List *files, *l;
|
|
||||||
|
|
||||||
/* Check for changed files */
|
|
||||||
emd = ECORE_FILE_MONITOR_DNOTIFY(em);
|
|
||||||
for (l = emd->files; l;)
|
|
||||||
{
|
|
||||||
Ecore_File *f;
|
|
||||||
char buf[PATH_MAX];
|
|
||||||
int mtime;
|
|
||||||
|
|
||||||
f = l->data;
|
|
||||||
l = l->next;
|
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", em->path, f->name);
|
|
||||||
mtime = ecore_file_mod_time(buf);
|
|
||||||
if (mtime < f->mtime)
|
|
||||||
{
|
|
||||||
em->func(em->data, em, f->type, ECORE_FILE_EVENT_DELETED, buf);
|
|
||||||
emd->files = evas_list_remove(emd->files, f);
|
|
||||||
free(f->name);
|
|
||||||
free(f);
|
|
||||||
}
|
|
||||||
else if (mtime > f->mtime)
|
|
||||||
em->func(em->data, em, f->type, ECORE_FILE_EVENT_CHANGED, buf);
|
|
||||||
f->mtime = mtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
files = ecore_file_ls(em->path);
|
|
||||||
for (l = files; l; l = l->next)
|
|
||||||
{
|
|
||||||
Ecore_File *f;
|
|
||||||
char *file;
|
|
||||||
char buf[PATH_MAX];
|
|
||||||
|
|
||||||
file = l->data;
|
|
||||||
if (_ecore_file_monitor_checking(em, file))
|
|
||||||
{
|
|
||||||
free(file);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
f = calloc(1, sizeof(Ecore_File));
|
|
||||||
if (!f)
|
|
||||||
{
|
|
||||||
free(file);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", em->path, file);
|
|
||||||
f->name = file;
|
|
||||||
f->mtime = ecore_file_mod_time(buf);
|
|
||||||
f->type = ecore_file_is_dir(buf) ?
|
|
||||||
ECORE_FILE_TYPE_DIRECTORY :
|
|
||||||
ECORE_FILE_TYPE_FILE;
|
|
||||||
em->func(em->data, em, f->type, ECORE_FILE_EVENT_CREATED, buf);
|
|
||||||
emd->files = evas_list_append(emd->files, f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
_ecore_file_monitor_checking(Ecore_File_Monitor *em, char *name)
|
|
||||||
{
|
|
||||||
Ecore_File_Monitor_Dnotify *emd;
|
|
||||||
Evas_List *l;
|
|
||||||
|
|
||||||
emd = ECORE_FILE_MONITOR_DNOTIFY(em);
|
|
||||||
for (l = emd->files; l; l = l->next)
|
|
||||||
{
|
|
||||||
Ecore_File *f;
|
|
||||||
|
|
||||||
f = l->data;
|
|
||||||
if (!strcmp(f->name, name))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -6,7 +6,7 @@
|
||||||
/*
|
/*
|
||||||
* TODO:
|
* TODO:
|
||||||
* - When several subdirectories are created really fast, the code
|
* - When several subdirectories are created really fast, the code
|
||||||
* doesn't keep up! Putting in a random printf() makes it work..
|
* doesn't keep up!
|
||||||
* - Same for deletion of files in deleted directories!
|
* - Same for deletion of files in deleted directories!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -17,48 +17,46 @@
|
||||||
typedef struct _Ecore_File_Monitor_Fam Ecore_File_Monitor_Fam;
|
typedef struct _Ecore_File_Monitor_Fam Ecore_File_Monitor_Fam;
|
||||||
typedef struct _Ecore_File Ecore_File;
|
typedef struct _Ecore_File Ecore_File;
|
||||||
|
|
||||||
|
#define ECORE_FILE_MONITOR_FAM(x) ((Ecore_File_Monitor_Fam *)(x))
|
||||||
|
|
||||||
struct _Ecore_File_Monitor_Fam
|
struct _Ecore_File_Monitor_Fam
|
||||||
{
|
{
|
||||||
Ecore_File_Monitor monitor;
|
Ecore_File_Monitor monitor;
|
||||||
FAMRequest *request;
|
FAMRequest *request;
|
||||||
Evas_List *files;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Ecore_File
|
struct _Ecore_File
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
Ecore_File_Type type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ECORE_FILE_MONITOR_FAM(x) ((Ecore_File_Monitor_Fam *)(x))
|
|
||||||
|
|
||||||
static Ecore_Fd_Handler *_fdh = NULL;
|
static Ecore_Fd_Handler *_fdh = NULL;
|
||||||
static FAMConnection *_fc = NULL;
|
static FAMConnection *_fc = NULL;
|
||||||
static Evas_List *_monitors = NULL;
|
static Evas_List *_monitors = NULL;
|
||||||
|
|
||||||
static int _ecore_file_monitor_handler(void *data, Ecore_Fd_Handler *fdh);
|
static int _ecore_file_monitor_fam_handler(void *data, Ecore_Fd_Handler *fdh);
|
||||||
static Ecore_File * _ecore_file_monitor_file_find(Ecore_File_Monitor *em, char *name);
|
static Ecore_File *_ecore_file_monitor_fam_file_find(Ecore_File_Monitor *em, char *name);
|
||||||
static Ecore_File_Event _ecore_file_monitor_event_get(FAMCodes change);
|
static Ecore_File_Event _ecore_file_monitor_fam_event_get(FAMCodes code, int self, int is_dir);
|
||||||
|
|
||||||
int
|
int
|
||||||
ecore_file_monitor_init(void)
|
ecore_file_monitor_fam_init(void)
|
||||||
{
|
{
|
||||||
_fc = calloc(1, sizeof(FAMConnection));
|
_fc = calloc(1, sizeof(FAMConnection));
|
||||||
if (!_fc) return 0;
|
if (!_fc) return 0;
|
||||||
|
|
||||||
FAMOpen(_fc);
|
FAMOpen(_fc);
|
||||||
_fdh = ecore_main_fd_handler_add(FAMCONNECTION_GETFD(_fc), ECORE_FD_READ, _ecore_file_monitor_handler,
|
_fdh = ecore_main_fd_handler_add(FAMCONNECTION_GETFD(_fc), ECORE_FD_READ,
|
||||||
NULL, NULL, NULL);
|
_ecore_file_monitor_fam_handler, NULL, NULL, NULL);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ecore_file_monitor_shutdown(void)
|
ecore_file_monitor_fam_shutdown(void)
|
||||||
{
|
{
|
||||||
Evas_List *l;
|
Evas_List *l;
|
||||||
for (l = _monitors; l; l = l->next)
|
for (l = _monitors; l; l = l->next)
|
||||||
ecore_file_monitor_del(ECORE_FILE_MONITOR(l->data));
|
ecore_file_monitor_fam_del(ECORE_FILE_MONITOR(l->data));
|
||||||
evas_list_free(_monitors);
|
evas_list_free(_monitors);
|
||||||
if (_fdh) ecore_main_fd_handler_del(_fdh);
|
if (_fdh) ecore_main_fd_handler_del(_fdh);
|
||||||
if (_fc)
|
if (_fc)
|
||||||
|
@ -70,67 +68,61 @@ ecore_file_monitor_shutdown(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
Ecore_File_Monitor *
|
Ecore_File_Monitor *
|
||||||
ecore_file_monitor_add(const char *path,
|
ecore_file_monitor_fam_add(const char *path,
|
||||||
void (*func) (void *data,
|
void (*func) (void *data,
|
||||||
Ecore_File_Monitor *em,
|
Ecore_File_Monitor *em,
|
||||||
Ecore_File_Type type,
|
|
||||||
Ecore_File_Event event,
|
Ecore_File_Event event,
|
||||||
const char *path),
|
const char *path),
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
Ecore_File_Monitor *em;
|
Ecore_File_Monitor *em;
|
||||||
Ecore_File_Monitor_Fam *emf;
|
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
emf = calloc(1, sizeof(Ecore_File_Monitor_Fam));
|
em = calloc(1, sizeof(Ecore_File_Monitor_Fam));
|
||||||
em = ECORE_FILE_MONITOR(emf);
|
|
||||||
if (!em) return NULL;
|
if (!em) return NULL;
|
||||||
|
|
||||||
em->func = func;
|
em->func = func;
|
||||||
em->data = data;
|
em->data = data;
|
||||||
|
|
||||||
_monitors = evas_list_append(_monitors, em);
|
|
||||||
|
|
||||||
em->path = strdup(path);
|
em->path = strdup(path);
|
||||||
len = strlen(em->path);
|
len = strlen(em->path);
|
||||||
if (em->path[len - 1] == '/')
|
if (em->path[len - 1] == '/')
|
||||||
em->path[len - 1] = '\0';
|
em->path[len - 1] = 0;
|
||||||
|
|
||||||
if (ecore_file_exists(em->path))
|
if (ecore_file_exists(em->path))
|
||||||
{
|
{
|
||||||
em->type = ecore_file_is_dir(em->path) ?
|
ECORE_FILE_MONITOR_FAM(em)->request = calloc(1, sizeof(FAMRequest));
|
||||||
ECORE_FILE_TYPE_DIRECTORY :
|
if (!ECORE_FILE_MONITOR_FAM(em)->request)
|
||||||
ECORE_FILE_TYPE_FILE;
|
{
|
||||||
|
ecore_file_monitor_fam_del(em);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (ecore_file_is_dir(em->path))
|
||||||
|
{
|
||||||
|
FAMMonitorDirectory(_fc, em->path, ECORE_FILE_MONITOR_FAM(em)->request, em);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FAMMonitorFile(_fc, em->path, ECORE_FILE_MONITOR_FAM(em)->request, em);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ecore_file_monitor_fam_del(em);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: Check if calloc succeded! */
|
_monitors = evas_list_append(_monitors, em);
|
||||||
emf->request = calloc(1, sizeof(FAMRequest));
|
|
||||||
if (em->type == ECORE_FILE_TYPE_DIRECTORY)
|
|
||||||
{
|
|
||||||
FAMMonitorDirectory(_fc, em->path, emf->request, em);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FAMMonitorFile(_fc, em->path, emf->request, em);
|
|
||||||
em->func(em->data, em, em->type, ECORE_FILE_EVENT_EXISTS, em->path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
em->type = ECORE_FILE_TYPE_NONE;
|
|
||||||
em->func(em->data, em, em->type, ECORE_FILE_EVENT_DELETED, em->path);
|
|
||||||
}
|
|
||||||
|
|
||||||
return em;
|
return em;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ecore_file_monitor_del(Ecore_File_Monitor *em)
|
ecore_file_monitor_fam_del(Ecore_File_Monitor *em)
|
||||||
{
|
{
|
||||||
Ecore_File_Monitor_Fam *emf;
|
|
||||||
Evas_List *l;
|
Evas_List *l;
|
||||||
|
|
||||||
emf = ECORE_FILE_MONITOR_FAM(em);
|
for (l = em->files; l; l = l->next)
|
||||||
for (l = emf->files; l; l = l->next)
|
|
||||||
{
|
{
|
||||||
Ecore_File *f;
|
Ecore_File *f;
|
||||||
|
|
||||||
|
@ -138,18 +130,21 @@ ecore_file_monitor_del(Ecore_File_Monitor *em)
|
||||||
free(f->name);
|
free(f->name);
|
||||||
free(f);
|
free(f);
|
||||||
}
|
}
|
||||||
evas_list_free(emf->files);
|
evas_list_free(em->files);
|
||||||
|
|
||||||
_monitors = evas_list_remove(_monitors, em);
|
_monitors = evas_list_remove(_monitors, em);
|
||||||
|
|
||||||
FAMCancelMonitor(_fc, emf->request);
|
if (ECORE_FILE_MONITOR_FAM(em)->request)
|
||||||
free(emf->request);
|
{
|
||||||
|
FAMCancelMonitor(_fc, ECORE_FILE_MONITOR_FAM(em)->request);
|
||||||
|
free(ECORE_FILE_MONITOR_FAM(em)->request);
|
||||||
|
}
|
||||||
free(em->path);
|
free(em->path);
|
||||||
free(em);
|
free(em);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_ecore_file_monitor_handler(void *data, Ecore_Fd_Handler *fdh)
|
_ecore_file_monitor_fam_handler(void *data, Ecore_Fd_Handler *fdh)
|
||||||
{
|
{
|
||||||
int pending, i;
|
int pending, i;
|
||||||
|
|
||||||
|
@ -158,62 +153,107 @@ _ecore_file_monitor_handler(void *data, Ecore_Fd_Handler *fdh)
|
||||||
for (i = 0; i < pending; i++)
|
for (i = 0; i < pending; i++)
|
||||||
{
|
{
|
||||||
Ecore_File_Monitor *em;
|
Ecore_File_Monitor *em;
|
||||||
Ecore_File_Monitor_Fam *emf;
|
|
||||||
FAMEvent fe;
|
FAMEvent fe;
|
||||||
Ecore_File_Event event;
|
Ecore_File_Event event;
|
||||||
char buf[PATH_MAX];
|
char buf[PATH_MAX];
|
||||||
|
int len, self;
|
||||||
|
|
||||||
|
buf[0] = 0;
|
||||||
|
|
||||||
FAMNextEvent(_fc, &fe);
|
FAMNextEvent(_fc, &fe);
|
||||||
event = _ecore_file_monitor_event_get(fe.code);
|
len = strlen(fe.filename);
|
||||||
|
if (fe.filename[len - 1] == '/')
|
||||||
|
fe.filename[len - 1] = 0;
|
||||||
|
self = !strcmp(em->path, fe.filename);
|
||||||
|
if (!self)
|
||||||
|
snprintf(buf, sizeof(buf), "%s/%s", em->path, fe.filename);
|
||||||
|
|
||||||
|
event = _ecore_file_monitor_fam_event_get(fe.code, self, ecore_file_is_dir(buf));
|
||||||
em = fe.userdata;
|
em = fe.userdata;
|
||||||
emf = ECORE_FILE_MONITOR_FAM(em);
|
|
||||||
if (!em) continue;
|
if (!em) continue;
|
||||||
if (event == ECORE_FILE_EVENT_NONE) continue;
|
if (event == ECORE_FILE_EVENT_NONE) continue;
|
||||||
if ((em->type == ECORE_FILE_TYPE_DIRECTORY)
|
#if 0
|
||||||
&& !strcmp(em->path, fe.filename))
|
if (!strcmp(em->path, fe.filename))
|
||||||
continue;
|
{
|
||||||
/* Create path */
|
Evas_List *l;
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", em->path, fe.filename);
|
|
||||||
if (event == ECORE_FILE_EVENT_DELETED)
|
if (event == ECORE_FILE_EVENT_DELETED)
|
||||||
{
|
{
|
||||||
Ecore_File *f;
|
/* Notify all files deleted */
|
||||||
|
for (l = em->files; l;)
|
||||||
f = _ecore_file_monitor_file_find(em, fe.filename);
|
|
||||||
if (f)
|
|
||||||
{
|
{
|
||||||
emf->files = evas_list_remove(emf->files, f);
|
Ecore_File *f;
|
||||||
em->func(em->data, em, f->type, event, buf);
|
char buf[PATH_MAX];
|
||||||
|
|
||||||
|
f = l->data;
|
||||||
|
l = l->next;
|
||||||
|
snprintf(buf, sizeof(buf), "%s/%s", em->path, f->name);
|
||||||
|
em->func(em->data, em, f->type, ECORE_FILE_EVENT_DELETED, buf);
|
||||||
free(f->name);
|
free(f->name);
|
||||||
free(f);
|
free(f);
|
||||||
}
|
}
|
||||||
|
em->files = evas_list_free(em->files);
|
||||||
|
em->func(em->data, em, em->type, event, em->path);
|
||||||
|
em->type = ECORE_FILE_TYPE_NONE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
em->func(em->data, em, em->type, event, em->path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Ecore_File *f;
|
Ecore_File *f;
|
||||||
|
|
||||||
|
switch (event)
|
||||||
|
{
|
||||||
|
case ECORE_FILE_EVENT_NONE:
|
||||||
|
break;
|
||||||
|
case ECORE_FILE_EVENT_EXISTS:
|
||||||
|
f = _ecore_file_monitor_fam_file_find(em, fe.filename);
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
em->func(em->data, em, f->type, event, buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ECORE_FILE_EVENT_CREATED:
|
||||||
f = calloc(1, sizeof(Ecore_File));
|
f = calloc(1, sizeof(Ecore_File));
|
||||||
if (!f) continue;
|
if (!f) break;
|
||||||
|
|
||||||
f->type = ecore_file_is_dir(buf) ?
|
f->type = ecore_file_is_dir(buf) ?
|
||||||
ECORE_FILE_TYPE_DIRECTORY :
|
ECORE_FILE_TYPE_DIRECTORY :
|
||||||
ECORE_FILE_TYPE_FILE;
|
ECORE_FILE_TYPE_FILE;
|
||||||
f->name = strdup(fe.filename);
|
f->name = strdup(fe.filename);
|
||||||
emf->files = evas_list_append(emf->files, f);
|
em->files = evas_list_append(em->files, f);
|
||||||
em->func(em->data, em, f->type, event, buf);
|
em->func(em->data, em, f->type, event, buf);
|
||||||
|
break;
|
||||||
|
case ECORE_FILE_EVENT_DELETED:
|
||||||
|
f = _ecore_file_monitor_fam_file_find(em, fe.filename);
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
em->files = evas_list_remove(em->files, f);
|
||||||
|
em->func(em->data, em, f->type, event, buf);
|
||||||
|
free(f->name);
|
||||||
|
free(f);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case ECORE_FILE_EVENT_CHANGED:
|
||||||
|
em->func(em->data, em, f->type, event, buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Ecore_File *
|
static Ecore_File *
|
||||||
_ecore_file_monitor_file_find(Ecore_File_Monitor *em, char *name)
|
_ecore_file_monitor_fam_file_find(Ecore_File_Monitor *em, char *name)
|
||||||
{
|
{
|
||||||
Ecore_File_Monitor_Fam *emf;
|
|
||||||
Evas_List *l;
|
Evas_List *l;
|
||||||
|
|
||||||
emf = ECORE_FILE_MONITOR_FAM(em);
|
for (l = em->files; l; l = l->next)
|
||||||
for (l = emf->files; l; l = l->next)
|
|
||||||
{
|
{
|
||||||
Ecore_File *f;
|
Ecore_File *f;
|
||||||
f = l->data;
|
f = l->data;
|
||||||
|
@ -224,18 +264,31 @@ _ecore_file_monitor_file_find(Ecore_File_Monitor *em, char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
static Ecore_File_Event
|
static Ecore_File_Event
|
||||||
_ecore_file_monitor_event_get(FAMCodes code)
|
_ecore_file_monitor_fam_event_get(FAMCodes code, int self, int is_dir)
|
||||||
{
|
{
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case FAMCreated:
|
case FAMCreated:
|
||||||
return ECORE_FILE_EVENT_CREATED;
|
if (self)
|
||||||
|
return ECORE_FILE_EVENT_NONE;
|
||||||
|
else if (is_dir)
|
||||||
|
return ECORE_FILE_EVENT_CREATED_DIRECTORY;
|
||||||
|
else
|
||||||
|
return ECORE_FILE_EVENT_CREATED_FILE;
|
||||||
|
break;
|
||||||
case FAMDeleted:
|
case FAMDeleted:
|
||||||
return ECORE_FILE_EVENT_DELETED;
|
if (self)
|
||||||
|
return ECORE_FILE_EVENT_DELETED_SELF;
|
||||||
|
else if (is_dir)
|
||||||
|
return ECORE_FILE_EVENT_DELETED_DIRECTORY;
|
||||||
|
else
|
||||||
|
return ECORE_FILE_EVENT_DELETED_FILE;
|
||||||
|
break;
|
||||||
case FAMChanged:
|
case FAMChanged:
|
||||||
return ECORE_FILE_EVENT_CHANGED;
|
if (!is_dir)
|
||||||
|
return ECORE_FILE_EVENT_MODIFIED;
|
||||||
|
break;
|
||||||
case FAMExists:
|
case FAMExists:
|
||||||
return ECORE_FILE_EVENT_EXISTS;
|
|
||||||
case FAMStartExecuting:
|
case FAMStartExecuting:
|
||||||
case FAMStopExecuting:
|
case FAMStopExecuting:
|
||||||
case FAMMoved:
|
case FAMMoved:
|
||||||
|
|
|
@ -5,81 +5,78 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO:
|
* TODO:
|
||||||
* - Everything!
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_INOTIFY
|
#ifdef HAVE_INOTIFY
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <linux/inotify.h>
|
||||||
|
|
||||||
typedef struct _Ecore_File_Monitor_Inotify Ecore_File_Monitor_Inotify;
|
typedef struct _Ecore_File_Monitor_Inotify Ecore_File_Monitor_Inotify;
|
||||||
typedef struct _Ecore_File Ecore_File;
|
|
||||||
|
|
||||||
#define ECORE_FILE_MONITOR_INOTIFY(x) ((Ecore_File_Monitor_Inotify *)(x))
|
#define ECORE_FILE_MONITOR_INOTIFY(x) ((Ecore_File_Monitor_Inotify *)(x))
|
||||||
|
|
||||||
struct _Ecore_File_Monitor_Inotify
|
struct _Ecore_File_Monitor_Inotify
|
||||||
{
|
{
|
||||||
Ecore_File_Monitor monitor;
|
Ecore_File_Monitor monitor;
|
||||||
int fd;
|
int wd;
|
||||||
Evas_List *files;
|
|
||||||
unsigned char deleted;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Ecore_File
|
static Ecore_Fd_Handler *_fdh = NULL;
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
int mtime;
|
|
||||||
Ecore_File_Type type;
|
|
||||||
};
|
|
||||||
|
|
||||||
static Ecore_Event_Handler *_eh;
|
|
||||||
static Evas_List *_monitors = NULL;
|
static Evas_List *_monitors = NULL;
|
||||||
static int _lock = 0;
|
|
||||||
|
|
||||||
static int _ecore_file_monitor_handler(void *data, int type, void *event);
|
static int _ecore_file_monitor_inotify_handler(void *data, Ecore_Fd_Handler *fdh);
|
||||||
static void _ecore_file_monitor_check(Ecore_File_Monitor *em);
|
static Ecore_File_Monitor *_ecore_file_monitor_inotify_monitor_find(int wd);
|
||||||
static int _ecore_file_monitor_checking(Ecore_File_Monitor *em, char *path);
|
static void _ecore_file_monitor_inotify_events(Ecore_File_Monitor *em,
|
||||||
|
char *file, int mask);
|
||||||
|
|
||||||
int
|
int
|
||||||
ecore_file_monitor_init(void)
|
ecore_file_monitor_inotify_init(void)
|
||||||
{
|
{
|
||||||
_eh = ecore_event_handler_add(ECORE_EVENT_SIGNAL_REALTIME, _ecore_file_monitor_handler, NULL);
|
int fd;
|
||||||
|
|
||||||
|
fd = open("/dev/inotify", O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
_fdh = ecore_main_fd_handler_add(fd, ECORE_FD_READ, _ecore_file_monitor_inotify_handler,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
if (!_fdh)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ecore_file_monitor_shutdown(void)
|
ecore_file_monitor_inotify_shutdown(void)
|
||||||
{
|
{
|
||||||
Evas_List *l;
|
int fd;
|
||||||
|
|
||||||
if (_eh) ecore_event_handler_del(_eh);
|
if (_fdh)
|
||||||
for (l = _monitors; l;)
|
|
||||||
{
|
{
|
||||||
Ecore_File_Monitor *em;
|
fd = ecore_main_fd_handler_fd_get(_fdh);
|
||||||
|
ecore_main_fd_handler_del(_fdh);
|
||||||
em = l->data;
|
close(fd);
|
||||||
l = l->next;
|
|
||||||
ecore_file_monitor_del(em);
|
|
||||||
}
|
}
|
||||||
evas_list_free(_monitors);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ecore_File_Monitor *
|
Ecore_File_Monitor *
|
||||||
ecore_file_monitor_add(const char *path,
|
ecore_file_monitor_inotify_add(const char *path,
|
||||||
void (*func) (void *data, Ecore_File_Monitor *em,
|
void (*func) (void *data, Ecore_File_Monitor *em,
|
||||||
Ecore_File_Type type,
|
|
||||||
Ecore_File_Event event,
|
Ecore_File_Event event,
|
||||||
const char *path),
|
const char *path),
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
Ecore_File_Monitor *em;
|
Ecore_File_Monitor *em;
|
||||||
Ecore_File_Monitor_Inotify *emd;
|
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (!path) return NULL;
|
em = calloc(1, sizeof(Ecore_File_Monitor_Inotify));
|
||||||
if (!func) return NULL;
|
|
||||||
|
|
||||||
emd = calloc(1, sizeof(Ecore_File_Monitor_Inotify));
|
|
||||||
em = ECORE_FILE_MONITOR(emd);
|
|
||||||
if (!em) return NULL;
|
if (!em) return NULL;
|
||||||
|
|
||||||
em->func = func;
|
em->func = func;
|
||||||
|
@ -88,62 +85,31 @@ ecore_file_monitor_add(const char *path,
|
||||||
em->path = strdup(path);
|
em->path = strdup(path);
|
||||||
len = strlen(em->path);
|
len = strlen(em->path);
|
||||||
if (em->path[len - 1] == '/')
|
if (em->path[len - 1] == '/')
|
||||||
em->path[len - 1] = '\0';
|
em->path[len - 1] = 0;
|
||||||
|
|
||||||
if (ecore_file_exists(em->path))
|
if (ecore_file_exists(em->path))
|
||||||
{
|
{
|
||||||
em->type = ecore_file_is_dir(em->path) ?
|
struct inotify_watch_request request;
|
||||||
ECORE_FILE_TYPE_DIRECTORY :
|
|
||||||
ECORE_FILE_TYPE_FILE;
|
|
||||||
|
|
||||||
if (em->type == ECORE_FILE_TYPE_DIRECTORY)
|
request.name = em->path;
|
||||||
|
request.mask = IN_MODIFY|
|
||||||
|
IN_MOVED_FROM|IN_MOVED_TO|
|
||||||
|
IN_DELETE_SUBDIR|IN_DELETE_FILE|
|
||||||
|
IN_CREATE_SUBDIR|IN_CREATE_FILE|
|
||||||
|
IN_DELETE_SELF|IN_UNMOUNT;
|
||||||
|
ECORE_FILE_MONITOR_INOTIFY(em)->wd = ioctl(ecore_main_fd_handler_fd_get(_fdh),
|
||||||
|
INOTIFY_WATCH, &request);
|
||||||
|
if (ECORE_FILE_MONITOR_INOTIFY(em)->wd < 0)
|
||||||
{
|
{
|
||||||
/* Check for subdirs */
|
printf("ioctl error\n");
|
||||||
Evas_List *files, *l;
|
ecore_file_monitor_inotify_del(em);
|
||||||
|
|
||||||
files = ecore_file_ls(em->path);
|
|
||||||
for (l = files; l; l = l->next)
|
|
||||||
{
|
|
||||||
Ecore_File *f;
|
|
||||||
char *file;
|
|
||||||
char buf[PATH_MAX];
|
|
||||||
|
|
||||||
file = l->data;
|
|
||||||
f = calloc(1, sizeof(Ecore_File));
|
|
||||||
if (!f)
|
|
||||||
{
|
|
||||||
free(file);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", em->path, file);
|
|
||||||
f->name = file;
|
|
||||||
f->mtime = ecore_file_mod_time(buf);
|
|
||||||
f->type = ecore_file_is_dir(buf) ?
|
|
||||||
ECORE_FILE_TYPE_DIRECTORY :
|
|
||||||
ECORE_FILE_TYPE_FILE;
|
|
||||||
em->func(em->data, em, f->type, ECORE_FILE_EVENT_EXISTS, buf);
|
|
||||||
emd->files = evas_list_append(emd->files, f);
|
|
||||||
}
|
|
||||||
evas_list_free(files);
|
|
||||||
|
|
||||||
emd->fd = open(em->path, O_RDONLY);
|
|
||||||
if (fcntl(emd->fd, F_SETSIG, SIGRTMIN + 1))
|
|
||||||
printf("ERROR: F_SETSIG\n");
|
|
||||||
if (fcntl(emd->fd, F_NOTIFY, DN_ACCESS|DN_MODIFY|DN_CREATE|DN_DELETE|DN_MULTISHOT))
|
|
||||||
printf("ERROR: F_NOTIFY\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* TODO: We do not support monitoring files! */
|
|
||||||
free(em);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
em->type = ECORE_FILE_TYPE_NONE;
|
ecore_file_monitor_inotify_del(em);
|
||||||
em->func(em->data, em, em->type, ECORE_FILE_EVENT_DELETED, em->path);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_monitors = evas_list_append(_monitors, em);
|
_monitors = evas_list_append(_monitors, em);
|
||||||
|
@ -152,165 +118,106 @@ ecore_file_monitor_add(const char *path,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ecore_file_monitor_del(Ecore_File_Monitor *em)
|
ecore_file_monitor_inotify_del(Ecore_File_Monitor *em)
|
||||||
{
|
{
|
||||||
Ecore_File_Monitor_Inotify *emd;
|
int fd;
|
||||||
Evas_List *l;
|
|
||||||
|
|
||||||
emd = ECORE_FILE_MONITOR_INOTIFY(em);
|
|
||||||
if (_lock)
|
|
||||||
{
|
|
||||||
emd->deleted = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
close(emd->fd);
|
|
||||||
/* Remove files */
|
|
||||||
for (l = emd->files; l; l = l->next)
|
|
||||||
{
|
|
||||||
Ecore_File *f;
|
|
||||||
f = l->data;
|
|
||||||
free(f->name);
|
|
||||||
free(f);
|
|
||||||
}
|
|
||||||
evas_list_free(emd->files);
|
|
||||||
|
|
||||||
_monitors = evas_list_remove(_monitors, em);
|
_monitors = evas_list_remove(_monitors, em);
|
||||||
|
|
||||||
|
fd = ecore_main_fd_handler_fd_get(_fdh);
|
||||||
|
if (ECORE_FILE_MONITOR_INOTIFY(em)->wd)
|
||||||
|
ioctl(fd, INOTIFY_IGNORE, ECORE_FILE_MONITOR_INOTIFY(em)->wd);
|
||||||
free(em->path);
|
free(em->path);
|
||||||
free(em);
|
free(em);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_ecore_file_monitor_handler(void *data, int type, void *event)
|
_ecore_file_monitor_inotify_handler(void *data, Ecore_Fd_Handler *fdh)
|
||||||
{
|
{
|
||||||
Ecore_Event_Signal_Realtime *ev;
|
|
||||||
Evas_List *monitor;
|
|
||||||
|
|
||||||
ev = event;
|
|
||||||
_lock = 1;
|
|
||||||
for (monitor = _monitors; monitor;)
|
|
||||||
{
|
|
||||||
Ecore_File_Monitor *em;
|
Ecore_File_Monitor *em;
|
||||||
Ecore_File_Monitor_Inotify *emd;
|
char buffer[16384];
|
||||||
|
struct inotify_event *event;
|
||||||
|
int i = 0;
|
||||||
|
int event_size;
|
||||||
|
ssize_t size;
|
||||||
|
|
||||||
em = monitor->data;
|
size = read(ecore_main_fd_handler_fd_get(fdh), buffer, sizeof(buffer));
|
||||||
emd = ECORE_FILE_MONITOR_INOTIFY(em);
|
while (i < size)
|
||||||
monitor = monitor->next;
|
|
||||||
|
|
||||||
if (emd->fd == ev->data.si_fd)
|
|
||||||
_ecore_file_monitor_check(em);
|
|
||||||
}
|
|
||||||
_lock = 0;
|
|
||||||
for (monitor = _monitors; monitor;)
|
|
||||||
{
|
{
|
||||||
Ecore_File_Monitor *em;
|
event = (struct inotify_event *)&buffer[i];
|
||||||
Ecore_File_Monitor_Inotify *emd;
|
event_size = sizeof(struct inotify_event) + event->len;
|
||||||
|
i += event_size;
|
||||||
|
|
||||||
em = monitor->data;
|
em = _ecore_file_monitor_inotify_monitor_find(event->wd);
|
||||||
emd = ECORE_FILE_MONITOR_INOTIFY(em);
|
if (!em) continue;
|
||||||
monitor = monitor->next;
|
|
||||||
|
|
||||||
if (emd->deleted)
|
_ecore_file_monitor_inotify_events(em, event->name, event->mask);
|
||||||
ecore_file_monitor_del(em);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
static Ecore_File_Monitor *
|
||||||
static Ecore_File_Monitor_Request *
|
_ecore_file_monitor_inotify_monitor_find(int wd)
|
||||||
_ecore_file_monitor_request_find(Ecore_File_Monitor *em, char *path)
|
|
||||||
{
|
{
|
||||||
Evas_List *l;
|
Evas_List *l;
|
||||||
|
|
||||||
for (l = em->requests; l; l = l->next)
|
for (l = _monitors; l; l = l->next)
|
||||||
{
|
{
|
||||||
Ecore_File_Monitor_Request *er;
|
Ecore_File_Monitor *em;
|
||||||
|
|
||||||
er = l->data;
|
em = l->data;
|
||||||
if (!strcmp(er->path, path))
|
if (ECORE_FILE_MONITOR_INOTIFY(em)->wd == wd)
|
||||||
return er;
|
return em;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_ecore_file_monitor_check(Ecore_File_Monitor *em)
|
_ecore_file_monitor_inotify_events(Ecore_File_Monitor *em, char *file, int mask)
|
||||||
{
|
{
|
||||||
Ecore_File_Monitor_Inotify *emd;
|
|
||||||
Evas_List *files, *l;
|
|
||||||
|
|
||||||
/* Check for changed files */
|
|
||||||
emd = ECORE_FILE_MONITOR_INOTIFY(em);
|
|
||||||
for (l = emd->files; l;)
|
|
||||||
{
|
|
||||||
Ecore_File *f;
|
|
||||||
char buf[PATH_MAX];
|
char buf[PATH_MAX];
|
||||||
int mtime;
|
if (file)
|
||||||
|
|
||||||
f = l->data;
|
|
||||||
l = l->next;
|
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", em->path, f->name);
|
|
||||||
mtime = ecore_file_mod_time(buf);
|
|
||||||
if (mtime < f->mtime)
|
|
||||||
{
|
|
||||||
em->func(em->data, em, f->type, ECORE_FILE_EVENT_DELETED, buf);
|
|
||||||
emd->files = evas_list_remove(emd->files, f);
|
|
||||||
free(f->name);
|
|
||||||
free(f);
|
|
||||||
}
|
|
||||||
else if (mtime > f->mtime)
|
|
||||||
em->func(em->data, em, f->type, ECORE_FILE_EVENT_CHANGED, buf);
|
|
||||||
f->mtime = mtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
files = ecore_file_ls(em->path);
|
|
||||||
for (l = files; l; l = l->next)
|
|
||||||
{
|
|
||||||
Ecore_File *f;
|
|
||||||
char *file;
|
|
||||||
char buf[PATH_MAX];
|
|
||||||
|
|
||||||
file = l->data;
|
|
||||||
if (_ecore_file_monitor_checking(em, file))
|
|
||||||
{
|
|
||||||
free(file);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
f = calloc(1, sizeof(Ecore_File));
|
|
||||||
if (!f)
|
|
||||||
{
|
|
||||||
free(file);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", em->path, file);
|
snprintf(buf, sizeof(buf), "%s/%s", em->path, file);
|
||||||
f->name = file;
|
else
|
||||||
f->mtime = ecore_file_mod_time(buf);
|
strcpy(buf, em->path);
|
||||||
f->type = ecore_file_is_dir(buf) ?
|
|
||||||
ECORE_FILE_TYPE_DIRECTORY :
|
|
||||||
ECORE_FILE_TYPE_FILE;
|
|
||||||
em->func(em->data, em, f->type, ECORE_FILE_EVENT_CREATED, buf);
|
|
||||||
emd->files = evas_list_append(emd->files, f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
if (mask & IN_MODIFY)
|
||||||
_ecore_file_monitor_checking(Ecore_File_Monitor *em, char *name)
|
|
||||||
{
|
|
||||||
Ecore_File_Monitor_Inotify *emd;
|
|
||||||
Evas_List *l;
|
|
||||||
|
|
||||||
emd = ECORE_FILE_MONITOR_INOTIFY(em);
|
|
||||||
for (l = emd->files; l; l = l->next)
|
|
||||||
{
|
{
|
||||||
Ecore_File *f;
|
if (!ecore_file_is_dir(buf))
|
||||||
|
em->func(em->data, em, ECORE_FILE_EVENT_MODIFIED, buf);
|
||||||
f = l->data;
|
}
|
||||||
if (!strcmp(f->name, name))
|
if (mask & IN_MOVED_FROM)
|
||||||
return 1;
|
{
|
||||||
|
printf("MOVE_FROM ");
|
||||||
|
}
|
||||||
|
if (mask & IN_MOVED_TO)
|
||||||
|
{
|
||||||
|
printf("MOVE_TO ");
|
||||||
|
}
|
||||||
|
if (mask & IN_DELETE_SUBDIR)
|
||||||
|
{
|
||||||
|
em->func(em->data, em, ECORE_FILE_EVENT_DELETED_DIRECTORY, buf);
|
||||||
|
}
|
||||||
|
if (mask & IN_DELETE_FILE)
|
||||||
|
{
|
||||||
|
em->func(em->data, em, ECORE_FILE_EVENT_DELETED_FILE, buf);
|
||||||
|
}
|
||||||
|
if (mask & IN_CREATE_SUBDIR)
|
||||||
|
{
|
||||||
|
em->func(em->data, em, ECORE_FILE_EVENT_CREATED_DIRECTORY, buf);
|
||||||
|
}
|
||||||
|
if (mask & IN_CREATE_FILE)
|
||||||
|
{
|
||||||
|
em->func(em->data, em, ECORE_FILE_EVENT_CREATED_FILE, buf);
|
||||||
|
}
|
||||||
|
if (mask & IN_DELETE_SELF)
|
||||||
|
{
|
||||||
|
em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
|
||||||
|
}
|
||||||
|
if (mask & IN_UNMOUNT)
|
||||||
|
{
|
||||||
|
printf("UNMOUNT ");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,13 +14,23 @@
|
||||||
* - Change poll time
|
* - Change poll time
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef struct _Ecore_File_Monitor_Poll Ecore_File_Monitor_Poll;
|
||||||
typedef struct _Ecore_File Ecore_File;
|
typedef struct _Ecore_File Ecore_File;
|
||||||
|
|
||||||
|
#define ECORE_FILE_MONITOR_POLL(x) ((Ecore_File_Monitor_Poll *)(x))
|
||||||
|
|
||||||
|
struct _Ecore_File_Monitor_Poll
|
||||||
|
{
|
||||||
|
Ecore_File_Monitor monitor;
|
||||||
|
int mtime;
|
||||||
|
unsigned char deleted;
|
||||||
|
};
|
||||||
|
|
||||||
struct _Ecore_File
|
struct _Ecore_File
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
int mtime;
|
int mtime;
|
||||||
Ecore_File_Type type;
|
unsigned char is_dir;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ECORE_FILE_INTERVAL_MIN 1.0
|
#define ECORE_FILE_INTERVAL_MIN 1.0
|
||||||
|
@ -32,18 +42,18 @@ static Ecore_Timer *_timer = NULL;
|
||||||
static Evas_List *_monitors = NULL;
|
static Evas_List *_monitors = NULL;
|
||||||
static int _lock = 0;
|
static int _lock = 0;
|
||||||
|
|
||||||
static int _ecore_file_monitor_handler(void *data);
|
static int _ecore_file_monitor_poll_handler(void *data);
|
||||||
static void _ecore_file_monitor_check(Ecore_File_Monitor *em);
|
static void _ecore_file_monitor_poll_check(Ecore_File_Monitor *em);
|
||||||
static int _ecore_file_monitor_checking(Ecore_File_Monitor *em, char *name);
|
static int _ecore_file_monitor_poll_checking(Ecore_File_Monitor *em, char *name);
|
||||||
|
|
||||||
int
|
int
|
||||||
ecore_file_monitor_init(void)
|
ecore_file_monitor_poll_init(void)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ecore_file_monitor_shutdown(void)
|
ecore_file_monitor_poll_shutdown(void)
|
||||||
{
|
{
|
||||||
Evas_List *l;
|
Evas_List *l;
|
||||||
for (l = _monitors; l;)
|
for (l = _monitors; l;)
|
||||||
|
@ -64,9 +74,8 @@ ecore_file_monitor_shutdown(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
Ecore_File_Monitor *
|
Ecore_File_Monitor *
|
||||||
ecore_file_monitor_add(const char *path,
|
ecore_file_monitor_poll_add(const char *path,
|
||||||
void (*func) (void *data, Ecore_File_Monitor *em,
|
void (*func) (void *data, Ecore_File_Monitor *em,
|
||||||
Ecore_File_Type type,
|
|
||||||
Ecore_File_Event event,
|
Ecore_File_Event event,
|
||||||
const char *path),
|
const char *path),
|
||||||
void *data)
|
void *data)
|
||||||
|
@ -77,11 +86,11 @@ ecore_file_monitor_add(const char *path,
|
||||||
if (!path) return NULL;
|
if (!path) return NULL;
|
||||||
if (!func) return NULL;
|
if (!func) return NULL;
|
||||||
|
|
||||||
em = calloc(1, sizeof(Ecore_File_Monitor));
|
em = calloc(1, sizeof(Ecore_File_Monitor_Poll));
|
||||||
if (!em) return NULL;
|
if (!em) return NULL;
|
||||||
|
|
||||||
if (!_timer)
|
if (!_timer)
|
||||||
_timer = ecore_timer_add(_interval, _ecore_file_monitor_handler, NULL);
|
_timer = ecore_timer_add(_interval, _ecore_file_monitor_poll_handler, NULL);
|
||||||
else
|
else
|
||||||
ecore_timer_interval_set(_timer, ECORE_FILE_INTERVAL_MIN);
|
ecore_timer_interval_set(_timer, ECORE_FILE_INTERVAL_MIN);
|
||||||
|
|
||||||
|
@ -93,15 +102,10 @@ ecore_file_monitor_add(const char *path,
|
||||||
em->func = func;
|
em->func = func;
|
||||||
em->data = data;
|
em->data = data;
|
||||||
|
|
||||||
em->mtime = ecore_file_mod_time(em->path);
|
ECORE_FILE_MONITOR_POLL(em)->mtime = ecore_file_mod_time(em->path);
|
||||||
if (ecore_file_exists(em->path))
|
if (ecore_file_exists(em->path))
|
||||||
{
|
{
|
||||||
em->type = ecore_file_is_dir(em->path) ?
|
if (ecore_file_is_dir(em->path))
|
||||||
ECORE_FILE_TYPE_DIRECTORY :
|
|
||||||
ECORE_FILE_TYPE_FILE;
|
|
||||||
|
|
||||||
em->func(em->data, em, em->type, ECORE_FILE_EVENT_EXISTS, em->path);
|
|
||||||
if (em->type == ECORE_FILE_TYPE_DIRECTORY)
|
|
||||||
{
|
{
|
||||||
/* Check for subdirs */
|
/* Check for subdirs */
|
||||||
Evas_List *files, *l;
|
Evas_List *files, *l;
|
||||||
|
@ -124,10 +128,7 @@ ecore_file_monitor_add(const char *path,
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", em->path, file);
|
snprintf(buf, sizeof(buf), "%s/%s", em->path, file);
|
||||||
f->name = file;
|
f->name = file;
|
||||||
f->mtime = ecore_file_mod_time(buf);
|
f->mtime = ecore_file_mod_time(buf);
|
||||||
f->type = ecore_file_is_dir(buf) ?
|
f->is_dir = ecore_file_is_dir(buf);
|
||||||
ECORE_FILE_TYPE_DIRECTORY :
|
|
||||||
ECORE_FILE_TYPE_FILE;
|
|
||||||
em->func(em->data, em, f->type, ECORE_FILE_EVENT_EXISTS, buf);
|
|
||||||
em->files = evas_list_append(em->files, f);
|
em->files = evas_list_append(em->files, f);
|
||||||
}
|
}
|
||||||
evas_list_free(files);
|
evas_list_free(files);
|
||||||
|
@ -135,8 +136,8 @@ ecore_file_monitor_add(const char *path,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
em->type = ECORE_FILE_TYPE_NONE;
|
ecore_file_monitor_poll_del(em);
|
||||||
em->func(em->data, em, em->type, ECORE_FILE_EVENT_DELETED, em->path);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_monitors = evas_list_append(_monitors, em);
|
_monitors = evas_list_append(_monitors, em);
|
||||||
|
@ -145,13 +146,13 @@ ecore_file_monitor_add(const char *path,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ecore_file_monitor_del(Ecore_File_Monitor *em)
|
ecore_file_monitor_poll_del(Ecore_File_Monitor *em)
|
||||||
{
|
{
|
||||||
Evas_List *l;
|
Evas_List *l;
|
||||||
|
|
||||||
if (_lock)
|
if (_lock)
|
||||||
{
|
{
|
||||||
em->deleted = 1;
|
ECORE_FILE_MONITOR_POLL(em)->deleted = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +180,7 @@ ecore_file_monitor_del(Ecore_File_Monitor *em)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_ecore_file_monitor_handler(void *data __UNUSED__)
|
_ecore_file_monitor_poll_handler(void *data __UNUSED__)
|
||||||
{
|
{
|
||||||
Evas_List *monitor;
|
Evas_List *monitor;
|
||||||
|
|
||||||
|
@ -191,7 +192,7 @@ _ecore_file_monitor_handler(void *data __UNUSED__)
|
||||||
|
|
||||||
em = monitor->data;
|
em = monitor->data;
|
||||||
monitor = monitor->next;
|
monitor = monitor->next;
|
||||||
_ecore_file_monitor_check(em);
|
_ecore_file_monitor_poll_check(em);
|
||||||
}
|
}
|
||||||
_lock = 0;
|
_lock = 0;
|
||||||
if (_interval > ECORE_FILE_INTERVAL_MAX)
|
if (_interval > ECORE_FILE_INTERVAL_MAX)
|
||||||
|
@ -204,38 +205,24 @@ _ecore_file_monitor_handler(void *data __UNUSED__)
|
||||||
|
|
||||||
em = monitor->data;
|
em = monitor->data;
|
||||||
monitor = monitor->next;
|
monitor = monitor->next;
|
||||||
if (em->deleted)
|
if (ECORE_FILE_MONITOR_POLL(em)->deleted)
|
||||||
ecore_file_monitor_del(em);
|
ecore_file_monitor_del(em);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_ecore_file_monitor_check(Ecore_File_Monitor *em)
|
_ecore_file_monitor_poll_check(Ecore_File_Monitor *em)
|
||||||
{
|
{
|
||||||
int mtime;
|
int mtime;
|
||||||
|
int is_dir;
|
||||||
|
|
||||||
mtime = ecore_file_mod_time(em->path);
|
mtime = ecore_file_mod_time(em->path);
|
||||||
switch (em->type)
|
is_dir = ecore_file_is_dir(em->path);
|
||||||
|
if (mtime < ECORE_FILE_MONITOR_POLL(em)->mtime)
|
||||||
{
|
{
|
||||||
case ECORE_FILE_TYPE_FILE:
|
|
||||||
if (mtime < em->mtime)
|
|
||||||
{
|
|
||||||
em->func(em->data, em, em->type, ECORE_FILE_EVENT_DELETED, em->path);
|
|
||||||
em->type = ECORE_FILE_TYPE_NONE;
|
|
||||||
_interval = ECORE_FILE_INTERVAL_MIN;
|
|
||||||
}
|
|
||||||
else if (mtime > em->mtime)
|
|
||||||
{
|
|
||||||
em->func(em->data, em, em->type, ECORE_FILE_EVENT_CHANGED, em->path);
|
|
||||||
_interval = ECORE_FILE_INTERVAL_MIN;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ECORE_FILE_TYPE_DIRECTORY:
|
|
||||||
if (mtime < em->mtime)
|
|
||||||
{
|
|
||||||
/* Deleted */
|
|
||||||
Evas_List *l;
|
Evas_List *l;
|
||||||
|
Ecore_File_Event event;
|
||||||
|
|
||||||
/* Notify all files deleted */
|
/* Notify all files deleted */
|
||||||
for (l = em->files; l;)
|
for (l = em->files; l;)
|
||||||
|
@ -246,13 +233,16 @@ _ecore_file_monitor_check(Ecore_File_Monitor *em)
|
||||||
f = l->data;
|
f = l->data;
|
||||||
l = l->next;
|
l = l->next;
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", em->path, f->name);
|
snprintf(buf, sizeof(buf), "%s/%s", em->path, f->name);
|
||||||
em->func(em->data, em, f->type, ECORE_FILE_EVENT_DELETED, buf);
|
if (f->is_dir)
|
||||||
|
event = ECORE_FILE_EVENT_DELETED_DIRECTORY;
|
||||||
|
else
|
||||||
|
event = ECORE_FILE_EVENT_DELETED_FILE;
|
||||||
|
em->func(em->data, em, event, buf);
|
||||||
free(f->name);
|
free(f->name);
|
||||||
free(f);
|
free(f);
|
||||||
}
|
}
|
||||||
em->files = evas_list_free(em->files);
|
em->files = evas_list_free(em->files);
|
||||||
em->func(em->data, em, em->type, ECORE_FILE_EVENT_DELETED, em->path);
|
em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
|
||||||
em->type = ECORE_FILE_TYPE_NONE;
|
|
||||||
_interval = ECORE_FILE_INTERVAL_MIN;
|
_interval = ECORE_FILE_INTERVAL_MIN;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -265,6 +255,7 @@ _ecore_file_monitor_check(Ecore_File_Monitor *em)
|
||||||
Ecore_File *f;
|
Ecore_File *f;
|
||||||
char buf[PATH_MAX];
|
char buf[PATH_MAX];
|
||||||
int mtime;
|
int mtime;
|
||||||
|
Ecore_File_Event event;
|
||||||
|
|
||||||
f = l->data;
|
f = l->data;
|
||||||
l = l->next;
|
l = l->next;
|
||||||
|
@ -272,22 +263,27 @@ _ecore_file_monitor_check(Ecore_File_Monitor *em)
|
||||||
mtime = ecore_file_mod_time(buf);
|
mtime = ecore_file_mod_time(buf);
|
||||||
if (mtime < f->mtime)
|
if (mtime < f->mtime)
|
||||||
{
|
{
|
||||||
em->func(em->data, em, f->type, ECORE_FILE_EVENT_DELETED, buf);
|
if (f->is_dir)
|
||||||
|
event = ECORE_FILE_EVENT_DELETED_DIRECTORY;
|
||||||
|
else
|
||||||
|
event = ECORE_FILE_EVENT_DELETED_FILE;
|
||||||
|
|
||||||
|
em->func(em->data, em, event, buf);
|
||||||
em->files = evas_list_remove(em->files, f);
|
em->files = evas_list_remove(em->files, f);
|
||||||
free(f->name);
|
free(f->name);
|
||||||
free(f);
|
free(f);
|
||||||
_interval = ECORE_FILE_INTERVAL_MIN;
|
_interval = ECORE_FILE_INTERVAL_MIN;
|
||||||
}
|
}
|
||||||
else if (mtime > f->mtime)
|
else if ((mtime > f->mtime) && !(f->is_dir))
|
||||||
{
|
{
|
||||||
em->func(em->data, em, f->type, ECORE_FILE_EVENT_CHANGED, buf);
|
em->func(em->data, em, ECORE_FILE_EVENT_MODIFIED, buf);
|
||||||
_interval = ECORE_FILE_INTERVAL_MIN;
|
_interval = ECORE_FILE_INTERVAL_MIN;
|
||||||
}
|
}
|
||||||
f->mtime = mtime;
|
f->mtime = mtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for new files */
|
/* Check for new files */
|
||||||
if (em->mtime < mtime)
|
if (ECORE_FILE_MONITOR_POLL(em)->mtime < mtime)
|
||||||
{
|
{
|
||||||
Evas_List *files;
|
Evas_List *files;
|
||||||
|
|
||||||
|
@ -298,9 +294,10 @@ _ecore_file_monitor_check(Ecore_File_Monitor *em)
|
||||||
Ecore_File *f;
|
Ecore_File *f;
|
||||||
char *file;
|
char *file;
|
||||||
char buf[PATH_MAX];
|
char buf[PATH_MAX];
|
||||||
|
Ecore_File_Event event;
|
||||||
|
|
||||||
file = l->data;
|
file = l->data;
|
||||||
if (_ecore_file_monitor_checking(em, file))
|
if (_ecore_file_monitor_poll_checking(em, file))
|
||||||
{
|
{
|
||||||
free(file);
|
free(file);
|
||||||
continue;
|
continue;
|
||||||
|
@ -316,67 +313,24 @@ _ecore_file_monitor_check(Ecore_File_Monitor *em)
|
||||||
|
|
||||||
f->name = file;
|
f->name = file;
|
||||||
f->mtime = ecore_file_mod_time(buf);
|
f->mtime = ecore_file_mod_time(buf);
|
||||||
f->type = ecore_file_is_dir(buf) ?
|
f->is_dir = ecore_file_is_dir(buf);
|
||||||
ECORE_FILE_TYPE_DIRECTORY :
|
if (f->is_dir)
|
||||||
ECORE_FILE_TYPE_FILE;
|
event = ECORE_FILE_EVENT_CREATED_DIRECTORY;
|
||||||
em->func(em->data, em, f->type, ECORE_FILE_EVENT_CREATED, buf);
|
else
|
||||||
|
event = ECORE_FILE_EVENT_CREATED_FILE;
|
||||||
|
em->func(em->data, em, event, buf);
|
||||||
em->files = evas_list_append(em->files, f);
|
em->files = evas_list_append(em->files, f);
|
||||||
}
|
}
|
||||||
em->func(em->data, em, em->type, ECORE_FILE_EVENT_CHANGED, em->path);
|
if (!ecore_file_is_dir(em->path))
|
||||||
|
em->func(em->data, em, ECORE_FILE_EVENT_MODIFIED, em->path);
|
||||||
_interval = ECORE_FILE_INTERVAL_MIN;
|
_interval = ECORE_FILE_INTERVAL_MIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
ECORE_FILE_MONITOR_POLL(em)->mtime = mtime;
|
||||||
case ECORE_FILE_TYPE_NONE:
|
|
||||||
if (mtime > em->mtime)
|
|
||||||
{
|
|
||||||
/* Something has been created! */
|
|
||||||
em->type = ecore_file_is_dir(em->path) ?
|
|
||||||
ECORE_FILE_TYPE_DIRECTORY :
|
|
||||||
ECORE_FILE_TYPE_FILE;
|
|
||||||
|
|
||||||
em->func(em->data, em, em->type, ECORE_FILE_EVENT_CREATED, em->path);
|
|
||||||
if (em->type == ECORE_FILE_TYPE_DIRECTORY)
|
|
||||||
{
|
|
||||||
/* Check for subdirs */
|
|
||||||
Evas_List *files, *l;
|
|
||||||
|
|
||||||
em->func(em->data, em, em->type, ECORE_FILE_EVENT_CREATED, em->path);
|
|
||||||
files = ecore_file_ls(em->path);
|
|
||||||
for (l = files; l; l = l->next)
|
|
||||||
{
|
|
||||||
Ecore_File *f;
|
|
||||||
char *file;
|
|
||||||
char buf[PATH_MAX];
|
|
||||||
|
|
||||||
file = l->data;
|
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", em->path, file);
|
|
||||||
f = calloc(1, sizeof(Ecore_File));
|
|
||||||
if (!f)
|
|
||||||
{
|
|
||||||
free(file);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
f->name = file;
|
|
||||||
f->mtime = ecore_file_mod_time(buf);
|
|
||||||
f->type = ecore_file_is_dir(buf) ?
|
|
||||||
ECORE_FILE_TYPE_DIRECTORY :
|
|
||||||
ECORE_FILE_TYPE_FILE;
|
|
||||||
em->func(em->data, em, f->type, ECORE_FILE_EVENT_CREATED, buf);
|
|
||||||
em->files = evas_list_append(em->files, f);
|
|
||||||
}
|
|
||||||
evas_list_free(files);
|
|
||||||
}
|
|
||||||
_interval = ECORE_FILE_INTERVAL_MIN;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
em->mtime = mtime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_ecore_file_monitor_checking(Ecore_File_Monitor *em, char *name)
|
_ecore_file_monitor_poll_checking(Ecore_File_Monitor *em, char *name)
|
||||||
{
|
{
|
||||||
Evas_List *l;
|
Evas_List *l;
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,6 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "Ecore.h"
|
#include "Ecore.h"
|
||||||
|
@ -18,27 +12,52 @@
|
||||||
int ecore_file_monitor_init(void);
|
int ecore_file_monitor_init(void);
|
||||||
int ecore_file_monitor_shutdown(void);
|
int ecore_file_monitor_shutdown(void);
|
||||||
|
|
||||||
|
#define ECORE_FILE_MONITOR(x) ((Ecore_File_Monitor *)(x))
|
||||||
|
|
||||||
struct _Ecore_File_Monitor
|
struct _Ecore_File_Monitor
|
||||||
{
|
{
|
||||||
void (*func) (void *data,
|
void (*func) (void *data,
|
||||||
Ecore_File_Monitor *ecore_file_monitor,
|
Ecore_File_Monitor *ecore_file_monitor,
|
||||||
Ecore_File_Type type,
|
|
||||||
Ecore_File_Event event,
|
Ecore_File_Event event,
|
||||||
const char *path);
|
const char *path);
|
||||||
|
|
||||||
char *path;
|
char *path;
|
||||||
Ecore_File_Type type;
|
|
||||||
void *data;
|
void *data;
|
||||||
Evas_List *files;
|
Evas_List *files;
|
||||||
#ifdef HAVE_POLL
|
|
||||||
int mtime;
|
|
||||||
unsigned char deleted;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
#ifdef HAVE_INOTIFY
|
||||||
#define HAVE_POLL
|
EAPI int ecore_file_monitor_inotify_init(void);
|
||||||
#define HAVE_FAM
|
EAPI int ecore_file_monitor_inotify_shutdown(void);
|
||||||
#define HAVE_DNOTIFY
|
EAPI Ecore_File_Monitor *ecore_file_monitor_inotify_add(const char *path,
|
||||||
#define HAVE_INOTIFY
|
void (*func) (void *data,
|
||||||
*/
|
Ecore_File_Monitor *ecore_file_monitor,
|
||||||
|
Ecore_File_Event event,
|
||||||
|
const char *path),
|
||||||
|
void *data);
|
||||||
|
EAPI void ecore_file_monitor_inotify_del(Ecore_File_Monitor *ecore_file_monitor);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_FAM
|
||||||
|
EAPI int ecore_file_monitor_fam_init(void);
|
||||||
|
EAPI int ecore_file_monitor_fam_shutdown(void);
|
||||||
|
EAPI Ecore_File_Monitor *ecore_file_monitor_fam_add(const char *path,
|
||||||
|
void (*func) (void *data,
|
||||||
|
Ecore_File_Monitor *ecore_file_monitor,
|
||||||
|
Ecore_File_Event event,
|
||||||
|
const char *path),
|
||||||
|
void *data);
|
||||||
|
EAPI void ecore_file_monitor_fam_del(Ecore_File_Monitor *ecore_file_monitor);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_POLL
|
||||||
|
EAPI int ecore_file_monitor_poll_init(void);
|
||||||
|
EAPI int ecore_file_monitor_poll_shutdown(void);
|
||||||
|
EAPI Ecore_File_Monitor *ecore_file_monitor_poll_add(const char *path,
|
||||||
|
void (*func) (void *data,
|
||||||
|
Ecore_File_Monitor *ecore_file_monitor,
|
||||||
|
Ecore_File_Event event,
|
||||||
|
const char *path),
|
||||||
|
void *data);
|
||||||
|
EAPI void ecore_file_monitor_poll_del(Ecore_File_Monitor *ecore_file_monitor);
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue