From 367d77233bd1e466e154bc326f1c8ccdbda90c89 Mon Sep 17 00:00:00 2001 From: Tor Lillqvist Date: Wed, 12 Mar 2008 19:09:11 +0000 Subject: [PATCH] Expand gio/win32/Makefile. 2008-03-12 Tor Lillqvist * configure.in: Expand gio/win32/Makefile. 2008-03-12 Tor Lillqvist Bug 517419 - gio win32 directory monitor Implementation by Vlad Grecescu. * win32/Makefile.am * win32/gwin32directorymonitor.h * win32/gwin32directorymonitor.c: New files. * giomodule.c: Set up the GWin32DirectoryMonitor plumbing. * Makefile.am: Add the win32 subdirectory. svn path=/trunk/; revision=6698 --- ChangeLog | 4 + configure.in | 1 + gio/ChangeLog | 13 +++ gio/Makefile.am | 6 ++ gio/giomodule.c | 5 ++ gio/win32/Makefile.am | 21 +++++ gio/win32/gwin32directorymonitor.c | 163 +++++++++++++++++++++++++++++++++++++ gio/win32/gwin32directorymonitor.h | 62 ++++++++++++++ 8 files changed, 275 insertions(+) create mode 100644 gio/win32/Makefile.am create mode 100644 gio/win32/gwin32directorymonitor.c create mode 100644 gio/win32/gwin32directorymonitor.h diff --git a/ChangeLog b/ChangeLog index 56d3304..51afc4e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2008-03-12 Tor Lillqvist + + * configure.in: Expand gio/win32/Makefile. + 2008-03-12 Matthias Clasen * configure.in: Bump version to 2.17.0 diff --git a/configure.in b/configure.in index 2a6d676..b10ebb1 100644 --- a/configure.in +++ b/configure.in @@ -3235,6 +3235,7 @@ gio/Makefile gio/xdgmime/Makefile gio/inotify/Makefile gio/fam/Makefile +gio/win32/Makefile gio/tests/Makefile po/Makefile.in docs/Makefile diff --git a/gio/ChangeLog b/gio/ChangeLog index 04fbda5..aaf9d22 100644 --- a/gio/ChangeLog +++ b/gio/ChangeLog @@ -1,5 +1,18 @@ 2008-03-12 Tor Lillqvist + Bug 517419 - gio win32 directory monitor + Implementation by Vlad Grecescu. + + * win32/Makefile.am + * win32/gwin32directorymonitor.h + * win32/gwin32directorymonitor.c: New files. + + * giomodule.c: Set up the GWin32DirectoryMonitor plumbing. + + * Makefile.am: Add the win32 subdirectory. + +2008-03-12 Tor Lillqvist + * glocalfileinfo.h: Introduce a macro GLocalFileStat that is the normal struct stat on Unix but struct _stati64 on Windows to have access to 64-bit file size information. Use that instead of struct diff --git a/gio/Makefile.am b/gio/Makefile.am index 07f6af1..af58380 100644 --- a/gio/Makefile.am +++ b/gio/Makefile.am @@ -86,6 +86,12 @@ SUBDIRS += inotify platform_libadd += inotify/libinotify.la endif +if OS_WIN32 +SUBDIRS += win32 +platform_libadd += win32/libgiowin32.la +endif + + SUBDIRS += . if HAVE_FAM diff --git a/gio/giomodule.c b/gio/giomodule.c index fd1391b..4aa32c3 100644 --- a/gio/giomodule.c +++ b/gio/giomodule.c @@ -290,6 +290,8 @@ extern GType _g_inotify_file_monitor_get_type (void); extern GType _g_unix_volume_monitor_get_type (void); extern GType _g_local_vfs_get_type (void); +extern GType g_win32_directory_monitor_get_type (void); + void _g_io_modules_ensure_loaded (void) { @@ -330,6 +332,9 @@ _g_io_modules_ensure_loaded (void) _g_inotify_directory_monitor_get_type (); _g_inotify_file_monitor_get_type (); #endif +#ifdef G_OS_WIN32 + g_win32_directory_monitor_get_type (); +#endif #ifdef G_OS_UNIX _g_unix_volume_monitor_get_type (); #endif diff --git a/gio/win32/Makefile.am b/gio/win32/Makefile.am new file mode 100644 index 0000000..0b8b30a --- /dev/null +++ b/gio/win32/Makefile.am @@ -0,0 +1,21 @@ +include $(top_srcdir)/Makefile.decl + +NULL = + +noinst_LTLIBRARIES = libgiowin32.la + +libgiowin32_la_SOURCES = \ + gwin32directorymonitor.c \ + gwin32directorymonitor.h \ + $(NULL) + +libgiowin32_la_CFLAGS = \ + -DG_LOG_DOMAIN=\"GLib-GIO\" \ + -I$(top_srcdir) \ + -I$(top_srcdir)/glib \ + -I$(top_srcdir)/gmodule \ + -I$(top_srcdir)/gio \ + $(GLIB_DEBUG_FLAGS) \ + -DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\" \ + -DGIO_COMPILATION \ + -DG_DISABLE_DEPRECATED diff --git a/gio/win32/gwin32directorymonitor.c b/gio/win32/gwin32directorymonitor.c new file mode 100644 index 0000000..3db0f4a --- /dev/null +++ b/gio/win32/gwin32directorymonitor.c @@ -0,0 +1,163 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Vlad Grecescu + * + */ + +#include "config.h" +#include "gwin32directorymonitor.h" +#include "giomodule.h" +#include + +G_DEFINE_TYPE_WITH_CODE (GWin32DirectoryMonitor, g_win32_directory_monitor, G_TYPE_LOCAL_DIRECTORY_MONITOR, +g_io_extension_point_implement (G_LOCAL_DIRECTORY_MONITOR_EXTENSION_POINT_NAME, + g_define_type_id, + "readdirectorychanges", + 20)) + +struct _GWin32DirectoryMonitorPrivate { + OVERLAPPED overlapped; + DWORD buffer_allocated_bytes; + gchar* file_notify_buffer; + DWORD buffer_filled_bytes; + HANDLE hDirectory; + /** needed in the APC where we only have this private struct */ + GFileMonitor * self; +}; + +static void g_win32_directory_monitor_finalize (GObject* base); +static gboolean g_win32_directory_monitor_cancel (GFileMonitor* base); +static GObject * g_win32_directory_monitor_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties); + +static gboolean g_win32_directory_monitor_is_supported(void) { + return TRUE; +} + +static void g_win32_directory_monitor_finalize (GObject* base) { + GWin32DirectoryMonitor * self; + self = G_WIN32_DIRECTORY_MONITOR (base); + + g_free (self->priv->file_notify_buffer); + g_free (self->priv); + + if (G_OBJECT_CLASS (g_win32_directory_monitor_parent_class)->finalize) + (*G_OBJECT_CLASS (g_win32_directory_monitor_parent_class)->finalize) (base); +} + + +static gboolean g_win32_directory_monitor_cancel (GFileMonitor* base) { + GWin32DirectoryMonitor * self; + self = G_WIN32_DIRECTORY_MONITOR (base); + + /* this triggers a last callback() with nBytes=0 */ + CloseHandle (self->priv->hDirectory); + + if (G_FILE_MONITOR_CLASS (g_win32_directory_monitor_parent_class)->cancel) + (*G_FILE_MONITOR_CLASS (g_win32_directory_monitor_parent_class)->cancel) (base); + return TRUE; +} + +void CALLBACK g_win32_directory_monitor_callback (DWORD error, DWORD nBytes, GWin32DirectoryMonitorPrivate* lpOverlapped) +{ + gulong offset; + PFILE_NOTIFY_INFORMATION pfile_notify_walker; + gulong file_name_len; + gchar* file_name; + GFile * file; + + static GFileMonitorEvent events[] = {0, + G_FILE_MONITOR_EVENT_CREATED, /* FILE_ACTION_ADDED */ + G_FILE_MONITOR_EVENT_DELETED, /* FILE_ACTION_REMOVED */ + G_FILE_MONITOR_EVENT_CHANGED, /* FILE_ACTION_MODIFIED */ + G_FILE_MONITOR_EVENT_DELETED, /* FILE_ACTION_RENAMED_OLD_NAME */ + G_FILE_MONITOR_EVENT_CREATED, /* FILE_ACTION_RENAMED_NEW_NAME */ + }; + + if (!nBytes) /* monitor was cancelled/finalized */ + return; + + if (g_file_monitor_is_cancelled (G_FILE_MONITOR (lpOverlapped->self))) + return; /* and ReadDirectoryChangesW doesn't get called this time */ + + offset = 0; + do { + pfile_notify_walker = (PFILE_NOTIFY_INFORMATION)(lpOverlapped->file_notify_buffer + offset); + offset += pfile_notify_walker->NextEntryOffset; + file_name = g_utf16_to_utf8 (pfile_notify_walker->FileName, pfile_notify_walker->FileNameLength / sizeof(WCHAR), NULL, &file_name_len, NULL); + file = g_file_new_for_path (file_name); + g_file_monitor_emit_event (lpOverlapped->self, file, NULL, events [pfile_notify_walker->Action]); + g_object_unref (file); + g_free (file_name); + } while (pfile_notify_walker->NextEntryOffset); + + ReadDirectoryChangesW (lpOverlapped->hDirectory, (gpointer)lpOverlapped->file_notify_buffer, lpOverlapped->buffer_allocated_bytes, FALSE, + FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | + FILE_NOTIFY_CHANGE_SIZE, &lpOverlapped->buffer_filled_bytes, &lpOverlapped->overlapped, g_win32_directory_monitor_callback); +} + +static GObject * g_win32_directory_monitor_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties) { + GObject * obj; + GWin32DirectoryMonitorClass * klass; + GObjectClass * parent_class; + GWin32DirectoryMonitor * self; + gchar * dirname; + gboolean result; + + klass = G_WIN32_DIRECTORY_MONITOR_CLASS (g_type_class_peek (G_TYPE_WIN32_DIRECTORY_MONITOR)); + parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); + obj = parent_class->constructor (type, n_construct_properties, construct_properties); + self = G_WIN32_DIRECTORY_MONITOR (obj); + dirname = G_LOCAL_DIRECTORY_MONITOR (obj)->dirname; + + self->priv->hDirectory = CreateFile (dirname, FILE_LIST_DIRECTORY, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); + g_assert (self->priv->hDirectory != INVALID_HANDLE_VALUE); /* harsh */ + + result = ReadDirectoryChangesW (self->priv->hDirectory, (gpointer)self->priv->file_notify_buffer, self->priv->buffer_allocated_bytes, FALSE, + FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | + FILE_NOTIFY_CHANGE_SIZE, &self->priv->buffer_filled_bytes, &self->priv->overlapped, g_win32_directory_monitor_callback); + g_assert (result); /* harsh */ + + return obj; +} + +static void g_win32_directory_monitor_class_init (GWin32DirectoryMonitorClass * klass) { + + g_win32_directory_monitor_parent_class = g_type_class_peek_parent (klass); + + G_OBJECT_CLASS (klass)->constructor = g_win32_directory_monitor_constructor; + G_OBJECT_CLASS (klass)->finalize = g_win32_directory_monitor_finalize; + G_FILE_MONITOR_CLASS (klass)->cancel = g_win32_directory_monitor_cancel; + + G_LOCAL_DIRECTORY_MONITOR_CLASS (klass)->mount_notify = FALSE; + G_LOCAL_DIRECTORY_MONITOR_CLASS (klass)->is_supported = g_win32_directory_monitor_is_supported; +} + +static void g_win32_directory_monitor_init (GWin32DirectoryMonitor * self) +{ + self->priv = (GWin32DirectoryMonitorPrivate*)g_new0 (GWin32DirectoryMonitorPrivate, 1); + g_assert (self->priv != 0); + + self->priv->buffer_allocated_bytes = 32768; + self->priv->file_notify_buffer = g_new0 (gchar, self->priv->buffer_allocated_bytes); + g_assert (self->priv->file_notify_buffer); + + self->priv->self = G_FILE_MONITOR (self); +} diff --git a/gio/win32/gwin32directorymonitor.h b/gio/win32/gwin32directorymonitor.h new file mode 100644 index 0000000..fedc8f8 --- /dev/null +++ b/gio/win32/gwin32directorymonitor.h @@ -0,0 +1,62 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Vlad Grecescu + * + */ +#ifndef __G_WIN32_DIRECTORY_MONITOR_H__ +#define __G_WIN32_DIRECTORY_MONITOR_H__ + +#include +#include +#include +#include +#include + +#include "glocaldirectorymonitor.h" +#include "giomodule.h" + +G_BEGIN_DECLS + + +#define G_TYPE_WIN32_DIRECTORY_MONITOR (g_win32_directory_monitor_get_type ()) +#define G_WIN32_DIRECTORY_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_WIN32_DIRECTORY_MONITOR, GWin32DirectoryMonitor)) +#define G_WIN32_DIRECTORY_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_WIN32_DIRECTORY_MONITOR, GWin32DirectoryMonitorClass)) +#define G_IS_WIN32_DIRECTORY_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_WIN32_DIRECTORY_MONITOR)) +#define G_IS_WIN32_DIRECTORY_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_WIN32_DIRECTORY_MONITOR)) +#define G_WIN32_DIRECTORY_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_WIN32_DIRECTORY_MONITOR, GWin32DirectoryMonitorClass)) + +typedef struct _GWin32DirectoryMonitor GWin32DirectoryMonitor; +typedef struct _GWin32DirectoryMonitorClass GWin32DirectoryMonitorClass; +typedef struct _GWin32DirectoryMonitorPrivate GWin32DirectoryMonitorPrivate; + +struct _GWin32DirectoryMonitor { + GLocalDirectoryMonitor parent_instance; + GWin32DirectoryMonitorPrivate * priv; +}; +struct _GWin32DirectoryMonitorClass { + GLocalDirectoryMonitorClass parent_class; +}; + +GType g_win32_directory_monitor_get_type (void); +void g_win32_directory_monitor_register (GIOModule *module); + +G_END_DECLS + +#endif /* __G_WIN32_DIRECTORY_MONITOR_H__ */ -- 2.7.4