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); }
static void ih_event_callback (ik_event_t *event, inotify_sub *sub) { gchar *fullpath; GFileMonitorEvent eflags; GFile* parent; GFile* child; eflags = ih_mask_to_EventFlags (event->mask); parent = g_file_new_for_path (sub->dirname); if (event->name) fullpath = g_strdup_printf ("%s/%s", sub->dirname, event->name); else fullpath = g_strdup_printf ("%s/", sub->dirname); 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_object_unref (parent); }
static void ih_event_callback (ik_event_t *event, inotify_sub *sub, gboolean file_event) { gchar *fullpath; GFileMonitorEvent eflags; GFile* child; GFile* other; 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) { 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 */ } 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); }
static gboolean ih_event_callback (ik_event_t *event, inotify_sub *sub, gboolean file_event) { gboolean interesting; g_assert (!file_event); /* XXX hardlink support */ if (event->mask & IN_MOVE) { /* 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 */ interesting = 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 */ interesting = 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 /* unpaired event -- no 'other' field */ interesting = g_file_monitor_source_handle_event (sub->user_data, ih_mask_to_EventFlags (event->mask), event->name, NULL, NULL, event->timestamp); if (event->mask & IN_CREATE) { const gchar *parent_dir; gchar *fullname; struct stat buf; gint s; /* The kernel reports IN_CREATE for two types of events: * * - creat(), in which case IN_CLOSE_WRITE will come soon; or * - link(), mkdir(), mknod(), etc., in which case it won't * * We can attempt to detect the second case and send the * CHANGES_DONE immediately so that the user isn't left waiting. * * The detection for link() is not 100% reliable since the link * count could be 1 if the original link was deleted or if * O_TMPFILE was being used, but in that case the virtual * CHANGES_DONE will be emitted to close the loop. */ parent_dir = _ip_get_path_for_wd (event->wd); fullname = _ih_fullpath_from_event (event, parent_dir, NULL); s = stat (fullname, &buf); g_free (fullname); /* if it doesn't look like the result of creat()... */ if (s != 0 || !S_ISREG (buf.st_mode) || buf.st_nlink != 1) g_file_monitor_source_handle_event (sub->user_data, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, event->name, NULL, NULL, event->timestamp); } return interesting; }