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:
sebastid 2005-03-30 06:35:12 +00:00 committed by sebastid
parent 78939419b3
commit 40ec35d38d
9 changed files with 635 additions and 876 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
} }

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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;

View File

@ -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