示例#1
0
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);
}
示例#2
0
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;
}