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)
fi
AC_MSG_CHECKING(wheter ecore_file module is to be built)
have_ecore_file="no"
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,
[ --disable-ecore-file disable the ecore_file module], [
if [ test "$enableval" = "yes" ]; then
if test "$enableval" = "yes"; then
AC_MSG_RESULT(yes)
have_ecore_file="yes"
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=""
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 ])
# I'm to stupid to get fam working right :)
# PKG_CHECK_MODULES(FAM, gamin >= 0.0.23,
#if test "x$use_fam" = "xyes"; then
# AC_CHECK_LIB(fam, FAMOpen,
# [
# AC_DEFINE(HAVE_FAM, 1, [ File monitoring with FAM ])
@ -773,6 +811,31 @@ if [ test "x$have_ecore_file" = "xyes" ]; then
# 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
AM_CONDITIONAL(BUILD_ECORE_FILE, false)
fi
@ -884,7 +947,8 @@ echo " Ecore_Evas FB Support...: $have_ecore_evas_fb"
echo " Ecore_Buffer............: $have_ecore_evas_buffer"
echo " Ecore_Ipc...............: $have_ecore_ipc (OpenSSL: $use_openssl)"
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 "Now type 'make' ('gmake' on some systems) to compile $PACKAGE."
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_Event Ecore_File_Monitor_Event;
typedef enum {
ECORE_FILE_TYPE_NONE,
ECORE_FILE_TYPE_FILE,
ECORE_FILE_TYPE_DIRECTORY
} Ecore_File_Type;
typedef enum {
ECORE_FILE_EVENT_NONE,
ECORE_FILE_EVENT_EXISTS,
ECORE_FILE_EVENT_CREATED,
ECORE_FILE_EVENT_DELETED,
ECORE_FILE_EVENT_CHANGED
ECORE_FILE_EVENT_CREATED_FILE,
ECORE_FILE_EVENT_CREATED_DIRECTORY,
ECORE_FILE_EVENT_DELETED_FILE,
ECORE_FILE_EVENT_DELETED_DIRECTORY,
ECORE_FILE_EVENT_DELETED_SELF,
ECORE_FILE_EVENT_MODIFIED
} 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,
void (*func) (void *data,
Ecore_File_Monitor *ecore_file_monitor,
Ecore_File_Type type,
Ecore_File_Event event,
const char *path),
void *data);
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

View File

@ -19,7 +19,6 @@ ecore_file_private.h \
ecore_file_monitor.c \
ecore_file_monitor_fam.c \
ecore_file_monitor_inotify.c \
ecore_file_monitor_dnotify.c \
ecore_file_monitor_poll.c
libecore_file_la_LIBADD = \
@ -35,6 +34,5 @@ ecore_file_private.h \
ecore_file_monitor.c \
ecore_file_monitor_fam.c \
ecore_file_monitor_inotify.c \
ecore_file_monitor_dnotify.c \
ecore_file_monitor_poll.c

View File

