forked from enlightenment/efl
Add Windows directory monitoring to ecore_file. It was tough.
A lot of thanks to Lars Munch for his great help SVN revision: 43617
This commit is contained in:
parent
9f839063c8
commit
a2f8b6a526
|
@ -86,6 +86,7 @@ want_cipher="no"
|
|||
want_signature="no"
|
||||
want_poll="yes"
|
||||
want_inotify="no"
|
||||
want_notify_win32="no"
|
||||
want_tslib="no"
|
||||
want_glib="no"
|
||||
|
||||
|
@ -136,6 +137,7 @@ case "$host_os" in
|
|||
want_ecore_evas_software_16_wince="yes"
|
||||
;;
|
||||
mingw*)
|
||||
want_notify_win32="yes"
|
||||
want_curl="yes"
|
||||
want_glib="auto"
|
||||
want_ecore_imf="yes"
|
||||
|
@ -837,9 +839,11 @@ ECORE_CHECK_MODULE([File], [${want_ecore_file}])
|
|||
|
||||
have_poll="no"
|
||||
have_inotify="no"
|
||||
have_notify_win32="no"
|
||||
if test "x${have_ecore_file}" = "xyes" ; then
|
||||
ECORE_CHECK_POLL([${want_poll}], [have_poll="yes"], [have_poll="no"])
|
||||
ECORE_CHECK_INOTIFY([${want_inotify}], [have_inotify="yes"], [have_inotify="no"])
|
||||
ECORE_CHECK_NOTIFY_WIN32([${want_notify_win32}], [have_notify_win32="yes"], [have_notify_win32="no"])
|
||||
|
||||
if test "x${have_ecore_con}" = "xyes" ; then
|
||||
requirements_ecore_file="ecore-con ${requirements_ecore_file}"
|
||||
|
@ -1205,6 +1209,7 @@ fi
|
|||
echo " Ecore_File...................: $have_ecore_file"
|
||||
if test "x$have_ecore_file" = "xyes" ; then
|
||||
echo " Inotify....................: $have_inotify"
|
||||
echo " Windows notification.......: $have_notify_win32"
|
||||
echo " Poll.......................: $have_poll"
|
||||
echo " CURL.......................: $have_curl"
|
||||
fi
|
||||
|
|
|
@ -84,6 +84,37 @@ else
|
|||
m4_default([$3], [:])
|
||||
fi
|
||||
])
|
||||
|
||||
dnl use: ECORE_CHECK_NOTIFY_WIN32(default-enabled[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
|
||||
AC_DEFUN([ECORE_CHECK_NOTIFY_WIN32],
|
||||
[
|
||||
_ecore_want_notify_win32=$1
|
||||
_ecore_have_notify_win32="no"
|
||||
|
||||
AC_ARG_ENABLE(notify-win32,
|
||||
[AC_HELP_STRING([--disable-notify-win32], [disable Windows notification in the ecore_file module])],
|
||||
[
|
||||
if test "x${enableval}" = "xyes" ; then
|
||||
_ecore_want_notify_win32="yes"
|
||||
else
|
||||
_ecore_want_notify_win32="no"
|
||||
fi
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING(whether Windows notification is to be used for filemonitoring)
|
||||
AC_MSG_RESULT(${_ecore_want_notify_win32})
|
||||
|
||||
if test "x${_ecore_want_notify_win32}" = "xyes" ; then
|
||||
AC_DEFINE([HAVE_NOTIFY_WIN32], [1], [ File monitoring with Windows notification ])
|
||||
_ecore_have_notify_win32="yes"
|
||||
fi
|
||||
|
||||
if test "x${_ecore_have_notify_win32}" = "xyes" ; then
|
||||
m4_default([$2], [:])
|
||||
else
|
||||
m4_default([$3], [:])
|
||||
fi
|
||||
])
|
||||
|
||||
dnl use: ECORE_CHECK_CURL(default-enabled[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
|
||||
AC_DEFUN([ECORE_CHECK_CURL],
|
||||
|
|
|
@ -25,6 +25,7 @@ libecore_file_la_SOURCES = \
|
|||
ecore_file.c \
|
||||
ecore_file_monitor.c \
|
||||
ecore_file_monitor_inotify.c \
|
||||
ecore_file_monitor_win32.c \
|
||||
ecore_file_monitor_poll.c \
|
||||
ecore_file_path.c \
|
||||
ecore_file_download.c
|
||||
|
|
|
@ -13,6 +13,9 @@ typedef enum {
|
|||
#ifdef HAVE_INOTIFY
|
||||
ECORE_FILE_MONITOR_TYPE_INOTIFY,
|
||||
#endif
|
||||
#ifdef HAVE_NOTIFY_WIN32
|
||||
ECORE_FILE_MONITOR_TYPE_NOTIFY_WIN32,
|
||||
#endif
|
||||
#ifdef HAVE_POLL
|
||||
ECORE_FILE_MONITOR_TYPE_POLL
|
||||
#endif
|
||||
|
@ -28,6 +31,11 @@ ecore_file_monitor_init(void)
|
|||
if (ecore_file_monitor_inotify_init())
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef HAVE_NOTIFY_WIN32
|
||||
monitor_type = ECORE_FILE_MONITOR_TYPE_NOTIFY_WIN32;
|
||||
if (ecore_file_monitor_win32_init())
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef HAVE_POLL
|
||||
monitor_type = ECORE_FILE_MONITOR_TYPE_POLL;
|
||||
if (ecore_file_monitor_poll_init())
|
||||
|
@ -49,6 +57,11 @@ ecore_file_monitor_shutdown(void)
|
|||
ecore_file_monitor_inotify_shutdown();
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_NOTIFY_WIN32
|
||||
case ECORE_FILE_MONITOR_TYPE_NOTIFY_WIN32:
|
||||
ecore_file_monitor_win32_shutdown();
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_POLL
|
||||
case ECORE_FILE_MONITOR_TYPE_POLL:
|
||||
ecore_file_monitor_poll_shutdown();
|
||||
|
@ -66,10 +79,11 @@ ecore_file_monitor_shutdown(void)
|
|||
*/
|
||||
EAPI 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)
|
||||
void (*func) (void *data,
|
||||
Ecore_File_Monitor *em,
|
||||
Ecore_File_Event event,
|
||||
const char *path),
|
||||
void *data)
|
||||
{
|
||||
switch (monitor_type)
|
||||
{
|
||||
|
@ -79,6 +93,10 @@ ecore_file_monitor_add(const char *path,
|
|||
case ECORE_FILE_MONITOR_TYPE_INOTIFY:
|
||||
return ecore_file_monitor_inotify_add(path, func, data);
|
||||
#endif
|
||||
#ifdef HAVE_NOTIFY_WIN32
|
||||
case ECORE_FILE_MONITOR_TYPE_NOTIFY_WIN32:
|
||||
return ecore_file_monitor_win32_add(path, func, data);
|
||||
#endif
|
||||
#ifdef HAVE_POLL
|
||||
case ECORE_FILE_MONITOR_TYPE_POLL:
|
||||
return ecore_file_monitor_poll_add(path, func, data);
|
||||
|
@ -103,6 +121,11 @@ ecore_file_monitor_del(Ecore_File_Monitor *em)
|
|||
ecore_file_monitor_inotify_del(em);
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_NOTIFY_WIN32
|
||||
case ECORE_FILE_MONITOR_TYPE_NOTIFY_WIN32:
|
||||
ecore_file_monitor_win32_del(em);
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_POLL
|
||||
case ECORE_FILE_MONITOR_TYPE_POLL:
|
||||
ecore_file_monitor_poll_del(em);
|
||||
|
|
|
@ -0,0 +1,310 @@
|
|||
/*
|
||||
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NOTIFY_WIN32
|
||||
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# undef WIN32_LEAN_AND_MEAN
|
||||
# include <process.h>
|
||||
|
||||
# include "ecore_file_private.h"
|
||||
|
||||
|
||||
typedef struct _Ecore_File_Monitor_Win32 Ecore_File_Monitor_Win32;
|
||||
typedef struct _Ecore_File_Monitor_Win32_Data Ecore_File_Monitor_Win32_Data;
|
||||
|
||||
/* 4096 = 256 * sizeof(FILE_NOTIFY_INFORMATION) */
|
||||
# define ECORE_FILE_MONITOR_WIN32_BUFFER_SIZE 4096
|
||||
# define ECORE_FILE_MONITOR_WIN32(x) ((Ecore_File_Monitor_Win32 *)(x))
|
||||
|
||||
struct _Ecore_File_Monitor_Win32_Data
|
||||
{
|
||||
char buffer[ECORE_FILE_MONITOR_WIN32_BUFFER_SIZE];
|
||||
OVERLAPPED overlapped;
|
||||
HANDLE handle;
|
||||
HANDLE event;
|
||||
Ecore_File_Monitor *monitor;
|
||||
Ecore_Win32_Handler *h;
|
||||
DWORD buf_length;
|
||||
int is_dir;
|
||||
};
|
||||
|
||||
struct _Ecore_File_Monitor_Win32
|
||||
{
|
||||
Ecore_File_Monitor monitor;
|
||||
Ecore_File_Monitor_Win32_Data *file;
|
||||
Ecore_File_Monitor_Win32_Data *dir;
|
||||
};
|
||||
|
||||
static Ecore_File_Monitor *_monitors = NULL;
|
||||
|
||||
static int _ecore_file_monitor_win32_cb(void *data, Ecore_Win32_Handler *wh);
|
||||
|
||||
|
||||
static Ecore_File_Monitor_Win32_Data *
|
||||
_ecore_file_monitor_win32_data_new(Ecore_File_Monitor *monitor, int type)
|
||||
{
|
||||
Ecore_File_Monitor_Win32_Data *md;
|
||||
DWORD filter;
|
||||
|
||||
md = (Ecore_File_Monitor_Win32_Data *)calloc(1, sizeof(Ecore_File_Monitor_Win32_Data));
|
||||
if (!md) return NULL;
|
||||
|
||||
md->handle = CreateFile(monitor->path,
|
||||
FILE_LIST_DIRECTORY,
|
||||
FILE_SHARE_READ |
|
||||
FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS |
|
||||
FILE_FLAG_OVERLAPPED,
|
||||
NULL);
|
||||
if (md->handle == INVALID_HANDLE_VALUE)
|
||||
goto free_md;
|
||||
|
||||
md->event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (!md->event)
|
||||
goto close_handle;
|
||||
|
||||
ZeroMemory (&md->overlapped, sizeof(md->overlapped));
|
||||
md->overlapped.hEvent = md->event;
|
||||
|
||||
filter = (type == 0) ? FILE_NOTIFY_CHANGE_FILE_NAME : FILE_NOTIFY_CHANGE_DIR_NAME;
|
||||
filter |=
|
||||
FILE_NOTIFY_CHANGE_ATTRIBUTES |
|
||||
FILE_NOTIFY_CHANGE_SIZE |
|
||||
FILE_NOTIFY_CHANGE_LAST_WRITE |
|
||||
FILE_NOTIFY_CHANGE_LAST_ACCESS |
|
||||
FILE_NOTIFY_CHANGE_CREATION |
|
||||
FILE_NOTIFY_CHANGE_SECURITY;
|
||||
|
||||
if (!ReadDirectoryChangesW(md->handle,
|
||||
md->buffer,
|
||||
ECORE_FILE_MONITOR_WIN32_BUFFER_SIZE,
|
||||
FALSE,
|
||||
filter,
|
||||
&md->buf_length,
|
||||
&md->overlapped,
|
||||
NULL))
|
||||
goto close_event;
|
||||
|
||||
md->h = ecore_main_win32_handler_add(md->event,
|
||||
_ecore_file_monitor_win32_cb,
|
||||
md);
|
||||
if (!md->h)
|
||||
goto close_event;
|
||||
|
||||
md->monitor = monitor;
|
||||
md->is_dir = type;
|
||||
|
||||
return md;
|
||||
|
||||
close_event:
|
||||
CloseHandle(md->event);
|
||||
close_handle:
|
||||
CloseHandle(md->handle);
|
||||
free_md:
|
||||
free(md);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_file_monitor_win32_data_free(Ecore_File_Monitor_Win32_Data *md)
|
||||
{
|
||||
if (!md) return;
|
||||
|
||||
CloseHandle(md->event);
|
||||
CloseHandle (md->handle);
|
||||
free (md);
|
||||
}
|
||||
|
||||
static int
|
||||
_ecore_file_monitor_win32_cb(void *data, Ecore_Win32_Handler *wh)
|
||||
{
|
||||
char filename[PATH_MAX];
|
||||
PFILE_NOTIFY_INFORMATION fni;
|
||||
Ecore_File_Monitor_Win32_Data *md;
|
||||
wchar_t *wname;
|
||||
char *name;
|
||||
DWORD filter;
|
||||
DWORD offset;
|
||||
DWORD buf_length;
|
||||
Ecore_File_Event event = ECORE_FILE_EVENT_NONE;
|
||||
|
||||
md = (Ecore_File_Monitor_Win32_Data *)data;
|
||||
|
||||
if (!GetOverlappedResult (md->handle, &md->overlapped, &buf_length, TRUE))
|
||||
return 1;
|
||||
|
||||
fni = (PFILE_NOTIFY_INFORMATION)md->buffer;
|
||||
do {
|
||||
if (!fni)
|
||||
break;
|
||||
offset = fni->NextEntryOffset;
|
||||
|
||||
wname = (wchar_t *)malloc(sizeof(wchar_t) * (fni->FileNameLength + 1));
|
||||
if (!wname)
|
||||
return 0;
|
||||
|
||||
memcpy(wname, fni->FileName, fni->FileNameLength);
|
||||
wname[fni->FileNameLength]='\0';
|
||||
name = evil_wchar_to_char(wname);
|
||||
free(wname);
|
||||
if (!name)
|
||||
return 0;
|
||||
|
||||
_snprintf(filename, PATH_MAX, "%s\\%s", md->monitor->path, name);
|
||||
free(name);
|
||||
|
||||
switch (fni->Action)
|
||||
{
|
||||
case FILE_ACTION_ADDED:
|
||||
if (md->is_dir)
|
||||
event = ECORE_FILE_EVENT_CREATED_DIRECTORY;
|
||||
else
|
||||
event = ECORE_FILE_EVENT_CREATED_FILE;
|
||||
break;
|
||||
case FILE_ACTION_REMOVED:
|
||||
if (md->is_dir)
|
||||
event = ECORE_FILE_EVENT_DELETED_DIRECTORY;
|
||||
else
|
||||
event = ECORE_FILE_EVENT_DELETED_FILE;
|
||||
break;
|
||||
case FILE_ACTION_MODIFIED:
|
||||
if (!md->is_dir)
|
||||
event = ECORE_FILE_EVENT_MODIFIED;
|
||||
break;
|
||||
case FILE_ACTION_RENAMED_OLD_NAME:
|
||||
if (md->is_dir)
|
||||
event = ECORE_FILE_EVENT_DELETED_DIRECTORY;
|
||||
else
|
||||
event = ECORE_FILE_EVENT_DELETED_FILE;
|
||||
break;
|
||||
case FILE_ACTION_RENAMED_NEW_NAME:
|
||||
if (md->is_dir)
|
||||
event = ECORE_FILE_EVENT_CREATED_DIRECTORY;
|
||||
else
|
||||
event = ECORE_FILE_EVENT_CREATED_FILE;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown event\n");
|
||||
event = ECORE_FILE_EVENT_NONE;
|
||||
break;
|
||||
}
|
||||
if (event != ECORE_FILE_EVENT_NONE)
|
||||
md->monitor->func(md->monitor->data, md->monitor, event, filename);
|
||||
|
||||
fni = (PFILE_NOTIFY_INFORMATION)((LPBYTE)fni + offset);
|
||||
} while (offset);
|
||||
|
||||
filter = (md->is_dir == 0) ? FILE_NOTIFY_CHANGE_FILE_NAME : FILE_NOTIFY_CHANGE_DIR_NAME;
|
||||
filter |=
|
||||
FILE_NOTIFY_CHANGE_ATTRIBUTES |
|
||||
FILE_NOTIFY_CHANGE_SIZE |
|
||||
FILE_NOTIFY_CHANGE_LAST_WRITE |
|
||||
FILE_NOTIFY_CHANGE_LAST_ACCESS |
|
||||
FILE_NOTIFY_CHANGE_CREATION |
|
||||
FILE_NOTIFY_CHANGE_SECURITY;
|
||||
|
||||
ReadDirectoryChangesW(md->handle,
|
||||
md->buffer,
|
||||
ECORE_FILE_MONITOR_WIN32_BUFFER_SIZE,
|
||||
FALSE,
|
||||
filter,
|
||||
&md->buf_length,
|
||||
&md->overlapped,
|
||||
NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ecore_file_monitor_win32_init(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ecore_file_monitor_win32_shutdown(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
Ecore_File_Monitor *
|
||||
ecore_file_monitor_win32_add(const char *path,
|
||||
void (*func) (void *data, Ecore_File_Monitor *em,
|
||||
Ecore_File_Event event,
|
||||
const char *path),
|
||||
void *data)
|
||||
{
|
||||
Ecore_File_Monitor_Win32 *m;
|
||||
Ecore_File_Monitor *em;
|
||||
size_t len;
|
||||
|
||||
if (!path || (*path == '\0')) return NULL;
|
||||
if (!ecore_file_exists(path) || !ecore_file_is_dir(path))
|
||||
return NULL;
|
||||
if (!func) return NULL;
|
||||
|
||||
em = (Ecore_File_Monitor *)calloc(1, sizeof(Ecore_File_Monitor_Win32));
|
||||
if (!em) return NULL;
|
||||
|
||||
em->func = func;
|
||||
em->data = data;
|
||||
|
||||
em->path = strdup(path);
|
||||
if (!em->path)
|
||||
{
|
||||
free(em);
|
||||
return NULL;
|
||||
}
|
||||
len = strlen(em->path);
|
||||
if (em->path[len - 1] == '/' || em->path[len - 1] == '\\')
|
||||
em->path[len - 1] = '\0';
|
||||
|
||||
m = ECORE_FILE_MONITOR_WIN32(em);
|
||||
|
||||
m->file = _ecore_file_monitor_win32_data_new(em, 0);
|
||||
if (!m->file)
|
||||
{
|
||||
free(em->path);
|
||||
free(em);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m->dir = _ecore_file_monitor_win32_data_new(em, 1);
|
||||
if (!m->dir)
|
||||
{
|
||||
_ecore_file_monitor_win32_data_free(m->file);
|
||||
free(em->path);
|
||||
free(em);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_monitors = ECORE_FILE_MONITOR(eina_inlist_append(EINA_INLIST_GET(_monitors), EINA_INLIST_GET(em)));
|
||||
|
||||
return em;
|
||||
}
|
||||
|
||||
void
|
||||
ecore_file_monitor_win32_del(Ecore_File_Monitor *em)
|
||||
{
|
||||
Ecore_File_Monitor_Win32 *m;
|
||||
|
||||
if (!em)
|
||||
return;
|
||||
|
||||
m = ECORE_FILE_MONITOR_WIN32(em);
|
||||
_ecore_file_monitor_win32_data_free(m->dir);
|
||||
_ecore_file_monitor_win32_data_free(m->file);
|
||||
free(em->path);
|
||||
free(em);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -57,6 +57,18 @@ Ecore_File_Monitor *ecore_file_monitor_inotify_add(const char *path,
|
|||
void *data);
|
||||
void ecore_file_monitor_inotify_del(Ecore_File_Monitor *ecore_file_monitor);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NOTIFY_WIN32
|
||||
int ecore_file_monitor_win32_init(void);
|
||||
int ecore_file_monitor_win32_shutdown(void);
|
||||
Ecore_File_Monitor *ecore_file_monitor_win32_add(const char *path,
|
||||
void (*func) (void *data,
|
||||
Ecore_File_Monitor *ecore_file_monitor,
|
||||
Ecore_File_Event event,
|
||||
const char *path),
|
||||
void *data);
|
||||
void ecore_file_monitor_win32_del(Ecore_File_Monitor *ecore_file_monitor);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_POLL
|
||||
int ecore_file_monitor_poll_init(void);
|
||||
|
|
Loading…
Reference in New Issue