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 void
g_local_file_monitor_mounts_changed (GUnixMountMonitor *mount_monitor,
                                     gpointer           user_data)
{
  GLocalFileMonitor *local_monitor = user_data;
  GUnixMountEntry *mount;
  gboolean is_mounted;
  GFile *file;

  /* Emulate unmount detection */
  mount = g_unix_mount_at (local_monitor->source->dirname, NULL);

  is_mounted = mount != NULL;

  if (mount)
    g_unix_mount_free (mount);

  if (local_monitor->was_mounted != is_mounted)
    {
      if (local_monitor->was_mounted && !is_mounted)
        {
          file = g_file_new_for_path (local_monitor->source->dirname);
          g_file_monitor_emit_event (G_FILE_MONITOR (local_monitor), file, NULL, G_FILE_MONITOR_EVENT_UNMOUNTED);
          g_object_unref (file);
        }
      local_monitor->was_mounted = is_mounted;
    }
}
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);
}
Exemple #4
0
static void
g_file_monitor_get_property (GObject    *object,
                             guint       prop_id,
                             GValue     *value,
                             GParamSpec *pspec)
{
  GFileMonitor *monitor;
  GFileMonitorPrivate *priv;

  monitor = G_FILE_MONITOR (object);
  priv = monitor->priv;

  switch (prop_id)
    {
    case PROP_RATE_LIMIT:
      g_value_set_int (value, priv->rate_limit_msec);
      break;

    case PROP_CANCELLED:
      G_LOCK (cancelled);
      g_value_set_boolean (value, priv->cancelled);
      G_UNLOCK (cancelled);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}
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);
}
Exemple #6
0
static gboolean
emit_cb (gpointer data)
{
  GFileMonitor *monitor = G_FILE_MONITOR (data);
  GSList *pending, *iter;
  
  pending = g_slist_reverse (monitor->priv->pending_file_changes);
  monitor->priv->pending_file_changes = NULL;
  if (monitor->priv->pending_file_change_source)
    {
      g_source_unref (monitor->priv->pending_file_change_source);
      monitor->priv->pending_file_change_source = NULL;
    }

  g_object_ref (monitor);
  for (iter = pending; iter; iter = iter->next)
    {
       FileChange *change = iter->data;
       g_signal_emit (monitor, signals[CHANGED], 0,
	  	      change->child, change->other_file, change->event_type);
       file_change_free (change);
    }
  g_slist_free (pending);
  g_object_unref (monitor);

  return FALSE;
}
/**
 * _g_local_directory_monitor_new:
 * @dirname: filename of the directory to monitor.
 * @flags: #GFileMonitorFlags.
 * 
 * Returns: new #GFileMonitor for the given @dirname.
 **/
