forked from enlightenment/efl
Eio: add file monitoring on Windows (might contain bugs, though)
SVN revision: 69867
This commit is contained in:
parent
516922d193
commit
e66849b1dc
|
@ -28,10 +28,209 @@
|
|||
* @cond LOCAL
|
||||
*/
|
||||
|
||||
typedef struct _Eio_Monitor_Win32_Watcher Eio_Monitor_Win32_Watcher;
|
||||
|
||||
/* 4096 = 256 * sizeof(FILE_NOTIFY_INFORMATION) */
|
||||
# define EIO_MONITOR_WIN32_BUFFER_SIZE 4096
|
||||
|
||||
struct _Eio_Monitor_Win32_Watcher
|
||||
{
|
||||
char buffer[EIO_MONITOR_WIN32_BUFFER_SIZE];
|
||||
OVERLAPPED overlapped;
|
||||
HANDLE handle;
|
||||
HANDLE event;
|
||||
Eio_Monitor *monitor;
|
||||
Ecore_Win32_Handler *h;
|
||||
DWORD buf_length;
|
||||
int is_dir;
|
||||
};
|
||||
|
||||
struct _Eio_Monitor_Backend
|
||||
{
|
||||
Eio_Monitor *parent;
|
||||
|
||||
Eio_Monitor_Win32_Watcher *file;
|
||||
Eio_Monitor_Win32_Watcher *dir;
|
||||
};
|
||||
|
||||
static Eina_Bool
|
||||
_eio_monitor_win32_cb(void *data, Ecore_Win32_Handler *wh __UNUSED__)
|
||||
{
|
||||
char filename[PATH_MAX];
|
||||
PFILE_NOTIFY_INFORMATION fni;
|
||||
Eio_Monitor_Win32_Watcher *w;
|
||||
wchar_t *wname;
|
||||
char *name;
|
||||
DWORD filter;
|
||||
DWORD offset;
|
||||
DWORD buf_length;
|
||||
int event = EIO_MONITOR_ERROR;
|
||||
|
||||
w = (Eio_Monitor_Win32_Watcher *)data;
|
||||
|
||||
if (!GetOverlappedResult(w->handle, &w->overlapped, &buf_length, TRUE))
|
||||
return ECORE_CALLBACK_RENEW;
|
||||
|
||||
fni = (PFILE_NOTIFY_INFORMATION)w->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 ECORE_CALLBACK_CANCEL;
|
||||
|
||||
_snprintf(filename, PATH_MAX, "%s\\%s", w->monitor->path, name);
|
||||
free(name);
|
||||
|
||||
switch (fni->Action)
|
||||
{
|
||||
case FILE_ACTION_ADDED:
|
||||
if (w->is_dir)
|
||||
event = EIO_MONITOR_DIRECTORY_CREATED;
|
||||
else
|
||||
event = EIO_MONITOR_FILE_CREATED;
|
||||
break;
|
||||
case FILE_ACTION_REMOVED:
|
||||
if (w->is_dir)
|
||||
event = EIO_MONITOR_DIRECTORY_DELETED;
|
||||
else
|
||||
event = EIO_MONITOR_FILE_DELETED;
|
||||
break;
|
||||
case FILE_ACTION_MODIFIED:
|
||||
if (!w->is_dir)
|
||||
event = EIO_MONITOR_FILE_MODIFIED;
|
||||
break;
|
||||
case FILE_ACTION_RENAMED_OLD_NAME:
|
||||
if (w->is_dir)
|
||||
event = EIO_MONITOR_DIRECTORY_DELETED;
|
||||
else
|
||||
event = EIO_MONITOR_FILE_DELETED;
|
||||
break;
|
||||
case FILE_ACTION_RENAMED_NEW_NAME:
|
||||
if (w->is_dir)
|
||||
event = EIO_MONITOR_DIRECTORY_CREATED;
|
||||
else
|
||||
event = EIO_MONITOR_FILE_CREATED;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown event\n");
|
||||
event = EIO_MONITOR_ERROR;
|
||||
break;
|
||||
}
|
||||
if (event != EIO_MONITOR_ERROR)
|
||||
_eio_monitor_send(w->monitor, filename, event);
|
||||
|
||||
fni = (PFILE_NOTIFY_INFORMATION)((LPBYTE)fni + offset);
|
||||
} while (offset);
|
||||
|
||||
filter = (w->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(w->handle,
|
||||
w->buffer,
|
||||
EIO_MONITOR_WIN32_BUFFER_SIZE,
|
||||
FALSE,
|
||||
filter,
|
||||
&w->buf_length,
|
||||
&w->overlapped,
|
||||
NULL);
|
||||
|
||||
return ECORE_CALLBACK_RENEW;
|
||||
}
|
||||
|
||||
static Eio_Monitor_Win32_Watcher *
|
||||
_eio_monitor_win32_watcher_new(Eio_Monitor *monitor, unsigned char is_dir)
|
||||
{
|
||||
Eio_Monitor_Win32_Watcher *w;
|
||||
DWORD filter;
|
||||
|
||||
w = (Eio_Monitor_Win32_Watcher *)calloc(1, sizeof(Eio_Monitor_Win32_Watcher));
|
||||
if (!w) return NULL;
|
||||
|
||||
w->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 (w->handle == INVALID_HANDLE_VALUE)
|
||||
goto free_w;
|
||||
|
||||
w->event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (!w->event)
|
||||
goto close_handle;
|
||||
|
||||
ZeroMemory (&w->overlapped, sizeof(w->overlapped));
|
||||
w->overlapped.hEvent = w->event;
|
||||
|
||||
filter = (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;
|
||||
|
||||
if (!ReadDirectoryChangesW(w->handle,
|
||||
w->buffer,
|
||||
EIO_MONITOR_WIN32_BUFFER_SIZE,
|
||||
FALSE,
|
||||
filter,
|
||||
&w->buf_length,
|
||||
&w->overlapped,
|
||||
NULL))
|
||||
goto close_event;
|
||||
|
||||
w->h = ecore_main_win32_handler_add(w->event,
|
||||
_eio_monitor_win32_cb,
|
||||
w);
|
||||
if (!w->h)
|
||||
goto close_event;
|
||||
|
||||
w->monitor = monitor;
|
||||
w->is_dir = is_dir;
|
||||
|
||||
return w;
|
||||
|
||||
close_event:
|
||||
CloseHandle(w->event);
|
||||
close_handle:
|
||||
CloseHandle(w->handle);
|
||||
free_w:
|
||||
free(w);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_eio_monitor_win32_watcher_free(Eio_Monitor_Win32_Watcher *w)
|
||||
{
|
||||
if (!w) return;
|
||||
|
||||
CloseHandle(w->event);
|
||||
CloseHandle (w->handle);
|
||||
free (w);
|
||||
}
|
||||
|
||||
/**
|
||||
* @endcond
|
||||
*/
|
||||
|
@ -46,7 +245,6 @@ struct _Eio_Monitor_Backend
|
|||
|
||||
void eio_monitor_backend_init(void)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
void eio_monitor_backend_shutdown(void)
|
||||
|
@ -55,10 +253,48 @@ void eio_monitor_backend_shutdown(void)
|
|||
|
||||
void eio_monitor_backend_add(Eio_Monitor *monitor)
|
||||
{
|
||||
Eio_Monitor_Backend *backend;
|
||||
|
||||
backend = calloc(1, sizeof (Eio_Monitor_Backend));
|
||||
if (!backend)
|
||||
{
|
||||
eio_monitor_fallback_add(monitor);
|
||||
return;
|
||||
}
|
||||
|
||||
backend->parent = monitor;
|
||||
backend->file = _eio_monitor_win32_watcher_new(monitor, 0);
|
||||
if (!backend->file)
|
||||
{
|
||||
free(backend);
|
||||
eio_monitor_fallback_add(monitor);
|
||||
return;
|
||||
}
|
||||
|
||||
backend->dir = _eio_monitor_win32_watcher_new(monitor, 1);
|
||||
if (!backend->dir)
|
||||
{
|
||||
_eio_monitor_win32_watcher_free(backend->file);
|
||||
free(backend);
|
||||
eio_monitor_fallback_add(monitor);
|
||||
return;
|
||||
}
|
||||
|
||||
monitor->backend = backend;
|
||||
}
|
||||
|
||||
void eio_monitor_backend_del(Eio_Monitor *monitor)
|
||||
{
|
||||
if (!monitor->backend)
|
||||
{
|
||||
eio_monitor_fallback_del(monitor);
|
||||
return ;
|
||||
}
|
||||
|
||||
_eio_monitor_win32_watcher_free(monitor->backend->file);
|
||||
_eio_monitor_win32_watcher_free(monitor->backend->dir);
|
||||
free(monitor->backend);
|
||||
monitor->backend = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue