parent
7dbcc92602
commit
813c77c392
|
@ -0,0 +1,6 @@
|
|||
.deps
|
||||
.libs
|
||||
Makefile
|
||||
Makefile.in
|
||||
*.lo
|
||||
libecore_file.la
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
|
||||
*/
|
||||
#ifndef ECORE_FILE_H
|
||||
#define ECORE_FILE_H
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - More events, move/rename of directory file
|
||||
*/
|
||||
|
||||
#ifdef EAPI
|
||||
#undef EAPI
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
# ifdef BUILDING_DLL
|
||||
# define EAPI __declspec(dllexport)
|
||||
# else
|
||||
# define EAPI __declspec(dllimport)
|
||||
# endif
|
||||
#else
|
||||
# ifdef GCC_HASCLASSVISIBILITY
|
||||
# define EAPI __attribute__ ((visibility("default")))
|
||||
# else
|
||||
# define EAPI
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <Evas.h>
|
||||
#include <time.h>
|
||||
|
||||
EAPI int ecore_file_init(void);
|
||||
EAPI int ecore_file_shutdown(void);
|
||||
EAPI time_t ecore_file_mod_time(char *file);
|
||||
EAPI int ecore_file_exists(char *file);
|
||||
EAPI int ecore_file_is_dir(char *file);
|
||||
EAPI int ecore_file_mkdir(char *dir);
|
||||
EAPI int ecore_file_mkpath(char *path);
|
||||
EAPI int ecore_file_cp(char *src, char *dst);
|
||||
EAPI char *ecore_file_realpath(char *file);
|
||||
EAPI char *ecore_file_get_file(char *path);
|
||||
EAPI char *ecore_file_get_dir(char *path);
|
||||
|
||||
EAPI int ecore_file_can_exec(char *file);
|
||||
EAPI char *ecore_file_readlink(char *link);
|
||||
EAPI Evas_List *ecore_file_ls(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_CREATED,
|
||||
ECORE_FILE_EVENT_DELETED,
|
||||
ECORE_FILE_EVENT_CHANGED,
|
||||
ECORE_FILE_EVENT_EXISTS
|
||||
} Ecore_File_Event;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
#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);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,38 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir)/src/lib/ecore \
|
||||
-I$(top_builddir)/src/lib/ecore \
|
||||
@evas_cflags@
|
||||
|
||||
libecore_file_la_LDFLAGS = -version-info 1:0:0 \
|
||||
-L$(top_builddir)/src/lib/ecore/.libs
|
||||
|
||||
if BUILD_ECORE_FILE
|
||||
|
||||
lib_LTLIBRARIES = libecore_file.la
|
||||
include_HEADERS = Ecore_File.h
|
||||
|
||||
libecore_file_la_SOURCES = \
|
||||
ecore_file.c \
|
||||
ecore_file_private.h \
|
||||
ecore_file_monitor_fam.c \
|
||||
ecore_file_monitor_inotify.c \
|
||||
ecore_file_monitor_dnotify.c \
|
||||
ecore_file_monitor_poll.c
|
||||
|
||||
libecore_file_la_LIBADD = \
|
||||
$(top_builddir)/src/lib/ecore/libecore.la \
|
||||
@fam_libs@ \
|
||||
@evas_libs@
|
||||
|
||||
endif
|
||||
|
||||
EXTRA_DIST = \
|
||||
ecore_file.c \
|
||||
ecore_file_private.h \
|
||||
ecore_file_monitor_fam.c \
|
||||
ecore_file_monitor_inotify.c \
|
||||
ecore_file_monitor_dnotify.c \
|
||||
ecore_file_monitor_poll.c
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
|
||||
*/
|
||||
#include "Ecore_File.h"
|
||||
#include "ecore_file_private.h"
|
||||
|
||||
/* externally accessible functions */
|
||||
int
|
||||
ecore_file_init()
|
||||
{
|
||||
if (!ecore_file_monitor_init())
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ecore_file_shutdown()
|
||||
{
|
||||
if (!ecore_file_monitor_shutdown())
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
time_t
|
||||
ecore_file_mod_time(char *file)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(file, &st) < 0) return 0;
|
||||
return st.st_mtime;
|
||||
}
|
||||
|
||||
int
|
||||
ecore_file_exists(char *file)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(file, &st) < 0) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ecore_file_is_dir(char *file)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(file, &st) < 0) return 0;
|
||||
if (S_ISDIR(st.st_mode)) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static mode_t default_mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
|
||||
|
||||
int
|
||||
ecore_file_mkdir(char *dir)
|
||||
{
|
||||
if (mkdir(dir, default_mode) < 0) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ecore_file_mkpath(char *path)
|
||||
{
|
||||
char ss[PATH_MAX];
|
||||
int i, ii;
|
||||
|
||||
ss[0] = 0;
|
||||
i = 0;
|
||||
ii = 0;
|
||||
while (path[i])
|
||||
{
|
||||
if (ii == sizeof(ss) - 1) return 0;
|
||||
ss[ii++] = path[i];
|
||||
ss[ii] = 0;
|
||||
if (path[i] == '/')
|
||||
{
|
||||
if (!ecore_file_is_dir(ss)) ecore_file_mkdir(ss);
|
||||
else if (!ecore_file_is_dir(ss)) return 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (!ecore_file_is_dir(ss)) ecore_file_mkdir(ss);
|
||||
else if (!ecore_file_is_dir(ss)) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ecore_file_cp(char *src, char *dst)
|
||||
{
|
||||
FILE *f1, *f2;
|
||||
char buf[16384];
|
||||
size_t num;
|
||||
|
||||
f1 = fopen(src, "rb");
|
||||
if (!f1) return 0;
|
||||
f2 = fopen(dst, "wb");
|
||||
if (!f2)
|
||||
{
|
||||
fclose(f1);
|
||||
return 0;
|
||||
}
|
||||
while ((num = fread(buf, 1, 16384, f1)) > 0) fwrite(buf, 1, num, f2);
|
||||
fclose(f1);
|
||||
fclose(f2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *
|
||||
ecore_file_realpath(char *file)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
struct stat st;
|
||||
|
||||
if (!realpath(file, buf) || stat(buf, &st)) return strdup("");
|
||||
return strdup(buf);
|
||||
}
|
||||
|
||||
char *
|
||||
ecore_file_get_file(char *path)
|
||||
{
|
||||
char *result = NULL;
|
||||
|
||||
if (!path) return NULL;
|
||||
if ((result = strrchr(path, '/'))) result++;
|
||||
else result = path;
|
||||
return result;
|
||||
}
|
||||
|
||||
char *
|
||||
ecore_file_get_dir(char *file)
|
||||
{
|
||||
char *p;
|
||||
char buf[PATH_MAX];
|
||||
|
||||
strncpy(buf, file, PATH_MAX);
|
||||
p = strrchr(buf, '/');
|
||||
if (!p)
|
||||
{
|
||||
return strdup(file);
|
||||
}
|
||||
*p = 0;
|
||||
return strdup(buf);
|
||||
}
|
||||
|
||||
int
|
||||
ecore_file_can_exec(char *file)
|
||||
{
|
||||
static int have_uid = 0;
|
||||
static uid_t uid = -1;
|
||||
static gid_t gid = -1;
|
||||
struct stat st;
|
||||
int ok;
|
||||
|
||||
if (!file) return 0;
|
||||
if (stat(file, &st) < 0) return 0;
|
||||
|
||||
ok = 0;
|
||||
if (!have_uid) uid = getuid();
|
||||
if (!have_uid) gid = getgid();
|
||||
have_uid = 1;
|
||||
if (st.st_uid == uid)
|
||||
{
|
||||
if (st.st_mode & S_IXUSR) ok = 1;
|
||||
}
|
||||
else if (st.st_gid == gid)
|
||||
{
|
||||
if (st.st_mode & S_IXGRP) ok = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (st.st_mode & S_IXOTH) ok = 1;
|
||||
}
|
||||
return(ok);
|
||||
}
|
||||
|
||||
char *
|
||||
ecore_file_readlink(char *link)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
int count;
|
||||
|
||||
if ((count = readlink(link, buf, sizeof(buf))) < 0) return NULL;
|
||||
buf[count] = 0;
|
||||
return strdup(buf);
|
||||
}
|
||||
|
||||
Evas_List *
|
||||
ecore_file_ls(char *dir)
|
||||
{
|
||||
DIR *dirp;
|
||||
struct dirent *dp;
|
||||
Evas_List *list;
|
||||
|
||||
dirp = opendir(dir);
|
||||
if (!dirp) return NULL;
|
||||
list = NULL;
|
||||
while ((dp = readdir(dirp)))
|
||||
{
|
||||
if ((strcmp(dp->d_name, ".")) && (strcmp(dp->d_name, "..")))
|
||||
{
|
||||
Evas_List *l;
|
||||
char *f;
|
||||
|
||||
/* insertion sort */
|
||||
for (l = list; l; l = l->next)
|
||||
{
|
||||
if (strcmp(l->data, dp->d_name) > 0)
|
||||
{
|
||||
f = strdup(dp->d_name);
|
||||
list = evas_list_prepend_relative(list, f, l->data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* nowhwre to go? just append it */
|
||||
f = strdup(dp->d_name);
|
||||
if (!l)
|
||||
list = evas_list_append(list, f);
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
|
||||
return list;
|
||||
}
|
|
@ -0,0 +1,323 @@
|
|||
/*
|
||||
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
|
||||
*/
|
||||
#include "ecore_file_private.h"
|
||||
#include "Ecore_File.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
|
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
|
||||
*/
|
||||
#include "ecore_file_private.h"
|
||||
#include "Ecore_File.h"
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - When several subdirectories are created really fast, the code
|
||||
* doesn't keep up! Putting in a random printf() makes it work..
|
||||
* - Same for deletion of files in deleted directories!
|
||||
*/
|
||||
|
||||
#ifdef HAVE_FAM
|
||||
|
||||
#include <fam.h>
|
||||
|
||||
typedef struct _Ecore_File_Monitor_Fam Ecore_File_Monitor_Fam;
|
||||
typedef struct _Ecore_File Ecore_File;
|
||||
|
||||
struct _Ecore_File_Monitor_Fam
|
||||
{
|
||||
Ecore_File_Monitor monitor;
|
||||
FAMRequest *request;
|
||||
Evas_List *files;
|
||||
};
|
||||
|
||||
struct _Ecore_File
|
||||
{
|
||||
char *name;
|
||||
Ecore_File_Type type;
|
||||
};
|
||||
|
||||
#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);
|
||||
|
||||
int
|
||||
ecore_file_monitor_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);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ecore_file_monitor_shutdown(void)
|
||||
{
|
||||
Evas_List *l;
|
||||
for (l = _monitors; l; l = l->next)
|
||||
ecore_file_monitor_del(ECORE_FILE_MONITOR(l->data));
|
||||
evas_list_free(_monitors);
|
||||
if (_fdh) ecore_main_fd_handler_del(_fdh);
|
||||
if (_fc)
|
||||
{
|
||||
FAMClose(_fc);
|
||||
free(_fc);
|
||||
}
|
||||
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_Fam *emf;
|
||||
int len;
|
||||
|
||||
emf = calloc(1, sizeof(Ecore_File_Monitor_Fam));
|
||||
em = ECORE_FILE_MONITOR(emf);
|
||||
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';
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
ecore_file_monitor_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)
|
||||
{
|
||||
Ecore_File *f;
|
||||
|
||||
f = l->data;
|
||||
free(f->name);
|
||||
free(f);
|
||||
}
|
||||
evas_list_free(emf->files);
|
||||
|
||||
_monitors = evas_list_remove(_monitors, em);
|
||||
|
||||
FAMCancelMonitor(_fc, emf->request);
|
||||
free(emf->request);
|
||||
free(em->path);
|
||||
free(em);
|
||||
}
|
||||
|
||||
static int
|
||||
_ecore_file_monitor_handler(void *data, Ecore_Fd_Handler *fdh)
|
||||
{
|
||||
int pending, i;
|
||||
|
||||
while ((pending = FAMPending(_fc)))
|
||||
{
|
||||
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];
|
||||
|
||||
FAMNextEvent(_fc, &fe);
|
||||
event = _ecore_file_monitor_event_get(fe.code);
|
||||
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)
|
||||
{
|
||||
Ecore_File *f;
|
||||
|
||||
f = _ecore_file_monitor_file_find(em, fe.filename);
|
||||
if (f)
|
||||
{
|
||||
emf->files = evas_list_remove(emf->files, f);
|
||||
em->func(em->data, em, f->type, event, buf);
|
||||
free(f->name);
|
||||
free(f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Ecore_File *f;
|
||||
|
||||
f = calloc(1, sizeof(Ecore_File));
|
||||
if (!f) continue;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static Ecore_File *
|
||||
_ecore_file_monitor_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)
|
||||
{
|
||||
Ecore_File *f;
|
||||
f = l->data;
|
||||
if (!strcmp(f->name, name))
|
||||
return f;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Ecore_File_Event
|
||||
_ecore_file_monitor_event_get(FAMCodes code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case FAMCreated:
|
||||
return ECORE_FILE_EVENT_CREATED;
|
||||
case FAMDeleted:
|
||||
return ECORE_FILE_EVENT_DELETED;
|
||||
case FAMChanged:
|
||||
return ECORE_FILE_EVENT_CHANGED;
|
||||
case FAMExists:
|
||||
return ECORE_FILE_EVENT_EXISTS;
|
||||
case FAMStartExecuting:
|
||||
case FAMStopExecuting:
|
||||
case FAMMoved:
|
||||
case FAMAcknowledge:
|
||||
case FAMEndExist:
|
||||
return ECORE_FILE_EVENT_NONE;
|
||||
}
|
||||
return ECORE_FILE_EVENT_NONE;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,317 @@
|
|||
/*
|
||||
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
|
||||
*/
|
||||
#include "ecore_file_private.h"
|
||||
#include "Ecore_File.h"
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - Everything!
|
||||
*/
|
||||
|
||||
#ifdef HAVE_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))
|
||||
|
||||
struct _Ecore_File_Monitor_Inotify
|
||||
{
|
||||
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_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);
|
||||
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_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);
|
||||
|
||||
_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_Inotify *emd;
|
||||
|
||||
em = monitor->data;
|
||||
emd = ECORE_FILE_MONITOR_INOTIFY(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_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)
|
||||
{
|
||||
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_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];
|
||||
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_Inotify *emd;
|
||||
Evas_List *l;
|
||||
|
||||
emd = ECORE_FILE_MONITOR_INOTIFY(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
|
|
@ -0,0 +1,397 @@
|
|||
/*
|
||||
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
|
||||
*/
|
||||
#include "ecore_file_private.h"
|
||||
#include "Ecore_File.h"
|
||||
|
||||
#ifdef HAVE_POLL
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - Implement recursive as an option!
|
||||
* - Keep whole path or just name of file? (Memory or CPU...)
|
||||
* - Remove requests without files?
|
||||
*/
|
||||
|
||||
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;
|
||||
Evas_List *files;
|
||||
unsigned char deleted;
|
||||
};
|
||||
|
||||
struct _Ecore_File
|
||||
{
|
||||
char *name;
|
||||
int mtime;
|
||||
Ecore_File_Type type;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
int
|
||||
ecore_file_monitor_init(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ecore_file_monitor_shutdown(void)
|
||||
{
|
||||
Evas_List *l;
|
||||
for (l = _monitors; l;)
|
||||
{
|
||||
Ecore_File_Monitor *em;
|
||||
|
||||
em = l->data;
|
||||
l = l->next;
|
||||
ecore_file_monitor_del(em);
|
||||
}
|
||||
evas_list_free(_monitors);
|
||||
if (_timer)
|
||||
{
|
||||
ecore_timer_del(_timer);
|
||||
_timer = NULL;
|
||||
}
|
||||
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_Poll *emf;
|
||||
int len;
|
||||
|
||||
if (!path) return NULL;
|
||||
if (!func) return NULL;
|
||||
|
||||
emf = calloc(1, sizeof(Ecore_File_Monitor_Poll));
|
||||
em = ECORE_FILE_MONITOR(emf);
|
||||
if (!em) return NULL;
|
||||
|
||||
if (!_timer)
|
||||
_timer = ecore_timer_add(1.0, _ecore_file_monitor_handler, NULL);
|
||||
|
||||
em->path = strdup(path);
|
||||
len = strlen(em->path);
|
||||
if (em->path[len - 1] == '/')
|
||||
em->path[len - 1] = '\0';
|
||||
|
||||
em->func = func;
|
||||
em->data = data;
|
||||
|
||||
emf->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;
|
||||
|
||||
#if 0
|
||||
em->func(em->data, em, em->type, ECORE_FILE_EVENT_EXISTS, em->path);
|
||||
#endif
|
||||
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);
|
||||
emf->files = evas_list_append(emf->files, f);
|
||||
}
|
||||
evas_list_free(files);
|
||||
}
|
||||
else
|
||||
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);
|
||||
}
|
||||
|
||||
_monitors = evas_list_append(_monitors, em);
|
||||
|
||||
return em;
|
||||
}
|
||||
|
||||
void
|
||||
ecore_file_monitor_del(Ecore_File_Monitor *em)
|
||||
{
|
||||
Ecore_File_Monitor_Poll *emf;
|
||||
Evas_List *l;
|
||||
|
||||
emf = ECORE_FILE_MONITOR_POLL(em);
|
||||
if (_lock)
|
||||
{
|
||||
emf->deleted = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remove files */
|
||||
for (l = emf->files; l; l = l->next)
|
||||
{
|
||||
Ecore_File *f;
|
||||
f = l->data;
|
||||
free(f->name);
|
||||
free(f);
|
||||
}
|
||||
evas_list_free(emf->files);
|
||||
|
||||
_monitors = evas_list_remove(_monitors, em);
|
||||
free(em->path);
|
||||
free(em);
|
||||
|
||||
if ((!_monitors) && (_timer))
|
||||
{
|
||||
ecore_timer_del(_timer);
|
||||
_timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
_ecore_file_monitor_handler(void *data)
|
||||
{
|
||||
Evas_List *monitor;
|
||||
|
||||
_lock = 1;
|
||||
for (monitor = _monitors; monitor;)
|
||||
{
|
||||
Ecore_File_Monitor *em;
|
||||
|
||||
em = monitor->data;
|
||||
monitor = monitor->next;
|
||||
_ecore_file_monitor_check(em);
|
||||
}
|
||||
_lock = 0;
|
||||
for (monitor = _monitors; monitor;)
|
||||
{
|
||||
Ecore_File_Monitor *em;
|
||||
Ecore_File_Monitor_Poll *emf;
|
||||
|
||||
em = monitor->data;
|
||||
emf = ECORE_FILE_MONITOR_POLL(em);
|
||||
monitor = monitor->next;
|
||||
if (emf->deleted)
|
||||
ecore_file_monitor_del(em);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_file_monitor_check(Ecore_File_Monitor *em)
|
||||
{
|
||||
Ecore_File_Monitor_Poll *emf;
|
||||
int mtime;
|
||||
|
||||
emf = ECORE_FILE_MONITOR_POLL(em);
|
||||
mtime = ecore_file_mod_time(em->path);
|
||||
switch (em->type)
|
||||
{
|
||||
case ECORE_FILE_TYPE_FILE:
|
||||
if (mtime < emf->mtime)
|
||||
{
|
||||
em->func(em->data, em, em->type, ECORE_FILE_EVENT_DELETED, em->path);
|
||||
em->type = ECORE_FILE_TYPE_NONE;
|
||||
}
|
||||
else if (mtime > emf->mtime)
|
||||
em->func(em->data, em, em->type, ECORE_FILE_EVENT_CHANGED, em->path);
|
||||
break;
|
||||
case ECORE_FILE_TYPE_DIRECTORY:
|
||||
if (mtime < emf->mtime)
|
||||
{
|
||||
/* Deleted */
|
||||
Evas_List *l;
|
||||
|
||||
/* Notify all files deleted */
|
||||
for (l = emf->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);
|
||||
}
|
||||
emf->files = evas_list_free(emf->files);
|
||||
#if 0
|
||||
em->func(em->data, em, em->type, ECORE_FILE_EVENT_DELETED, em->path);
|
||||
#endif
|
||||
em->type = ECORE_FILE_TYPE_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Evas_List *l;
|
||||
|
||||
/* Check for changed files */
|
||||
for (l = emf->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);
|
||||
emf->files = evas_list_remove(emf->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;
|
||||
}
|
||||
|
||||
/* Check for new files */
|
||||
if (emf->mtime < mtime)
|
||||
{
|
||||
Evas_List *files;
|
||||
|
||||
/* Files have been added or removed */
|
||||
#if 0
|
||||
em->func(em->data, em, em->type, ECORE_FILE_EVENT_CHANGED, em->path);
|
||||
#endif
|
||||
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);
|
||||
emf->files = evas_list_append(emf->files, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ECORE_FILE_TYPE_NONE:
|
||||
if (mtime > emf->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);
|
||||
emf->files = evas_list_append(emf->files, f);
|
||||
}
|
||||
evas_list_free(files);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
emf->mtime = mtime;
|
||||
}
|
||||
|
||||
static int
|
||||
_ecore_file_monitor_checking(Ecore_File_Monitor *em, char *name)
|
||||
{
|
||||
Evas_List *l;
|
||||
Ecore_File_Monitor_Poll *emf;
|
||||
|
||||
emf = ECORE_FILE_MONITOR_POLL(em);
|
||||
for (l = emf->files; l; l = l->next)
|
||||
{
|
||||
Ecore_File *f;
|
||||
|
||||
f = l->data;
|
||||
if (!strcmp(f->name, name))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,25 @@
|
|||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdlib.h>
|
||||
#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"
|
||||
|
||||
int ecore_file_monitor_init(void);
|
||||
int ecore_file_monitor_shutdown(void);
|
||||
|
||||
/*
|
||||
#define HAVE_POLL
|
||||
#define HAVE_FAM
|
||||
#define HAVE_DNOTIFY
|
||||
#define HAVE_INOTIFY
|
||||
*/
|
|
@ -0,0 +1,4 @@
|
|||
void
|
||||
_ecore_file_add_slash(char *path)
|
||||
{
|
||||
}
|
Loading…
Reference in New Issue