mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-02 23:43:39 +02:00
substantially rework file monitors
Remove all event merging and dispatch logic from GFileMonitor. The only implementation of GFileMonitor outside of glib is in gvfs and it already does these things properly. Get rid of GLocalDirectoryMonitor. We will use a single class, GLocalFileMonitor, for both directory and file monitoring. This will prevent every single backend from having to create two objects separately (eg: ginotifydirectorymonitor.c and ginotifyfilemonitor.c). Introduce GFileMonitorSource as a thread-safe cross-context dispatch mechanism. Put it in GLocalFileMonitor. All backends will be expected to dispatch via the source and not touch the GFileMonitor object at all from the worker thread. Remove all construct properties from GLocalFileMonitor and remove the "context" construct property from GFileMonitor. All backends must now get the information about what file to monitor from the ->start() call which is mandatory to implement. Remove the implementation of rate limiting in GFileMonitor and add an implementation in GLocalFileMonitor. gvfs never did anything with this anyway, but if it wanted to, it would have to implement it for itself. This was done in order to get the rate_limit field into the GFileMonitorSource so that it could be safely accessed from the worker thread. Expose g_local_file_is_remote() internally for NFS detection. With the "is_remote" functionality exposed, we can now move all functions for creating local file monitors to a proper location in glocalfilemonitor.c Port the inotify backend to adjust to the changes above. None of the other backends are ported yet. Those will come in future commits.
This commit is contained in:
@@ -15,8 +15,6 @@ libinotify_la_SOURCES = \
|
||||
inotify-helper.h \
|
||||
ginotifyfilemonitor.c \
|
||||
ginotifyfilemonitor.h \
|
||||
ginotifydirectorymonitor.c \
|
||||
ginotifydirectorymonitor.h \
|
||||
$(NULL)
|
||||
|
||||
libinotify_la_CFLAGS = \
|
||||
|
@@ -31,7 +31,7 @@
|
||||
|
||||
struct _GInotifyDirectoryMonitor
|
||||
{
|
||||
GLocalDirectoryMonitor parent_instance;
|
||||
GLocalFileMonitor parent_instance;
|
||||
inotify_sub *sub;
|
||||
};
|
||||
|
||||
|
@@ -19,6 +19,7 @@
|
||||
* Authors: Alexander Larsson <alexl@redhat.com>
|
||||
* John McCutchan <john@johnmccutchan.com>
|
||||
* Sebastian Dröge <slomo@circular-chaos.org>
|
||||
* Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -32,81 +33,13 @@
|
||||
struct _GInotifyFileMonitor
|
||||
{
|
||||
GLocalFileMonitor parent_instance;
|
||||
gchar *filename;
|
||||
gchar *dirname;
|
||||
|
||||
inotify_sub *sub;
|
||||
gboolean pair_moves;
|
||||
};
|
||||
|
||||
static gboolean g_inotify_file_monitor_cancel (GFileMonitor* monitor);
|
||||
|
||||
#define g_inotify_file_monitor_get_type _g_inotify_file_monitor_get_type
|
||||
G_DEFINE_TYPE_WITH_CODE (GInotifyFileMonitor, g_inotify_file_monitor, G_TYPE_LOCAL_FILE_MONITOR,
|
||||
g_io_extension_point_implement (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME,
|
||||
g_define_type_id,
|
||||
"inotify",
|
||||
20))
|
||||
|
||||
static void
|
||||
g_inotify_file_monitor_finalize (GObject *object)
|
||||
{
|
||||
GInotifyFileMonitor *inotify_monitor = G_INOTIFY_FILE_MONITOR (object);
|
||||
inotify_sub *sub = inotify_monitor->sub;
|
||||
|
||||
if (sub)
|
||||
{
|
||||
_ih_sub_cancel (sub);
|
||||
_ih_sub_free (sub);
|
||||
inotify_monitor->sub = NULL;
|
||||
}
|
||||
|
||||
g_free (inotify_monitor->filename);
|
||||
g_free (inotify_monitor->dirname);
|
||||
|
||||
G_OBJECT_CLASS (g_inotify_file_monitor_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
g_inotify_file_monitor_start (GLocalFileMonitor *local_monitor)
|
||||
{
|
||||
GInotifyFileMonitor *inotify_monitor = G_INOTIFY_FILE_MONITOR (local_monitor);
|
||||
const gchar *filename = NULL;
|
||||
gboolean watch_hardlinks;
|
||||
inotify_sub *sub = NULL;
|
||||
gboolean pair_moves;
|
||||
gboolean ret_ih_startup; /* return value of _ih_startup, for asserting */
|
||||
|
||||
filename = local_monitor->filename;
|
||||
g_assert (filename != NULL);
|
||||
|
||||
inotify_monitor->filename = g_path_get_basename (filename);
|
||||
inotify_monitor->dirname = g_path_get_dirname (filename);
|
||||
|
||||
/* Will never fail as is_supported() should be called before instantiating
|
||||
* anyway */
|
||||
/* assert on return value */
|
||||
ret_ih_startup = _ih_startup();
|
||||
g_assert (ret_ih_startup);
|
||||
|
||||
pair_moves = local_monitor->flags & G_FILE_MONITOR_SEND_MOVED;
|
||||
watch_hardlinks = local_monitor->flags & G_FILE_MONITOR_WATCH_HARD_LINKS;
|
||||
|
||||
sub = _ih_sub_new (inotify_monitor->dirname,
|
||||
inotify_monitor->filename,
|
||||
pair_moves,
|
||||
watch_hardlinks,
|
||||
inotify_monitor);
|
||||
|
||||
/* FIXME: what to do about errors here? we can't return NULL or another
|
||||
* kind of error and an assertion is probably too hard */
|
||||
g_assert (sub != NULL);
|
||||
|
||||
/* _ih_sub_add allways returns TRUE, see gio/inotify/inotify-helper.c line 109
|
||||
* g_assert (_ih_sub_add (sub)); */
|
||||
_ih_sub_add (sub);
|
||||
|
||||
inotify_monitor->sub = sub;
|
||||
}
|
||||
g_io_extension_point_implement (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME,
|
||||
g_define_type_id, "inotify", 20))
|
||||
|
||||
static gboolean
|
||||
g_inotify_file_monitor_is_supported (void)
|
||||
@@ -114,6 +47,55 @@ g_inotify_file_monitor_is_supported (void)
|
||||
return _ih_startup ();
|
||||
}
|
||||
|
||||
static void
|
||||
g_inotify_file_monitor_start (GLocalFileMonitor *local_monitor,
|
||||
const gchar *dirname,
|
||||
const gchar *basename,
|
||||
const gchar *filename,
|
||||
GFileMonitorSource *source)
|
||||
{
|
||||
GInotifyFileMonitor *inotify_monitor = G_INOTIFY_FILE_MONITOR (local_monitor);
|
||||
gboolean success;
|
||||
|
||||
/* should already have been called, from is_supported() */
|
||||
success = _ih_startup ();
|
||||
g_assert (success);
|
||||
|
||||
inotify_monitor->sub = _ih_sub_new (dirname, basename, filename != NULL, source);
|
||||
_ih_sub_add (inotify_monitor->sub);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_inotify_file_monitor_cancel (GFileMonitor *monitor)
|
||||
{
|
||||
GInotifyFileMonitor *inotify_monitor = G_INOTIFY_FILE_MONITOR (monitor);
|
||||
|
||||
if (inotify_monitor->sub)
|
||||
{
|
||||
_ih_sub_cancel (inotify_monitor->sub);
|
||||
_ih_sub_free (inotify_monitor->sub);
|
||||
inotify_monitor->sub = NULL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
g_inotify_file_monitor_finalize (GObject *object)
|
||||
{
|
||||
GInotifyFileMonitor *inotify_monitor = G_INOTIFY_FILE_MONITOR (object);
|
||||
|
||||
/* must surely have been cancelled already */
|
||||
g_assert (!inotify_monitor->sub);
|
||||
|
||||
G_OBJECT_CLASS (g_inotify_file_monitor_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
g_inotify_file_monitor_init (GInotifyFileMonitor* monitor)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
g_inotify_file_monitor_class_init (GInotifyFileMonitorClass* klass)
|
||||
{
|
||||
@@ -121,33 +103,10 @@ g_inotify_file_monitor_class_init (GInotifyFileMonitorClass* klass)
|
||||
GFileMonitorClass *file_monitor_class = G_FILE_MONITOR_CLASS (klass);
|
||||
GLocalFileMonitorClass *local_file_monitor_class = G_LOCAL_FILE_MONITOR_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = g_inotify_file_monitor_finalize;
|
||||
file_monitor_class->cancel = g_inotify_file_monitor_cancel;
|
||||
|
||||
local_file_monitor_class->is_supported = g_inotify_file_monitor_is_supported;
|
||||
local_file_monitor_class->start = g_inotify_file_monitor_start;
|
||||
}
|
||||
|
||||
static void
|
||||
g_inotify_file_monitor_init (GInotifyFileMonitor* monitor)
|
||||
{
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_inotify_file_monitor_cancel (GFileMonitor* monitor)
|
||||
{
|
||||
GInotifyFileMonitor *inotify_monitor = G_INOTIFY_FILE_MONITOR (monitor);
|
||||
inotify_sub *sub = inotify_monitor->sub;
|
||||
|
||||
if (sub)
|
||||
{
|
||||
_ih_sub_cancel (sub);
|
||||
_ih_sub_free (sub);
|
||||
inotify_monitor->sub = NULL;
|
||||
}
|
||||
|
||||
if (G_FILE_MONITOR_CLASS (g_inotify_file_monitor_parent_class)->cancel)
|
||||
(*G_FILE_MONITOR_CLASS (g_inotify_file_monitor_parent_class)->cancel) (monitor);
|
||||
|
||||
return TRUE;
|
||||
local_file_monitor_class->mount_notify = TRUE;
|
||||
file_monitor_class->cancel = g_inotify_file_monitor_cancel;
|
||||
|
||||
gobject_class->finalize = g_inotify_file_monitor_finalize;
|
||||
}
|
||||
|
@@ -32,7 +32,7 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define G_TYPE_INOTIFY_FILE_MONITOR (_g_inotify_file_monitor_get_type ())
|
||||
#define G_TYPE_INOTIFY_FILE_MONITOR (g_inotify_file_monitor_get_type ())
|
||||
#define G_INOTIFY_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_INOTIFY_FILE_MONITOR, GInotifyFileMonitor))
|
||||
#define G_INOTIFY_FILE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), G_TYPE_INOTIFY_FILE_MONITOR, GInotifyFileMonitorClass))
|
||||
#define G_IS_INOTIFY_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_INOTIFY_FILE_MONITOR))
|
||||
@@ -45,7 +45,7 @@ struct _GInotifyFileMonitorClass {
|
||||
GLocalFileMonitorClass parent_class;
|
||||
};
|
||||
|
||||
GType _g_inotify_file_monitor_get_type (void);
|
||||
GType g_inotify_file_monitor_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@@ -29,8 +29,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
/* Just include the local header to stop all the pain */
|
||||
#include <sys/inotify.h>
|
||||
#include <gio/glocalfile.h>
|
||||
#include <gio/gfilemonitor.h>
|
||||
#include <gio/glocalfilemonitor.h>
|
||||
#include <gio/gfile.h>
|
||||
#include "inotify-helper.h"
|
||||
#include "inotify-missing.h"
|
||||
@@ -109,6 +108,7 @@ _ih_sub_add (inotify_sub *sub)
|
||||
_im_add (sub);
|
||||
|
||||
G_UNLOCK (inotify_lock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ _ih_sub_cancel (inotify_sub *sub)
|
||||
}
|
||||
|
||||
G_UNLOCK (inotify_lock);
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -150,113 +150,60 @@ _ih_fullpath_from_event (ik_event_t *event,
|
||||
return fullpath;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
ih_event_is_paired_move (ik_event_t *event)
|
||||
{
|
||||
if (event->pair)
|
||||
{
|
||||
ik_event_t *paired = event->pair;
|
||||
/* intofiy(7): IN_MOVE == IN_MOVED_FROM | IN_MOVED_TO */
|
||||
return (event->mask | paired->mask) & IN_MOVE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
ih_event_callback (ik_event_t *event,
|
||||
ih_event_callback (ik_event_t *event,
|
||||
inotify_sub *sub,
|
||||
gboolean file_event)
|
||||
gboolean file_event)
|
||||
{
|
||||
gchar *fullpath;
|
||||
GFileMonitorEvent eflags;
|
||||
GFile* child;
|
||||
GFile* other;
|
||||
g_assert (!file_event); /* XXX hardlink support */
|
||||
|
||||
eflags = ih_mask_to_EventFlags (event->mask);
|
||||
fullpath = _ih_fullpath_from_event (event, sub->dirname,
|
||||
file_event ? sub->filename : NULL);
|
||||
child = g_file_new_for_path (fullpath);
|
||||
g_free (fullpath);
|
||||
|
||||
if (ih_event_is_paired_move (event) && sub->pair_moves)
|
||||
if (event->mask & IN_MOVE)
|
||||
{
|
||||
const char *parent_dir = (char *) _ip_get_path_for_wd (event->pair->wd);
|
||||
fullpath = _ih_fullpath_from_event (event->pair, parent_dir, NULL);
|
||||
other = g_file_new_for_path (fullpath);
|
||||
g_free (fullpath);
|
||||
eflags = G_FILE_MONITOR_EVENT_MOVED;
|
||||
event->pair = NULL; /* prevents the paired event to be emitted as well */
|
||||
/* We either have a rename (in the same directory) or a move
|
||||
* (between different directories).
|
||||
*/
|
||||
if (event->pair && event->pair->wd == event->wd)
|
||||
{
|
||||
/* this is a rename */
|
||||
g_file_monitor_source_handle_event (sub->user_data, G_FILE_MONITOR_EVENT_RENAMED,
|
||||
event->name, event->pair->name, NULL, event->timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
GFile *other;
|
||||
|
||||
if (event->pair)
|
||||
{
|
||||
const char *parent_dir;
|
||||
gchar *fullpath;
|
||||
|
||||
parent_dir = _ip_get_path_for_wd (event->pair->wd);
|
||||
fullpath = _ih_fullpath_from_event (event->pair, parent_dir, NULL);
|
||||
other = g_file_new_for_path (fullpath);
|
||||
g_free (fullpath);
|
||||
}
|
||||
else
|
||||
other = NULL;
|
||||
|
||||
/* this is either an incoming or outgoing move */
|
||||
g_file_monitor_source_handle_event (sub->user_data, ih_mask_to_EventFlags (event->mask),
|
||||
event->name, NULL, other, event->timestamp);
|
||||
|
||||
if (other)
|
||||
g_object_unref (other);
|
||||
}
|
||||
}
|
||||
else
|
||||
other = NULL;
|
||||
|
||||
g_file_monitor_emit_event (G_FILE_MONITOR (sub->user_data),
|
||||
child, other, eflags);
|
||||
|
||||
/* For paired moves or moves whose mask has been changed from IN_MOVED_TO to
|
||||
* IN_CREATE, notify also that it's probably the last change to the file,
|
||||
* emitting CHANGES_DONE_HINT.
|
||||
* The first (first part of the if's guard below) is the case of a normal
|
||||
* move within the monitored tree and in the same mounted volume.
|
||||
* The latter (second part of the guard) is the case of a move within the
|
||||
* same mounted volume, but from a not monitored directory.
|
||||
*
|
||||
* It's not needed in cases like moves across mounted volumes as the IN_CREATE
|
||||
* will be followed by a IN_MODIFY and IN_CLOSE_WRITE events.
|
||||
* Also not needed if sub->pair_moves is set as EVENT_MOVED will be emitted
|
||||
* instead of EVENT_CREATED which implies no further modification will be
|
||||
* applied to the file
|
||||
* See: https://bugzilla.gnome.org/show_bug.cgi?id=640077
|
||||
*/
|
||||
if ((!sub->pair_moves &&
|
||||
event->is_second_in_pair && (event->mask & IN_MOVED_TO)) ||
|
||||
(!ih_event_is_paired_move (event) &&
|
||||
(event->original_mask & IN_MOVED_TO) && (event->mask & IN_CREATE)))
|
||||
{
|
||||
g_file_monitor_emit_event (G_FILE_MONITOR (sub->user_data),
|
||||
child, NULL, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT);
|
||||
}
|
||||
|
||||
g_object_unref (child);
|
||||
if (other)
|
||||
g_object_unref (other);
|
||||
/* unpaired event -- no 'other' field */
|
||||
g_file_monitor_source_handle_event (sub->user_data, ih_mask_to_EventFlags (event->mask),
|
||||
event->name, NULL, NULL, event->timestamp);
|
||||
}
|
||||
|
||||
static void
|
||||
ih_not_missing_callback (inotify_sub *sub)
|
||||
{
|
||||
gchar *fullpath;
|
||||
GFileMonitorEvent eflags;
|
||||
guint32 mask;
|
||||
GFile* child;
|
||||
|
||||
if (sub->filename)
|
||||
{
|
||||
fullpath = g_strdup_printf ("%s/%s", sub->dirname, sub->filename);
|
||||
g_warning ("Missing callback called fullpath = %s\n", fullpath);
|
||||
if (!g_file_test (fullpath, G_FILE_TEST_EXISTS))
|
||||
{
|
||||
g_free (fullpath);
|
||||
return;
|
||||
}
|
||||
mask = IN_CREATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
fullpath = g_strdup_printf ("%s", sub->dirname);
|
||||
mask = IN_CREATE|IN_ISDIR;
|
||||
}
|
||||
|
||||
eflags = ih_mask_to_EventFlags (mask);
|
||||
child = g_file_new_for_path (fullpath);
|
||||
g_free (fullpath);
|
||||
|
||||
g_file_monitor_emit_event (G_FILE_MONITOR (sub->user_data),
|
||||
child, NULL, eflags);
|
||||
|
||||
g_object_unref (child);
|
||||
g_file_monitor_source_handle_event (sub->user_data, G_FILE_MONITOR_EVENT_CREATED,
|
||||
sub->filename, NULL, NULL, g_get_monotonic_time ());
|
||||
}
|
||||
|
||||
/* Transforms a inotify event to a GVFS event. */
|
||||
@@ -273,13 +220,15 @@ ih_mask_to_EventFlags (guint32 mask)
|
||||
case IN_ATTRIB:
|
||||
return G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED;
|
||||
case IN_MOVE_SELF:
|
||||
case IN_MOVED_FROM:
|
||||
case IN_DELETE:
|
||||
case IN_DELETE_SELF:
|
||||
return G_FILE_MONITOR_EVENT_DELETED;
|
||||
case IN_CREATE:
|
||||
case IN_MOVED_TO:
|
||||
return G_FILE_MONITOR_EVENT_CREATED;
|
||||
case IN_MOVED_FROM:
|
||||
return G_FILE_MONITOR_EVENT_MOVED_OUT;
|
||||
case IN_MOVED_TO:
|
||||
return G_FILE_MONITOR_EVENT_MOVED_IN;
|
||||
case IN_UNMOUNT:
|
||||
return G_FILE_MONITOR_EVENT_UNMOUNTED;
|
||||
case IN_Q_OVERFLOW:
|
||||
|
@@ -63,7 +63,7 @@ ik_event_new (struct inotify_event *kevent,
|
||||
if (event->len)
|
||||
event->name = g_strdup (kevent->name);
|
||||
else
|
||||
event->name = g_strdup ("");
|
||||
event->name = NULL;
|
||||
|
||||
return event;
|
||||
}
|
||||
@@ -72,7 +72,10 @@ void
|
||||
_ik_event_free (ik_event_t *event)
|
||||
{
|
||||
if (event->pair)
|
||||
_ik_event_free (event->pair);
|
||||
{
|
||||
event->pair->pair = NULL;
|
||||
_ik_event_free (event->pair);
|
||||
}
|
||||
|
||||
g_free (event->name);
|
||||
g_free (event);
|
||||
@@ -148,6 +151,7 @@ ik_source_try_to_pair_head (InotifyKernelSource *iks)
|
||||
g_queue_remove (&iks->queue, candidate);
|
||||
candidate->is_second_in_pair = TRUE;
|
||||
head->pair = candidate;
|
||||
candidate->pair = head;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@@ -438,9 +438,7 @@ ip_wd_delete (gpointer data,
|
||||
|
||||
static void
|
||||
ip_event_dispatch (GList *dir_list,
|
||||
GList *pair_dir_list,
|
||||
GList *file_list,
|
||||
GList *pair_file_list,
|
||||
ik_event_t *event)
|
||||
{
|
||||
GList *l;
|
||||
@@ -521,92 +519,13 @@ ip_event_dispatch (GList *dir_list,
|
||||
event_callback (event, sub, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
if (!event->pair)
|
||||
return;
|
||||
|
||||
for (l = pair_dir_list; l; l = l->next)
|
||||
{
|
||||
GList *subl;
|
||||
ip_watched_dir_t *dir = l->data;
|
||||
|
||||
for (subl = dir->subs; subl; subl = subl->next)
|
||||
{
|
||||
inotify_sub *sub = subl->data;
|
||||
|
||||
/* If the subscription and the event
|
||||
* contain a filename and they don't
|
||||
* match, we don't deliver this event.
|
||||
*/
|
||||
if (sub->filename &&
|
||||
event->pair->name &&
|
||||
strcmp (sub->filename, event->pair->name))
|
||||
continue;
|
||||
|
||||
/* If the subscription has a filename
|
||||
* but this event doesn't, we don't
|
||||
* deliver this event.
|
||||
*/
|
||||
if (sub->filename && !event->pair->name)
|
||||
continue;
|
||||
|
||||
/* If we're also watching the file directly
|
||||
* don't report events that will also be
|
||||
* reported on the file itself.
|
||||
*/
|
||||
if (sub->hardlinks)
|
||||
{
|
||||
event->mask &= ~IP_INOTIFY_FILE_MASK;
|
||||
if (!event->mask)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* FIXME: We might need to synthesize
|
||||
* DELETE/UNMOUNT events when
|
||||
* the filename doesn't match
|
||||
*/
|
||||
|
||||
event_callback (event->pair, sub, FALSE);
|
||||
|
||||
if (sub->hardlinks)
|
||||
{
|
||||
ip_watched_file_t *file;
|
||||
|
||||
file = g_hash_table_lookup (dir->files_hash, sub->filename);
|
||||
|
||||
if (file != NULL)
|
||||
{
|
||||
if (event->pair->mask & (IN_MOVED_FROM | IN_DELETE))
|
||||
ip_watched_file_stop (file);
|
||||
|
||||
if (event->pair->mask & (IN_MOVED_TO | IN_CREATE))
|
||||
ip_watched_file_start (file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (l = pair_file_list; l; l = l->next)
|
||||
{
|
||||
ip_watched_file_t *file = l->data;
|
||||
GList *subl;
|
||||
|
||||
for (subl = file->subs; subl; subl = subl->next)
|
||||
{
|
||||
inotify_sub *sub = subl->data;
|
||||
|
||||
event_callback (event->pair, sub, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ip_event_callback (ik_event_t *event)
|
||||
{
|
||||
GList* dir_list = NULL;
|
||||
GList* pair_dir_list = NULL;
|
||||
GList *file_list = NULL;
|
||||
GList *pair_file_list = NULL;
|
||||
|
||||
/* We can ignore the IGNORED events */
|
||||
if (event->mask & IN_IGNORED)
|
||||
@@ -618,15 +537,19 @@ ip_event_callback (ik_event_t *event)
|
||||
dir_list = g_hash_table_lookup (wd_dir_hash, GINT_TO_POINTER (event->wd));
|
||||
file_list = g_hash_table_lookup (wd_file_hash, GINT_TO_POINTER (event->wd));
|
||||
|
||||
if (event->pair)
|
||||
if (event->mask & IP_INOTIFY_DIR_MASK)
|
||||
ip_event_dispatch (dir_list, file_list, event);
|
||||
|
||||
/* Only deliver paired events if the wds are separate */
|
||||
if (event->pair && event->pair->wd != event->wd)
|
||||
{
|
||||
pair_dir_list = g_hash_table_lookup (wd_dir_hash, GINT_TO_POINTER (event->pair->wd));
|
||||
pair_file_list = g_hash_table_lookup (wd_file_hash, GINT_TO_POINTER (event->pair->wd));
|
||||
dir_list = g_hash_table_lookup (wd_dir_hash, GINT_TO_POINTER (event->pair->wd));
|
||||
file_list = g_hash_table_lookup (wd_file_hash, GINT_TO_POINTER (event->pair->wd));
|
||||
|
||||
if (event->pair->mask & IP_INOTIFY_DIR_MASK)
|
||||
ip_event_dispatch (dir_list, file_list, event->pair);
|
||||
}
|
||||
|
||||
if (event->mask & IP_INOTIFY_DIR_MASK)
|
||||
ip_event_dispatch (dir_list, pair_dir_list, file_list, pair_file_list, event);
|
||||
|
||||
/* We have to manage the missing list
|
||||
* when we get an event that means the
|
||||
* file has been deleted/moved/unmounted.
|
||||
|
@@ -46,7 +46,6 @@ dup_dirname (const gchar *dirname)
|
||||
inotify_sub*
|
||||
_ih_sub_new (const gchar *dirname,
|
||||
const gchar *filename,
|
||||
gboolean pair_moves,
|
||||
gboolean watch_hardlinks,
|
||||
gpointer user_data)
|
||||
{
|
||||
@@ -55,7 +54,6 @@ _ih_sub_new (const gchar *dirname,
|
||||
sub = g_new0 (inotify_sub, 1);
|
||||
sub->dirname = dup_dirname (dirname);
|
||||
sub->filename = g_strdup (filename);
|
||||
sub->pair_moves = pair_moves;
|
||||
sub->hardlinks = watch_hardlinks;
|
||||
sub->user_data = user_data;
|
||||
|
||||
|
@@ -35,7 +35,6 @@ typedef struct
|
||||
|
||||
inotify_sub *_ih_sub_new (const gchar *dirname,
|
||||
const gchar *filename,
|
||||
gboolean pair_moves,
|
||||
gboolean watch_hardlinks,
|
||||
gpointer user_data);
|
||||
void _ih_sub_free (inotify_sub *sub);
|
||||
|
Reference in New Issue
Block a user