diff options
author | Koop Mast <kwm@FreeBSD.org> | 2018-09-30 11:58:29 +0000 |
---|---|---|
committer | Koop Mast <kwm@FreeBSD.org> | 2018-09-30 11:58:29 +0000 |
commit | 951c1f5d1c7354f058f5919d858dbb0c174dc73e (patch) | |
tree | 6146e775343aaf339921799078894a48fef9aa15 /devel/glib20/files | |
parent | c9b47f0427d70ba42c2d53271f8b64b8e8096825 (diff) | |
download | ports-951c1f5d1c7354f058f5919d858dbb0c174dc73e.tar.gz ports-951c1f5d1c7354f058f5919d858dbb0c174dc73e.zip |
The FreeBSD GNOME team proudly presents GNOME 3.28 for FreeBSD.
The offical GNOME 3.28 release notes can be found at
https://help.gnome.org/misc/release-notes/3.28/
Thanks to Antoine Brodin for running the exp-runs.
PR: 229761
Notes
Notes:
svn path=/head/; revision=480951
Diffstat (limited to 'devel/glib20/files')
-rw-r--r-- | devel/glib20/files/patch-gio_filemonitor | 1038 | ||||
-rw-r--r-- | devel/glib20/files/patch-gio_glib-compile-schemas.c | 12 | ||||
-rw-r--r-- | devel/glib20/files/patch-gio_glocalfileoutputstream.c | 38 | ||||
-rw-r--r-- | devel/glib20/files/patch-gio_kqueue-kqueue-missing.c | 93 | ||||
-rw-r--r-- | devel/glib20/files/patch-gio_kqueue_Makefile.in | 87 | ||||
-rw-r--r-- | devel/glib20/files/patch-gio_kqueue_gkqueuefilemonitor.c | 463 | ||||
-rw-r--r-- | devel/glib20/files/patch-gio_kqueue_kqueue-helper.c | 409 | ||||
-rw-r--r-- | devel/glib20/files/patch-gio_kqueue_kqueue-helper.h | 40 |
8 files changed, 1099 insertions, 1081 deletions
diff --git a/devel/glib20/files/patch-gio_filemonitor b/devel/glib20/files/patch-gio_filemonitor deleted file mode 100644 index 883c7b1bbd8d..000000000000 --- a/devel/glib20/files/patch-gio_filemonitor +++ /dev/null @@ -1,1038 +0,0 @@ -# gio: Always purge kqueue subs from missing list -# https://gitlab.gnome.org/GNOME/glib/commit/e305fe971e4647d971428a772b7290b9c308a96f -# kqueue: Fix invalid emission of G_FILE_MONITOR_EVENT_MOVED event -# https://gitlab.gnome.org/GNOME/glib/commit/76072a2dde4a4acc8be8d3c47efbc6811ebe0c1e -# kqueue: Multiple fixes and simplifications -# https://gitlab.gnome.org/GNOME/glib/commit/aa39a0557c679fc345b0ba72a87c33152eb8ebcd -# gpollfilemonitor: Fix use-after-free caused by leaking GSource -# https://gitlab.gnome.org/GNOME/glib/commit/ba4a9538e14e8ba0ea037cab5f4b23aa47272a4c -# Reorder operations in _kqsub_cancel() to prevent races. -# https://gitlab.gnome.org/GNOME/glib/commit/ab179184b883ad378a420223f378071821f0c8b9 -# Convert gio/kqueue/Makefile.am to gio/kqueue/Makefile.in patch - ---- gio/gpollfilemonitor.c.orig 2016-10-22 05:17:34 UTC -+++ gio/gpollfilemonitor.c -@@ -50,7 +50,9 @@ g_poll_file_monitor_finalize (GObject* o - - poll_monitor = G_POLL_FILE_MONITOR (object); - -+ g_poll_file_monitor_cancel (G_FILE_MONITOR (poll_monitor)); - g_object_unref (poll_monitor->file); -+ g_clear_object (&poll_monitor->last_info); - - G_OBJECT_CLASS (g_poll_file_monitor_parent_class)->finalize (object); - } ---- gio/kqueue/Makefile.in.orig 2017-02-13 15:22:04 UTC -+++ gio/kqueue/Makefile.in -@@ -183,9 +183,8 @@ LTLIBRARIES = $(installed_test_LTLIBRARI - libkqueue_la_LIBADD = - am__objects_1 = - am_libkqueue_la_OBJECTS = libkqueue_la-gkqueuefilemonitor.lo \ -- libkqueue_la-kqueue-helper.lo libkqueue_la-kqueue-thread.lo \ -- libkqueue_la-kqueue-sub.lo libkqueue_la-kqueue-missing.lo \ -- libkqueue_la-kqueue-utils.lo libkqueue_la-kqueue-exclusions.lo \ -+ libkqueue_la-kqueue-helper.lo \ -+ libkqueue_la-kqueue-missing.lo \ - libkqueue_la-dep-list.lo $(am__objects_1) - libkqueue_la_OBJECTS = $(am_libkqueue_la_OBJECTS) - AM_V_lt = $(am__v_lt_@AM_V@) ---- gio/kqueue/gkqueuefilemonitor.c.orig 2016-10-22 05:18:22 UTC -+++ gio/kqueue/gkqueuefilemonitor.c -@@ -22,33 +22,73 @@ - - #include "config.h" - --#include "gkqueuefilemonitor.h" --#include "kqueue-helper.h" --#include "kqueue-exclusions.h" -+#include <sys/types.h> -+#include <sys/event.h> -+#include <sys/time.h> -+#include <sys/socket.h> -+#include <sys/stat.h> -+ -+#include <errno.h> -+#include <fcntl.h> -+#include <string.h> -+ -+#include <glib-object.h> -+#include <gio/gfilemonitor.h> -+#include <gio/glocalfilemonitor.h> -+#include <gio/giomodule.h> - #include <gio/gpollfilemonitor.h> - #include <gio/gfile.h> --#include <gio/giomodule.h> -+#include <glib-unix.h> -+#include "glib-private.h" - -+#include "kqueue-helper.h" -+#include "dep-list.h" - --struct _GKqueueFileMonitor -+G_LOCK_DEFINE_STATIC (kq_lock); -+static GSource *kq_source; -+static int kq_queue = -1; -+ -+#define G_TYPE_KQUEUE_FILE_MONITOR (g_kqueue_file_monitor_get_type ()) -+#define G_KQUEUE_FILE_MONITOR(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ -+ G_TYPE_KQUEUE_FILE_MONITOR, GKqueueFileMonitor)) -+ -+typedef GLocalFileMonitorClass GKqueueFileMonitorClass; -+ -+typedef struct - { - GLocalFileMonitor parent_instance; - - kqueue_sub *sub; -- -+#ifndef O_EVTONLY - GFileMonitor *fallback; - GFile *fbfile; --}; -+#endif -+} GKqueueFileMonitor; -+ -+GType g_kqueue_file_monitor_get_type (void); -+G_DEFINE_TYPE_WITH_CODE (GKqueueFileMonitor, g_kqueue_file_monitor, G_TYPE_LOCAL_FILE_MONITOR, -+ g_io_extension_point_implement (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME, -+ g_define_type_id, -+ "kqueue", -+ 20)) -+ -+#ifndef O_EVTONLY -+#define O_KQFLAG O_RDONLY -+#else -+#define O_KQFLAG O_EVTONLY -+#endif -+ -+#define NOTE_ALL (NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_RENAME) - - static gboolean g_kqueue_file_monitor_cancel (GFileMonitor* monitor); -+static gboolean g_kqueue_file_monitor_is_supported (void); - --G_DEFINE_TYPE_WITH_CODE (GKqueueFileMonitor, g_kqueue_file_monitor, G_TYPE_LOCAL_FILE_MONITOR, -- g_io_extension_point_implement (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME, -- g_define_type_id, -- "kqueue", -- 20)) -+static kqueue_sub *_kqsub_new (const gchar *, GLocalFileMonitor *, GFileMonitorSource *); -+static void _kqsub_free (kqueue_sub *); -+static gboolean _kqsub_cancel (kqueue_sub *); - - -+#ifndef O_EVTONLY - static void - _fallback_callback (GFileMonitor *unused, - GFile *first, -@@ -57,21 +97,41 @@ _fallback_callback (GFileMonitor *u - gpointer udata) - { - GKqueueFileMonitor *kq_mon = G_KQUEUE_FILE_MONITOR (udata); -- GFileMonitor *mon = G_FILE_MONITOR (kq_mon); -- g_assert (kq_mon != NULL); -- g_assert (mon != NULL); -- (void) unused; -- -- if (event == G_FILE_MONITOR_EVENT_CHANGED) -- { -- GLocalFileMonitor *local_monitor = G_LOCAL_FILE_MONITOR (kq_mon); - -- _kh_dir_diff (kq_mon->sub, local_monitor->source); -- } -- else -- g_file_monitor_emit_event (mon, first, second, event); -+ g_file_monitor_emit_event (G_FILE_MONITOR (kq_mon), first, second, event); - } - -+/* -+ * _ke_is_excluded: -+ * @full_path - a path to file to check. -+ * -+ * Returns: TRUE if the file should be excluded from the kqueue-powered -+ * monitoring, FALSE otherwise. -+ **/ -+gboolean -+_ke_is_excluded (const char *full_path) -+{ -+ GFile *f = NULL; -+ GMount *mount = NULL; -+ -+ f = g_file_new_for_path (full_path); -+ -+ if (f != NULL) { -+ mount = g_file_find_enclosing_mount (f, NULL, NULL); -+ g_object_unref (f); -+ } -+ -+ if ((mount != NULL && (g_mount_can_unmount (mount))) || g_str_has_prefix (full_path, "/mnt/")) -+ { -+ g_warning ("Excluding %s from kernel notification, falling back to poll", full_path); -+ if (mount) -+ g_object_unref (mount); -+ return TRUE; -+ } -+ -+ return FALSE; -+} -+#endif /* !O_EVTONLY */ - - static void - g_kqueue_file_monitor_finalize (GObject *object) -@@ -80,16 +140,18 @@ g_kqueue_file_monitor_finalize (GObject - - if (kqueue_monitor->sub) - { -- _kh_cancel_sub (kqueue_monitor->sub); -- _kh_sub_free (kqueue_monitor->sub); -+ _kqsub_cancel (kqueue_monitor->sub); -+ _kqsub_free (kqueue_monitor->sub); - kqueue_monitor->sub = NULL; - } - -+#ifndef O_EVTONLY - if (kqueue_monitor->fallback) - g_object_unref (kqueue_monitor->fallback); - - if (kqueue_monitor->fbfile) - g_object_unref (kqueue_monitor->fbfile); -+#endif - - if (G_OBJECT_CLASS (g_kqueue_file_monitor_parent_class)->finalize) - (*G_OBJECT_CLASS (g_kqueue_file_monitor_parent_class)->finalize) (object); -@@ -103,21 +165,25 @@ g_kqueue_file_monitor_start (GLocalFileM - GFileMonitorSource *source) - { - GKqueueFileMonitor *kqueue_monitor = G_KQUEUE_FILE_MONITOR (local_monitor); -- GObject *obj; -- GKqueueFileMonitorClass *klass; -- GObjectClass *parent_class; -- kqueue_sub *sub = NULL; -- gboolean ret_kh_startup = FALSE; -- const gchar *path = NULL; -- -- -- ret_kh_startup = _kh_startup (); -- g_assert (ret_kh_startup); -+ kqueue_sub *sub; -+ const gchar *path; - - path = filename; -- if (!path) -+ if (path == NULL) - path = dirname; - -+#ifndef O_EVTONLY -+ if (_ke_is_excluded (path)) -+ { -+ GFile *file = g_file_new_for_path (path); -+ kqueue_monitor->fbfile = file; -+ kqueue_monitor->fallback = _g_poll_file_monitor_new (file); -+ g_signal_connect (kqueue_monitor->fallback, "changed", -+ G_CALLBACK (_fallback_callback), kqueue_monitor); -+ return; -+ } -+#endif -+ - /* For a directory monitor, create a subscription object anyway. - * It will be used for directory diff calculation routines. - * Wait, directory diff in a GKqueueFileMonitor? -@@ -125,33 +191,13 @@ g_kqueue_file_monitor_start (GLocalFileM - * file, GIO uses a GKqueueFileMonitor object for that. If a directory - * will be created under that path, GKqueueFileMonitor will have to - * handle the directory notifications. */ -+ sub = _kqsub_new (path, local_monitor, source); -+ if (sub == NULL) -+ return; - -- sub = _kh_sub_new (path, TRUE, source); -- -- /* FIXME: what to do about errors here? we can't return NULL or another -- * kind of error and an assertion is probably too hard (same issue as in -- * the inotify backend) */ -- g_assert (sub != NULL); - kqueue_monitor->sub = sub; -- -- if (!_ke_is_excluded (path)) -- _kh_add_sub (sub); -- else -- { -- GFile *file = g_file_new_for_path (path); -- kqueue_monitor->fbfile = file; -- kqueue_monitor->fallback = _g_poll_file_monitor_new (file); -- g_signal_connect (kqueue_monitor->fallback, -- "changed", -- G_CALLBACK (_fallback_callback), -- kqueue_monitor); -- } --} -- --static gboolean --g_kqueue_file_monitor_is_supported (void) --{ -- return _kh_startup (); -+ if (!_kqsub_start_watching (sub)) -+ _km_add_missing (sub); - } - - static void -@@ -175,24 +221,218 @@ g_kqueue_file_monitor_init (GKqueueFileM - } - - static gboolean -+g_kqueue_file_monitor_callback (gint fd, GIOCondition condition, gpointer user_data) -+{ -+ gint64 now = g_source_get_time (kq_source); -+ kqueue_sub *sub; -+ GFileMonitorSource *source; -+ struct kevent ev; -+ struct timespec ts; -+ -+ memset (&ts, 0, sizeof(ts)); -+ while (kevent(fd, NULL, 0, &ev, 1, &ts) > 0) -+ { -+ GFileMonitorEvent mask = 0; -+ -+ if (ev.filter != EVFILT_VNODE || ev.udata == NULL) -+ continue; -+ -+ sub = ev.udata; -+ source = sub->source; -+ -+ if (ev.flags & EV_ERROR) -+ ev.fflags = NOTE_REVOKE; -+ -+ if (ev.fflags & (NOTE_DELETE | NOTE_REVOKE)) -+ { -+ _kqsub_cancel (sub); -+ _km_add_missing (sub); -+ } -+ -+ if (sub->is_dir && ev.fflags & (NOTE_WRITE | NOTE_EXTEND)) -+ { -+ _kh_dir_diff (sub); -+ ev.fflags &= ~(NOTE_WRITE | NOTE_EXTEND); -+ } -+ -+ if (ev.fflags & NOTE_DELETE) -+ { -+ mask = G_FILE_MONITOR_EVENT_DELETED; -+ } -+ else if (ev.fflags & NOTE_ATTRIB) -+ { -+ mask = G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED; -+ } -+ else if (ev.fflags & (NOTE_WRITE | NOTE_EXTEND)) -+ { -+ mask = G_FILE_MONITOR_EVENT_CHANGED; -+ } -+ else if (ev.fflags & NOTE_RENAME) -+ { -+ /* Since there’s apparently no way to get the new name of the -+ * file out of kqueue(), all we can do is say that this one has -+ * been deleted. */ -+ mask = G_FILE_MONITOR_EVENT_DELETED; -+ } -+ else if (ev.fflags & NOTE_REVOKE) -+ { -+ mask = G_FILE_MONITOR_EVENT_UNMOUNTED; -+ } -+ -+ if (mask) -+ g_file_monitor_source_handle_event (source, mask, NULL, NULL, NULL, now); -+ } -+ -+ return TRUE; -+} -+ -+static gboolean -+g_kqueue_file_monitor_is_supported (void) -+{ -+ int errsv; -+ -+ G_LOCK (kq_lock); -+ -+ if (kq_queue == -1) -+ { -+ kq_queue = kqueue (); -+ errsv = errno; -+ -+ if (kq_queue == -1) -+ { -+ g_warning ("Unable to create a kqueue: %s", g_strerror (errsv)); -+ G_UNLOCK (kq_lock); -+ return FALSE; -+ } -+ -+ kq_source = g_unix_fd_source_new (kq_queue, G_IO_IN); -+ g_source_set_callback (kq_source, (GSourceFunc) g_kqueue_file_monitor_callback, NULL, NULL); -+ g_source_attach (kq_source, GLIB_PRIVATE_CALL (g_get_worker_context) ()); -+ } -+ -+ G_UNLOCK (kq_lock); -+ -+ return TRUE; -+} -+ -+static gboolean - g_kqueue_file_monitor_cancel (GFileMonitor *monitor) - { - GKqueueFileMonitor *kqueue_monitor = G_KQUEUE_FILE_MONITOR (monitor); - - if (kqueue_monitor->sub) - { -- _kh_cancel_sub (kqueue_monitor->sub); -- _kh_sub_free (kqueue_monitor->sub); -+ _kqsub_cancel (kqueue_monitor->sub); -+ _kqsub_free (kqueue_monitor->sub); - kqueue_monitor->sub = NULL; - } -+#ifndef O_EVTONLY - else if (kqueue_monitor->fallback) - { - g_signal_handlers_disconnect_by_func (kqueue_monitor->fallback, _fallback_callback, kqueue_monitor); - g_file_monitor_cancel (kqueue_monitor->fallback); - } -+#endif - - if (G_FILE_MONITOR_CLASS (g_kqueue_file_monitor_parent_class)->cancel) - (*G_FILE_MONITOR_CLASS (g_kqueue_file_monitor_parent_class)->cancel) (monitor); - - return TRUE; - } -+ -+static kqueue_sub * -+_kqsub_new (const gchar *filename, GLocalFileMonitor *mon, GFileMonitorSource *source) -+{ -+ kqueue_sub *sub; -+ -+ sub = g_slice_new (kqueue_sub); -+ sub->filename = g_strdup (filename); -+ sub->mon = mon; -+ g_source_ref ((GSource *) source); -+ sub->source = source; -+ sub->fd = -1; -+ sub->deps = NULL; -+ sub->is_dir = 0; -+ -+ return sub; -+} -+ -+static void -+_kqsub_free (kqueue_sub *sub) -+{ -+ g_assert (sub->deps == NULL); -+ g_assert (sub->fd == -1); -+ -+ g_source_unref ((GSource *) sub->source); -+ g_free (sub->filename); -+ g_slice_free (kqueue_sub, sub); -+} -+ -+static gboolean -+_kqsub_cancel (kqueue_sub *sub) -+{ -+ struct kevent ev; -+ -+ /* Remove the event and close the file descriptor to automatically -+ * delete pending events. */ -+ if (sub->fd != -1) -+ { -+ EV_SET (&ev, sub->fd, EVFILT_VNODE, EV_DELETE, NOTE_ALL, 0, sub); -+ if (kevent (kq_queue, &ev, 1, NULL, 0, NULL) == -1) -+ { -+ g_warning ("Unable to remove event for %s: %s", sub->filename, g_strerror (errno)); -+ return FALSE; -+ } -+ close (sub->fd); -+ sub->fd = -1; -+ } -+ -+ _km_remove (sub); -+ -+ if (sub->deps) -+ { -+ dl_free (sub->deps); -+ sub->deps = NULL; -+ } -+ -+ return TRUE; -+} -+ -+gboolean -+_kqsub_start_watching (kqueue_sub *sub) -+{ -+ struct stat st; -+ struct kevent ev; -+ -+ sub->fd = open (sub->filename, O_KQFLAG); -+ if (sub->fd == -1) -+ return FALSE; -+ -+ if (fstat (sub->fd, &st) == -1) -+ { -+ g_warning ("fstat failed for %s: %s", sub->filename, g_strerror (errno)); -+ close (sub->fd); -+ sub->fd = -1; -+ return FALSE; -+ } -+ -+ sub->is_dir = (st.st_mode & S_IFDIR) ? 1 : 0; -+ if (sub->is_dir) -+ { -+ if (sub->deps) -+ dl_free (sub->deps); -+ -+ sub->deps = dl_listing (sub->filename); -+ } -+ -+ EV_SET (&ev, sub->fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_ALL, 0, sub); -+ if (kevent (kq_queue, &ev, 1, NULL, 0, NULL) == -1) -+ { -+ g_warning ("Unable to add event for %s: %s", sub->filename, g_strerror (errno)); -+ close (sub->fd); -+ sub->fd = -1; -+ return FALSE; -+ } -+ -+ return TRUE; -+} ---- gio/kqueue/kqueue-helper.c.orig 2016-10-22 05:18:22 UTC -+++ gio/kqueue/kqueue-helper.c -@@ -34,81 +34,6 @@ - #include <errno.h> - #include <pthread.h> - #include "kqueue-helper.h" --#include "kqueue-utils.h" --#include "kqueue-thread.h" --#include "kqueue-missing.h" --#include "kqueue-exclusions.h" -- --static gboolean kh_debug_enabled = FALSE; --#define KH_W if (kh_debug_enabled) g_warning -- --static GHashTable *subs_hash_table = NULL; --G_LOCK_DEFINE_STATIC (hash_lock); -- --static int kqueue_descriptor = -1; --static int kqueue_socket_pair[] = {-1, -1}; --static pthread_t kqueue_thread; -- -- --void _kh_file_appeared_cb (kqueue_sub *sub); -- --/** -- * accessor function for kqueue_descriptor -- **/ --int --get_kqueue_descriptor() --{ -- return kqueue_descriptor; --} -- --/** -- * convert_kqueue_events_to_gio: -- * @flags: a set of kqueue filter flags -- * @done: a pointer to #gboolean indicating that the -- * conversion has been done (out) -- * -- * Translates kqueue filter flags into GIO event flags. -- * -- * Returns: a #GFileMonitorEvent -- **/ --static GFileMonitorEvent --convert_kqueue_events_to_gio (uint32_t flags, gboolean *done) --{ -- g_assert (done != NULL); -- *done = FALSE; -- -- /* TODO: The following notifications should be emulated, if possible: -- * - G_FILE_MONITOR_EVENT_PRE_UNMOUNT -- */ -- if (flags & NOTE_DELETE) -- { -- *done = TRUE; -- return G_FILE_MONITOR_EVENT_DELETED; -- } -- if (flags & NOTE_ATTRIB) -- { -- *done = TRUE; -- return G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED; -- } -- if (flags & (NOTE_WRITE | NOTE_EXTEND)) -- { -- *done = TRUE; -- return G_FILE_MONITOR_EVENT_CHANGED; -- } -- if (flags & NOTE_RENAME) -- { -- *done = TRUE; -- return G_FILE_MONITOR_EVENT_MOVED; -- } -- if (flags & NOTE_REVOKE) -- { -- *done = TRUE; -- return G_FILE_MONITOR_EVENT_UNMOUNTED; -- } -- -- /* done is FALSE */ -- return 0; --} - - typedef struct { - kqueue_sub *sub; -@@ -236,323 +161,21 @@ static const traverse_cbs cbs = { - - - void --_kh_dir_diff (kqueue_sub *sub, GFileMonitorSource *source) -+_kh_dir_diff (kqueue_sub *sub) - { - dep_list *was; - handle_ctx ctx; - -- g_assert (sub != NULL); -- g_assert (source != NULL); -- - memset (&ctx, 0, sizeof (handle_ctx)); - ctx.sub = sub; -- ctx.source = source; -+ ctx.source = sub->source; - - was = sub->deps; - sub->deps = dl_listing (sub->filename); -- -+ - dl_calculate (was, sub->deps, &cbs, &ctx); - - dl_free (was); - } - - --/** -- * 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; -- GFileMonitorSource *source = 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; -- } -- -- source = sub->user_data; -- g_assert (source != 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, source); -- n.flags &= ~(NOTE_WRITE | NOTE_EXTEND); -- } -- -- if (n.flags) -- { -- gboolean done = FALSE; -- mask = convert_kqueue_events_to_gio (n.flags, &done); -- if (done == TRUE) -- g_file_monitor_source_handle_event (source, mask, NULL, NULL, NULL, g_get_monotonic_time ()); -- } -- -- return TRUE; --} -- -- --/* -- * _kh_startup_impl: -- * @unused: unused -- * -- * Kqueue backend startup code. Should be called only once. -- * -- * Returns: %TRUE on success, %FALSE otherwise. -- **/ --static gpointer --_kh_startup_impl (gpointer unused) --{ -- GIOChannel *channel = NULL; -- gboolean result = FALSE; -- -- kqueue_descriptor = kqueue (); -- result = (kqueue_descriptor != -1); -- if (!result) -- { -- KH_W ("Failed to initialize kqueue\n!"); -- return GINT_TO_POINTER (FALSE); -- } -- -- result = socketpair (AF_UNIX, SOCK_STREAM, 0, kqueue_socket_pair); -- if (result != 0) -- { -- KH_W ("Failed to create socket pair\n!"); -- return GINT_TO_POINTER (FALSE) ; -- } -- -- result = pthread_create (&kqueue_thread, -- NULL, -- _kqueue_thread_func, -- &kqueue_socket_pair[1]); -- if (result != 0) -- { -- KH_W ("Failed to run kqueue thread\n!"); -- return GINT_TO_POINTER (FALSE); -- } -- -- _km_init (_kh_file_appeared_cb); -- -- channel = g_io_channel_unix_new (kqueue_socket_pair[0]); -- g_io_add_watch (channel, G_IO_IN, process_kqueue_notifications, NULL); -- -- subs_hash_table = g_hash_table_new (g_direct_hash, g_direct_equal); -- -- KH_W ("started gio kqueue backend\n"); -- return GINT_TO_POINTER (TRUE); --} -- -- --/* -- * _kh_startup: -- * Kqueue backend initialization. -- * -- * Returns: %TRUE on success, %FALSE otherwise. -- **/ --gboolean --_kh_startup (void) --{ -- static GOnce init_once = G_ONCE_INIT; -- g_once (&init_once, _kh_startup_impl, NULL); -- return GPOINTER_TO_INT (init_once.retval); --} -- -- --/** -- * _kh_start_watching: -- * @sub: a #kqueue_sub -- * -- * Starts watching on a subscription. -- * -- * Returns: %TRUE on success, %FALSE otherwise. -- **/ --gboolean --_kh_start_watching (kqueue_sub *sub) --{ -- g_assert (kqueue_socket_pair[0] != -1); -- g_assert (sub != NULL); -- g_assert (sub->filename != NULL); -- -- /* kqueue requires a file descriptor to monitor. Sad but true */ --#if defined (O_EVTONLY) -- sub->fd = open (sub->filename, O_EVTONLY); --#else -- sub->fd = open (sub->filename, O_RDONLY); --#endif -- -- if (sub->fd == -1) -- { -- KH_W ("failed to open file %s (error %d)", sub->filename, errno); -- return FALSE; -- } -- -- _ku_file_information (sub->fd, &sub->is_dir, NULL); -- if (sub->is_dir) -- { -- /* I know, it is very bad to make such decisions in this way and here. -- * We already do have an user_data at the #kqueue_sub, and it may point to -- * GKqueueFileMonitor or GKqueueDirectoryMonitor. For a directory case, -- * we need to scan in contents for the further diffs. Ideally this process -- * should be delegated to the GKqueueDirectoryMonitor, but for now I will -- * do it in a dirty way right here. */ -- if (sub->deps) -- dl_free (sub->deps); -- -- sub->deps = dl_listing (sub->filename); -- } -- -- G_LOCK (hash_lock); -- g_hash_table_insert (subs_hash_table, GINT_TO_POINTER (sub->fd), sub); -- G_UNLOCK (hash_lock); -- -- _kqueue_thread_push_fd (sub->fd); -- -- /* Bump the kqueue thread. It will pick up a new sub entry to monitor */ -- if (!_ku_write (kqueue_socket_pair[0], "A", 1)) -- KH_W ("Failed to bump the kqueue thread (add fd, error %d)", errno); -- return TRUE; --} -- -- --/** -- * _kh_add_sub: -- * @sub: a #kqueue_sub -- * -- * Adds a subscription for monitoring. -- * -- * This funciton tries to start watching a subscription with -- * _kh_start_watching(). On failure, i.e. when a file does not exist yet, -- * the subscription will be added to a list of missing files to continue -- * watching when the file will appear. -- * -- * Returns: %TRUE -- **/ --gboolean --_kh_add_sub (kqueue_sub *sub) --{ -- g_assert (sub != NULL); -- -- if (!_kh_start_watching (sub)) -- _km_add_missing (sub); -- -- return TRUE; --} -- -- --/** -- * _kh_cancel_sub: -- * @sub a #kqueue_sub -- * -- * Stops monitoring on a subscription. -- * -- * Returns: %TRUE -- **/ --gboolean --_kh_cancel_sub (kqueue_sub *sub) --{ -- gboolean missing = FALSE; -- g_assert (kqueue_socket_pair[0] != -1); -- g_assert (sub != NULL); -- -- G_LOCK (hash_lock); -- missing = !g_hash_table_remove (subs_hash_table, GINT_TO_POINTER (sub->fd)); -- G_UNLOCK (hash_lock); -- -- if (missing) -- { -- /* If there were no fd for this subscription, file is still -- * missing. */ -- KH_W ("Removing subscription from missing"); -- _km_remove (sub); -- } -- else -- { -- /* fd will be closed in the kqueue thread */ -- _kqueue_thread_remove_fd (sub->fd); -- -- /* Bump the kqueue thread. It will pick up a new sub entry to remove*/ -- if (!_ku_write (kqueue_socket_pair[0], "R", 1)) -- KH_W ("Failed to bump the kqueue thread (remove fd, error %d)", errno); -- } -- -- return TRUE; --} -- -- --/** -- * _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); --} ---- gio/kqueue/kqueue-helper.h.orig 2016-10-22 05:18:22 UTC -+++ gio/kqueue/kqueue-helper.h -@@ -23,16 +23,31 @@ - #ifndef __KQUEUE_HELPER_H - #define __KQUEUE_HELPER_H - --#include "kqueue-sub.h" - #include <gio/glocalfilemonitor.h> - #include <gio/gfilemonitor.h> - --gboolean _kh_startup (void); --gboolean _kh_add_sub (kqueue_sub *sub); --gboolean _kh_cancel_sub (kqueue_sub *sub); -+#include "dep-list.h" - --gboolean _kh_start_watching (kqueue_sub *sub); -+/** -+ * kqueue_sub: -+ * @filename: a name of the file to monitor -+ * @fd: the associated file descriptor (used by kqueue) -+ * -+ * Represents a subscription on a file or directory. -+ */ -+typedef struct -+{ -+ GLocalFileMonitor *mon; -+ GFileMonitorSource *source; -+ gchar* filename; -+ int fd; -+ dep_list* deps; -+ int is_dir; -+} kqueue_sub; - --void _kh_dir_diff (kqueue_sub *sub, GFileMonitorSource *source); -+gboolean _kqsub_start_watching (kqueue_sub *sub); -+void _kh_dir_diff (kqueue_sub *sub); -+void _km_add_missing (kqueue_sub *sub); -+void _km_remove (kqueue_sub *sub); - - #endif /* __KQUEUE_HELPER_H */ ---- gio/kqueue/kqueue-missing.c.orig 2016-10-22 05:18:22 UTC -+++ gio/kqueue/kqueue-missing.c -@@ -23,12 +23,12 @@ - #include <glib.h> - - #include "kqueue-helper.h" --#include "kqueue-sub.h" --#include "kqueue-missing.h" - - - #define SCAN_MISSING_TIME 4 /* 1/4 Hz */ - -+void _kh_file_appeared_cb (kqueue_sub *sub); -+ - static gboolean km_scan_missing (gpointer user_data); - - static gboolean km_debug_enabled = FALSE; -@@ -38,21 +38,6 @@ static GSList *missing_subs_list = NULL; - G_LOCK_DEFINE_STATIC (missing_lock); - - static volatile gboolean scan_missing_running = FALSE; --static on_create_cb file_appeared_callback; -- -- --/** -- * _km_init: -- * @cb: a callback function. It will be called when a watched file -- * will appear. -- * -- * Initialize the kqueue-missing module (optional). -- **/ --void --_km_init (on_create_cb cb) --{ -- file_appeared_callback = cb; --} - - - /** -@@ -83,6 +68,35 @@ _km_add_missing (kqueue_sub *sub) - } - } - -+/** -+ * _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->mon), -+ child, -+ NULL, -+ G_FILE_MONITOR_EVENT_CREATED); -+ -+ g_object_unref (child); -+} - - /** - * km_scan_missing: -@@ -114,11 +128,10 @@ km_scan_missing (gpointer user_data) - g_assert (sub != NULL); - g_assert (sub->filename != NULL); - -- if (_kh_start_watching (sub)) -+ if (_kqsub_start_watching (sub)) - { - KM_W ("file %s now exists, starting watching", sub->filename); -- if (file_appeared_callback) -- file_appeared_callback (sub); -+ _kh_file_appeared_cb (sub); - not_missing = g_slist_prepend (not_missing, head); - } - } diff --git a/devel/glib20/files/patch-gio_glib-compile-schemas.c b/devel/glib20/files/patch-gio_glib-compile-schemas.c index e92fac5baff8..cdf50e71996a 100644 --- a/devel/glib20/files/patch-gio_glib-compile-schemas.c +++ b/devel/glib20/files/patch-gio_glib-compile-schemas.c @@ -1,6 +1,6 @@ ---- gio/glib-compile-schemas.c.orig 2012-06-14 16:39:22.000000000 +0200 -+++ gio/glib-compile-schemas.c 2012-06-14 16:39:55.000000000 +0200 -@@ -1204,11 +1204,13 @@ +--- gio/glib-compile-schemas.c.orig 2017-08-07 16:58:31.000000000 +0200 ++++ gio/glib-compile-schemas.c 2017-09-15 09:25:19.746310000 +0200 +@@ -1219,6 +1219,7 @@ parse_state_start_schema (ParseState *state, return; } @@ -8,8 +8,10 @@ if (path && (g_str_has_prefix (path, "/apps/") || g_str_has_prefix (path, "/desktop/") || g_str_has_prefix (path, "/system/"))) - g_printerr ("warning: Schema '%s' has path '%s'. Paths starting with " - "'/apps/', '/desktop/' or '/system/' are deprecated.\n", id, path); +@@ -1231,6 +1232,7 @@ parse_state_start_schema (ParseState *state, + g_printerr ("%s\n", message); + g_free (message); + } +#endif state->schema_state = schema_state_new (path, gettext_domain, diff --git a/devel/glib20/files/patch-gio_glocalfileoutputstream.c b/devel/glib20/files/patch-gio_glocalfileoutputstream.c deleted file mode 100644 index 9a373188836e..000000000000 --- a/devel/glib20/files/patch-gio_glocalfileoutputstream.c +++ /dev/null @@ -1,38 +0,0 @@ -From 45d4b59e3f7ef7b41db08f0c11ee5000126cfedb Mon Sep 17 00:00:00 2001 -From: Ting-Wei Lan <lantw@src.gnome.org> -Date: Sun, 4 Dec 2016 15:02:54 +0800 -Subject: [PATCH] glocalfileoutputstream: Fix symlink writing on FreeBSD and - NetBSD - -FreeBSD, DragonflyBSD and NetBSD support O_NOFOLLOW, but they use error -numbers that are different from what POSIX standard specifies. They are -not going to change the behavior, and existing programs on these systems -already take advantage of this difference. To support them, we have to -add a check in GIO to use different error numbers on these systems. - -https://bugzilla.gnome.org/show_bug.cgi?id=775593 ---- - gio/glocalfileoutputstream.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/gio/glocalfileoutputstream.c b/gio/glocalfileoutputstream.c -index 81184a671..4b3733cce 100644 ---- gio/glocalfileoutputstream.c -+++ gio/glocalfileoutputstream.c -@@ -763,7 +763,13 @@ handle_overwrite_open (const char *filename, - #ifdef O_NOFOLLOW - is_symlink = FALSE; - fd = g_open (filename, open_flags | O_NOFOLLOW, mode); -+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) -+ if (fd == -1 && errno == EMLINK) -+#elif defined(__NetBSD__) -+ if (fd == -1 && errno == EFTYPE) -+#else - if (fd == -1 && errno == ELOOP) -+#endif - { - /* Could be a symlink, or it could be a regular ELOOP error, - * but then the next open will fail too. */ --- -2.13.0 - diff --git a/devel/glib20/files/patch-gio_kqueue-kqueue-missing.c b/devel/glib20/files/patch-gio_kqueue-kqueue-missing.c new file mode 100644 index 000000000000..8cf553223e79 --- /dev/null +++ b/devel/glib20/files/patch-gio_kqueue-kqueue-missing.c @@ -0,0 +1,93 @@ +--- gio/kqueue/kqueue-missing.c.orig 2018-04-09 22:48:45.637366000 +0200 ++++ gio/kqueue/kqueue-missing.c 2018-04-09 22:48:55.840341000 +0200 +@@ -23,12 +23,12 @@ + #include <glib.h> + + #include "kqueue-helper.h" +-#include "kqueue-sub.h" +-#include "kqueue-missing.h" + + + #define SCAN_MISSING_TIME 4 /* 1/4 Hz */ + ++void _kh_file_appeared_cb (kqueue_sub *sub); ++ + static gboolean km_scan_missing (gpointer user_data); + + static gboolean km_debug_enabled = FALSE; +@@ -38,24 +38,9 @@ static GSList *missing_subs_list = NULL; + G_LOCK_DEFINE_STATIC (missing_lock); + + static volatile gboolean scan_missing_running = FALSE; +-static on_create_cb file_appeared_callback; + + + /** +- * _km_init: +- * @cb: a callback function. It will be called when a watched file +- * will appear. +- * +- * Initialize the kqueue-missing module (optional). +- **/ +-void +-_km_init (on_create_cb cb) +-{ +- file_appeared_callback = cb; +-} +- +- +-/** + * _km_add_missing: + * @sub: a #kqueue_sub + * +@@ -83,7 +68,36 @@ _km_add_missing (kqueue_sub *sub) + } + } + ++/** ++ * _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->mon), ++ child, ++ NULL, ++ G_FILE_MONITOR_EVENT_CREATED); ++ ++ g_object_unref (child); ++} ++ + /** + * km_scan_missing: + * @user_data: unused +@@ -114,11 +128,10 @@ km_scan_missing (gpointer user_data) + g_assert (sub != NULL); + g_assert (sub->filename != NULL); + +- if (_kh_start_watching (sub)) ++ if (_kqsub_start_watching (sub)) + { + KM_W ("file %s now exists, starting watching", sub->filename); +- if (file_appeared_callback) +- file_appeared_callback (sub); ++ _kh_file_appeared_cb (sub); + not_missing = g_slist_prepend (not_missing, head); + } + } diff --git a/devel/glib20/files/patch-gio_kqueue_Makefile.in b/devel/glib20/files/patch-gio_kqueue_Makefile.in new file mode 100644 index 000000000000..4e2a220ba9f7 --- /dev/null +++ b/devel/glib20/files/patch-gio_kqueue_Makefile.in @@ -0,0 +1,87 @@ +--- gio/kqueue/Makefile.in.orig 2018-04-09 23:09:21.018712000 +0200 ++++ gio/kqueue/Makefile.in 2018-04-09 23:09:38.517739000 +0200 +@@ -183,9 +183,7 @@ LTLIBRARIES = $(installed_test_LTLIBRARIES) $(noinst_L + libkqueue_la_LIBADD = + am__objects_1 = + am_libkqueue_la_OBJECTS = libkqueue_la-gkqueuefilemonitor.lo \ +- libkqueue_la-kqueue-helper.lo libkqueue_la-kqueue-thread.lo \ +- libkqueue_la-kqueue-sub.lo libkqueue_la-kqueue-missing.lo \ +- libkqueue_la-kqueue-utils.lo libkqueue_la-kqueue-exclusions.lo \ ++ libkqueue_la-kqueue-helper.lo libkqueue_la-kqueue-missing.lo \ + libkqueue_la-dep-list.lo $(am__objects_1) + libkqueue_la_OBJECTS = $(am_libkqueue_la_OBJECTS) + AM_V_lt = $(am__v_lt_@AM_V@) +@@ -777,19 +775,9 @@ all_test_ltlibs = $(test_ltlibraries) $(uninstalled_te + @ENABLE_INSTALLED_TESTS_TRUE@installed_test_meta_DATA = $(installed_testcases:=.test) + libkqueue_la_SOURCES = \ + gkqueuefilemonitor.c \ +- gkqueuefilemonitor.h \ + kqueue-helper.c \ + kqueue-helper.h \ +- kqueue-thread.c \ +- kqueue-thread.h \ +- kqueue-sub.c \ +- kqueue-sub.h \ + kqueue-missing.c \ +- kqueue-missing.h \ +- kqueue-utils.c \ +- kqueue-utils.h \ +- kqueue-exclusions.c \ +- kqueue-exclusions.h \ + dep-list.c \ + dep-list.h \ + $(NULL) +@@ -1009,12 +997,8 @@ distclean-compile: + + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkqueue_la-dep-list.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkqueue_la-gkqueuefilemonitor.Plo@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkqueue_la-kqueue-exclusions.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkqueue_la-kqueue-helper.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkqueue_la-kqueue-missing.Plo@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkqueue_la-kqueue-sub.Plo@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkqueue_la-kqueue-thread.Plo@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkqueue_la-kqueue-utils.Plo@am__quote@ + + .c.o: + @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@@ -1054,40 +1038,12 @@ libkqueue_la-kqueue-helper.lo: kqueue-helper.c + @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkqueue_la_CFLAGS) $(CFLAGS) -c -o libkqueue_la-kqueue-helper.lo `test -f 'kqueue-helper.c' || echo '$(srcdir)/'`kqueue-helper.c + +-libkqueue_la-kqueue-thread.lo: kqueue-thread.c +-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkqueue_la_CFLAGS) $(CFLAGS) -MT libkqueue_la-kqueue-thread.lo -MD -MP -MF $(DEPDIR)/libkqueue_la-kqueue-thread.Tpo -c -o libkqueue_la-kqueue-thread.lo `test -f 'kqueue-thread.c' || echo '$(srcdir)/'`kqueue-thread.c +-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkqueue_la-kqueue-thread.Tpo $(DEPDIR)/libkqueue_la-kqueue-thread.Plo +-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kqueue-thread.c' object='libkqueue_la-kqueue-thread.lo' libtool=yes @AMDEPBACKSLASH@ +-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkqueue_la_CFLAGS) $(CFLAGS) -c -o libkqueue_la-kqueue-thread.lo `test -f 'kqueue-thread.c' || echo '$(srcdir)/'`kqueue-thread.c +- +-libkqueue_la-kqueue-sub.lo: kqueue-sub.c +-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkqueue_la_CFLAGS) $(CFLAGS) -MT libkqueue_la-kqueue-sub.lo -MD -MP -MF $(DEPDIR)/libkqueue_la-kqueue-sub.Tpo -c -o libkqueue_la-kqueue-sub.lo `test -f 'kqueue-sub.c' || echo '$(srcdir)/'`kqueue-sub.c +-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkqueue_la-kqueue-sub.Tpo $(DEPDIR)/libkqueue_la-kqueue-sub.Plo +-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kqueue-sub.c' object='libkqueue_la-kqueue-sub.lo' libtool=yes @AMDEPBACKSLASH@ +-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkqueue_la_CFLAGS) $(CFLAGS) -c -o libkqueue_la-kqueue-sub.lo `test -f 'kqueue-sub.c' || echo '$(srcdir)/'`kqueue-sub.c +- + libkqueue_la-kqueue-missing.lo: kqueue-missing.c + @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkqueue_la_CFLAGS) $(CFLAGS) -MT libkqueue_la-kqueue-missing.lo -MD -MP -MF $(DEPDIR)/libkqueue_la-kqueue-missing.Tpo -c -o libkqueue_la-kqueue-missing.lo `test -f 'kqueue-missing.c' || echo '$(srcdir)/'`kqueue-missing.c + @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkqueue_la-kqueue-missing.Tpo $(DEPDIR)/libkqueue_la-kqueue-missing.Plo + @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kqueue-missing.c' object='libkqueue_la-kqueue-missing.lo' libtool=yes @AMDEPBACKSLASH@ + @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkqueue_la_CFLAGS) $(CFLAGS) -c -o libkqueue_la-kqueue-missing.lo `test -f 'kqueue-missing.c' || echo '$(srcdir)/'`kqueue-missing.c +- +-libkqueue_la-kqueue-utils.lo: kqueue-utils.c +-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkqueue_la_CFLAGS) $(CFLAGS) -MT libkqueue_la-kqueue-utils.lo -MD -MP -MF $(DEPDIR)/libkqueue_la-kqueue-utils.Tpo -c -o libkqueue_la-kqueue-utils.lo `test -f 'kqueue-utils.c' || echo '$(srcdir)/'`kqueue-utils.c +-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkqueue_la-kqueue-utils.Tpo $(DEPDIR)/libkqueue_la-kqueue-utils.Plo +-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kqueue-utils.c' object='libkqueue_la-kqueue-utils.lo' libtool=yes @AMDEPBACKSLASH@ +-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkqueue_la_CFLAGS) $(CFLAGS) -c -o libkqueue_la-kqueue-utils.lo `test -f 'kqueue-utils.c' || echo '$(srcdir)/'`kqueue-utils.c +- +-libkqueue_la-kqueue-exclusions.lo: kqueue-exclusions.c +-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkqueue_la_CFLAGS) $(CFLAGS) -MT libkqueue_la-kqueue-exclusions.lo -MD -MP -MF $(DEPDIR)/libkqueue_la-kqueue-exclusions.Tpo -c -o libkqueue_la-kqueue-exclusions.lo `test -f 'kqueue-exclusions.c' || echo '$(srcdir)/'`kqueue-exclusions.c +-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkqueue_la-kqueue-exclusions.Tpo $(DEPDIR)/libkqueue_la-kqueue-exclusions.Plo +-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kqueue-exclusions.c' object='libkqueue_la-kqueue-exclusions.lo' libtool=yes @AMDEPBACKSLASH@ +-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkqueue_la_CFLAGS) $(CFLAGS) -c -o libkqueue_la-kqueue-exclusions.lo `test -f 'kqueue-exclusions.c' || echo '$(srcdir)/'`kqueue-exclusions.c + + libkqueue_la-dep-list.lo: dep-list.c + @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkqueue_la_CFLAGS) $(CFLAGS) -MT libkqueue_la-dep-list.lo -MD -MP -MF $(DEPDIR)/libkqueue_la-dep-list.Tpo -c -o libkqueue_la-dep-list.lo `test -f 'dep-list.c' || echo '$(srcdir)/'`dep-list.c diff --git a/devel/glib20/files/patch-gio_kqueue_gkqueuefilemonitor.c b/devel/glib20/files/patch-gio_kqueue_gkqueuefilemonitor.c new file mode 100644 index 000000000000..e1166c9d71d1 --- /dev/null +++ b/devel/glib20/files/patch-gio_kqueue_gkqueuefilemonitor.c @@ -0,0 +1,463 @@ +--- gio/kqueue/gkqueuefilemonitor.c.orig 2018-04-07 04:10:22.000000000 +0200 ++++ gio/kqueue/gkqueuefilemonitor.c 2018-05-03 20:21:55.830634000 +0200 +@@ -22,33 +22,73 @@ + + #include "config.h" + +-#include "gkqueuefilemonitor.h" +-#include "kqueue-helper.h" +-#include "kqueue-exclusions.h" ++#include <sys/types.h> ++#include <sys/event.h> ++#include <sys/time.h> ++#include <sys/socket.h> ++#include <sys/stat.h> ++ ++#include <errno.h> ++#include <fcntl.h> ++#include <string.h> ++ ++#include <glib-object.h> ++#include <gio/gfilemonitor.h> ++#include <gio/glocalfilemonitor.h> ++#include <gio/giomodule.h> + #include <gio/gpollfilemonitor.h> + #include <gio/gfile.h> +-#include <gio/giomodule.h> ++#include <glib-unix.h> ++#include "glib-private.h" + ++#include "kqueue-helper.h" ++#include "dep-list.h" + +-struct _GKqueueFileMonitor ++G_LOCK_DEFINE_STATIC (kq_lock); ++static GSource *kq_source; ++static int kq_queue = -1; ++ ++#define G_TYPE_KQUEUE_FILE_MONITOR (g_kqueue_file_monitor_get_type ()) ++#define G_KQUEUE_FILE_MONITOR(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ ++ G_TYPE_KQUEUE_FILE_MONITOR, GKqueueFileMonitor)) ++ ++typedef GLocalFileMonitorClass GKqueueFileMonitorClass; ++ ++typedef struct + { + GLocalFileMonitor parent_instance; + + kqueue_sub *sub; +- ++#ifndef O_EVTONLY + GFileMonitor *fallback; + GFile *fbfile; +-}; ++#endif ++} GKqueueFileMonitor; + ++GType g_kqueue_file_monitor_get_type (void); ++G_DEFINE_TYPE_WITH_CODE (GKqueueFileMonitor, g_kqueue_file_monitor, G_TYPE_LOCAL_FILE_MONITOR, ++ g_io_extension_point_implement (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME, ++ g_define_type_id, ++ "kqueue", ++ 20)) ++ ++#ifndef O_EVTONLY ++#define O_KQFLAG O_RDONLY ++#else ++#define O_KQFLAG O_EVTONLY ++#endif ++ ++#define NOTE_ALL (NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_RENAME) ++ + static gboolean g_kqueue_file_monitor_cancel (GFileMonitor* monitor); ++static gboolean g_kqueue_file_monitor_is_supported (void); + +-G_DEFINE_TYPE_WITH_CODE (GKqueueFileMonitor, g_kqueue_file_monitor, G_TYPE_LOCAL_FILE_MONITOR, +- g_io_extension_point_implement (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME, +- g_define_type_id, +- "kqueue", +- 20)) ++static kqueue_sub *_kqsub_new (const gchar *, GLocalFileMonitor *, GFileMonitorSource *); ++static void _kqsub_free (kqueue_sub *); ++static gboolean _kqsub_cancel (kqueue_sub *); + + ++#ifndef O_EVTONLY + static void + _fallback_callback (GFileMonitor *unused, + GFile *first, +@@ -57,22 +97,42 @@ _fallback_callback (GFileMonitor *unused, + gpointer udata) + { + GKqueueFileMonitor *kq_mon = G_KQUEUE_FILE_MONITOR (udata); +- GFileMonitor *mon = G_FILE_MONITOR (kq_mon); +- g_assert (kq_mon != NULL); +- g_assert (mon != NULL); +- (void) unused; + +- if (event == G_FILE_MONITOR_EVENT_CHANGED) +- { +- GLocalFileMonitor *local_monitor = G_LOCAL_FILE_MONITOR (kq_mon); +- +- _kh_dir_diff (kq_mon->sub, local_monitor->source); +- } +- else +- g_file_monitor_emit_event (mon, first, second, event); ++ g_file_monitor_emit_event (G_FILE_MONITOR (kq_mon), first, second, event); + } + ++/* ++ * _ke_is_excluded: ++ * @full_path - a path to file to check. ++ * ++ * Returns: TRUE if the file should be excluded from the kqueue-powered ++ * monitoring, FALSE otherwise. ++ **/ ++gboolean ++_ke_is_excluded (const char *full_path) ++{ ++ GFile *f = NULL; ++ GMount *mount = NULL; + ++ f = g_file_new_for_path (full_path); ++ ++ if (f != NULL) { ++ mount = g_file_find_enclosing_mount (f, NULL, NULL); ++ g_object_unref (f); ++ } ++ ++ if ((mount != NULL && (g_mount_can_unmount (mount))) || g_str_has_prefix (full_path, "/mnt/")) ++ { ++ g_warning ("Excluding %s from kernel notification, falling back to poll", full_path); ++ if (mount) ++ g_object_unref (mount); ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++#endif /* !O_EVTONLY */ ++ + static void + g_kqueue_file_monitor_finalize (GObject *object) + { +@@ -80,16 +140,18 @@ g_kqueue_file_monitor_finalize (GObject *object) + + if (kqueue_monitor->sub) + { +- _kh_cancel_sub (kqueue_monitor->sub); +- _kh_sub_free (kqueue_monitor->sub); ++ _kqsub_cancel (kqueue_monitor->sub); ++ _kqsub_free (kqueue_monitor->sub); + kqueue_monitor->sub = NULL; + } + ++#ifndef O_EVTONLY + if (kqueue_monitor->fallback) + g_object_unref (kqueue_monitor->fallback); + + if (kqueue_monitor->fbfile) + g_object_unref (kqueue_monitor->fbfile); ++#endif + + if (G_OBJECT_CLASS (g_kqueue_file_monitor_parent_class)->finalize) + (*G_OBJECT_CLASS (g_kqueue_file_monitor_parent_class)->finalize) (object); +@@ -103,21 +165,25 @@ g_kqueue_file_monitor_start (GLocalFileMonitor *local_ + GFileMonitorSource *source) + { + GKqueueFileMonitor *kqueue_monitor = G_KQUEUE_FILE_MONITOR (local_monitor); +- GObject *obj; +- GKqueueFileMonitorClass *klass; +- GObjectClass *parent_class; +- kqueue_sub *sub = NULL; +- gboolean ret_kh_startup = FALSE; +- const gchar *path = NULL; ++ kqueue_sub *sub; ++ const gchar *path; + +- +- ret_kh_startup = _kh_startup (); +- g_assert (ret_kh_startup); +- + path = filename; +- if (!path) ++ if (path == NULL) + path = dirname; + ++#ifndef O_EVTONLY ++ if (_ke_is_excluded (path)) ++ { ++ GFile *file = g_file_new_for_path (path); ++ kqueue_monitor->fbfile = file; ++ kqueue_monitor->fallback = _g_poll_file_monitor_new (file); ++ g_signal_connect (kqueue_monitor->fallback, "changed", ++ G_CALLBACK (_fallback_callback), kqueue_monitor); ++ return; ++ } ++#endif ++ + /* For a directory monitor, create a subscription object anyway. + * It will be used for directory diff calculation routines. + * Wait, directory diff in a GKqueueFileMonitor? +@@ -125,35 +191,15 @@ g_kqueue_file_monitor_start (GLocalFileMonitor *local_ + * file, GIO uses a GKqueueFileMonitor object for that. If a directory + * will be created under that path, GKqueueFileMonitor will have to + * handle the directory notifications. */ ++ sub = _kqsub_new (path, local_monitor, source); ++ if (sub == NULL) ++ return; + +- sub = _kh_sub_new (path, TRUE, source); +- +- /* FIXME: what to do about errors here? we can't return NULL or another +- * kind of error and an assertion is probably too hard (same issue as in +- * the inotify backend) */ +- g_assert (sub != NULL); + kqueue_monitor->sub = sub; +- +- if (!_ke_is_excluded (path)) +- _kh_add_sub (sub); +- else +- { +- GFile *file = g_file_new_for_path (path); +- kqueue_monitor->fbfile = file; +- kqueue_monitor->fallback = _g_poll_file_monitor_new (file); +- g_signal_connect (kqueue_monitor->fallback, +- "changed", +- G_CALLBACK (_fallback_callback), +- kqueue_monitor); +- } ++ if (!_kqsub_start_watching (sub)) ++ _km_add_missing (sub); + } + +-static gboolean +-g_kqueue_file_monitor_is_supported (void) +-{ +- return _kh_startup (); +-} +- + static void + g_kqueue_file_monitor_class_init (GKqueueFileMonitorClass *klass) + { +@@ -175,24 +221,218 @@ g_kqueue_file_monitor_init (GKqueueFileMonitor *monito + } + + static gboolean ++g_kqueue_file_monitor_callback (gint fd, GIOCondition condition, gpointer user_data) ++{ ++ gint64 now = g_source_get_time (kq_source); ++ kqueue_sub *sub; ++ GFileMonitorSource *source; ++ struct kevent ev; ++ struct timespec ts; ++ ++ memset (&ts, 0, sizeof(ts)); ++ while (kevent(fd, NULL, 0, &ev, 1, &ts) > 0) ++ { ++ GFileMonitorEvent mask = 0; ++ ++ if (ev.filter != EVFILT_VNODE || ev.udata == NULL) ++ continue; ++ ++ sub = ev.udata; ++ source = sub->source; ++ ++ if (ev.flags & EV_ERROR) ++ ev.fflags = NOTE_REVOKE; ++ ++ if (ev.fflags & (NOTE_DELETE | NOTE_REVOKE)) ++ { ++ _kqsub_cancel (sub); ++ _km_add_missing (sub); ++ } ++ ++ if (sub->is_dir && ev.fflags & (NOTE_WRITE | NOTE_EXTEND)) ++ { ++ _kh_dir_diff (sub); ++ ev.fflags &= ~(NOTE_WRITE | NOTE_EXTEND); ++ } ++ ++ if (ev.fflags & NOTE_DELETE) ++ { ++ mask = G_FILE_MONITOR_EVENT_DELETED; ++ } ++ else if (ev.fflags & NOTE_ATTRIB) ++ { ++ mask = G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED; ++ } ++ else if (ev.fflags & (NOTE_WRITE | NOTE_EXTEND)) ++ { ++ mask = G_FILE_MONITOR_EVENT_CHANGED; ++ } ++ else if (ev.fflags & NOTE_RENAME) ++ { ++ /* Since there’s apparently no way to get the new name of the ++ * file out of kqueue(), all we can do is say that this one has ++ * been deleted. */ ++ mask = G_FILE_MONITOR_EVENT_DELETED; ++ } ++ else if (ev.fflags & NOTE_REVOKE) ++ { ++ mask = G_FILE_MONITOR_EVENT_UNMOUNTED; ++ } ++ ++ if (mask) ++ g_file_monitor_source_handle_event (source, mask, NULL, NULL, NULL, now); ++ } ++ ++ return TRUE; ++} ++ ++static gboolean ++g_kqueue_file_monitor_is_supported (void) ++{ ++ int errsv; ++ ++ G_LOCK (kq_lock); ++ ++ if (kq_queue == -1) ++ { ++ kq_queue = kqueue (); ++ errsv = errno; ++ ++ if (kq_queue == -1) ++ { ++ g_warning ("Unable to create a kqueue: %s", g_strerror (errsv)); ++ G_UNLOCK (kq_lock); ++ return FALSE; ++ } ++ ++ kq_source = g_unix_fd_source_new (kq_queue, G_IO_IN); ++ g_source_set_callback (kq_source, (GSourceFunc) g_kqueue_file_monitor_callback, NULL, NULL); ++ g_source_attach (kq_source, GLIB_PRIVATE_CALL (g_get_worker_context) ()); ++ } ++ ++ G_UNLOCK (kq_lock); ++ ++ return TRUE; ++} ++ ++static gboolean + g_kqueue_file_monitor_cancel (GFileMonitor *monitor) + { + GKqueueFileMonitor *kqueue_monitor = G_KQUEUE_FILE_MONITOR (monitor); + + if (kqueue_monitor->sub) + { +- _kh_cancel_sub (kqueue_monitor->sub); +- _kh_sub_free (kqueue_monitor->sub); ++ _kqsub_cancel (kqueue_monitor->sub); ++ _kqsub_free (kqueue_monitor->sub); + kqueue_monitor->sub = NULL; + } ++#ifndef O_EVTONLY + else if (kqueue_monitor->fallback) + { + g_signal_handlers_disconnect_by_func (kqueue_monitor->fallback, _fallback_callback, kqueue_monitor); + g_file_monitor_cancel (kqueue_monitor->fallback); + } ++#endif + + if (G_FILE_MONITOR_CLASS (g_kqueue_file_monitor_parent_class)->cancel) + (*G_FILE_MONITOR_CLASS (g_kqueue_file_monitor_parent_class)->cancel) (monitor); ++ ++ return TRUE; ++} ++ ++static kqueue_sub * ++_kqsub_new (const gchar *filename, GLocalFileMonitor *mon, GFileMonitorSource *source) ++{ ++ kqueue_sub *sub; ++ ++ sub = g_slice_new (kqueue_sub); ++ sub->filename = g_strdup (filename); ++ sub->mon = mon; ++ g_source_ref ((GSource *) source); ++ sub->source = source; ++ sub->fd = -1; ++ sub->deps = NULL; ++ sub->is_dir = 0; ++ ++ return sub; ++} ++ ++static void ++_kqsub_free (kqueue_sub *sub) ++{ ++ g_assert (sub->deps == NULL); ++ g_assert (sub->fd == -1); ++ ++ g_source_unref ((GSource *) sub->source); ++ g_free (sub->filename); ++ g_slice_free (kqueue_sub, sub); ++} ++ ++static gboolean ++_kqsub_cancel (kqueue_sub *sub) ++{ ++ struct kevent ev; ++ ++ /* Remove the event and close the file descriptor to automatically ++ * delete pending events. */ ++ if (sub->fd != -1) ++ { ++ EV_SET (&ev, sub->fd, EVFILT_VNODE, EV_DELETE, NOTE_ALL, 0, sub); ++ if (kevent (kq_queue, &ev, 1, NULL, 0, NULL) == -1) ++ { ++ g_warning ("Unable to remove event for %s: %s", sub->filename, g_strerror (errno)); ++ return FALSE; ++ } ++ close (sub->fd); ++ sub->fd = -1; ++ } ++ ++ _km_remove (sub); ++ ++ if (sub->deps) ++ { ++ dl_free (sub->deps); ++ sub->deps = NULL; ++ } ++ ++ return TRUE; ++} ++ ++gboolean ++_kqsub_start_watching (kqueue_sub *sub) ++{ ++ struct stat st; ++ struct kevent ev; ++ ++ sub->fd = open (sub->filename, O_KQFLAG); ++ if (sub->fd == -1) ++ return FALSE; ++ ++ if (fstat (sub->fd, &st) == -1) ++ { ++ g_warning ("fstat failed for %s: %s", sub->filename, g_strerror (errno)); ++ close (sub->fd); ++ sub->fd = -1; ++ return FALSE; ++ } ++ ++ sub->is_dir = (st.st_mode & S_IFDIR) ? 1 : 0; ++ if (sub->is_dir) ++ { ++ if (sub->deps) ++ dl_free (sub->deps); ++ ++ sub->deps = dl_listing (sub->filename); ++ } ++ ++ EV_SET (&ev, sub->fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_ALL, 0, sub); ++ if (kevent (kq_queue, &ev, 1, NULL, 0, NULL) == -1) ++ { ++ g_warning ("Unable to add event for %s: %s", sub->filename, g_strerror (errno)); ++ close (sub->fd); ++ sub->fd = -1; ++ return FALSE; ++ } + + return TRUE; + } diff --git a/devel/glib20/files/patch-gio_kqueue_kqueue-helper.c b/devel/glib20/files/patch-gio_kqueue_kqueue-helper.c new file mode 100644 index 000000000000..1dbae54548bf --- /dev/null +++ b/devel/glib20/files/patch-gio_kqueue_kqueue-helper.c @@ -0,0 +1,409 @@ +--- gio/kqueue/kqueue-helper.c.orig 2018-01-08 21:00:49.000000000 +0100 ++++ gio/kqueue/kqueue-helper.c 2018-04-09 22:46:58.181986000 +0200 +@@ -34,84 +34,7 @@ + #include <errno.h> + #include <pthread.h> + #include "kqueue-helper.h" +-#include "kqueue-utils.h" +-#include "kqueue-thread.h" +-#include "kqueue-missing.h" +-#include "kqueue-exclusions.h" + +-static gboolean kh_debug_enabled = FALSE; +-#define KH_W if (kh_debug_enabled) g_warning +- +-static GHashTable *subs_hash_table = NULL; +-G_LOCK_DEFINE_STATIC (hash_lock); +- +-static int kqueue_descriptor = -1; +-static int kqueue_socket_pair[] = {-1, -1}; +-static pthread_t kqueue_thread; +- +- +-void _kh_file_appeared_cb (kqueue_sub *sub); +- +-/** +- * accessor function for kqueue_descriptor +- **/ +-int +-get_kqueue_descriptor() +-{ +- return kqueue_descriptor; +-} +- +-/** +- * convert_kqueue_events_to_gio: +- * @flags: a set of kqueue filter flags +- * @done: a pointer to #gboolean indicating that the +- * conversion has been done (out) +- * +- * Translates kqueue filter flags into GIO event flags. +- * +- * Returns: a #GFileMonitorEvent +- **/ +-static GFileMonitorEvent +-convert_kqueue_events_to_gio (uint32_t flags, gboolean *done) +-{ +- g_assert (done != NULL); +- *done = FALSE; +- +- /* TODO: The following notifications should be emulated, if possible: +- * - G_FILE_MONITOR_EVENT_PRE_UNMOUNT +- */ +- if (flags & NOTE_DELETE) +- { +- *done = TRUE; +- return G_FILE_MONITOR_EVENT_DELETED; +- } +- if (flags & NOTE_ATTRIB) +- { +- *done = TRUE; +- return G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED; +- } +- if (flags & (NOTE_WRITE | NOTE_EXTEND)) +- { +- *done = TRUE; +- return G_FILE_MONITOR_EVENT_CHANGED; +- } +- if (flags & NOTE_RENAME) +- { +- /* Since there’s apparently no way to get the new name of the file out of +- * kqueue(), all we can do is say that this one has been deleted. */ +- *done = TRUE; +- return G_FILE_MONITOR_EVENT_DELETED; +- } +- if (flags & NOTE_REVOKE) +- { +- *done = TRUE; +- return G_FILE_MONITOR_EVENT_UNMOUNTED; +- } +- +- /* done is FALSE */ +- return 0; +-} +- + typedef struct { + kqueue_sub *sub; + GFileMonitorSource *source; +@@ -238,318 +161,21 @@ static const traverse_cbs cbs = { + + + void +-_kh_dir_diff (kqueue_sub *sub, GFileMonitorSource *source) ++_kh_dir_diff (kqueue_sub *sub) + { + dep_list *was; + handle_ctx ctx; + +- g_assert (sub != NULL); +- g_assert (source != NULL); +- + memset (&ctx, 0, sizeof (handle_ctx)); + ctx.sub = sub; +- ctx.source = source; ++ ctx.source = sub->source; + + was = sub->deps; + sub->deps = dl_listing (sub->filename); +- ++ + dl_calculate (was, sub->deps, &cbs, &ctx); + + dl_free (was); + } + + +-/** +- * 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; +- GFileMonitorSource *source = 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; +- } +- +- source = sub->user_data; +- g_assert (source != 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, source); +- n.flags &= ~(NOTE_WRITE | NOTE_EXTEND); +- } +- +- if (n.flags) +- { +- gboolean done = FALSE; +- mask = convert_kqueue_events_to_gio (n.flags, &done); +- if (done == TRUE) +- g_file_monitor_source_handle_event (source, mask, NULL, NULL, NULL, g_get_monotonic_time ()); +- } +- +- return TRUE; +-} +- +- +-/* +- * _kh_startup_impl: +- * @unused: unused +- * +- * Kqueue backend startup code. Should be called only once. +- * +- * Returns: %TRUE on success, %FALSE otherwise. +- **/ +-static gpointer +-_kh_startup_impl (gpointer unused) +-{ +- GIOChannel *channel = NULL; +- gboolean result = FALSE; +- +- kqueue_descriptor = kqueue (); +- result = (kqueue_descriptor != -1); +- if (!result) +- { +- KH_W ("Failed to initialize kqueue\n!"); +- return GINT_TO_POINTER (FALSE); +- } +- +- result = socketpair (AF_UNIX, SOCK_STREAM, 0, kqueue_socket_pair); +- if (result != 0) +- { +- KH_W ("Failed to create socket pair\n!"); +- return GINT_TO_POINTER (FALSE) ; +- } +- +- result = pthread_create (&kqueue_thread, +- NULL, +- _kqueue_thread_func, +- &kqueue_socket_pair[1]); +- if (result != 0) +- { +- KH_W ("Failed to run kqueue thread\n!"); +- return GINT_TO_POINTER (FALSE); +- } +- +- _km_init (_kh_file_appeared_cb); +- +- channel = g_io_channel_unix_new (kqueue_socket_pair[0]); +- g_io_add_watch (channel, G_IO_IN, process_kqueue_notifications, NULL); +- +- subs_hash_table = g_hash_table_new (g_direct_hash, g_direct_equal); +- +- KH_W ("started gio kqueue backend\n"); +- return GINT_TO_POINTER (TRUE); +-} +- +- +-/* +- * _kh_startup: +- * Kqueue backend initialization. +- * +- * Returns: %TRUE on success, %FALSE otherwise. +- **/ +-gboolean +-_kh_startup (void) +-{ +- static GOnce init_once = G_ONCE_INIT; +- g_once (&init_once, _kh_startup_impl, NULL); +- return GPOINTER_TO_INT (init_once.retval); +-} +- +- +-/** +- * _kh_start_watching: +- * @sub: a #kqueue_sub +- * +- * Starts watching on a subscription. +- * +- * Returns: %TRUE on success, %FALSE otherwise. +- **/ +-gboolean +-_kh_start_watching (kqueue_sub *sub) +-{ +- g_assert (kqueue_socket_pair[0] != -1); +- g_assert (sub != NULL); +- g_assert (sub->filename != NULL); +- +- /* kqueue requires a file descriptor to monitor. Sad but true */ +-#if defined (O_EVTONLY) +- sub->fd = open (sub->filename, O_EVTONLY); +-#else +- sub->fd = open (sub->filename, O_RDONLY); +-#endif +- +- if (sub->fd == -1) +- { +- KH_W ("failed to open file %s (error %d)", sub->filename, errno); +- return FALSE; +- } +- +- _ku_file_information (sub->fd, &sub->is_dir, NULL); +- if (sub->is_dir) +- { +- /* I know, it is very bad to make such decisions in this way and here. +- * We already do have an user_data at the #kqueue_sub, and it may point to +- * GKqueueFileMonitor or GKqueueDirectoryMonitor. For a directory case, +- * we need to scan in contents for the further diffs. Ideally this process +- * should be delegated to the GKqueueDirectoryMonitor, but for now I will +- * do it in a dirty way right here. */ +- if (sub->deps) +- dl_free (sub->deps); +- +- sub->deps = dl_listing (sub->filename); +- } +- +- G_LOCK (hash_lock); +- g_hash_table_insert (subs_hash_table, GINT_TO_POINTER (sub->fd), sub); +- G_UNLOCK (hash_lock); +- +- _kqueue_thread_push_fd (sub->fd); +- +- /* Bump the kqueue thread. It will pick up a new sub entry to monitor */ +- if (!_ku_write (kqueue_socket_pair[0], "A", 1)) +- KH_W ("Failed to bump the kqueue thread (add fd, error %d)", errno); +- return TRUE; +-} +- +- +-/** +- * _kh_add_sub: +- * @sub: a #kqueue_sub +- * +- * Adds a subscription for monitoring. +- * +- * This funciton tries to start watching a subscription with +- * _kh_start_watching(). On failure, i.e. when a file does not exist yet, +- * the subscription will be added to a list of missing files to continue +- * watching when the file will appear. +- * +- * Returns: %TRUE +- **/ +-gboolean +-_kh_add_sub (kqueue_sub *sub) +-{ +- g_assert (sub != NULL); +- +- if (!_kh_start_watching (sub)) +- _km_add_missing (sub); +- +- return TRUE; +-} +- +- +-/** +- * _kh_cancel_sub: +- * @sub a #kqueue_sub +- * +- * Stops monitoring on a subscription. +- * +- * Returns: %TRUE +- **/ +-gboolean +-_kh_cancel_sub (kqueue_sub *sub) +-{ +- gboolean removed = FALSE; +- g_assert (kqueue_socket_pair[0] != -1); +- g_assert (sub != NULL); +- +- _km_remove (sub); +- +- G_LOCK (hash_lock); +- removed = g_hash_table_remove (subs_hash_table, GINT_TO_POINTER (sub->fd)); +- G_UNLOCK (hash_lock); +- +- if (removed) +- { +- /* fd will be closed in the kqueue thread */ +- _kqueue_thread_remove_fd (sub->fd); +- +- /* Bump the kqueue thread. It will pick up a new sub entry to remove*/ +- if (!_ku_write (kqueue_socket_pair[0], "R", 1)) +- KH_W ("Failed to bump the kqueue thread (remove fd, error %d)", errno); +- } +- +- return TRUE; +-} +- +- +-/** +- * _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); +-} diff --git a/devel/glib20/files/patch-gio_kqueue_kqueue-helper.h b/devel/glib20/files/patch-gio_kqueue_kqueue-helper.h new file mode 100644 index 000000000000..053e895488e7 --- /dev/null +++ b/devel/glib20/files/patch-gio_kqueue_kqueue-helper.h @@ -0,0 +1,40 @@ +--- gio/kqueue/kqueue-helper.h.orig 2018-04-09 22:47:22.070991000 +0200 ++++ gio/kqueue/kqueue-helper.h 2018-04-09 22:47:44.329479000 +0200 +@@ -23,16 +23,31 @@ + #ifndef __KQUEUE_HELPER_H + #define __KQUEUE_HELPER_H + +-#include "kqueue-sub.h" + #include <gio/glocalfilemonitor.h> + #include <gio/gfilemonitor.h> + +-gboolean _kh_startup (void); +-gboolean _kh_add_sub (kqueue_sub *sub); +-gboolean _kh_cancel_sub (kqueue_sub *sub); ++#include "dep-list.h" + +-gboolean _kh_start_watching (kqueue_sub *sub); ++/** ++ * kqueue_sub: ++ * @filename: a name of the file to monitor ++ * @fd: the associated file descriptor (used by kqueue) ++ * ++ * Represents a subscription on a file or directory. ++ */ ++typedef struct ++{ ++ GLocalFileMonitor *mon; ++ GFileMonitorSource *source; ++ gchar* filename; ++ int fd; ++ dep_list* deps; ++ int is_dir; ++} kqueue_sub; + +-void _kh_dir_diff (kqueue_sub *sub, GFileMonitorSource *source); ++gboolean _kqsub_start_watching (kqueue_sub *sub); ++void _kh_dir_diff (kqueue_sub *sub); ++void _km_add_missing (kqueue_sub *sub); ++void _km_remove (kqueue_sub *sub); + + #endif /* __KQUEUE_HELPER_H */ |