gtestutils: Fix a typo in a documentation comment
[glib.git] / gio / fam / gfamfilemonitor.c
blob50474c8e5e5bc732308bab5d1c50c1bf3cb452a1
1 /*
2 * Copyright © 2015 Canonical Limited
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General
15 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 * Author: Ryan Lortie <desrt@desrt.ca>
20 #include "config.h"
22 #include <gio/glocalfilemonitor.h>
23 #include <gio/giomodule.h>
24 #include "glib-private.h"
25 #include <glib-unix.h>
26 #include <fam.h>
28 static GMutex fam_lock;
29 static gboolean fam_initialised;
30 static FAMConnection fam_connection;
31 static GSource *fam_source;
33 #define G_TYPE_FAM_FILE_MONITOR (g_fam_file_monitor_get_type ())
34 #define G_FAM_FILE_MONITOR(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
35 G_TYPE_FAM_FILE_MONITOR, GFamFileMonitor))
37 typedef GLocalFileMonitorClass GFamFileMonitorClass;
39 typedef struct
41 GLocalFileMonitor parent_instance;
43 FAMRequest request;
44 } GFamFileMonitor;
46 static GType g_fam_file_monitor_get_type (void);
47 G_DEFINE_DYNAMIC_TYPE (GFamFileMonitor, g_fam_file_monitor, G_TYPE_LOCAL_FILE_MONITOR)
49 static gboolean
50 g_fam_file_monitor_callback (gint fd,
51 GIOCondition condition,
52 gpointer user_data)
54 gint64 now = g_source_get_time (fam_source);
56 g_mutex_lock (&fam_lock);
58 while (FAMPending (&fam_connection))
60 const gchar *child;
61 FAMEvent ev;
63 if (FAMNextEvent (&fam_connection, &ev) != 1)
65 /* The daemon died. We're in a really bad situation now
66 * because we potentially have a bunch of request structures
67 * outstanding which no longer make any sense to anyone.
69 * The best thing that we can do is do nothing. Notification
70 * won't work anymore for this process.
72 g_mutex_unlock (&fam_lock);
74 g_warning ("Lost connection to FAM (file monitoring) service. Expect no further file monitor events.");
76 return FALSE;
79 /* We expect ev.filename to be a relative path for children in a
80 * monitored directory, and an absolute path for a monitored file
81 * or the directory itself.
83 if (ev.filename[0] != '/')
84 child = ev.filename;
85 else
86 child = NULL;
88 switch (ev.code)
90 case FAMAcknowledge:
91 g_source_unref (ev.userdata);
92 break;
94 case FAMChanged:
95 g_file_monitor_source_handle_event (ev.userdata, G_FILE_MONITOR_EVENT_CHANGED, child, NULL, NULL, now);
96 break;
98 case FAMDeleted:
99 g_file_monitor_source_handle_event (ev.userdata, G_FILE_MONITOR_EVENT_DELETED, child, NULL, NULL, now);
100 break;
102 case FAMCreated:
103 g_file_monitor_source_handle_event (ev.userdata, G_FILE_MONITOR_EVENT_CREATED, child, NULL, NULL, now);
104 break;
106 default:
107 /* unknown type */
108 break;
112 g_mutex_unlock (&fam_lock);
114 return TRUE;
117 static gboolean
118 g_fam_file_monitor_is_supported (void)
120 g_mutex_lock (&fam_lock);
122 if (!fam_initialised)
124 fam_initialised = FAMOpen2 (&fam_connection, "GLib GIO") == 0;
126 if (fam_initialised)
128 #ifdef HAVE_FAM_NO_EXISTS
129 /* This is a gamin extension that avoids sending all the
130 * Exists event for dir monitors
132 FAMNoExists (&fam_connection);
133 #endif
135 fam_source = g_unix_fd_source_new (FAMCONNECTION_GETFD (&fam_connection), G_IO_IN);
136 g_source_set_callback (fam_source, (GSourceFunc) g_fam_file_monitor_callback, NULL, NULL);
137 g_source_attach (fam_source, GLIB_PRIVATE_CALL(g_get_worker_context) ());
141 g_mutex_unlock (&fam_lock);
143 g_print ("II %d\n", fam_initialised);
145 return fam_initialised;
148 static gboolean
149 g_fam_file_monitor_cancel (GFileMonitor *monitor)
151 GFamFileMonitor *gffm = G_FAM_FILE_MONITOR (monitor);
153 g_mutex_lock (&fam_lock);
155 g_assert (fam_initialised);
157 FAMCancelMonitor (&fam_connection, &gffm->request);
159 g_mutex_unlock (&fam_lock);
161 return TRUE;
164 static void
165 g_fam_file_monitor_start (GLocalFileMonitor *local_monitor,
166 const gchar *dirname,
167 const gchar *basename,
168 const gchar *filename,
169 GFileMonitorSource *source)
171 GFamFileMonitor *gffm = G_FAM_FILE_MONITOR (local_monitor);
173 g_mutex_lock (&fam_lock);
175 g_assert (fam_initialised);
177 g_source_ref ((GSource *) source);
179 if (dirname)
180 FAMMonitorDirectory (&fam_connection, dirname, &gffm->request, source);
181 else
182 FAMMonitorFile (&fam_connection, filename, &gffm->request, source);
184 g_mutex_unlock (&fam_lock);
187 static void
188 g_fam_file_monitor_init (GFamFileMonitor* monitor)
192 static void
193 g_fam_file_monitor_class_init (GFamFileMonitorClass *class)
195 GFileMonitorClass *file_monitor_class = G_FILE_MONITOR_CLASS (class);
197 class->is_supported = g_fam_file_monitor_is_supported;
198 class->start = g_fam_file_monitor_start;
199 file_monitor_class->cancel = g_fam_file_monitor_cancel;
202 static void
203 g_fam_file_monitor_class_finalize (GFamFileMonitorClass *class)
207 void
208 g_io_module_load (GIOModule *module)
210 g_type_module_use (G_TYPE_MODULE (module));
212 g_fam_file_monitor_register_type (G_TYPE_MODULE (module));
214 g_io_extension_point_implement (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME,
215 G_TYPE_FAM_FILE_MONITOR, "fam", 10);
217 g_io_extension_point_implement (G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME,
218 G_TYPE_FAM_FILE_MONITOR, "fam", 10);
221 void
222 g_io_module_unload (GIOModule *module)
224 g_assert_not_reached ();
227 char **
228 g_io_module_query (void)
230 char *eps[] = {
231 G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME,
232 G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME,
233 NULL
236 return g_strdupv (eps);