GFileMonitor*
_g_local_directory_monitor_new (const char         *dirname,
				GFileMonitorFlags   flags,
				GError            **error)
{
  static GOnce once_init = G_ONCE_INIT;
  GTypeClass *type_class;
  GFileMonitor *monitor;
  GType type;

  type_class = NULL;
  g_once (&once_init, get_default_local_directory_monitor, &type_class);
  type = (GType)once_init.retval;

  monitor = NULL;
  if (type != G_TYPE_INVALID)
    monitor = G_FILE_MONITOR (g_object_new (type, "dirname", dirname, "flags", flags, NULL));
  else
    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                         _("Unable to find default local directory monitor type"));

  /* This is non-null on first pass here. Unref the class now.
   * This is to avoid unloading the module and then loading it
   * again which would happen if we unrefed the class
   * before creating the monitor.
   */
  
  if (type_class)
    g_type_class_unref (type_class);
  
  return monitor;
}
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);
}
Exemple #9
0
static void
g_file_monitor_dispose (GObject *object)
{
  GFileMonitor *monitor;
  
  monitor = G_FILE_MONITOR (object);

  /* Make sure we cancel on last unref */
  g_file_monitor_cancel (monitor);
  
  if (G_OBJECT_CLASS (g_file_monitor_parent_class)->dispose)
    (*G_OBJECT_CLASS (g_file_monitor_parent_class)->dispose) (object);
}
Exemple #10
0
static void
node_emit_one_event(node_t *f, GList *subs, node_t *other, int event)
{
    GList* idx;
    
    FN_W ("%s %s %d\n", __func__, NODE_NAME(f), event);

#ifdef GIO_COMPILATION
    for (idx = subs; idx; idx = idx->next) {
        g_file_monitor_emit_event(G_FILE_MONITOR(idx->data), f->gfile,
          (other == NULL ? NULL : other->gfile), event);
    }
#else
    for (idx = subs; idx; idx = idx->next) {
        gam_server_emit_one_event(NODE_NAME(f), gam_subscription_is_dir(idx->data), event, idx->data, 1);
    }
#endif
}
Exemple #11
0
static void
g_file_monitor_finalize (GObject *object)
{
  GFileMonitor *monitor;

  monitor = G_FILE_MONITOR (object);

  if (monitor->priv->timeout)
    {
      g_source_destroy (monitor->priv->timeout);
      g_source_unref (monitor->priv->timeout);
    }

  g_hash_table_destroy (monitor->priv->rate_limiter);
  
  if (G_OBJECT_CLASS (g_file_monitor_parent_class)->finalize)
    (*G_OBJECT_CLASS (g_file_monitor_parent_class)->finalize) (object);
}
Exemple #12
0
/**
 * _kh_file_appeared_cb:
 * @sub: a #kqueue_sub
 *
 * A callback function for kqueue-missing subsystem.
 *
 * Signals that a missing file has finally appeared in the filesystem.
 * Emits %G_FILE_MONITOR_EVENT_CREATED.
 **/
