(root)/
glib-2.79.0/
gio/
glocalfilemonitor.c
       1  /* GIO - GLib Input, Output and Streaming Library
       2   *
       3   * Copyright (C) 2006-2007 Red Hat, Inc.
       4   *
       5   * SPDX-License-Identifier: LGPL-2.1-or-later
       6   *
       7   * This library is free software; you can redistribute it and/or
       8   * modify it under the terms of the GNU Lesser General Public
       9   * License as published by the Free Software Foundation; either
      10   * version 2.1 of the License, or (at your option) any later version.
      11   *
      12   * This library is distributed in the hope that it will be useful,
      13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15   * Lesser General Public License for more details.
      16   *
      17   * You should have received a copy of the GNU Lesser General
      18   * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      19   *
      20   * Author: Alexander Larsson <alexl@redhat.com>
      21   */
      22  
      23  #include "config.h"
      24  
      25  #include "gioenumtypes.h"
      26  #include "glocalfilemonitor.h"
      27  #include "giomodule-priv.h"
      28  #include "gioerror.h"
      29  #include "glibintl.h"
      30  #include "glocalfile.h"
      31  #include "glib-private.h"
      32  
      33  #include <string.h>
      34  
      35  #define DEFAULT_RATE_LIMIT                           800 * G_TIME_SPAN_MILLISECOND
      36  #define VIRTUAL_CHANGES_DONE_DELAY                     2 * G_TIME_SPAN_SECOND
      37  
      38  /* GFileMonitorSource is a GSource responsible for emitting the changed
      39   * signals in the owner-context of the GFileMonitor.
      40   *
      41   * It contains functionality for cross-thread queuing of events.  It
      42   * also handles merging of CHANGED events and emission of CHANGES_DONE
      43   * events.
      44   *
      45   * We use the "priv" pointer in the external struct to store it.
      46   */
      47  struct _GFileMonitorSource {
      48    GSource       source;
      49  
      50    GMutex        lock;
      51    GWeakRef      instance_ref;
      52    GFileMonitorFlags flags;
      53    gchar        *dirname;
      54    gchar        *basename;
      55    gchar        *filename;
      56    GSequence    *pending_changes; /* sorted by ready time */
      57    GHashTable   *pending_changes_table;
      58    GQueue        event_queue;
      59    gint64        rate_limit;
      60  };
      61  
      62  /* PendingChange is a struct to keep track of a file that needs to have
      63   * (at least) a CHANGES_DONE_HINT event sent for it in the near future.
      64   *
      65   * If 'dirty' is TRUE then a CHANGED event also needs to be sent.
      66   *
      67   * last_emission is the last time a CHANGED event was emitted.  It is
      68   * used to calculate the time to send the next event.
      69   */
      70  typedef struct {
      71    gchar    *child;
      72    guint64   last_emission : 63;
      73    guint64   dirty         :  1;
      74  } PendingChange;
      75  
      76  /* QueuedEvent is a signal that will be sent immediately, as soon as the
      77   * source gets a chance to dispatch.  The existence of any queued event
      78   * implies that the source is ready now.
      79   */
      80  typedef struct
      81  {
      82    GFileMonitorEvent event_type;
      83    GFile *child;
      84    GFile *other;
      85  } QueuedEvent;
      86  
      87  static gint64
      88  pending_change_get_ready_time (const PendingChange *change,
      89                                 GFileMonitorSource  *fms)
      90  {
      91    if (change->dirty)
      92      return change->last_emission + fms->rate_limit;
      93    else
      94      return change->last_emission + VIRTUAL_CHANGES_DONE_DELAY;
      95  }
      96  
      97  static int
      98  pending_change_compare_ready_time (gconstpointer a_p,
      99                                     gconstpointer b_p,
     100                                     gpointer      user_data)
     101  {
     102    GFileMonitorSource *fms = user_data;
     103    const PendingChange *a = a_p;
     104    const PendingChange *b = b_p;
     105    gint64 ready_time_a;
     106    gint64 ready_time_b;
     107  
     108    ready_time_a = pending_change_get_ready_time (a, fms);
     109    ready_time_b = pending_change_get_ready_time (b, fms);
     110  
     111    if (ready_time_a < ready_time_b)
     112      return -1;
     113    else
     114      return ready_time_a > ready_time_b;
     115  }
     116  
     117  static void
     118  pending_change_free (gpointer data)
     119  {
     120    PendingChange *change = data;
     121  
     122    g_free (change->child);
     123  
     124    g_slice_free (PendingChange, change);
     125  }
     126  
     127  static void
     128  queued_event_free (QueuedEvent *event)
     129  {
     130    g_object_unref (event->child);
     131    if (event->other)
     132      g_object_unref (event->other);
     133  
     134    g_slice_free (QueuedEvent, event);
     135  }
     136  
     137  static gint64
     138  g_file_monitor_source_get_ready_time (GFileMonitorSource *fms)
     139  {
     140    GSequenceIter *iter;
     141  
     142    if (fms->event_queue.length)
     143      return 0;
     144  
     145    iter = g_sequence_get_begin_iter (fms->pending_changes);
     146    if (g_sequence_iter_is_end (iter))
     147      return -1;
     148  
     149    return pending_change_get_ready_time (g_sequence_get (iter), fms);
     150  }
     151  
     152  static void
     153  g_file_monitor_source_update_ready_time (GFileMonitorSource *fms)
     154  {
     155    g_source_set_ready_time ((GSource *) fms, g_file_monitor_source_get_ready_time (fms));
     156  }
     157  
     158  static GSequenceIter *
     159  g_file_monitor_source_find_pending_change (GFileMonitorSource *fms,
     160                                             const gchar        *child)
     161  {
     162    return g_hash_table_lookup (fms->pending_changes_table, child);
     163  }
     164  
     165  static void
     166  g_file_monitor_source_add_pending_change (GFileMonitorSource *fms,
     167                                            const gchar        *child,
     168                                            gint64              now)
     169  {
     170    PendingChange *change;
     171    GSequenceIter *iter;
     172  
     173    change = g_slice_new (PendingChange);
     174    change->child = g_strdup (child);
     175    change->last_emission = now;
     176    change->dirty = FALSE;
     177  
     178    iter = g_sequence_insert_sorted (fms->pending_changes, change, pending_change_compare_ready_time, fms);
     179    g_hash_table_insert (fms->pending_changes_table, change->child, iter);
     180  }
     181  
     182  static gboolean
     183  g_file_monitor_source_set_pending_change_dirty (GFileMonitorSource *fms,
     184                                                  GSequenceIter      *iter)
     185  {
     186    PendingChange *change;
     187  
     188    change = g_sequence_get (iter);
     189  
     190    /* if it was already dirty then this change is 'uninteresting' */
     191    if (change->dirty)
     192      return FALSE;
     193  
     194    change->dirty = TRUE;
     195  
     196    g_sequence_sort_changed (iter, pending_change_compare_ready_time, fms);
     197  
     198    return TRUE;
     199  }
     200  
     201  static gboolean
     202  g_file_monitor_source_get_pending_change_dirty (GFileMonitorSource *fms,
     203                                                  GSequenceIter      *iter)
     204  {
     205    PendingChange *change;
     206  
     207    change = g_sequence_get (iter);
     208  
     209    return change->dirty;
     210  }
     211  
     212  static void
     213  g_file_monitor_source_remove_pending_change (GFileMonitorSource *fms,
     214                                               GSequenceIter      *iter,
     215                                               const gchar        *child)
     216  {
     217    /* must remove the hash entry first -- its key is owned by the data
     218     * which will be freed when removing the sequence iter
     219     */
     220    g_hash_table_remove (fms->pending_changes_table, child);
     221    g_sequence_remove (iter);
     222  }
     223  
     224  static void
     225  g_file_monitor_source_queue_event (GFileMonitorSource *fms,
     226                                     GFileMonitorEvent   event_type,
     227                                     const gchar        *child,
     228                                     GFile              *other)
     229  {
     230    QueuedEvent *event;
     231  
     232    event = g_slice_new (QueuedEvent);
     233    event->event_type = event_type;
     234    if (child != NULL && fms->dirname != NULL)
     235      event->child = g_local_file_new_from_dirname_and_basename (fms->dirname, child);
     236    else if (child != NULL)
     237      {
     238        gchar *dirname = g_path_get_dirname (fms->filename);
     239        event->child = g_local_file_new_from_dirname_and_basename (dirname, child);
     240        g_free (dirname);
     241      }
     242    else if (fms->dirname)
     243      event->child = _g_local_file_new (fms->dirname);
     244    else if (fms->filename)
     245      event->child = _g_local_file_new (fms->filename);
     246    event->other = other;
     247    if (other)
     248      g_object_ref (other);
     249  
     250    g_queue_push_tail (&fms->event_queue, event);
     251  }
     252  
     253  static gboolean
     254  g_file_monitor_source_file_changed (GFileMonitorSource *fms,
     255                                      const gchar        *child,
     256                                      gint64              now)
     257  {
     258    GSequenceIter *pending;
     259    gboolean interesting;
     260  
     261    pending = g_file_monitor_source_find_pending_change (fms, child);
     262  
     263    /* If there is no pending change, emit one and create a record,
     264     * else: just mark the existing record as dirty.
     265     */
     266    if (!pending)
     267      {
     268        g_file_monitor_source_queue_event (fms, G_FILE_MONITOR_EVENT_CHANGED, child, NULL);
     269        g_file_monitor_source_add_pending_change (fms, child, now);
     270        interesting = TRUE;
     271      }
     272    else
     273      interesting = g_file_monitor_source_set_pending_change_dirty (fms, pending);
     274  
     275    g_file_monitor_source_update_ready_time (fms);
     276  
     277    return interesting;
     278  }
     279  
     280  static void
     281  g_file_monitor_source_file_changes_done (GFileMonitorSource *fms,
     282                                           const gchar        *child)
     283  {
     284    GSequenceIter *pending;
     285  
     286    pending = g_file_monitor_source_find_pending_change (fms, child);
     287    if (pending)
     288      {
     289        /* If it is dirty, make sure we push out the last CHANGED event */
     290        if (g_file_monitor_source_get_pending_change_dirty (fms, pending))
     291          g_file_monitor_source_queue_event (fms, G_FILE_MONITOR_EVENT_CHANGED, child, NULL);
     292  
     293        g_file_monitor_source_queue_event (fms, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, child, NULL);
     294        g_file_monitor_source_remove_pending_change (fms, pending, child);
     295      }
     296  }
     297  
     298  static void
     299  g_file_monitor_source_file_created (GFileMonitorSource *fms,
     300                                      const gchar        *child,
     301                                      gint64              event_time)
     302  {
     303    /* Unlikely, but if we have pending changes for this filename, make
     304     * sure we flush those out first, before creating the new ones.
     305     */
     306    g_file_monitor_source_file_changes_done (fms, child);
     307  
     308    /* Emit CREATE and add a pending changes record */
     309    g_file_monitor_source_queue_event (fms, G_FILE_MONITOR_EVENT_CREATED, child, NULL);
     310    g_file_monitor_source_add_pending_change (fms, child, event_time);
     311  }
     312  
     313  static void
     314  g_file_monitor_source_send_event (GFileMonitorSource *fms,
     315                                    GFileMonitorEvent   event_type,
     316                                    const gchar        *child,
     317                                    GFile              *other)
     318  {
     319    /* always flush any pending changes before we queue a new event */
     320    g_file_monitor_source_file_changes_done (fms, child);
     321    g_file_monitor_source_queue_event (fms, event_type, child, other);
     322  }
     323  
     324  static void
     325  g_file_monitor_source_send_synthetic_created (GFileMonitorSource *fms,
     326                                                const gchar        *child)
     327  {
     328    g_file_monitor_source_file_changes_done (fms, child);
     329    g_file_monitor_source_queue_event (fms, G_FILE_MONITOR_EVENT_CREATED, child, NULL);
     330    g_file_monitor_source_queue_event (fms, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, child, NULL);
     331  }
     332  
     333  #ifndef G_DISABLE_ASSERT
     334  static gboolean
     335  is_basename (const gchar *name)
     336  {
     337    if (name[0] == '.' && ((name[1] == '.' && name[2] == '\0') || name[1] == '\0'))
     338      return FALSE;
     339  
     340    return !strchr (name, '/');
     341  }
     342  #endif  /* !G_DISABLE_ASSERT */
     343  
     344  gboolean
     345  g_file_monitor_source_handle_event (GFileMonitorSource *fms,
     346                                      GFileMonitorEvent   event_type,
     347                                      const gchar        *child,
     348                                      const gchar        *rename_to,
     349                                      GFile              *other,
     350                                      gint64              event_time)
     351  {
     352    gboolean interesting = TRUE;
     353  
     354    g_assert (!child || is_basename (child));
     355    g_assert (!rename_to || is_basename (rename_to));
     356  
     357    if (fms->basename && (!child || !g_str_equal (child, fms->basename))
     358                      && (!rename_to || !g_str_equal (rename_to, fms->basename)))
     359      return TRUE;
     360  
     361    g_mutex_lock (&fms->lock);
     362  
     363    /* NOTE:
     364     *
     365     * We process events even if the file monitor has already been disposed.
     366     * The reason is that we must not take a reference to the instance here as
     367     * destroying it from the event handling thread will lead to a deadlock when
     368     * taking the lock in _ih_sub_cancel.
     369     *
     370     * This results in seemingly-unbounded growth of the `event_queue` with the
     371     * calls to `g_file_monitor_source_queue_event()`. However, each of those sets
     372     * the ready time on the #GSource, which means that it will be dispatched in
     373     * a subsequent iteration of the #GMainContext it’s attached to. At that
     374     * point, `g_file_monitor_source_dispatch()` will return %FALSE, and this will
     375     * trigger finalisation of the source. That will clear the `event_queue`.
     376     *
     377     * If the source is no longer attached, this will return early to prevent
     378     * unbounded queueing.
     379     */
     380    if (g_source_is_destroyed ((GSource *) fms))
     381      {
     382        g_mutex_unlock (&fms->lock);
     383        return TRUE;
     384      }
     385  
     386    switch (event_type)
     387      {
     388      case G_FILE_MONITOR_EVENT_CREATED:
     389        g_assert (!other && !rename_to);
     390        g_file_monitor_source_file_created (fms, child, event_time);
     391        break;
     392  
     393      case G_FILE_MONITOR_EVENT_CHANGED:
     394        g_assert (!other && !rename_to);
     395        interesting = g_file_monitor_source_file_changed (fms, child, event_time);
     396        break;
     397  
     398      case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
     399        g_assert (!other && !rename_to);
     400        g_file_monitor_source_file_changes_done (fms, child);
     401        break;
     402  
     403      case G_FILE_MONITOR_EVENT_MOVED_IN:
     404        g_assert (!rename_to);
     405        if (fms->flags & G_FILE_MONITOR_WATCH_MOVES)
     406          g_file_monitor_source_send_event (fms, G_FILE_MONITOR_EVENT_MOVED_IN, child, other);
     407        else
     408          g_file_monitor_source_send_synthetic_created (fms, child);
     409        break;
     410  
     411      case G_FILE_MONITOR_EVENT_MOVED_OUT:
     412        g_assert (!rename_to);
     413        if (fms->flags & G_FILE_MONITOR_WATCH_MOVES)
     414          g_file_monitor_source_send_event (fms, G_FILE_MONITOR_EVENT_MOVED_OUT, child, other);
     415        else if (other && (fms->flags & G_FILE_MONITOR_SEND_MOVED))
     416          g_file_monitor_source_send_event (fms, G_FILE_MONITOR_EVENT_MOVED, child, other);
     417        else
     418          g_file_monitor_source_send_event (fms, G_FILE_MONITOR_EVENT_DELETED, child, NULL);
     419        break;
     420  
     421      case G_FILE_MONITOR_EVENT_RENAMED:
     422        g_assert (!other && rename_to);
     423        if (fms->flags & (G_FILE_MONITOR_WATCH_MOVES | G_FILE_MONITOR_SEND_MOVED))
     424          {
     425            GFile *other_file;
     426            const gchar *dirname;
     427            gchar *allocated_dirname = NULL;
     428            GFileMonitorEvent event;
     429  
     430            event = (fms->flags & G_FILE_MONITOR_WATCH_MOVES) ? G_FILE_MONITOR_EVENT_RENAMED : G_FILE_MONITOR_EVENT_MOVED;
     431  
     432            if (fms->dirname != NULL)
     433              dirname = fms->dirname;
     434            else
     435              {
     436                allocated_dirname = g_path_get_dirname (fms->filename);
     437                dirname = allocated_dirname;
     438              }
     439  
     440            other_file = g_local_file_new_from_dirname_and_basename (dirname, rename_to);
     441            g_file_monitor_source_file_changes_done (fms, rename_to);
     442            g_file_monitor_source_send_event (fms, event, child, other_file);
     443  
     444            g_object_unref (other_file);
     445            g_free (allocated_dirname);
     446          }
     447        else
     448          {
     449            g_file_monitor_source_send_event (fms, G_FILE_MONITOR_EVENT_DELETED, child, NULL);
     450            g_file_monitor_source_send_synthetic_created (fms, rename_to);
     451          }
     452        break;
     453  
     454      case G_FILE_MONITOR_EVENT_DELETED:
     455      case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
     456      case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
     457      case G_FILE_MONITOR_EVENT_UNMOUNTED:
     458        g_assert (!other && !rename_to);
     459        g_file_monitor_source_send_event (fms, event_type, child, NULL);
     460        break;
     461  
     462      case G_FILE_MONITOR_EVENT_MOVED:
     463        /* was never available in this API */
     464      default:
     465        g_assert_not_reached ();
     466      }
     467  
     468    g_file_monitor_source_update_ready_time (fms);
     469  
     470    g_mutex_unlock (&fms->lock);
     471  
     472    return interesting;
     473  }
     474  
     475  static gint64
     476  g_file_monitor_source_get_rate_limit (GFileMonitorSource *fms)
     477  {
     478    gint64 rate_limit;
     479  
     480    g_mutex_lock (&fms->lock);
     481    rate_limit = fms->rate_limit;
     482    g_mutex_unlock (&fms->lock);
     483  
     484    return rate_limit;
     485  }
     486  
     487  static gboolean
     488  g_file_monitor_source_set_rate_limit (GFileMonitorSource *fms,
     489                                        gint64              rate_limit)
     490  {
     491    gboolean changed;
     492  
     493    g_mutex_lock (&fms->lock);
     494  
     495    if (rate_limit != fms->rate_limit)
     496      {
     497        fms->rate_limit = rate_limit;
     498  
     499        g_sequence_sort (fms->pending_changes, pending_change_compare_ready_time, fms);
     500        g_file_monitor_source_update_ready_time (fms);
     501  
     502        changed = TRUE;
     503      }
     504    else
     505      changed = FALSE;
     506  
     507    g_mutex_unlock (&fms->lock);
     508  
     509    return changed;
     510  }
     511  
     512  static gboolean
     513  g_file_monitor_source_dispatch (GSource     *source,
     514                                  GSourceFunc  callback,
     515                                  gpointer     user_data)
     516  {
     517    GFileMonitorSource *fms = (GFileMonitorSource *) source;
     518    QueuedEvent *event;
     519    GQueue event_queue;
     520    gint64 now;
     521    GFileMonitor *instance = NULL;
     522  
     523    /* make sure the monitor still exists */
     524    instance = g_weak_ref_get (&fms->instance_ref);
     525    if (instance == NULL)
     526      return FALSE;
     527  
     528    now = g_source_get_time (source);
     529  
     530    /* Acquire the lock once and grab all events in one go, handling the
     531     * queued events first.  This avoids strange possibilities in cases of
     532     * long delays, such as CHANGED events coming before CREATED events.
     533     *
     534     * We do this by converting the applicable pending changes into queued
     535     * events (after the ones already queued) and then stealing the entire
     536     * event queue in one go.
     537     */
     538    g_mutex_lock (&fms->lock);
     539  
     540    /* Create events for any pending changes that are due to fire */
     541    while (!g_sequence_is_empty (fms->pending_changes))
     542      {
     543        GSequenceIter *iter = g_sequence_get_begin_iter (fms->pending_changes);
     544        PendingChange *pending = g_sequence_get (iter);
     545  
     546        /* We've gotten to a pending change that's not ready.  Stop. */
     547        if (pending_change_get_ready_time (pending, fms) > now)
     548          break;
     549  
     550        if (pending->dirty)
     551          {
     552            /* It's time to send another CHANGED and update the record */
     553            g_file_monitor_source_queue_event (fms, G_FILE_MONITOR_EVENT_CHANGED, pending->child, NULL);
     554            pending->last_emission = now;
     555            pending->dirty = FALSE;
     556  
     557            g_sequence_sort_changed (iter, pending_change_compare_ready_time, fms);
     558          }
     559        else
     560          {
     561            /* It's time to send CHANGES_DONE and remove the pending record */
     562            g_file_monitor_source_queue_event (fms, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, pending->child, NULL);
     563            g_file_monitor_source_remove_pending_change (fms, iter, pending->child);
     564          }
     565      }
     566  
     567    /* Steal the queue */
     568    memcpy (&event_queue, &fms->event_queue, sizeof event_queue);
     569    memset (&fms->event_queue, 0, sizeof fms->event_queue);
     570  
     571    g_file_monitor_source_update_ready_time (fms);
     572  
     573    g_mutex_unlock (&fms->lock);
     574    g_clear_object (&instance);
     575  
     576    /* We now have our list of events to deliver */
     577    while ((event = g_queue_pop_head (&event_queue)))
     578      {
     579        /* an event handler could destroy 'instance', so check each time */
     580        instance = g_weak_ref_get (&fms->instance_ref);
     581        if (instance != NULL)
     582          g_file_monitor_emit_event (instance, event->child, event->other, event->event_type);
     583  
     584        g_clear_object (&instance);
     585        queued_event_free (event);
     586      }
     587  
     588    return TRUE;
     589  }
     590  
     591  static void
     592  g_file_monitor_source_dispose (GFileMonitorSource *fms)
     593  {
     594    GHashTableIter iter;
     595    gpointer seqiter;
     596    QueuedEvent *event;
     597  
     598    g_mutex_lock (&fms->lock);
     599  
     600    g_hash_table_iter_init (&iter, fms->pending_changes_table);
     601    while (g_hash_table_iter_next (&iter, NULL, &seqiter))
     602      {
     603        g_hash_table_iter_remove (&iter);
     604        g_sequence_remove (seqiter);
     605      }
     606  
     607    while ((event = g_queue_pop_head (&fms->event_queue)))
     608      queued_event_free (event);
     609  
     610    g_assert (g_sequence_is_empty (fms->pending_changes));
     611    g_assert (g_hash_table_size (fms->pending_changes_table) == 0);
     612    g_assert (fms->event_queue.length == 0);
     613    g_weak_ref_set (&fms->instance_ref, NULL);
     614  
     615    g_file_monitor_source_update_ready_time (fms);
     616  
     617    g_source_destroy ((GSource *) fms);
     618  
     619    g_mutex_unlock (&fms->lock);
     620  }
     621  
     622  static void
     623  g_file_monitor_source_finalize (GSource *source)
     624  {
     625    GFileMonitorSource *fms = (GFileMonitorSource *) source;
     626  
     627    /* should already have been cleared in dispose of the monitor */
     628    g_assert (g_weak_ref_get (&fms->instance_ref) == NULL);
     629    g_weak_ref_clear (&fms->instance_ref);
     630  
     631    g_assert (g_sequence_is_empty (fms->pending_changes));
     632    g_assert (g_hash_table_size (fms->pending_changes_table) == 0);
     633    g_assert (fms->event_queue.length == 0);
     634  
     635    g_hash_table_unref (fms->pending_changes_table);
     636    g_sequence_free (fms->pending_changes);
     637  
     638    g_free (fms->dirname);
     639    g_free (fms->basename);
     640    g_free (fms->filename);
     641  
     642    g_mutex_clear (&fms->lock);
     643  }
     644  
     645  static guint
     646  str_hash0 (gconstpointer str)
     647  {
     648    return str ? g_str_hash (str) : 0;
     649  }
     650  
     651  static gboolean
     652  str_equal0 (gconstpointer a,
     653              gconstpointer b)
     654  {
     655    return g_strcmp0 (a, b) == 0;
     656  }
     657  
     658  static GFileMonitorSource *
     659  g_file_monitor_source_new (gpointer           instance,
     660                             const gchar       *filename,
     661                             gboolean           is_directory,
     662                             GFileMonitorFlags  flags)
     663  {
     664    static GSourceFuncs source_funcs = {
     665      NULL, NULL,
     666      g_file_monitor_source_dispatch,
     667      g_file_monitor_source_finalize,
     668      NULL, NULL
     669    };
     670    GFileMonitorSource *fms;
     671    GSource *source;
     672  
     673    source = g_source_new (&source_funcs, sizeof (GFileMonitorSource));
     674    fms = (GFileMonitorSource *) source;
     675  
     676    g_source_set_static_name (source, "GFileMonitorSource");
     677  
     678    g_mutex_init (&fms->lock);
     679    g_weak_ref_init (&fms->instance_ref, instance);
     680    fms->pending_changes = g_sequence_new (pending_change_free);
     681    fms->pending_changes_table = g_hash_table_new (str_hash0, str_equal0);
     682    fms->rate_limit = DEFAULT_RATE_LIMIT;
     683    fms->flags = flags;
     684  
     685    if (is_directory)
     686      {
     687        fms->dirname = g_strdup (filename);
     688        fms->basename = NULL;
     689        fms->filename = NULL;
     690      }
     691    else if (flags & G_FILE_MONITOR_WATCH_HARD_LINKS)
     692      {
     693        fms->dirname = NULL;
     694        fms->basename = NULL;
     695        fms->filename = g_strdup (filename);
     696      }
     697    else
     698      {
     699        fms->dirname = g_path_get_dirname (filename);
     700        fms->basename = g_path_get_basename (filename);
     701        fms->filename = NULL;
     702      }
     703  
     704    return fms;
     705  }
     706  
     707  G_DEFINE_ABSTRACT_TYPE (GLocalFileMonitor, g_local_file_monitor, G_TYPE_FILE_MONITOR)
     708  
     709  enum {
     710    PROP_0,
     711    PROP_RATE_LIMIT,
     712  };
     713  
     714  static void
     715  g_local_file_monitor_get_property (GObject *object, guint prop_id,
     716                                     GValue *value, GParamSpec *pspec)
     717  {
     718    GLocalFileMonitor *monitor = G_LOCAL_FILE_MONITOR (object);
     719    gint64 rate_limit;
     720  
     721    g_assert (prop_id == PROP_RATE_LIMIT);
     722  
     723    rate_limit = g_file_monitor_source_get_rate_limit (monitor->source);
     724    rate_limit /= G_TIME_SPAN_MILLISECOND;
     725  
     726    g_value_set_int (value, rate_limit);
     727  }
     728  
     729  static void
     730  g_local_file_monitor_set_property (GObject *object, guint prop_id,
     731                                     const GValue *value, GParamSpec *pspec)
     732  {
     733    GLocalFileMonitor *monitor = G_LOCAL_FILE_MONITOR (object);
     734    gint64 rate_limit;
     735  
     736    g_assert (prop_id == PROP_RATE_LIMIT);
     737  
     738    rate_limit = g_value_get_int (value);
     739    rate_limit *= G_TIME_SPAN_MILLISECOND;
     740  
     741    if (g_file_monitor_source_set_rate_limit (monitor->source, rate_limit))
     742      g_object_notify (object, "rate-limit");
     743  }
     744  
     745  #ifndef G_OS_WIN32
     746  static void
     747  g_local_file_monitor_mounts_changed (GUnixMountMonitor *mount_monitor,
     748                                       gpointer           user_data)
     749  {
     750    GLocalFileMonitor *local_monitor = user_data;
     751    GUnixMountEntry *mount;
     752    gboolean is_mounted;
     753    GFile *file;
     754  
     755    /* Emulate unmount detection */
     756    mount = g_unix_mount_at (local_monitor->source->dirname, NULL);
     757  
     758    is_mounted = mount != NULL;
     759  
     760    if (mount)
     761      g_unix_mount_free (mount);
     762  
     763    if (local_monitor->was_mounted != is_mounted)
     764      {
     765        if (local_monitor->was_mounted && !is_mounted)
     766          {
     767            file = g_file_new_for_path (local_monitor->source->dirname);
     768            g_file_monitor_emit_event (G_FILE_MONITOR (local_monitor), file, NULL, G_FILE_MONITOR_EVENT_UNMOUNTED);
     769            g_object_unref (file);
     770          }
     771        local_monitor->was_mounted = is_mounted;
     772      }
     773  }
     774  #endif
     775  
     776  static void
     777  g_local_file_monitor_start (GLocalFileMonitor *local_monitor,
     778                              const gchar       *filename,
     779                              gboolean           is_directory,
     780                              GFileMonitorFlags  flags,
     781                              GMainContext      *context)
     782  {
     783    GLocalFileMonitorClass *class = G_LOCAL_FILE_MONITOR_GET_CLASS (local_monitor);
     784    GFileMonitorSource *source;
     785  
     786    g_return_if_fail (G_IS_LOCAL_FILE_MONITOR (local_monitor));
     787  
     788    g_assert (!local_monitor->source);
     789  
     790    source = g_file_monitor_source_new (local_monitor, filename, is_directory, flags);
     791    local_monitor->source = source; /* owns the ref */
     792  
     793    if (is_directory && !class->mount_notify && (flags & G_FILE_MONITOR_WATCH_MOUNTS))
     794      {
     795  #ifdef G_OS_WIN32
     796        /*claim everything was mounted */
     797        local_monitor->was_mounted = TRUE;
     798  #else
     799        GUnixMountEntry *mount;
     800  
     801        /* Emulate unmount detection */
     802  
     803        mount = g_unix_mount_at (local_monitor->source->dirname, NULL);
     804  
     805        local_monitor->was_mounted = mount != NULL;
     806  
     807        if (mount)
     808          g_unix_mount_free (mount);
     809  
     810        local_monitor->mount_monitor = g_unix_mount_monitor_get ();
     811        g_signal_connect_object (local_monitor->mount_monitor, "mounts-changed",
     812                                 G_CALLBACK (g_local_file_monitor_mounts_changed), local_monitor,
     813                                 G_CONNECT_DEFAULT);
     814  #endif
     815      }
     816  
     817    g_source_attach ((GSource *) source, context);
     818  
     819    G_LOCAL_FILE_MONITOR_GET_CLASS (local_monitor)->start (local_monitor,
     820                                                           source->dirname, source->basename, source->filename,
     821                                                           source);
     822  }
     823  
     824  static void
     825  g_local_file_monitor_dispose (GObject *object)
     826  {
     827    GLocalFileMonitor *local_monitor = G_LOCAL_FILE_MONITOR (object);
     828  
     829    g_file_monitor_source_dispose (local_monitor->source);
     830  
     831    G_OBJECT_CLASS (g_local_file_monitor_parent_class)->dispose (object);
     832  }
     833  
     834  static void
     835  g_local_file_monitor_finalize (GObject *object)
     836  {
     837    GLocalFileMonitor *local_monitor = G_LOCAL_FILE_MONITOR (object);
     838  
     839    g_source_unref ((GSource *) local_monitor->source);
     840  
     841    G_OBJECT_CLASS (g_local_file_monitor_parent_class)->finalize (object);
     842  }
     843  
     844  static void
     845  g_local_file_monitor_init (GLocalFileMonitor* local_monitor)
     846  {
     847  }
     848  
     849  static void g_local_file_monitor_class_init (GLocalFileMonitorClass *class)
     850  {
     851    GObjectClass *gobject_class = G_OBJECT_CLASS (class);
     852  
     853    gobject_class->get_property = g_local_file_monitor_get_property;
     854    gobject_class->set_property = g_local_file_monitor_set_property;
     855    gobject_class->dispose = g_local_file_monitor_dispose;
     856    gobject_class->finalize = g_local_file_monitor_finalize;
     857  
     858    g_object_class_override_property (gobject_class, PROP_RATE_LIMIT, "rate-limit");
     859  }
     860  
     861  static GLocalFileMonitor *
     862  g_local_file_monitor_new (gboolean   is_remote_fs,
     863                            gboolean   is_directory,
     864                            GError   **error)
     865  {
     866    GType type = G_TYPE_INVALID;
     867  
     868    if (is_remote_fs)
     869      type = _g_io_module_get_default_type (G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME,
     870                                            "GIO_USE_FILE_MONITOR",
     871                                            G_STRUCT_OFFSET (GLocalFileMonitorClass, is_supported));
     872  
     873    /* Fallback rather to poll file monitor for remote files, see gfile.c. */
     874    if (type == G_TYPE_INVALID && (!is_remote_fs || is_directory))
     875      type = _g_io_module_get_default_type (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME,
     876                                            "GIO_USE_FILE_MONITOR",
     877                                            G_STRUCT_OFFSET (GLocalFileMonitorClass, is_supported));
     878  
     879    if (type == G_TYPE_INVALID)
     880      {
     881        g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
     882                             _("Unable to find default local file monitor type"));
     883        return NULL;
     884      }
     885  
     886    return g_object_new (type, NULL);
     887  }
     888  
     889  GFileMonitor *
     890  g_local_file_monitor_new_for_path (const gchar        *pathname,
     891                                     gboolean            is_directory,
     892                                     GFileMonitorFlags   flags,
     893                                     GError            **error)
     894  {
     895    GLocalFileMonitor *monitor;
     896    gboolean is_remote_fs;
     897  
     898    is_remote_fs = g_local_file_is_nfs_home (pathname);
     899  
     900    monitor = g_local_file_monitor_new (is_remote_fs, is_directory, error);
     901  
     902    if (monitor)
     903      g_local_file_monitor_start (monitor, pathname, is_directory, flags, g_main_context_get_thread_default ());
     904  
     905    return G_FILE_MONITOR (monitor);
     906  }
     907  
     908  GFileMonitor *
     909  g_local_file_monitor_new_in_worker (const gchar           *pathname,
     910                                      gboolean               is_directory,
     911                                      GFileMonitorFlags      flags,
     912                                      GFileMonitorCallback   callback,
     913                                      gpointer               user_data,
     914                                      GClosureNotify         destroy_user_data,
     915                                      GError               **error)
     916  {
     917    GLocalFileMonitor *monitor;
     918    gboolean is_remote_fs;
     919  
     920    is_remote_fs = g_local_file_is_nfs_home (pathname);
     921  
     922    monitor = g_local_file_monitor_new (is_remote_fs, is_directory, error);
     923  
     924    if (monitor)
     925      {
     926        if (callback)
     927          g_signal_connect_data (monitor, "changed", G_CALLBACK (callback),
     928                                 user_data, destroy_user_data, G_CONNECT_DEFAULT);
     929  
     930        g_local_file_monitor_start (monitor, pathname, is_directory, flags, GLIB_PRIVATE_CALL(g_get_worker_context) ());
     931      }
     932  
     933    return G_FILE_MONITOR (monitor);
     934  }