static GObject * g_local_directory_monitor_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GObject *obj; GLocalDirectoryMonitorClass *klass; GObjectClass *parent_class; GLocalDirectoryMonitor *local_monitor; const gchar *dirname = NULL; gint i; klass = G_LOCAL_DIRECTORY_MONITOR_CLASS (g_type_class_peek (G_TYPE_LOCAL_DIRECTORY_MONITOR)); parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); obj = parent_class->constructor (type, n_construct_properties, construct_properties); local_monitor = G_LOCAL_DIRECTORY_MONITOR (obj); for (i = 0; i < n_construct_properties; i++) { if (strcmp ("dirname", g_param_spec_get_name (construct_properties[i].pspec)) == 0) { g_warn_if_fail (G_VALUE_HOLDS_STRING (construct_properties[i].value)); dirname = g_value_get_string (construct_properties[i].value); break; } } local_monitor->dirname = g_strdup (dirname); if (!klass->mount_notify) { #ifdef G_OS_WIN32 /*claim everything was mounted */ local_monitor->was_mounted = TRUE; #else GUnixMountEntry *mount; /* Emulate unmount detection */ mount = g_unix_mount_at (local_monitor->dirname, NULL); local_monitor->was_mounted = mount != NULL; if (mount) g_unix_mount_free (mount); local_monitor->mount_monitor = g_unix_mount_monitor_new (); g_signal_connect_object (local_monitor->mount_monitor, "mounts-changed", G_CALLBACK (mounts_changed), local_monitor, 0); #endif } return obj; }
static gboolean g_local_directory_monitor_cancel (GFileMonitor *monitor) { GLocalDirectoryMonitor *local_monitor = G_LOCAL_DIRECTORY_MONITOR (monitor); if (local_monitor->mount_monitor) { g_signal_handlers_disconnect_by_func (local_monitor->mount_monitor, mounts_changed, local_monitor); g_object_unref (local_monitor->mount_monitor); local_monitor->mount_monitor = NULL; } return TRUE; }
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; wchar_t *wdirname; 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); wdirname = g_utf8_to_utf16 (G_LOCAL_DIRECTORY_MONITOR (obj)->dirname, -1, NULL, NULL, NULL); self->priv->hDirectory = CreateFileW (wdirname, FILE_LIST_DIRECTORY, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); g_free (wdirname); if (self->priv->hDirectory == INVALID_HANDLE_VALUE) { /* Ignore errors */ return obj; } 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); /* Ignore errors */ return obj; }
static void g_local_directory_monitor_finalize (GObject *object) { GLocalDirectoryMonitor *local_monitor; local_monitor = G_LOCAL_DIRECTORY_MONITOR (object); g_free (local_monitor->dirname); if (local_monitor->mount_monitor) { g_signal_handlers_disconnect_by_func (local_monitor->mount_monitor, mounts_changed, local_monitor); g_object_unref (local_monitor->mount_monitor); local_monitor->mount_monitor = NULL; } G_OBJECT_CLASS (g_local_directory_monitor_parent_class)->finalize (object); }
static void g_local_directory_monitor_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GLocalDirectoryMonitor *local_monitor = G_LOCAL_DIRECTORY_MONITOR (object); switch (property_id) { case PROP_DIRNAME: local_monitor->dirname = g_value_dup_string (value); break; case PROP_FLAGS: local_monitor->flags = g_value_get_flags (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } }
static void CALLBACK g_win32_directory_monitor_callback (DWORD error, DWORD nBytes, LPOVERLAPPED lpOverlapped) { gulong offset; PFILE_NOTIFY_INFORMATION pfile_notify_walker; glong file_name_len; gchar *file_name; gchar *path; GFile *file; GWin32DirectoryMonitorPrivate *priv = (GWin32DirectoryMonitorPrivate *) lpOverlapped; 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 priv->self is NULL the GWin32DirectoryMonitor object has been destroyed. */ if (priv->self == NULL || g_file_monitor_is_cancelled (priv->self) || priv->file_notify_buffer == NULL) { g_free (priv->file_notify_buffer); g_free (priv); return; } offset = 0; do { pfile_notify_walker = (PFILE_NOTIFY_INFORMATION)(priv->file_notify_buffer + offset); if (pfile_notify_walker->Action > 0) { file_name = g_utf16_to_utf8 (pfile_notify_walker->FileName, pfile_notify_walker->FileNameLength / sizeof(WCHAR), NULL, &file_name_len, NULL); path = g_build_filename(G_LOCAL_DIRECTORY_MONITOR (priv->self)->dirname, file_name, NULL); file = g_file_new_for_path (path); g_file_monitor_emit_event (priv->self, file, NULL, events [pfile_notify_walker->Action]); g_object_unref (file); g_free (path); g_free (file_name); } offset += pfile_notify_walker->NextEntryOffset; } while (pfile_notify_walker->NextEntryOffset); ReadDirectoryChangesW (priv->hDirectory, (gpointer)priv->file_notify_buffer, priv->buffer_allocated_bytes, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE, &priv->buffer_filled_bytes, &priv->overlapped, g_win32_directory_monitor_callback); }