(root)/
glib-2.79.0/
gio/
kqueue/
gkqueuefilemonitor.c
       1  /*******************************************************************************
       2    Copyright (c) 2011, 2012 Dmitry Matveev <me@dmitrymatveev.co.uk>
       3  
       4    Permission is hereby granted, free of charge, to any person obtaining a copy
       5    of this software and associated documentation files (the "Software"), to deal
       6    in the Software without restriction, including without limitation the rights
       7    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       8    copies of the Software, and to permit persons to whom the Software is
       9    furnished to do so, subject to the following conditions:
      10  
      11    The above copyright notice and this permission notice shall be included in
      12    all copies or substantial portions of the Software.
      13  
      14    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      17    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      19    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      20    THE SOFTWARE.
      21  *******************************************************************************/
      22  
      23  #include "config.h"
      24  
      25  #include <sys/types.h>
      26  #include <sys/event.h>
      27  #include <sys/time.h>
      28  #include <sys/socket.h>
      29  #include <sys/stat.h>
      30  
      31  #include <errno.h>
      32  #include <fcntl.h>
      33  #include <string.h>
      34  
      35  #ifndef O_CLOEXEC
      36  #define O_CLOEXEC 0
      37  #endif
      38  
      39  #include <glib-object.h>
      40  #include <glib/gfileutils.h>
      41  #include <gio/gfilemonitor.h>
      42  #include <gio/glocalfilemonitor.h>
      43  #include <gio/giomodule.h>
      44  #include <gio/gpollfilemonitor.h>
      45  #include <gio/gfile.h>
      46  #include <glib-unix.h>
      47  #include "glib-private.h"
      48  
      49  #include "kqueue-helper.h"
      50  #include "dep-list.h"
      51  
      52  G_LOCK_DEFINE_STATIC (kq_lock);
      53  static GSource       *kq_source;
      54  static int	      kq_queue = -1;
      55  
      56  #define G_TYPE_KQUEUE_FILE_MONITOR	(g_kqueue_file_monitor_get_type ())
      57  #define G_KQUEUE_FILE_MONITOR(inst)	(G_TYPE_CHECK_INSTANCE_CAST ((inst), \
      58  					G_TYPE_KQUEUE_FILE_MONITOR, GKqueueFileMonitor))
      59  
      60  /* C11 allows type redefinition, but GLib is configured to use C89, which causes
      61   * clang to show warnings when we use a C11 feature. Since the C89 requirement
      62   * is mostly used to support MSVC, we simply ignore the warning here because
      63   * this file is never going to be useful on Windows. */
      64  #ifdef __clang__
      65  #pragma clang diagnostic push
      66  #pragma clang diagnostic ignored "-Wtypedef-redefinition"
      67  #endif
      68  
      69  typedef GLocalFileMonitorClass GKqueueFileMonitorClass;
      70  
      71  /* When the file we are monitoring is a directory, sub_dir is subscribed to the
      72   * directory itself and sub_file is NULL.
      73   *
      74   * When the file we are monitoring is a regular file, sub_dir is subscribed to
      75   * the directory containing the file and sub_file is subscribed to the file
      76   * being monitored. We have to monitor both because it is possible that the
      77   * file chosen for monitoring doesn't exist when the file monitor is started.
      78   * We monitor on its parent in order to get notification when it is created.
      79   *
      80   * To distinguish between a directory monitor and a regular file monitor, check
      81   * whether sub_file is NULL. */
      82  struct _GKqueueFileMonitor
      83  {
      84    GLocalFileMonitor parent_instance;
      85  
      86    kqueue_sub *sub_dir;
      87    kqueue_sub *sub_file;
      88  #ifndef O_EVTONLY
      89    GFileMonitor *fallback;
      90    GFile *fbfile;
      91  #endif
      92  };
      93  
      94  #ifdef __clang__
      95  #pragma clang diagnostic pop
      96  #endif
      97  
      98  GType g_kqueue_file_monitor_get_type (void);
      99  G_DEFINE_TYPE_WITH_CODE (GKqueueFileMonitor, g_kqueue_file_monitor, G_TYPE_LOCAL_FILE_MONITOR,
     100  	g_io_extension_point_implement (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME,
     101  		g_define_type_id,
     102                  "kqueue",
     103  		20))
     104  
     105  #ifndef O_EVTONLY
     106  #define O_KQFLAG O_RDONLY
     107  #else
     108  #define O_KQFLAG O_EVTONLY
     109  #endif
     110  
     111  static inline unsigned int
     112  note_all (void)
     113  {
     114    unsigned int notes = NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE;
     115  #ifdef NOTE_TRUNCATE
     116    notes |= NOTE_TRUNCATE;
     117  #endif
     118  #ifdef NOTE_CLOSE_WRITE
     119    notes |= NOTE_CLOSE_WRITE;
     120  #endif
     121    return notes;
     122  }
     123  
     124  static gboolean g_kqueue_file_monitor_cancel (GFileMonitor* monitor);
     125  static gboolean g_kqueue_file_monitor_is_supported (void);
     126  
     127  static kqueue_sub	*_kqsub_new (gchar *, gchar *, GKqueueFileMonitor *, GFileMonitorSource *);
     128  static void		 _kqsub_free (kqueue_sub *);
     129  static void		 _kqsub_cancel (kqueue_sub *);
     130  
     131  
     132  #ifndef O_EVTONLY
     133  static void
     134  _fallback_callback (GFileMonitor      *unused,
     135                      GFile             *first,
     136                      GFile             *second,
     137                      GFileMonitorEvent  event,
     138                      gpointer           udata)
     139  {
     140    GKqueueFileMonitor *kq_mon = G_KQUEUE_FILE_MONITOR (udata);
     141  
     142    g_file_monitor_emit_event (G_FILE_MONITOR (kq_mon), first, second, event);
     143  }
     144  
     145  /*
     146   * _ke_is_excluded:
     147   * @full_path - a path to file to check.
     148   *
     149   * Returns: TRUE if the file should be excluded from the kqueue-powered
     150   *      monitoring, FALSE otherwise.
     151   **/
     152  static gboolean
     153  _ke_is_excluded (const char *full_path)
     154  {
     155    GFile *f = NULL;
     156    GMount *mount = NULL;
     157  
     158    f = g_file_new_for_path (full_path);
     159  
     160    if (f != NULL) {
     161      mount = g_file_find_enclosing_mount (f, NULL, NULL);
     162      g_object_unref (f);
     163    }
     164  
     165    if (mount != NULL && (g_str_has_prefix (full_path, "/media/") || g_str_has_prefix (full_path, "/run/media/")))
     166    {
     167      g_warning ("Excluding %s from kernel notification, falling back to poll", full_path);
     168      if (mount)
     169        g_object_unref (mount);
     170      return TRUE;
     171    }
     172  
     173    return FALSE;
     174  }
     175  #endif /* !O_EVTONLY */
     176  
     177  static void
     178  g_kqueue_file_monitor_finalize (GObject *object)
     179  {
     180    GKqueueFileMonitor *kqueue_monitor = G_KQUEUE_FILE_MONITOR (object);
     181  
     182    if (kqueue_monitor->sub_dir)
     183      {
     184        _kqsub_cancel (kqueue_monitor->sub_dir);
     185        _kqsub_free (kqueue_monitor->sub_dir);
     186        kqueue_monitor->sub_dir = NULL;
     187      }
     188  
     189    if (kqueue_monitor->sub_file)
     190      {
     191        _kqsub_cancel (kqueue_monitor->sub_file);
     192        _kqsub_free (kqueue_monitor->sub_file);
     193        kqueue_monitor->sub_file = NULL;
     194      }
     195  
     196  #ifndef O_EVTONLY
     197    if (kqueue_monitor->fallback)
     198      g_object_unref (kqueue_monitor->fallback);
     199  
     200    if (kqueue_monitor->fbfile)
     201      g_object_unref (kqueue_monitor->fbfile);
     202  #endif
     203  
     204    if (G_OBJECT_CLASS (g_kqueue_file_monitor_parent_class)->finalize)
     205      (*G_OBJECT_CLASS (g_kqueue_file_monitor_parent_class)->finalize) (object);
     206  }
     207  
     208  static void
     209  g_kqueue_file_monitor_start (GLocalFileMonitor *local_monitor,
     210                               const gchar *dirname,
     211                               const gchar *basename,
     212                               const gchar *filename,
     213                               GFileMonitorSource *source)
     214  {
     215    GKqueueFileMonitor *kqueue_monitor = G_KQUEUE_FILE_MONITOR (local_monitor);
     216    kqueue_sub *sub_dir = NULL, *sub_file = NULL;
     217    gchar *path_dir, *path_file, *file_basename;
     218  
     219    /* There are three possible cases here:
     220     *
     221     *  1. Directory: dirname != NULL, basename == NULL, filename == NULL
     222     *  2. Regular file: dirname != NULL, basename != NULL, filename == NULL
     223     *  3. Hard links: dirname == NULL, basename == NULL, filename != NULL
     224     *
     225     *  Note that we don't distinguish between case 2 and 3. Kqueue monitors
     226     *  files based on file descriptors, so we always receive events come from
     227     *  hard links.
     228     */
     229    if (filename != NULL)
     230      {
     231        path_dir = g_path_get_dirname (filename);
     232        path_file = g_strdup (filename);
     233        file_basename = g_path_get_basename (filename);
     234      }
     235    else
     236      {
     237        path_dir = g_strdup (dirname);
     238        if (basename != NULL)
     239          {
     240            path_file = g_build_filename (dirname, basename, NULL);
     241            file_basename = g_strdup (basename);
     242          }
     243        else
     244          {
     245            path_file = NULL;
     246            file_basename = NULL;
     247          }
     248      }
     249  
     250  #ifndef O_EVTONLY
     251    if (_ke_is_excluded (path_dir))
     252      {
     253        GFile *file;
     254        if (path_file != NULL)
     255          file = g_file_new_for_path (path_file);
     256        else
     257          file = g_file_new_for_path (path_dir);
     258        g_free (path_dir);
     259        g_free (path_file);
     260        g_free (file_basename);
     261        kqueue_monitor->fbfile = file;
     262        kqueue_monitor->fallback = _g_poll_file_monitor_new (file);
     263        g_signal_connect (kqueue_monitor->fallback, "changed",
     264  			G_CALLBACK (_fallback_callback), kqueue_monitor);
     265        return;
     266      }
     267  #endif
     268  
     269    /* For a directory monitor, create a subscription object anyway.
     270     * It will be used for directory diff calculation routines. 
     271     * Wait, directory diff in a GKqueueFileMonitor?
     272     * Yes, it is. When a file monitor is started on a non-existent
     273     * file, GIO uses a GKqueueFileMonitor object for that. If a directory
     274     * will be created under that path, GKqueueFileMonitor will have to
     275     * handle the directory notifications. */
     276    sub_dir = _kqsub_new (g_steal_pointer (&path_dir), NULL,
     277                          kqueue_monitor, source);
     278    if (!_kqsub_start_watching (sub_dir))
     279      _km_add_missing (sub_dir);
     280  
     281    /* Unlike GInotifyFileMonitor, which always uses a directory monitor
     282     * regardless of the type of the file being monitored, kqueue doesn't
     283     * give us events generated by files under it when we are monitoring
     284     * a directory. We have to monitor the file itself to know changes which
     285     * was made to the file itself. */
     286    if (path_file != NULL)
     287      {
     288        sub_file = _kqsub_new (g_steal_pointer (&path_file),
     289                               g_steal_pointer (&file_basename),
     290                               kqueue_monitor, source);
     291        if (!_kqsub_start_watching (sub_file))
     292          _km_add_missing (sub_file);
     293      }
     294  
     295    kqueue_monitor->sub_dir = sub_dir;
     296    kqueue_monitor->sub_file = sub_file;
     297    g_clear_pointer (&path_dir, g_free);
     298    g_clear_pointer (&path_file, g_free);
     299    g_clear_pointer (&file_basename, g_free);
     300  }
     301  
     302  static void
     303  g_kqueue_file_monitor_class_init (GKqueueFileMonitorClass *klass)
     304  {
     305    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     306    GFileMonitorClass *file_monitor_class = G_FILE_MONITOR_CLASS (klass);
     307    GLocalFileMonitorClass *local_file_monitor_class = G_LOCAL_FILE_MONITOR_CLASS (klass);
     308  
     309    gobject_class->finalize = g_kqueue_file_monitor_finalize;
     310    file_monitor_class->cancel = g_kqueue_file_monitor_cancel;
     311  
     312    local_file_monitor_class->is_supported = g_kqueue_file_monitor_is_supported;
     313    local_file_monitor_class->start = g_kqueue_file_monitor_start;
     314    local_file_monitor_class->mount_notify = TRUE; /* TODO: ??? */
     315  }
     316  
     317  static void
     318  g_kqueue_file_monitor_init (GKqueueFileMonitor *monitor)
     319  {
     320  }
     321  
     322  static gboolean
     323  g_kqueue_file_monitor_callback (gint fd, GIOCondition condition, gpointer user_data)
     324  {
     325    gint64 now = g_source_get_time (kq_source);
     326    kqueue_sub *sub;
     327    GFileMonitorSource *source;
     328    struct kevent ev;
     329    struct timespec ts;
     330  
     331    memset (&ts, 0, sizeof(ts));
     332  
     333    /* We must hold the global lock before accessing any kqueue_sub because it is
     334     * possible for other threads to call g_kqueue_file_monitor_cancel, which may
     335     * free the kqueue_sub struct we are accessing. */
     336    G_LOCK (kq_lock);
     337  
     338    while (kevent(fd, NULL, 0, &ev, 1, &ts) > 0)
     339      {
     340          if (ev.filter != EVFILT_VNODE || ev.udata == NULL)
     341            continue;
     342  
     343          sub = ev.udata;
     344          source = sub->source;
     345  
     346          /* When we are monitoring a regular file which already exists, ignore
     347           * events generated by its parent directory. This has to be the first
     348           * check to prevent the following code to emit useless events */
     349          if (sub->is_dir && sub->mon->sub_file != NULL && sub->mon->sub_file->fd != -1)
     350            continue;
     351  
     352          if (ev.flags & EV_ERROR)
     353            ev.fflags = NOTE_REVOKE;
     354  
     355          if (sub->is_dir && ev.fflags & (NOTE_WRITE | NOTE_EXTEND))
     356            {
     357              /* If we are monitoring on a non-existent regular file, trigger the
     358               * rescan of missing files immediately so we don't have to wait for
     359               * 4 seconds for discovering missing files. We pass the sub_file
     360               * corresponding to the GKqueueFileMonitor to 'check_this_sub_only'
     361               * argument to prevent _km_scan_missing from emitting 'CREATED'
     362               * events because _kh_dir_diff will do it for us. */
     363              if (sub->mon->sub_file != NULL && sub->mon->sub_file->fd == -1)
     364                _km_scan_missing (sub->mon->sub_file);
     365  
     366              /* If we are monitoring a regular file, don't emit 'DELETED' events
     367               * from the directory monitor because it will be emitted from the
     368               * file itself when a NOTE_DELETE is reported on sub_file. */
     369              _kh_dir_diff (sub, sub->mon->sub_file == NULL);
     370  
     371  #ifdef NOTE_TRUNCATE
     372              ev.fflags &= ~(NOTE_WRITE | NOTE_EXTEND | NOTE_TRUNCATE);
     373  #else
     374              ev.fflags &= ~(NOTE_WRITE | NOTE_EXTEND);
     375  #endif
     376            }
     377  
     378          /* Here starts the long section of mapping kqueue events to
     379           * GFileMonitorEvent. Since kqueue can return multiple events in a
     380           * single kevent struct, we must use 'if' instead of 'else if'. */
     381          if (ev.fflags & NOTE_DELETE)
     382            {
     383              struct stat st;
     384              if (fstat (sub->fd, &st) < 0)
     385                st.st_nlink = 0;
     386  
     387              g_file_monitor_source_handle_event (source,
     388                                                  G_FILE_MONITOR_EVENT_DELETED,
     389                                                  sub->basename, NULL, NULL, now);
     390  
     391              /* If the last reference to the file was removed, delete the
     392               * subscription from kqueue and add it to the missing list.
     393               * If you are monitoring a file which has hard link count higher
     394               * than 1, it is possible for the same file to emit 'DELETED'
     395               * events multiple times. */
     396              if (st.st_nlink == 0)
     397                {
     398                  _kqsub_cancel (sub);
     399                  _km_add_missing (sub);
     400                }
     401            }
     402           if (ev.fflags & NOTE_REVOKE)
     403             {
     404               g_file_monitor_source_handle_event (source,
     405                                                   G_FILE_MONITOR_EVENT_UNMOUNTED,
     406                                                   sub->basename, NULL, NULL, now);
     407               _kqsub_cancel (sub);
     408               _km_add_missing (sub);
     409             }
     410          if (ev.fflags & NOTE_ATTRIB)
     411            {
     412              g_file_monitor_source_handle_event (source,
     413                                                  G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED,
     414                                                  sub->basename, NULL, NULL, now);
     415            }
     416  #ifdef NOTE_TRUNCATE
     417          if (ev.fflags & (NOTE_WRITE | NOTE_EXTEND | NOTE_TRUNCATE))
     418  #else
     419          if (ev.fflags & (NOTE_WRITE | NOTE_EXTEND))
     420  #endif
     421            {
     422              g_file_monitor_source_handle_event (source,
     423                                                  G_FILE_MONITOR_EVENT_CHANGED,
     424                                                  sub->basename, NULL, NULL, now);
     425            }
     426          if (ev.fflags & NOTE_RENAME)
     427            {
     428              /* Since there’s apparently no way to get the new name of the
     429               * file out of kqueue(), all we can do is say that this one has
     430               * been deleted. */
     431              g_file_monitor_source_handle_event (source,
     432                                                  G_FILE_MONITOR_EVENT_DELETED,
     433                                                  sub->basename, NULL, NULL, now);
     434            }
     435  #ifdef NOTE_CLOSE_WRITE
     436          if (ev.fflags & NOTE_CLOSE_WRITE)
     437            {
     438              g_file_monitor_source_handle_event (source,
     439                                                  G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT,
     440                                                  sub->basename, NULL, NULL, now);
     441            }
     442  #endif
     443  
     444          /* Handle the case when a file is created again shortly after it was
     445           * deleted. It has to be the last check because 'DELETED' must happen
     446           * before 'CREATED'. */
     447          if (ev.fflags & (NOTE_DELETE | NOTE_REVOKE))
     448            _km_scan_missing (NULL);
     449      }
     450  
     451    G_UNLOCK (kq_lock);
     452  
     453    return TRUE;
     454  }
     455  
     456  static gboolean
     457  g_kqueue_file_monitor_is_supported (void)
     458  {
     459    int errsv;
     460  
     461    G_LOCK (kq_lock);
     462  
     463    if (kq_queue == -1)
     464      {
     465        kq_queue = kqueue ();
     466        errsv = errno;
     467  
     468        if (kq_queue == -1)
     469          {
     470            g_warning ("Unable to create a kqueue: %s", g_strerror (errsv));
     471            G_UNLOCK (kq_lock);
     472            return FALSE;
     473          }
     474  
     475        kq_source = g_unix_fd_source_new (kq_queue, G_IO_IN);
     476        g_source_set_callback (kq_source, (GSourceFunc) g_kqueue_file_monitor_callback, NULL, NULL);
     477        g_source_attach (kq_source, GLIB_PRIVATE_CALL (g_get_worker_context) ());
     478      }
     479  
     480    G_UNLOCK (kq_lock);
     481  
     482    return TRUE;
     483  }
     484  
     485  static gboolean
     486  g_kqueue_file_monitor_cancel (GFileMonitor *monitor)
     487  {
     488    GKqueueFileMonitor *kqueue_monitor = G_KQUEUE_FILE_MONITOR (monitor);
     489  
     490    /* We must hold the global lock before calling _kqsub_cancel. However, we
     491     * cannot call G_LOCK in _kqsub_cancel because it is also used by
     492     * g_kqueue_file_monitor_callback, which already holds the lock itself. */
     493    G_LOCK (kq_lock);
     494  
     495    if (kqueue_monitor->sub_dir)
     496      {
     497        _kqsub_cancel (kqueue_monitor->sub_dir);
     498        _kqsub_free (kqueue_monitor->sub_dir);
     499        kqueue_monitor->sub_dir = NULL;
     500      }
     501    if (kqueue_monitor->sub_file)
     502      {
     503        _kqsub_cancel (kqueue_monitor->sub_file);
     504        _kqsub_free (kqueue_monitor->sub_file);
     505        kqueue_monitor->sub_file = NULL;
     506      }
     507  
     508    G_UNLOCK (kq_lock);
     509  
     510  #ifndef O_EVTONLY
     511    if (kqueue_monitor->fallback)
     512      {
     513        g_signal_handlers_disconnect_by_func (kqueue_monitor->fallback, _fallback_callback, kqueue_monitor);
     514        g_file_monitor_cancel (kqueue_monitor->fallback);
     515      }
     516  #endif
     517  
     518    if (G_FILE_MONITOR_CLASS (g_kqueue_file_monitor_parent_class)->cancel)
     519      (*G_FILE_MONITOR_CLASS (g_kqueue_file_monitor_parent_class)->cancel) (monitor);
     520  
     521    return TRUE;
     522  }
     523  
     524  static kqueue_sub *
     525  _kqsub_new (gchar *filename, gchar *basename, GKqueueFileMonitor *mon, GFileMonitorSource *source)
     526  {
     527    kqueue_sub *sub;
     528  
     529    sub = g_slice_new (kqueue_sub);
     530    sub->filename = filename;
     531    sub->basename = basename;
     532    sub->mon = mon;
     533    g_source_ref ((GSource *) source);
     534    sub->source = source;
     535    sub->fd = -1;
     536    sub->deps = NULL;
     537    sub->is_dir = 0;
     538  
     539    return sub;
     540  }
     541  
     542  static void
     543  _kqsub_free (kqueue_sub *sub)
     544  {
     545    g_assert (sub->deps == NULL);
     546    g_assert (sub->fd == -1);
     547  
     548    g_source_unref ((GSource *) sub->source);
     549    g_free (sub->filename);
     550    g_free (sub->basename);
     551    g_slice_free (kqueue_sub, sub);
     552  }
     553  
     554  static void
     555  _kqsub_cancel (kqueue_sub *sub)
     556  {
     557    /* WARNING: Before calling this function, you must hold a lock on kq_lock
     558     * or you will cause use-after-free in g_kqueue_file_monitor_callback. */
     559  
     560    struct kevent ev;
     561  
     562    /* Remove the event and close the file descriptor to automatically
     563     * delete pending events. */
     564    if (sub->fd != -1)
     565      {
     566        EV_SET (&ev, sub->fd, EVFILT_VNODE, EV_DELETE, note_all (), 0, sub);
     567        if (kevent (kq_queue, &ev, 1, NULL, 0, NULL) == -1)
     568          {
     569            g_warning ("Unable to remove event for %s: %s", sub->filename, g_strerror (errno));
     570          }
     571        close (sub->fd);
     572        sub->fd = -1;
     573      }
     574  
     575    _km_remove (sub);
     576  
     577    if (sub->deps)
     578      {
     579        dl_free (sub->deps);
     580        sub->deps = NULL;
     581      }
     582  }
     583  
     584  gboolean
     585  _kqsub_start_watching (kqueue_sub *sub)
     586  {
     587    struct stat st;
     588    struct kevent ev;
     589  
     590    sub->fd = open (sub->filename, O_KQFLAG | O_CLOEXEC);
     591    if (sub->fd == -1)
     592        return FALSE;
     593  
     594    if (fstat (sub->fd, &st) == -1)
     595      {
     596        g_warning ("fstat failed for %s: %s", sub->filename, g_strerror (errno));
     597        close (sub->fd);
     598        sub->fd = -1;
     599        return FALSE;
     600      }
     601  
     602    sub->is_dir = (st.st_mode & S_IFDIR) ? 1 : 0;
     603    if (sub->is_dir)
     604      {
     605        if (sub->deps)
     606          dl_free (sub->deps);
     607  
     608        sub->deps = dl_listing (sub->filename);
     609      }
     610  
     611    EV_SET (&ev, sub->fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, note_all (), 0, sub);
     612    if (kevent (kq_queue, &ev, 1, NULL, 0, NULL) == -1)
     613      {
     614        g_warning ("Unable to add event for %s: %s", sub->filename, g_strerror (errno));
     615        close (sub->fd);
     616        sub->fd = -1;
     617        return FALSE;
     618      }
     619  
     620    return TRUE;
     621  }