]> git.pld-linux.org Git - packages/NetworkManager.git/blob - systemd-fallback.patch
- systemd fallback mode patch
[packages/NetworkManager.git] / systemd-fallback.patch
1 diff -u -Nr NetworkManager-0.9.3.995/configure.ac NetworkManager-0.9.3.995-systemd-fallback/configure.ac
2 --- NetworkManager-0.9.3.995/configure.ac       2012-03-02 01:05:21.000000000 +0100
3 +++ NetworkManager-0.9.3.995-systemd-fallback/configure.ac      2012-03-06 16:55:58.294793902 +0100
4 @@ -344,7 +344,7 @@
5  case $with_session_tracking in
6      ck|none) ;;
7      systemd)
8 -        PKG_CHECK_MODULES(SYSTEMD, [libsystemd-login])
9 +        PKG_CHECK_MODULES(SYSTEMD, [libsystemd-daemon libsystemd-login])
10          ;;
11      *)
12         AC_MSG_ERROR(--with-session-tracking must be one of [none, ck, systemd])
13 diff -u -Nr NetworkManager-0.9.3.995/src/nm-session-monitor-systemd.c NetworkManager-0.9.3.995-systemd-fallback/src/nm-session-monitor-systemd.c
14 --- NetworkManager-0.9.3.995/src/nm-session-monitor-systemd.c   2012-02-27 16:57:16.000000000 +0100
15 +++ NetworkManager-0.9.3.995-systemd-fallback/src/nm-session-monitor-systemd.c  2012-03-06 16:55:01.285264295 +0100
16 @@ -28,6 +28,10 @@
17  #include <glib/gstdio.h>
18  #include <systemd/sd-login.h>
19  #include <stdlib.h>
20 +#include <systemd/sd-daemon.h>
21 +#include <sys/stat.h>
22 +#include <gio/gio.h>
23 +#include "nm-logging.h"
24  
25  #include "nm-session-utils.h"
26  #include "nm-session-monitor.h"
27 @@ -107,10 +111,20 @@
28         return source;
29  }
30  
31 +/********************************************************************/
32 +
33 +#define CKDB_PATH "/var/run/ConsoleKit/database"
34 +
35  struct _NMSessionMonitor {
36         GObject parent_instance;
37  
38         GSource *sd_source;
39 +
40 +       GKeyFile *database;
41 +       GFileMonitor *database_monitor;
42 +       time_t database_mtime;
43 +       GHashTable *sessions_by_uid;
44 +       GHashTable *sessions_by_user;
45  };
46  
47  struct _NMSessionMonitorClass {
48 @@ -130,6 +144,215 @@
49  
50  /* ---------------------------------------------------------------------------------------------------- */
51  
52 +typedef struct {
53 +       char *user;
54 +       uid_t uid;
55 +       gboolean local;
56 +       gboolean active;
57 +} Session;
58 +
59 +static void
60 +session_free (Session *s)
61 +{
62 +       g_free (s->user);
63 +       memset (s, 0, sizeof (Session));
64 +       g_free (s);
65 +}
66 +
67 +static gboolean
68 +check_key (GKeyFile *keyfile, const char *group, const char *key, GError **error)
69 +{
70 +       if (g_key_file_has_key (keyfile, group, key, error))
71 +               return TRUE;
72 +
73 +       if (!error) {
74 +               g_set_error (error,
75 +                                NM_SESSION_MONITOR_ERROR,
76 +                                NM_SESSION_MONITOR_ERROR_MALFORMED_DATABASE,
77 +                                "ConsoleKit database " CKDB_PATH " group '%s' had no '%s' key",
78 +                                group, key);
79 +       }
80 +       return FALSE;
81 +}
82 +
83 +static Session *
84 +session_new (GKeyFile *keyfile, const char *group, GError **error)
85 +{
86 +       GError *local = NULL;
87 +       Session *s;
88 +       const char *uname = NULL;
89 +
90 +       s = g_new0 (Session, 1);
91 +       g_assert (s);
92 +
93 +       s->uid = G_MAXUINT; /* paranoia */
94 +       if (!check_key (keyfile, group, "uid", &local))
95 +               goto error;
96 +       s->uid = (uid_t) g_key_file_get_integer (keyfile, group, "uid", &local);
97 +       if (local)
98 +               goto error;
99 +
100 +       if (!check_key (keyfile, group, "is_active", &local))
101 +               goto error;
102 +       s->active = g_key_file_get_boolean (keyfile, group, "is_active", &local);
103 +       if (local)
104 +               goto error;
105 +
106 +       if (!check_key (keyfile, group, "is_local", &local))
107 +               goto error;
108 +       s->local = g_key_file_get_boolean (keyfile, group, "is_local", &local);
109 +       if (local)
110 +               goto error;
111 +
112 +       if (!nm_session_uid_to_user (s->uid, &uname, error))
113 +               return FALSE;
114 +       s->user = g_strdup (uname);
115 +
116 +       return s;
117 +
118 +error:
119 +       session_free (s);
120 +       g_propagate_error (error, local);
121 +       return NULL;
122 +}
123 +
124 +static void
125 +session_merge (Session *src, Session *dest)
126 +{
127 +       g_return_if_fail (src != NULL);
128 +       g_return_if_fail (dest != NULL);
129 +
130 +       g_warn_if_fail (g_strcmp0 (src->user, dest->user) == 0);
131 +       g_warn_if_fail (src->uid == dest->uid);
132 +
133 +       dest->local = (dest->local || src->local);
134 +       dest->active = (dest->active || src->active);
135 +}
136 +
137 +/********************************************************************/
138 +
139 +static void
140 +free_database (NMSessionMonitor *self)
141 +{
142 +       if (self->database != NULL) {
143 +               g_key_file_free (self->database);
144 +               self->database = NULL;
145 +       }
146 +
147 +       g_hash_table_remove_all (self->sessions_by_uid);
148 +       g_hash_table_remove_all (self->sessions_by_user);
149 +}
150 +
151 +static gboolean
152 +reload_database (NMSessionMonitor *self, GError **error)
153 +{
154 +       struct stat statbuf;
155 +       char **groups = NULL;
156 +       gsize len = 0, i;
157 +       Session *s;
158 +
159 +       free_database (self);
160 +
161 +       errno = 0;
162 +       if (stat (CKDB_PATH, &statbuf) != 0) {
163 +               g_set_error (error,
164 +                            NM_SESSION_MONITOR_ERROR,
165 +                            errno == ENOENT ? NM_SESSION_MONITOR_ERROR_NO_DATABASE : NM_SESSION_MONITOR_ERROR_IO_ERROR,
166 +                            "Error statting file " CKDB_PATH ": %s",
167 +                            strerror (errno));
168 +               goto error;
169 +       }
170 +       self->database_mtime = statbuf.st_mtime;
171 +
172 +       self->database = g_key_file_new ();
173 +       if (!g_key_file_load_from_file (self->database, CKDB_PATH, G_KEY_FILE_NONE, error))
174 +               goto error;
175 +
176 +       groups = g_key_file_get_groups (self->database, &len);
177 +       if (!groups) {
178 +               g_set_error_literal (error,
179 +                                    NM_SESSION_MONITOR_ERROR,
180 +                                    NM_SESSION_MONITOR_ERROR_IO_ERROR,
181 +                                    "Could not load groups from " CKDB_PATH "");
182 +               goto error;
183 +       }
184 +
185 +       for (i = 0; i < len; i++) {
186 +               Session *found;
187 +
188 +               if (!g_str_has_prefix (groups[i], "Session "))
189 +                       continue;
190 +
191 +               s = session_new (self->database, groups[i], error);
192 +               if (!s)
193 +                       goto error;
194 +
195 +               found = g_hash_table_lookup (self->sessions_by_user, (gpointer) s->user);
196 +               if (found) {
197 +                       session_merge (s, found);
198 +                       session_free (s);
199 +               } else {
200 +                       /* Entirely new user */
201 +                       g_hash_table_insert (self->sessions_by_user, (gpointer) s->user, s);
202 +                       g_hash_table_insert (self->sessions_by_uid, GUINT_TO_POINTER (s->uid), s);
203 +               }
204 +       }
205 +
206 +       g_strfreev (groups);
207 +       return TRUE;
208 +
209 +error:
210 +       if (groups)
211 +               g_strfreev (groups);
212 +       free_database (self);
213 +       return FALSE;
214 +}
215 +
216 +static gboolean
217 +ensure_database (NMSessionMonitor *self, GError **error)
218 +{
219 +       gboolean ret = FALSE;
220 +
221 +       if (self->database != NULL) {
222 +               struct stat statbuf;
223 +
224 +               errno = 0;
225 +               if (stat (CKDB_PATH, &statbuf) != 0) {
226 +                       g_set_error (error,
227 +                                    NM_SESSION_MONITOR_ERROR,
228 +                                    errno == ENOENT ? NM_SESSION_MONITOR_ERROR_NO_DATABASE : NM_SESSION_MONITOR_ERROR_IO_ERROR,
229 +                                    "Error statting file " CKDB_PATH " to check timestamp: %s",
230 +                                    strerror (errno));
231 +                       goto out;
232 +               }
233 +
234 +               if (statbuf.st_mtime == self->database_mtime) {
235 +                       ret = TRUE;
236 +                       goto out;
237 +               }
238 +       }
239 +
240 +       ret = reload_database (self, error);
241 +
242 +out:
243 +       return ret;
244 +}
245 +
246 +static void
247 +on_file_monitor_changed (GFileMonitor *    file_monitor,
248 +                         GFile *           file,
249 +                         GFile *           other_file,
250 +                         GFileMonitorEvent event_type,
251 +                         gpointer          user_data)
252 +{
253 +       NMSessionMonitor *self = NM_SESSION_MONITOR (user_data);
254 +
255 +       /* throw away cache */
256 +       free_database (self);
257 +
258 +       g_signal_emit (self, signals[CHANGED_SIGNAL], 0);
259 +}
260 +
261  static gboolean
262  sessions_changed (gpointer user_data)
263  {
264 @@ -143,9 +366,50 @@
265  static void
266  nm_session_monitor_init (NMSessionMonitor *monitor)
267  {
268 -       monitor->sd_source = sd_source_new ();
269 -       g_source_set_callback (monitor->sd_source, sessions_changed, monitor, NULL);
270 -       g_source_attach (monitor->sd_source, NULL);
271 +       if (sd_booted () > 0) {
272 +               monitor->sd_source = sd_source_new ();
273 +               g_source_set_callback (monitor->sd_source, sessions_changed, monitor, NULL);
274 +               g_source_attach (monitor->sd_source, NULL);
275 +
276 +               monitor->database_monitor = NULL;
277 +               monitor->database = NULL;
278 +       } else {
279 +               monitor->sd_source = NULL;
280 +
281 +               GError *error = NULL;
282 +               GFile *file;
283 +
284 +               /* Sessions-by-user is responsible for destroying the Session objects */
285 +               monitor->sessions_by_user = g_hash_table_new_full (g_str_hash, g_str_equal,
286 +                                                               NULL, (GDestroyNotify) session_free);
287 +               monitor->sessions_by_uid = g_hash_table_new (g_direct_hash, g_direct_equal);
288 +
289 +
290 +               error = NULL;
291 +               if (!ensure_database (monitor, &error)) {
292 +                       /* Ignore the first error if the CK database isn't found yet */
293 +                       if (g_error_matches (error,
294 +                                            NM_SESSION_MONITOR_ERROR,
295 +                                            NM_SESSION_MONITOR_ERROR_NO_DATABASE) == FALSE) {
296 +                               nm_log_err (LOGD_CORE, "Error loading " CKDB_PATH ": %s", error->message);
297 +                       }
298 +                       g_error_free (error);
299 +               }
300 +
301 +               error = NULL;
302 +               file = g_file_new_for_path (CKDB_PATH);
303 +               monitor->database_monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &error);
304 +               g_object_unref (file);
305 +               if (monitor->database_monitor == NULL) {
306 +                       nm_log_err (LOGD_CORE, "Error monitoring " CKDB_PATH ": %s", error->message);
307 +                       g_error_free (error);
308 +               } else {
309 +                       g_signal_connect (monitor->database_monitor,
310 +                                         "changed",
311 +                                         G_CALLBACK (on_file_monitor_changed),
312 +                                         monitor);
313 +               }
314 +       }
315  }
316  
317  static void
318 @@ -158,6 +422,12 @@
319                 g_source_unref (monitor->sd_source);
320         }
321  
322 +       if (monitor->database_monitor != NULL)
323 +               g_object_unref (monitor->database_monitor);
324 +
325 +       if (monitor->database != NULL)
326 +               free_database (monitor);
327 +
328         if (G_OBJECT_CLASS (nm_session_monitor_parent_class)->finalize != NULL)
329                 G_OBJECT_CLASS (nm_session_monitor_parent_class)->finalize (object);
330  }
331 @@ -206,15 +476,36 @@
332                                       uid_t *out_uid,
333                                       GError **error)
334  {
335 -       uid_t uid;
336 +       if (monitor->sd_source != NULL) {
337 +               uid_t uid;
338  
339 -       if (!nm_session_user_to_uid (username, &uid, error))
340 -               return FALSE;
341 +               if (!nm_session_user_to_uid (username, &uid, error))
342 +                       return FALSE;
343  
344 -       if (out_uid)
345 -               *out_uid = uid;
346 +               if (out_uid)
347 +                       *out_uid = uid;
348  
349 -       return nm_session_monitor_uid_has_session (monitor, uid, NULL, error);
350 +               return nm_session_monitor_uid_has_session (monitor, uid, NULL, error);
351 +       } else {
352 +               Session *s;
353 +
354 +               if (!ensure_database (monitor, error))
355 +                       return FALSE;
356 +
357 +               s = g_hash_table_lookup (monitor->sessions_by_user, (gpointer) username);
358 +               if (!s) {
359 +                       g_set_error (error,
360 +                                    NM_SESSION_MONITOR_ERROR,
361 +                                    NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
362 +                                    "No session found for user '%s'",
363 +                                    username);
364 +                       return FALSE;
365 +               }
366 +
367 +               if (out_uid)
368 +                       *out_uid = s->uid;
369 +               return TRUE;
370 +       }
371  }
372  
373  gboolean
374 @@ -222,12 +513,31 @@
375                                  const char *username,
376                                  GError **error)
377  {
378 -       uid_t uid;
379 +       if (monitor->sd_source != NULL) {
380 +               uid_t uid;
381  
382 -       if (!nm_session_user_to_uid (username, &uid, error))
383 -               return FALSE;
384 +               if (!nm_session_user_to_uid (username, &uid, error))
385 +                       return FALSE;
386 +
387 +               return nm_session_monitor_uid_active (monitor, uid, error);
388 +       } else {
389 +               Session *s;
390 +
391 +               if (!ensure_database (monitor, error))
392 +                       return FALSE;
393 +
394 +               s = g_hash_table_lookup (monitor->sessions_by_user, (gpointer) username);
395 +               if (!s) {
396 +                       g_set_error (error,
397 +                                    NM_SESSION_MONITOR_ERROR,
398 +                                    NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
399 +                                    "No session found for user '%s'",
400 +                                    username);
401 +                       return FALSE;
402 +               }
403  
404 -       return nm_session_monitor_uid_active (monitor, uid, error);
405 +               return s->active;
406 +       }
407  }
408  
409  gboolean
410 @@ -236,10 +546,31 @@
411                                      const char **out_user,
412                                      GError **error)
413  {
414 -       if (!nm_session_uid_to_user (uid, out_user, error))
415 -               return FALSE;
416 +       if (monitor->sd_source != NULL) {
417 +               if (!nm_session_uid_to_user (uid, out_user, error))
418 +                       return FALSE;
419  
420 -       return sd_uid_get_sessions (uid, FALSE, NULL) > 0;
421 +               return sd_uid_get_sessions (uid, FALSE, NULL) > 0;
422 +       } else {
423 +               Session *s;
424 +
425 +               if (!ensure_database (monitor, error))
426 +                       return FALSE;
427 +
428 +               s = g_hash_table_lookup (monitor->sessions_by_uid, GUINT_TO_POINTER (uid));
429 +               if (!s) {
430 +                       g_set_error (error,
431 +                                    NM_SESSION_MONITOR_ERROR,
432 +                                    NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
433 +                                    "No session found for uid %d",
434 +                                    uid);
435 +                       return FALSE;
436 +               }
437 +
438 +               if (out_user)
439 +                       *out_user = s->user;
440 +               return TRUE;
441 +       }
442  }
443  
444  gboolean
445 @@ -247,5 +578,24 @@
446                                 uid_t uid,
447                                 GError **error)
448  {
449 -       return sd_uid_get_sessions (uid, TRUE, NULL) > 0;
450 +       if (monitor->sd_source != NULL)
451 +               return sd_uid_get_sessions (uid, TRUE, NULL) > 0;
452 +       else {
453 +               Session *s;
454 +
455 +               if (!ensure_database (monitor, error))
456 +                       return FALSE;
457 +
458 +               s = g_hash_table_lookup (monitor->sessions_by_uid, GUINT_TO_POINTER (uid));
459 +               if (!s) {
460 +                       g_set_error (error,
461 +                                    NM_SESSION_MONITOR_ERROR,
462 +                                    NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
463 +                                    "No session found for uid '%d'",
464 +                                    uid);
465 +                       return FALSE;
466 +               }
467 +
468 +               return s->active;
469 +       }
470  }
This page took 0.073571 seconds and 3 git commands to generate.