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
|
* @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
|
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
|
* @endcond
|
||||||
*/
|
*/
|
||||||
|
@ -46,7 +245,6 @@ struct _Eio_Monitor_Backend
|
||||||
|
|
||||||
void eio_monitor_backend_init(void)
|
void eio_monitor_backend_init(void)
|
||||||
{
|
{
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void eio_monitor_backend_shutdown(void)
|
void eio_monitor_backend_shutdown(void)
|
||||||
|
@ -55,10 +253,48 @@ void eio_monitor_backend_shutdown(void)
|
||||||
|
|
||||||
void eio_monitor_backend_add(Eio_Monitor *monitor)
|
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)
|
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