@ -3,8 +3,124 @@
*/
#include "ecore_file_private.h"
Ecore_File_Type
ecore_file_monitor_type_get(Ecore_File_Monitor *em)
typedef enum {
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:
* - 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!
*/
@ -17,48 +17,46 @@
typedef struct _Ecore_File_Monitor_Fam Ecore_File_Monitor_Fam;
typedef struct _Ecore_File Ecore_File;
#define ECORE_FILE_MONITOR_FAM(x) ((Ecore_File_Monitor_Fam *)(x))
struct _Ecore_File_Monitor_Fam
{
Ecore_File_Monitor monitor;
Ecore_File_Monitor monitor;
FAMRequest *request;
Evas_List *files;
};
struct _Ecore_File
{
char *name;
Ecore_File_Type type;
char *name;
};
#define ECORE_FILE_MONITOR_FAM(x) ((Ecore_File_Monitor_Fam *)(x))
static Ecore_Fd_Handler *_fdh = NULL;
static FAMConnection *_fc = NULL;
static Evas_List *_monitors = NULL;
static int _ecore_file_monitor_handler(void *data, Ecore_Fd_Handler *fdh);
static Ecore_File * _ecore_file_monitor_file_find(Ecore_File_Monitor *em, char *name);
static Ecore_File_Event _ecore_file_monitor_event_get(FAMCodes change);
static int _ecore_file_monitor_fam_handler(void *data, Ecore_Fd_Handler *fdh);
static Ecore_File *_ecore_file_monitor_fam_file_find(Ecore_File_Monitor *em, char *name);
static Ecore_File_Event _ecore_file_monitor_fam_event_get(FAMCodes code, int self, int is_dir);
int
ecore_file_monitor_init(void)
ecore_file_monitor_fam_init(void)
{
_fc = calloc(1, sizeof(FAMConnection));
if (!_fc) return 0;
FAMOpen(_fc);
_fdh = ecore_main_fd_handler_add(FAMCONNECTION_GETFD(_fc), ECORE_FD_READ, _ecore_file_monitor_handler,
NULL, NULL, NULL);
_fdh = ecore_main_fd_handler_add(FAMCONNECTION_GETFD(_fc), ECORE_FD_READ,
_ecore_file_monitor_fam_handler, NULL, NULL, NULL);
return 1;
}
int
ecore_file_monitor_shutdown(void)
ecore_file_monitor_fam_shutdown(void)
{
Evas_List *l;
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);
if (_fdh) ecore_main_fd_handler_del(_fdh);
if (_fc)
@ -70,67 +68,61 @@ ecore_file_monitor_shutdown(void)
}
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_fam_add(const char *path,
void (*func) (void *data,
Ecore_File_Monitor *em,
Ecore_File_Event event,
const char *path),
void *data)
{
Ecore_File_Monitor *em;
Ecore_File_Monitor_Fam *emf;
int len;
emf = calloc(1, sizeof(Ecore_File_Monitor_Fam));
em = ECORE_FILE_MONITOR(emf);
em = calloc(1, sizeof(Ecore_File_Monitor_Fam));
if (!em) return NULL;
em->func = func;
em->data = data;
_monitors = evas_list_append(_monitors, em);
em->path = strdup(path);
len = strlen(em->path);
if (em->path[len - 1] == '/')
em->path[len - 1] = '\0';
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;
/* TODO: Check if calloc succeded! */
emf->request = calloc(1, sizeof(FAMRequest));
if (em->type == ECORE_FILE_TYPE_DIRECTORY)
ECORE_FILE_MONITOR_FAM(em)->request = calloc(1, sizeof(FAMRequest));
if (!ECORE_FILE_MONITOR_FAM(em)->request)
{
FAMMonitorDirectory(_fc, em->path, emf->request, em);
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, emf->request, em);
em->func(em->data, em, em->type, ECORE_FILE_EVENT_EXISTS, em->path);
FAMMonitorFile(_fc, em->path, ECORE_FILE_MONITOR_FAM(em)->request, em);
}
}
else
{
em->type = ECORE_FILE_TYPE_NONE;
em->func(em->data, em, em->type, ECORE_FILE_EVENT_DELETED, em->path);
ecore_file_monitor_fam_del(em);
return NULL;
}
_monitors = evas_list_append(_monitors, em);
return em;
}
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;
emf = ECORE_FILE_MONITOR_FAM(em);
for (l = emf->files; l; l = l->next)
for (l = em->files; l; l = l->next)
{
Ecore_File *f;
@ -138,18 +130,21 @@ ecore_file_monitor_del(Ecore_File_Monitor *em)
free(f->name);
free(f);
}
evas_list_free(emf->files);
evas_list_free(em->files);
_monitors = evas_list_remove(_monitors, em);
FAMCancelMonitor(_fc, emf->request);
free(emf->request);
if (ECORE_FILE_MONITOR_FAM(em)->request)
{
FAMCancelMonitor(_fc, ECORE_FILE_MONITOR_FAM(em)->request);
free(ECORE_FILE_MONITOR_FAM(em)->request);
}
free(em->path);
free(em);
}
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;
@ -158,62 +153,107 @@ _ecore_file_monitor_handler(void *data, Ecore_Fd_Handler *fdh)
for (i = 0; i < pending; i++)
{
Ecore_File_Monitor *em;
Ecore_File_Monitor_Fam *emf;
FAMEvent fe;
Ecore_File_Event event;
char buf[PATH_MAX];
int len, self;
buf[0] = 0;
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;
emf = ECORE_FILE_MONITOR_FAM(em);
if (!em) continue;
if (event == ECORE_FILE_EVENT_NONE) continue;
if ((em->type == ECORE_FILE_TYPE_DIRECTORY)
&& !strcmp(em->path, fe.filename))
continue;
/* Create path */
snprintf(buf, sizeof(buf), "%s/%s", em->path, fe.filename);
if (event == ECORE_FILE_EVENT_DELETED)
#if 0
if (!strcmp(em->path, fe.filename))
{
Ecore_File *f;
Evas_List *l;
f = _ecore_file_monitor_file_find(em, fe.filename);
if (f)
if (event == ECORE_FILE_EVENT_DELETED)
{
emf->files = evas_list_remove(emf->files, f);
em->func(em->data, em, f->type, event, buf);
free(f->name);
free(f);
/* Notify all files deleted */
for (l = em->files; l;)
{
Ecore_File *f;
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);
}
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
{
Ecore_File *f;
f = calloc(1, sizeof(Ecore_File));
if (!f) continue;
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));
if (!f) break;
f->type = ecore_file_is_dir(buf) ?
ECORE_FILE_TYPE_DIRECTORY :
ECORE_FILE_TYPE_FILE;
f->name = strdup(fe.filename);
emf->files = evas_list_append(emf->files, f);
em->func(em->data, em, f->type, event, buf);
f->type = ecore_file_is_dir(buf) ?
ECORE_FILE_TYPE_DIRECTORY :
ECORE_FILE_TYPE_FILE;
f->name = strdup(fe.filename);
em->files = evas_list_append(em->files, f);
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;
}
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;
emf = ECORE_FILE_MONITOR_FAM(em);
for (l = emf->files; l; l = l->next)
for (l = em->files; l; l = l->next)
{
Ecore_File *f;
f = l->data;
@ -224,18 +264,31 @@ _ecore_file_monitor_file_find(Ecore_File_Monitor *em, char *name)
}
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)
{
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:
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:
return ECORE_FILE_EVENT_CHANGED;
if (!is_dir)
return ECORE_FILE_EVENT_MODIFIED;
break;
case FAMExists:
return ECORE_FILE_EVENT_EXISTS;
case FAMStartExecuting:
case FAMStopExecuting:
case FAMMoved:

View File

@ -5,81 +5,78 @@
/*
* TODO:
* - Everything!
*/
#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 Ecore_File;
#define ECORE_FILE_MONITOR_INOTIFY(x) ((Ecore_File_Monitor_Inotify *)(x))
struct _Ecore_File_Monitor_Inotify
{
Ecore_File_Monitor monitor;
int fd;
Evas_List *files;
unsigned char deleted;
int wd;
};
struct _Ecore_File
{
char *name;
int mtime;
Ecore_File_Type type;
};
static Ecore_Fd_Handler *_fdh = NULL;
static Evas_List *_monitors = NULL;
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);
static int _ecore_file_monitor_inotify_handler(void *data, Ecore_Fd_Handler *fdh);
static Ecore_File_Monitor *_ecore_file_monitor_inotify_monitor_find(int wd);
static void _ecore_file_monitor_inotify_events(Ecore_File_Monitor *em,
char *file, int mask);
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;
}
int
ecore_file_monitor_shutdown(void)
ecore_file_monitor_inotify_shutdown(void)
{
Evas_List *l;
int fd;
if (_eh) ecore_event_handler_del(_eh);
for (l = _monitors; l;)
if (_fdh)
{
Ecore_File_Monitor *em;
em = l->data;
l = l->next;
ecore_file_monitor_del(em);
fd = ecore_main_fd_handler_fd_get(_fdh);
ecore_main_fd_handler_del(_fdh);
close(fd);
}
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_inotify_add(const char *path,
void (*func) (void *data, Ecore_File_Monitor *em,
Ecore_File_Event event,
const char *path),
void *data)
{
Ecore_File_Monitor *em;
Ecore_File_Monitor_Inotify *emd;
int len;
if (!path) return NULL;
if (!func) return NULL;
emd = calloc(1, sizeof(Ecore_File_Monitor_Inotify));
em = ECORE_FILE_MONITOR(emd);
em = calloc(1, sizeof(Ecore_File_Monitor_Inotify));
if (!em) return NULL;
em->func = func;
@ -88,62 +85,31 @@ ecore_file_monitor_add(const char *path,
em->path = strdup(path);
len = strlen(em->path);
if (em->path[len - 1] == '/')
em->path[len - 1] = '\0';
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;
struct inotify_watch_request request;
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 */
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);
printf("ioctl error\n");
ecore_file_monitor_inotify_del(em);
return NULL;
}
}
else
{
em->type = ECORE_FILE_TYPE_NONE;
em->func(em->data, em, em->type, ECORE_FILE_EVENT_DELETED, em->path);
ecore_file_monitor_inotify_del(em);
return NULL;
}
_monitors = evas_list_append(_monitors, em);
@ -152,165 +118,106 @@ ecore_file_monitor_add(const char *path,
}
void
ecore_file_monitor_del(Ecore_File_Monitor *em)
ecore_file_monitor_inotify_del(Ecore_File_Monitor *em)
{
Ecore_File_Monitor_Inotify *emd;
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);
int fd;
_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);
}
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;
Ecore_File_Monitor *em;
char buffer[16384];
struct inotify_event *event;
int i = 0;
int event_size;
ssize_t size;
ev = event;
_lock = 1;
for (monitor = _monitors; monitor;)
size = read(ecore_main_fd_handler_fd_get(fdh), buffer, sizeof(buffer));
while (i < size)
{
Ecore_File_Monitor *em;
Ecore_File_Monitor_Inotify *emd;
event = (struct inotify_event *)&buffer[i];
event_size = sizeof(struct inotify_event) + event->len;
i += event_size;
em = monitor->data;
emd = ECORE_FILE_MONITOR_INOTIFY(em);
monitor = monitor->next;
em = _ecore_file_monitor_inotify_monitor_find(event->wd);
if (!em) continue;
if (emd->fd == ev->data.si_fd)
_ecore_file_monitor_check(em);
_ecore_file_monitor_inotify_events(em, event->name, event->mask);
}
_lock = 0;
for (monitor = _monitors; monitor;)
{
Ecore_File_Monitor *em;
Ecore_File_Monitor_Inotify *emd;
em = monitor->data;
emd = ECORE_FILE_MONITOR_INOTIFY(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)
static Ecore_File_Monitor *
_ecore_file_monitor_inotify_monitor_find(int wd)
{
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;
if (!strcmp(er->path, path))
return er;
em = l->data;
if (ECORE_FILE_MONITOR_INOTIFY(em)->wd == wd)
return em;
}
return NULL;
}
#endif
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;
char buf[PATH_MAX];
if (file)
snprintf(buf, sizeof(buf), "%s/%s", em->path, file);
else
strcpy(buf, em->path);
/* Check for changed files */
emd = ECORE_FILE_MONITOR_INOTIFY(em);
for (l = emd->files; l;)
if (mask & IN_MODIFY)
{
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;
if (!ecore_file_is_dir(buf))
em->func(em->data, em, ECORE_FILE_EVENT_MODIFIED, buf);
}
files = ecore_file_ls(em->path);
for (l = files; l; l = l->next)
if (mask & IN_MOVED_FROM)
{
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);
printf("MOVE_FROM ");
}
}
static int
_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)
if (mask & IN_MOVED_TO)
{
Ecore_File *f;
f = l->data;
if (!strcmp(f->name, name))
return 1;
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

View File

@ -14,13 +14,23 @@
* - Change poll time
*/
typedef struct _Ecore_File Ecore_File;
typedef struct _Ecore_File_Monitor_Poll Ecore_File_Monitor_Poll;
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
{
char *name;
int mtime;
Ecore_File_Type type;
char *name;
int mtime;
unsigned char is_dir;
};
#define ECORE_FILE_INTERVAL_MIN 1.0
@ -32,18 +42,18 @@ static Ecore_Timer *_timer = NULL;
static Evas_List *_monitors = NULL;
static int _lock = 0;
static int _ecore_file_monitor_handler(void *data);
static void _ecore_file_monitor_check(Ecore_File_Monitor *em);
static int _ecore_file_monitor_checking(Ecore_File_Monitor *em, char *name);
static int _ecore_file_monitor_poll_handler(void *data);
static void _ecore_file_monitor_poll_check(Ecore_File_Monitor *em);
static int _ecore_file_monitor_poll_checking(Ecore_File_Monitor *em, char *name);
int
ecore_file_monitor_init(void)
ecore_file_monitor_poll_init(void)
{
return 1;
}
int
ecore_file_monitor_shutdown(void)
ecore_file_monitor_poll_shutdown(void)
{
Evas_List *l;
for (l = _monitors; l;)
@ -64,12 +74,11 @@ ecore_file_monitor_shutdown(void)
}
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_poll_add(const char *path,
void (*func) (void *data, Ecore_File_Monitor *em,
Ecore_File_Event event,
const char *path),
void *data)
{
Ecore_File_Monitor *em;
int len;
@ -77,11 +86,11 @@ ecore_file_monitor_add(const char *path,
if (!path) 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 (!_timer)
_timer = ecore_timer_add(_interval, _ecore_file_monitor_handler, NULL);
_timer = ecore_timer_add(_interval, _ecore_file_monitor_poll_handler, NULL);
else
ecore_timer_interval_set(_timer, ECORE_FILE_INTERVAL_MIN);
@ -93,15 +102,10 @@ ecore_file_monitor_add(const char *path,
em->func = func;
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))
{
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_EXISTS, em->path);
if (em->type == ECORE_FILE_TYPE_DIRECTORY)
if (ecore_file_is_dir(em->path))
{
/* Check for subdirs */
Evas_List *files, *l;
@ -124,10 +128,7 @@ ecore_file_monitor_add(const char *path,
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);
f->is_dir = ecore_file_is_dir(buf);
em->files = evas_list_append(em->files, f);
}
evas_list_free(files);
@ -135,8 +136,8 @@ ecore_file_monitor_add(const char *path,
}
else
{
em->type = ECORE_FILE_TYPE_NONE;
em->func(em->data, em, em->type, ECORE_FILE_EVENT_DELETED, em->path);
ecore_file_monitor_poll_del(em);
return NULL;
}
_monitors = evas_list_append(_monitors, em);
@ -145,13 +146,13 @@ ecore_file_monitor_add(const char *path,
}
void
ecore_file_monitor_del(Ecore_File_Monitor *em)
ecore_file_monitor_poll_del(Ecore_File_Monitor *em)
{
Evas_List *l;
if (_lock)
{
em->deleted = 1;
ECORE_FILE_MONITOR_POLL(em)->deleted = 1;
return;
}
@ -179,7 +180,7 @@ ecore_file_monitor_del(Ecore_File_Monitor *em)
}
static int
_ecore_file_monitor_handler(void *data __UNUSED__)
_ecore_file_monitor_poll_handler(void *data __UNUSED__)
{
Evas_List *monitor;
@ -191,7 +192,7 @@ _ecore_file_monitor_handler(void *data __UNUSED__)
em = monitor->data;
monitor = monitor->next;
_ecore_file_monitor_check(em);
_ecore_file_monitor_poll_check(em);
}
_lock = 0;
if (_interval > ECORE_FILE_INTERVAL_MAX)
@ -204,179 +205,132 @@ _ecore_file_monitor_handler(void *data __UNUSED__)
em = monitor->data;
monitor = monitor->next;
if (em->deleted)
if (ECORE_FILE_MONITOR_POLL(em)->deleted)
ecore_file_monitor_del(em);
}
return 1;
}
static void
_ecore_file_monitor_check(Ecore_File_Monitor *em)
_ecore_file_monitor_poll_check(Ecore_File_Monitor *em)
{
int mtime;
int is_dir;
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 */
for (l = em->files; l;)
{
Ecore_File *f;
char buf[PATH_MAX];
/* Notify all files deleted */
for (l = em->files; l;)
{
Ecore_File *f;
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);
}
em->files = evas_list_free(em->files);
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
{
Evas_List *l;
/* Check for changed files */
for (l = em->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);
em->files = evas_list_remove(em->files, f);
free(f->name);
free(f);
_interval = ECORE_FILE_INTERVAL_MIN;
}
else if (mtime > f->mtime)
{
em->func(em->data, em, f->type, ECORE_FILE_EVENT_CHANGED, buf);
_interval = ECORE_FILE_INTERVAL_MIN;
}
f->mtime = mtime;
}
/* Check for new files */
if (em->mtime < mtime)
{
Evas_List *files;
/* Files have been added or removed */
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;
}
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);
}
em->func(em->data, em, em->type, ECORE_FILE_EVENT_CHANGED, em->path);
_interval = ECORE_FILE_INTERVAL_MIN;
}
}
break;
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;
f = l->data;
l = l->next;
snprintf(buf, sizeof(buf), "%s/%s", em->path, f->name);
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);
}
em->files = evas_list_free(em->files);
em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
_interval = ECORE_FILE_INTERVAL_MIN;
}
em->mtime = mtime;
else
{
Evas_List *l;
/* Check for changed files */
for (l = em->files; l;)
{
Ecore_File *f;
char buf[PATH_MAX];
int mtime;
Ecore_File_Event event;
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)
{
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);
free(f->name);
free(f);
_interval = ECORE_FILE_INTERVAL_MIN;
}
else if ((mtime > f->mtime) && !(f->is_dir))
{
em->func(em->data, em, ECORE_FILE_EVENT_MODIFIED, buf);
_interval = ECORE_FILE_INTERVAL_MIN;
}
f->mtime = mtime;
}
/* Check for new files */
if (ECORE_FILE_MONITOR_POLL(em)->mtime < mtime)
{
Evas_List *files;
/* Files have been added or removed */
files = ecore_file_ls(em->path);
for (l = files; l; l = l->next)
{
Ecore_File *f;
char *file;
char buf[PATH_MAX];
Ecore_File_Event event;
file = l->data;
if (_ecore_file_monitor_poll_checking(em, file))
{
free(file);
continue;
}
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->is_dir = ecore_file_is_dir(buf);
if (f->is_dir)
event = ECORE_FILE_EVENT_CREATED_DIRECTORY;
else
event = ECORE_FILE_EVENT_CREATED_FILE;
em->func(em->data, em, event, buf);
em->files = evas_list_append(em->files, f);
}
if (!ecore_file_is_dir(em->path))
em->func(em->data, em, ECORE_FILE_EVENT_MODIFIED, em->path);
_interval = ECORE_FILE_INTERVAL_MIN;
}
}
ECORE_FILE_MONITOR_POLL(em)->mtime = mtime;
}
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;

View File

@ -4,12 +4,6 @@
#include <stdio.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 "Ecore.h"
@ -18,27 +12,52 @@
int ecore_file_monitor_init(void);
int ecore_file_monitor_shutdown(void);
#define ECORE_FILE_MONITOR(x) ((Ecore_File_Monitor *)(x))
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;
Evas_List *files;
#ifdef HAVE_POLL
int mtime;
unsigned char deleted;
#endif
};
/*
#define HAVE_POLL
#define HAVE_FAM
#define HAVE_DNOTIFY
#define HAVE_INOTIFY
*/
#ifdef HAVE_INOTIFY
EAPI int ecore_file_monitor_inotify_init(void);
EAPI int ecore_file_monitor_inotify_shutdown(void);
EAPI Ecore_File_Monitor *ecore_file_monitor_inotify_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_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