void
_kh_file_appeared_cb (kqueue_sub *sub)
{
  GFile* child;

  g_assert (sub != NULL);
  g_assert (sub->filename);

  if (!g_file_test (sub->filename, G_FILE_TEST_EXISTS))
    return;

  child = g_file_new_for_path (sub->filename);

  g_file_monitor_emit_event (G_FILE_MONITOR (sub->user_data),
                             child,
                             NULL,
                             G_FILE_MONITOR_EVENT_CREATED);

  g_object_unref (child);
}
Exemple #13
0
static void
g_file_monitor_set_property (GObject      *object,
                             guint         prop_id,
                             const GValue *value,
                             GParamSpec   *pspec)
{
  GFileMonitor *monitor;

  monitor = G_FILE_MONITOR (object);

  switch (prop_id)
    {
    case PROP_RATE_LIMIT:
      g_file_monitor_set_rate_limit (monitor, g_value_get_int (value));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}
static void
mounts_changed (GUnixMountMonitor *mount_monitor,
                gpointer           user_data)
{
  GLocalDirectoryMonitor *local_monitor = user_data;
  GUnixMountEntry *mount;
  gboolean is_mounted;
  GFile *file;
  
  /* Emulate unmount detection */
#ifdef G_OS_WIN32
  mount = NULL;
  /*claim everything was mounted */
  is_mounted = TRUE;
#else  
  mount = g_unix_mount_at (local_monitor->dirname, NULL);
  
  is_mounted = mount != NULL;
  
  if (mount)
    g_unix_mount_free (mount);
#endif

  if (local_monitor->was_mounted != is_mounted)
    {
      if (local_monitor->was_mounted && !is_mounted)
        {
          file = g_file_new_for_path (local_monitor->dirname);
          g_file_monitor_emit_event (G_FILE_MONITOR (local_monitor),
				     file, NULL,
				     G_FILE_MONITOR_EVENT_UNMOUNTED);
          g_object_unref (file);
        }
      local_monitor->was_mounted = is_mounted;
    }
}
Exemple #15
0
static void
g_file_monitor_dispose (GObject *object)
{
  GFileMonitor *monitor;
  GFileMonitorPrivate *priv;
  
  monitor = G_FILE_MONITOR (object);
  priv = monitor->priv;

  if (priv->pending_file_change_source)
    {
      g_source_destroy (priv->pending_file_change_source);
      g_source_unref (priv->pending_file_change_source);
      priv->pending_file_change_source = NULL;
    }
  g_slist_foreach (priv->pending_file_changes, (GFunc) file_change_free, NULL);
  g_slist_free (priv->pending_file_changes);
  priv->pending_file_changes = NULL;

  /* Make sure we cancel on last unref */
  g_file_monitor_cancel (monitor);

  G_OBJECT_CLASS (g_file_monitor_parent_class)->dispose (object);
}
Exemple #16
0
static void
foreach_monitors_free (gpointer data, gpointer user_data)
{
	g_file_monitor_cancel (G_FILE_MONITOR (data));
}
Exemple #17
0
GFileMonitor *_g_local_directory_monitor_new(const char *dirname, GFileMonitorFlags flags,
                                             GMainContext *context, gboolean is_remote_fs,
                                             gboolean do_start, GError **error)
{
    return G_FILE_MONITOR(g_object_new(G_TYPE_LOCAL_DIRECTORY_MONITOR, NULL));
}
/**
 * process_kqueue_notifications:
 * @gioc: unused.
 * @cond: unused.
 * @data: unused.
 *
 * Processes notifications, coming from the kqueue thread.
 *
 * Reads notifications from the command file descriptor, emits the
 * "changed" event on the appropriate monitor.
 *
 * A typical GIO Channel callback function.
 *
 * Returns: %TRUE
 **/
static gboolean
process_kqueue_notifications (GIOChannel   *gioc,
                              GIOCondition  cond,
                              gpointer      data)
{
  struct kqueue_notification n;
  kqueue_sub *sub = NULL;
  GFileMonitor *monitor = NULL;
  GFileMonitorEvent mask = 0;
  
  g_assert (kqueue_socket_pair[0] != -1);
  if (!_ku_read (kqueue_socket_pair[0], &n, sizeof (struct kqueue_notification)))
    {
      KH_W ("Failed to read a kqueue notification, error %d", errno);
      return TRUE;
    }

  G_LOCK (hash_lock);
  sub = (kqueue_sub *) g_hash_table_lookup (subs_hash_table, GINT_TO_POINTER (n.fd));
  G_UNLOCK (hash_lock);

  if (sub == NULL)
    {
      KH_W ("Got a notification for a deleted or non-existing subscription %d",
             n.fd);
      return TRUE;
    }

  monitor = G_FILE_MONITOR (sub->user_data);
  g_assert (monitor != NULL);

  if (n.flags & (NOTE_DELETE | NOTE_REVOKE))
    {
      if (sub->deps)
        {
          dl_free (sub->deps);
          sub->deps = NULL;  
        }  
      _km_add_missing (sub);

      if (!(n.flags & NOTE_REVOKE))
        {
          /* Note that NOTE_REVOKE is issued by the kqueue thread
           * on EV_ERROR kevent. In this case, a file descriptor is
           * already closed from the kqueue thread, no need to close
           * it manually */ 
          _kh_cancel_sub (sub);
        }
    }

  if (sub->is_dir && n.flags & (NOTE_WRITE | NOTE_EXTEND))
    {
      _kh_dir_diff (sub, monitor);  
      n.flags &= ~(NOTE_WRITE | NOTE_EXTEND);
    }

  if (n.flags)
    {
      gboolean done = FALSE;
      mask = convert_kqueue_events_to_gio (n.flags, &done);
      if (done == TRUE)
        {
          GFile *file = g_file_new_for_path (sub->filename);
          g_file_monitor_emit_event (monitor, file, NULL, mask);
          g_object_unref (file);
        }
    }

  return TRUE;
}