Merge branch 'wip/lantw/freebsd-kqueue-complex' into 'master'
[glib.git] / gio / kqueue / gkqueuefilemonitor.c
blob3088296b51c44c5ee81f839cfb5bf8e1c90bd9d8
1 /*******************************************************************************
2 Copyright (c) 2011, 2012 Dmitry Matveev <me@dmitrymatveev.co.uk>
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:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
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 *******************************************************************************/
23 #include "config.h"
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>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <string.h>
35 #include <glib-object.h>
36 #include <glib/gfileutils.h>
37 #include <gio/gfilemonitor.h>
38 #include <gio/glocalfilemonitor.h>
39 #include <gio/giomodule.h>
40 #include <gio/gpollfilemonitor.h>
41 #include <gio/gfile.h>
42 #include <glib-unix.h>
43 #include "glib-private.h"
45 #include "kqueue-helper.h"
46 #include "dep-list.h"
48 G_LOCK_DEFINE_STATIC (kq_lock);
49 static GSource *kq_source;
50 static int kq_queue = -1;
52 #define G_TYPE_KQUEUE_FILE_MONITOR (g_kqueue_file_monitor_get_type ())
53 #define G_KQUEUE_FILE_MONITOR(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
54 G_TYPE_KQUEUE_FILE_MONITOR, GKqueueFileMonitor))
56 /* C11 allows type redefinition, but GLib is configured to use C89, which causes
57 * clang to show warnings when we use a C11 feature. Since the C89 requirement
58 * is mostly used to support MSVC, we simply ignore the warning here because
59 * this file is never going to be useful on Windows. */
60 #ifdef __clang__
61 #pragma clang diagnostic push
62 #pragma clang diagnostic ignored "-Wtypedef-redefinition"
63 #endif
65 typedef GLocalFileMonitorClass GKqueueFileMonitorClass;
67 /* When the file we are monitoring is a directory, sub_dir is subscribed to the
68 * directory itself and sub_file is NULL.
70 * When the file we are monitoring is a regular file, sub_dir is subscribed to
71 * the directory containing the file and sub_file is subscribed to the file
72 * being monitored. We have to monitor both because it is possible that the
73 * file chosen for monitoring doesn't exist when the file monitor is started.
74 * We monitor on its parent in order to get notification when it is created.
76 * To distinguish between a directory monitor and a regular file monitor, check
77 * whether sub_file is NULL. */
78 typedef struct _GKqueueFileMonitor
80 GLocalFileMonitor parent_instance;
82 kqueue_sub *sub_dir;
83 kqueue_sub *sub_file;
84 #ifndef O_EVTONLY
85 GFileMonitor *fallback;
86 GFile *fbfile;
87 #endif
88 } GKqueueFileMonitor;
90 #ifdef __clang__
91 #pragma clang diagnostic pop
92 #endif
94 GType g_kqueue_file_monitor_get_type (void);
95 G_DEFINE_TYPE_WITH_CODE (GKqueueFileMonitor, g_kqueue_file_monitor, G_TYPE_LOCAL_FILE_MONITOR,
96 g_io_extension_point_implement (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME,
97 g_define_type_id,
98 "kqueue",
99 20))
101 #ifndef O_EVTONLY
102 #define O_KQFLAG O_RDONLY
103 #else
104 #define O_KQFLAG O_EVTONLY
105 #endif
107 static inline unsigned int
108 note_all (void)
110 unsigned int notes = NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME;
111 #ifdef NOTE_TRUNCATE
112 notes |= NOTE_TRUNCATE;
113 #endif
114 #ifdef NOTE_CLOSE_WRITE
115 notes |= NOTE_CLOSE_WRITE;
116 #endif
117 return notes;
120 static gboolean g_kqueue_file_monitor_cancel (GFileMonitor* monitor);
121 static gboolean g_kqueue_file_monitor_is_supported (void);
123 static kqueue_sub *_kqsub_new (gchar *, gchar *, GKqueueFileMonitor *, GFileMonitorSource *);
124 static void _kqsub_free (kqueue_sub *);
125 static gboolean _kqsub_cancel (kqueue_sub *);
128 #ifndef O_EVTONLY
129 static void
130 _fallback_callback (GFileMonitor *unused,
131 GFile *first,
132 GFile *second,
133 GFileMonitorEvent event,
134 gpointer udata)
136 GKqueueFileMonitor *kq_mon = G_KQUEUE_FILE_MONITOR (udata);
138 g_file_monitor_emit_event (G_FILE_MONITOR (kq_mon), first, second, event);
142 * _ke_is_excluded:
143 * @full_path - a path to file to check.
145 * Returns: TRUE if the file should be excluded from the kqueue-powered
146 * monitoring, FALSE otherwise.
148 static gboolean
149 _ke_is_excluded (const char *full_path)
151 GFile *f = NULL;
152 GMount *mount = NULL;
154 f = g_file_new_for_path (full_path);
156 if (f != NULL) {
157 mount = g_file_find_enclosing_mount (f, NULL, NULL);
158 g_object_unref (f);
161 if (mount != NULL && (g_str_has_prefix (full_path, "/media/") || g_str_has_prefix (full_path, "/run/media/")))
163 g_warning ("Excluding %s from kernel notification, falling back to poll", full_path);
164 if (mount)
165 g_object_unref (mount);
166 return TRUE;
169 return FALSE;
171 #endif /* !O_EVTONLY */
173 static void
174 g_kqueue_file_monitor_finalize (GObject *object)
176 GKqueueFileMonitor *kqueue_monitor = G_KQUEUE_FILE_MONITOR (object);
178 if (kqueue_monitor->sub_dir)
180 _kqsub_cancel (kqueue_monitor->sub_dir);
181 _kqsub_free (kqueue_monitor->sub_dir);
182 kqueue_monitor->sub_dir = NULL;
185 if (kqueue_monitor->sub_file)
187 _kqsub_cancel (kqueue_monitor->sub_file);
188 _kqsub_free (kqueue_monitor->sub_file);
189 kqueue_monitor->sub_file = NULL;
192 #ifndef O_EVTONLY
193 if (kqueue_monitor->fallback)
194 g_object_unref (kqueue_monitor->fallback);
196 if (kqueue_monitor->fbfile)
197 g_object_unref (kqueue_monitor->fbfile);
198 #endif
200 if (G_OBJECT_CLASS (g_kqueue_file_monitor_parent_class)->finalize)
201 (*G_OBJECT_CLASS (g_kqueue_file_monitor_parent_class)->finalize) (object);
204 static void
205 g_kqueue_file_monitor_start (GLocalFileMonitor *local_monitor,
206 const gchar *dirname,
207 const gchar *basename,
208 const gchar *filename,
209 GFileMonitorSource *source)
211 GKqueueFileMonitor *kqueue_monitor = G_KQUEUE_FILE_MONITOR (local_monitor);
212 kqueue_sub *sub_dir = NULL, *sub_file = NULL;
213 gchar *path_dir, *path_file, *file_basename;
215 /* There are three possible cases here:
217 * 1. Directory: dirname != NULL, basename == NULL, filename == NULL
218 * 2. Regular file: dirname != NULL, basename != NULL, filename == NULL
219 * 3. Hard links: dirname == NULL, basename == NULL, filename != NULL
221 * Note that we don't distinguish between case 2 and 3. Kqueue monitors
222 * files based on file descriptors, so we always receive events come from
223 * hard links.
225 if (filename != NULL)
227 path_dir = g_path_get_dirname (filename);
228 path_file = g_strdup (filename);
229 file_basename = g_path_get_basename (filename);
231 else
233 path_dir = g_strdup (dirname);
234 if (basename != NULL)
236 path_file = g_build_filename (dirname, basename, NULL);
237 file_basename = g_strdup (basename);
239 else
241 path_file = NULL;
242 file_basename = NULL;
246 #ifndef O_EVTONLY
247 if (_ke_is_excluded (path_dir))
249 GFile *file;
250 if (path_file != NULL)
251 file = g_file_new_for_path (path_file);
252 else
253 file = g_file_new_for_path (path_dir);
254 g_free (path_dir);
255 g_free (path_file);
256 g_free (file_basename);
257 kqueue_monitor->fbfile = file;
258 kqueue_monitor->fallback = _g_poll_file_monitor_new (file);
259 g_signal_connect (kqueue_monitor->fallback, "changed",
260 G_CALLBACK (_fallback_callback), kqueue_monitor);
261 return;
263 #endif
265 /* For a directory monitor, create a subscription object anyway.
266 * It will be used for directory diff calculation routines.
267 * Wait, directory diff in a GKqueueFileMonitor?
268 * Yes, it is. When a file monitor is started on an non-existent
269 * file, GIO uses a GKqueueFileMonitor object for that. If a directory
270 * will be created under that path, GKqueueFileMonitor will have to
271 * handle the directory notifications. */
272 sub_dir = _kqsub_new (g_steal_pointer (&path_dir), NULL,
273 kqueue_monitor, source);
274 if (!_kqsub_start_watching (sub_dir))
275 _km_add_missing (sub_dir);
277 /* Unlike GInotifyFileMonitor, which always uses a directory monitor
278 * regardless of the type of the file being monitored, kqueue doesn't
279 * give us events generated by files under it when we are monitoring
280 * a directory. We have to monitor the file itself to know changes which
281 * was made to the file itself. */
282 if (path_file != NULL)
284 sub_file = _kqsub_new (g_steal_pointer (&path_file),
285 g_steal_pointer (&file_basename),
286 kqueue_monitor, source);
287 if (!_kqsub_start_watching (sub_file))
288 _km_add_missing (sub_file);
291 kqueue_monitor->sub_dir = sub_dir;
292 kqueue_monitor->sub_file = sub_file;
293 g_clear_pointer (&path_dir, g_free);
294 g_clear_pointer (&path_file, g_free);
295 g_clear_pointer (&file_basename, g_free);
298 static void
299 g_kqueue_file_monitor_class_init (GKqueueFileMonitorClass *klass)
301 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
302 GFileMonitorClass *file_monitor_class = G_FILE_MONITOR_CLASS (klass);
303 GLocalFileMonitorClass *local_file_monitor_class = G_LOCAL_FILE_MONITOR_CLASS (klass);
305 gobject_class->finalize = g_kqueue_file_monitor_finalize;
306 file_monitor_class->cancel = g_kqueue_file_monitor_cancel;
308 local_file_monitor_class->is_supported = g_kqueue_file_monitor_is_supported;
309 local_file_monitor_class->start = g_kqueue_file_monitor_start;
310 local_file_monitor_class->mount_notify = TRUE; /* TODO: ??? */
313 static void
314 g_kqueue_file_monitor_init (GKqueueFileMonitor *monitor)
318 static gboolean
319 g_kqueue_file_monitor_callback (gint fd, GIOCondition condition, gpointer user_data)
321 gint64 now = g_source_get_time (kq_source);
322 kqueue_sub *sub;
323 GFileMonitorSource *source;
324 struct kevent ev;
325 struct timespec ts;
327 memset (&ts, 0, sizeof(ts));
329 /* We must hold the global lock before accessing any kqueue_sub because it is
330 * possible for other threads to call g_kqueue_file_monitor_cancel, which may
331 * free the kqueue_sub struct we are accessing. */
332 G_LOCK (kq_lock);
334 while (kevent(fd, NULL, 0, &ev, 1, &ts) > 0)
336 if (ev.filter != EVFILT_VNODE || ev.udata == NULL)
337 continue;
339 sub = ev.udata;
340 source = sub->source;
342 /* When we are monitoring a regular file which already exists, ignore
343 * events generated by its parent directory. This has to be the first
344 * check to prevent the following code to emit useless events */
345 if (sub->is_dir && sub->mon->sub_file != NULL && sub->mon->sub_file->fd != -1)
346 continue;
348 if (ev.flags & EV_ERROR)
349 ev.fflags = NOTE_REVOKE;
351 if (sub->is_dir && ev.fflags & (NOTE_WRITE | NOTE_EXTEND))
353 /* If we are monitoring on a non-existent regular file, trigger the
354 * rescan of missing files immediately so we don't have to wait for
355 * 4 seconds for discovering missing files. We pass the sub_file
356 * corresponding to the GKqueueFileMonitor to 'check_this_sub_only'
357 * argument to prevent _km_scan_missing from emiting 'CREATED'
358 * events because _kh_dir_diff will do it for us. */
359 if (sub->mon->sub_file != NULL && sub->mon->sub_file->fd == -1)
360 _km_scan_missing (sub->mon->sub_file);
362 /* If we are monitoring a regular file, don't emit 'DELETED' events
363 * from the directory monitor because it will be emitted from the
364 * file itself when a NOTE_DELETE is reported on sub_file. */
365 _kh_dir_diff (sub, sub->mon->sub_file == NULL);
367 #ifdef NOTE_TRUNCATE
368 ev.fflags &= ~(NOTE_WRITE | NOTE_EXTEND | NOTE_TRUNCATE);
369 #else
370 ev.fflags &= ~(NOTE_WRITE | NOTE_EXTEND);
371 #endif
374 /* Here starts the long section of mapping kqueue events to
375 * GFileMonitorEvent. Since kqueue can return multiple events in a
376 * single kevent struct, we must use 'if' instead of 'else if'. */
377 if (ev.fflags & NOTE_DELETE)
379 struct stat st;
380 if (fstat (sub->fd, &st) < 0)
381 st.st_nlink = 0;
383 g_file_monitor_source_handle_event (source,
384 G_FILE_MONITOR_EVENT_DELETED,
385 sub->basename, NULL, NULL, now);
387 /* If the last reference to the file was removed, delete the
388 * subscription from kqueue and add it to the missing list.
389 * If you are monitoring a file which has hard link count higher
390 * than 1, it is possible for the same file to emit 'DELETED'
391 * events multiple times. */
392 if (st.st_nlink == 0)
394 _kqsub_cancel (sub);
395 _km_add_missing (sub);
398 if (ev.fflags & NOTE_REVOKE)
400 g_file_monitor_source_handle_event (source,
401 G_FILE_MONITOR_EVENT_UNMOUNTED,
402 sub->basename, NULL, NULL, now);
403 _kqsub_cancel (sub);
404 _km_add_missing (sub);
406 if (ev.fflags & NOTE_ATTRIB)
408 g_file_monitor_source_handle_event (source,
409 G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED,
410 sub->basename, NULL, NULL, now);
412 #ifdef NOTE_TRUNCATE
413 if (ev.fflags & (NOTE_WRITE | NOTE_EXTEND | NOTE_TRUNCATE))
414 #else
415 if (ev.fflags & (NOTE_WRITE | NOTE_EXTEND))
416 #endif
418 g_file_monitor_source_handle_event (source,
419 G_FILE_MONITOR_EVENT_CHANGED,
420 sub->basename, NULL, NULL, now);
422 if (ev.fflags & NOTE_RENAME)
424 /* Since there’s apparently no way to get the new name of the
425 * file out of kqueue(), all we can do is say that this one has
426 * been deleted. */
427 g_file_monitor_source_handle_event (source,
428 G_FILE_MONITOR_EVENT_DELETED,
429 sub->basename, NULL, NULL, now);
431 #ifdef NOTE_CLOSE_WRITE
432 if (ev.fflags & NOTE_CLOSE_WRITE)
434 g_file_monitor_source_handle_event (source,
435 G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT,
436 sub->basename, NULL, NULL, now);
438 #endif
440 /* Handle the case when a file is created again shortly after it was
441 * deleted. It has to be the last check because 'DELETED' must happen
442 * before 'CREATED'. */
443 if (ev.fflags & (NOTE_DELETE | NOTE_REVOKE))
444 _km_scan_missing (NULL);
447 G_UNLOCK (kq_lock);
449 return TRUE;
452 static gboolean
453 g_kqueue_file_monitor_is_supported (void)
455 int errsv;
457 G_LOCK (kq_lock);
459 if (kq_queue == -1)
461 kq_queue = kqueue ();
462 errsv = errno;
464 if (kq_queue == -1)
466 g_warning ("Unable to create a kqueue: %s", g_strerror (errsv));
467 G_UNLOCK (kq_lock);
468 return FALSE;
471 kq_source = g_unix_fd_source_new (kq_queue, G_IO_IN);
472 g_source_set_callback (kq_source, (GSourceFunc) g_kqueue_file_monitor_callback, NULL, NULL);
473 g_source_attach (kq_source, GLIB_PRIVATE_CALL (g_get_worker_context) ());
476 G_UNLOCK (kq_lock);
478 return TRUE;
481 static gboolean
482 g_kqueue_file_monitor_cancel (GFileMonitor *monitor)
484 GKqueueFileMonitor *kqueue_monitor = G_KQUEUE_FILE_MONITOR (monitor);
486 /* We must hold the global lock before calling _kqsub_cancel. However, we
487 * cannot call G_LOCK in _kqsub_cancel because it is also used by
488 * g_kqueue_file_monitor_callback, which already holds the lock itself. */
489 G_LOCK (kq_lock);
491 if (kqueue_monitor->sub_dir)
493 _kqsub_cancel (kqueue_monitor->sub_dir);
494 _kqsub_free (kqueue_monitor->sub_dir);
495 kqueue_monitor->sub_dir = NULL;
497 if (kqueue_monitor->sub_file)
499 _kqsub_cancel (kqueue_monitor->sub_file);
500 _kqsub_free (kqueue_monitor->sub_file);
501 kqueue_monitor->sub_file = NULL;
504 G_UNLOCK (kq_lock);
506 #ifndef O_EVTONLY
507 if (kqueue_monitor->fallback)
509 g_signal_handlers_disconnect_by_func (kqueue_monitor->fallback, _fallback_callback, kqueue_monitor);
510 g_file_monitor_cancel (kqueue_monitor->fallback);
512 #endif
514 if (G_FILE_MONITOR_CLASS (g_kqueue_file_monitor_parent_class)->cancel)
515 (*G_FILE_MONITOR_CLASS (g_kqueue_file_monitor_parent_class)->cancel) (monitor);
517 return TRUE;
520 static kqueue_sub *
521 _kqsub_new (gchar *filename, gchar *basename, GKqueueFileMonitor *mon, GFileMonitorSource *source)
523 kqueue_sub *sub;
525 sub = g_slice_new (kqueue_sub);
526 sub->filename = filename;
527 sub->basename = basename;
528 sub->mon = mon;
529 g_source_ref ((GSource *) source);
530 sub->source = source;
531 sub->fd = -1;
532 sub->deps = NULL;
533 sub->is_dir = 0;
535 return sub;
538 static void
539 _kqsub_free (kqueue_sub *sub)
541 g_assert (sub->deps == NULL);
542 g_assert (sub->fd == -1);
544 g_source_unref ((GSource *) sub->source);
545 g_free (sub->filename);
546 g_free (sub->basename);
547 g_slice_free (kqueue_sub, sub);
550 static gboolean
551 _kqsub_cancel (kqueue_sub *sub)
553 /* WARNING: Before calling this function, you must hold a lock on kq_lock
554 * or you will cause use-after-free in g_kqueue_file_monitor_callback. */
556 struct kevent ev;
558 /* Remove the event and close the file descriptor to automatically
559 * delete pending events. */
560 if (sub->fd != -1)
562 EV_SET (&ev, sub->fd, EVFILT_VNODE, EV_DELETE, note_all (), 0, sub);
563 if (kevent (kq_queue, &ev, 1, NULL, 0, NULL) == -1)
565 g_warning ("Unable to remove event for %s: %s", sub->filename, g_strerror (errno));
566 return FALSE;
568 close (sub->fd);
569 sub->fd = -1;
572 _km_remove (sub);
574 if (sub->deps)
576 dl_free (sub->deps);
577 sub->deps = NULL;
580 return TRUE;
583 gboolean
584 _kqsub_start_watching (kqueue_sub *sub)
586 struct stat st;
587 struct kevent ev;
589 sub->fd = open (sub->filename, O_KQFLAG);
590 if (sub->fd == -1)
591 return FALSE;
593 if (fstat (sub->fd, &st) == -1)
595 g_warning ("fstat failed for %s: %s", sub->filename, g_strerror (errno));
596 close (sub->fd);
597 sub->fd = -1;
598 return FALSE;
601 sub->is_dir = (st.st_mode & S_IFDIR) ? 1 : 0;
602 if (sub->is_dir)
604 if (sub->deps)
605 dl_free (sub->deps);
607 sub->deps = dl_listing (sub->filename);
610 EV_SET (&ev, sub->fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, note_all (), 0, sub);
611 if (kevent (kq_queue, &ev, 1, NULL, 0, NULL) == -1)
613 g_warning ("Unable to add event for %s: %s", sub->filename, g_strerror (errno));
614 close (sub->fd);
615 sub->fd = -1;
616 return FALSE;
619 return TRUE;