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