Branch data Line data Source code
1 : : /*
2 : : * Copyright © 2009, 2010 Codethink Limited
3 : : * Copyright © 2010 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General Public
18 : : * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : *
20 : : * Authors: Ryan Lortie <desrt@desrt.ca>
21 : : * Matthias Clasen <mclasen@redhat.com>
22 : : */
23 : :
24 : : #include "config.h"
25 : :
26 : : #include "gsettingsbackendinternal.h"
27 : : #include "gsimplepermission.h"
28 : : #include "giomodule-priv.h"
29 : :
30 : : #include <string.h>
31 : : #include <stdlib.h>
32 : : #include <glib.h>
33 : : #include <glibintl.h>
34 : :
35 : :
36 : : typedef struct _GSettingsBackendClosure GSettingsBackendClosure;
37 : : typedef struct _GSettingsBackendWatch GSettingsBackendWatch;
38 : :
39 : : struct _GSettingsBackendPrivate
40 : : {
41 : : GSettingsBackendWatch *watches;
42 : : GMutex lock;
43 : : };
44 : :
45 : 755 : G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GSettingsBackend, g_settings_backend, G_TYPE_OBJECT)
46 : :
47 : : /* For g_settings_backend_sync_default(), we only want to actually do
48 : : * the sync if the backend already exists. This avoids us creating an
49 : : * entire GSettingsBackend in order to call a do-nothing sync()
50 : : * operation on it. This variable lets us avoid that.
51 : : */
52 : : static gboolean g_settings_has_backend;
53 : :
54 : : /**
55 : : * GSettingsBackend:
56 : : *
57 : : * The `GSettingsBackend` interface defines a generic interface for
58 : : * non-strictly-typed data that is stored in a hierarchy. To implement
59 : : * an alternative storage backend for [class@Gio.Settings], you need to
60 : : * implement the `GSettingsBackend` interface and then make it implement the
61 : : * extension point `G_SETTINGS_BACKEND_EXTENSION_POINT_NAME`.
62 : : *
63 : : * The interface defines methods for reading and writing values, a
64 : : * method for determining if writing of certain values will fail
65 : : * (lockdown) and a change notification mechanism.
66 : : *
67 : : * The semantics of the interface are very precisely defined and
68 : : * implementations must carefully adhere to the expectations of
69 : : * callers that are documented on each of the interface methods.
70 : : *
71 : : * Some of the `GSettingsBackend` functions accept or return a
72 : : * [struct@GLib.Tree]. These trees always have strings as keys and
73 : : * [struct@GLib.Variant] as values.
74 : : *
75 : : * The `GSettingsBackend` API is exported to allow third-party
76 : : * implementations, but does not carry the same stability guarantees
77 : : * as the public GIO API. For this reason, you have to define the
78 : : * C preprocessor symbol `G_SETTINGS_ENABLE_BACKEND` before including
79 : : * `gio/gsettingsbackend.h`.
80 : : **/
81 : :
82 : : static gboolean
83 : 145 : is_key (const gchar *key)
84 : : {
85 : : gint length;
86 : : gint i;
87 : :
88 : 145 : g_return_val_if_fail (key != NULL, FALSE);
89 : 145 : g_return_val_if_fail (key[0] == '/', FALSE);
90 : :
91 : 3303 : for (i = 1; key[i]; i++)
92 : 3158 : g_return_val_if_fail (key[i] != '/' || key[i + 1] != '/', FALSE);
93 : :
94 : 145 : length = i;
95 : :
96 : 145 : g_return_val_if_fail (key[length - 1] != '/', FALSE);
97 : :
98 : 145 : return TRUE;
99 : : }
100 : :
101 : : static gboolean
102 : 27 : is_path (const gchar *path)
103 : : {
104 : : gint length;
105 : : gint i;
106 : :
107 : 27 : g_return_val_if_fail (path != NULL, FALSE);
108 : 27 : g_return_val_if_fail (path[0] == '/', FALSE);
109 : :
110 : 289 : for (i = 1; path[i]; i++)
111 : 262 : g_return_val_if_fail (path[i] != '/' || path[i + 1] != '/', FALSE);
112 : :
113 : 27 : length = i;
114 : :
115 : 27 : g_return_val_if_fail (path[length - 1] == '/', FALSE);
116 : :
117 : 27 : return TRUE;
118 : : }
119 : :
120 : : struct _GSettingsBackendWatch
121 : : {
122 : : /* Always access the target via the weak reference */
123 : : GWeakRef target;
124 : : /* The pointer is only for comparison from the weak notify,
125 : : * at which point the target might already be close to
126 : : * destroyed. It's not safe to use it for anything anymore
127 : : * at that point */
128 : : GObject *target_ptr;
129 : : const GSettingsListenerVTable *vtable;
130 : : GMainContext *context;
131 : : GSettingsBackendWatch *next;
132 : : };
133 : :
134 : : struct _GSettingsBackendClosure
135 : : {
136 : : void (*function) (GObject *target,
137 : : GSettingsBackend *backend,
138 : : const gchar *name,
139 : : gpointer origin_tag,
140 : : gchar **names);
141 : :
142 : : GMainContext *context;
143 : : GObject *target;
144 : : GSettingsBackend *backend;
145 : : gchar *name;
146 : : gpointer origin_tag;
147 : : gchar **names;
148 : : };
149 : :
150 : : static void
151 : 80 : g_settings_backend_watch_weak_notify (gpointer data,
152 : : GObject *where_the_object_was)
153 : : {
154 : 80 : GSettingsBackend *backend = data;
155 : : GSettingsBackendWatch **ptr;
156 : :
157 : : /* search and remove */
158 : 80 : g_mutex_lock (&backend->priv->lock);
159 : 98 : for (ptr = &backend->priv->watches; *ptr; ptr = &(*ptr)->next)
160 : 98 : if ((*ptr)->target_ptr == where_the_object_was)
161 : : {
162 : 80 : GSettingsBackendWatch *tmp = *ptr;
163 : :
164 : 80 : *ptr = tmp->next;
165 : 80 : g_weak_ref_clear (&tmp->target);
166 : 80 : g_slice_free (GSettingsBackendWatch, tmp);
167 : :
168 : 80 : g_mutex_unlock (&backend->priv->lock);
169 : 80 : return;
170 : : }
171 : :
172 : : /* we didn't find it. that shouldn't happen. */
173 : : g_assert_not_reached ();
174 : : }
175 : :
176 : : /*< private >
177 : : * g_settings_backend_watch:
178 : : * @backend: a #GSettingsBackend
179 : : * @target: the GObject (typically GSettings instance) to call back to
180 : : * @context: (nullable): a #GMainContext, or %NULL
181 : : * ...: callbacks...
182 : : *
183 : : * Registers a new watch on a #GSettingsBackend.
184 : : *
185 : : * note: %NULL @context does not mean "default main context" but rather,
186 : : * "it is okay to dispatch in any context". If the default main context
187 : : * is specifically desired then it must be given.
188 : : *
189 : : * note also: if you want to get meaningful values for the @origin_tag
190 : : * that appears as an argument to some of the callbacks, you *must* have
191 : : * @context as %NULL. Otherwise, you are subject to cross-thread
192 : : * dispatching and whatever owned @origin_tag at the time that the event
193 : : * occurred may no longer own it. This is a problem if you consider that
194 : : * you may now be the new owner of that address and mistakenly think
195 : : * that the event in question originated from yourself.
196 : : *
197 : : * tl;dr: If you give a non-%NULL @context then you must ignore the
198 : : * value of @origin_tag given to any callbacks.
199 : : **/
200 : : void
201 : 82 : g_settings_backend_watch (GSettingsBackend *backend,
202 : : const GSettingsListenerVTable *vtable,
203 : : GObject *target,
204 : : GMainContext *context)
205 : : {
206 : : GSettingsBackendWatch *watch;
207 : :
208 : : /* For purposes of discussion, we assume that our target is a
209 : : * GSettings instance.
210 : : *
211 : : * Our strategy to defend against the final reference dropping on the
212 : : * GSettings object in a thread other than the one that is doing the
213 : : * dispatching is as follows:
214 : : *
215 : : * 1) hold a strong reference on the GSettings during an outstanding
216 : : * dispatch. This ensures that the delivery is always possible while
217 : : * the GSettings object is alive, and if this was the last reference
218 : : * then it will be dropped from the dispatch thread.
219 : : *
220 : : * 2) hold a weak reference on the GSettings at other times. This
221 : : * allows us to receive early notification of pending destruction
222 : : * of the object. At this point, it is still safe to obtain a
223 : : * reference on the GObject to keep it alive, so #1 will work up
224 : : * to that point. After that point, we'll have been able to drop
225 : : * the watch from the list.
226 : : *
227 : : * Note, in particular, that it's not possible to simply have an
228 : : * "unwatch" function that gets called from the finalize function of
229 : : * the GSettings instance because, by that point it is no longer
230 : : * possible to keep the object alive using g_object_ref() and we would
231 : : * have no way of knowing this.
232 : : *
233 : : * Note also that we need to hold a reference on the main context here
234 : : * since the GSettings instance may be finalized before the closure runs.
235 : : *
236 : : * All access to the list holds a mutex. We have some strategies to
237 : : * avoid some of the pain that would be associated with that.
238 : : */
239 : :
240 : 82 : watch = g_slice_new (GSettingsBackendWatch);
241 : 82 : watch->context = context;
242 : 82 : watch->vtable = vtable;
243 : 82 : g_weak_ref_init (&watch->target, target);
244 : 82 : watch->target_ptr = target;
245 : 82 : g_object_weak_ref (target, g_settings_backend_watch_weak_notify, backend);
246 : :
247 : : /* linked list prepend */
248 : 82 : g_mutex_lock (&backend->priv->lock);
249 : 82 : watch->next = backend->priv->watches;
250 : 82 : backend->priv->watches = watch;
251 : 82 : g_mutex_unlock (&backend->priv->lock);
252 : 82 : }
253 : :
254 : : void
255 : 10 : g_settings_backend_unwatch (GSettingsBackend *backend,
256 : : GObject *target)
257 : : {
258 : : /* Our caller surely owns a reference on 'target', so the order of
259 : : * these two calls is unimportant.
260 : : */
261 : 10 : g_object_weak_unref (target, g_settings_backend_watch_weak_notify, backend);
262 : 10 : g_settings_backend_watch_weak_notify (backend, target);
263 : 10 : }
264 : :
265 : : static gboolean
266 : 166 : g_settings_backend_invoke_closure (gpointer user_data)
267 : : {
268 : 166 : GSettingsBackendClosure *closure = user_data;
269 : :
270 : 166 : closure->function (closure->target, closure->backend, closure->name,
271 : : closure->origin_tag, closure->names);
272 : :
273 : 166 : if (closure->context)
274 : 150 : g_main_context_unref (closure->context);
275 : 166 : g_object_unref (closure->backend);
276 : 166 : g_object_unref (closure->target);
277 : 166 : g_strfreev (closure->names);
278 : 166 : g_free (closure->name);
279 : :
280 : 166 : g_slice_free (GSettingsBackendClosure, closure);
281 : :
282 : 166 : return FALSE;
283 : : }
284 : :
285 : : static void
286 : 154 : g_settings_backend_dispatch_signal (GSettingsBackend *backend,
287 : : gsize function_offset,
288 : : const gchar *name,
289 : : gpointer origin_tag,
290 : : const gchar * const *names)
291 : : {
292 : : GSettingsBackendWatch *watch;
293 : 154 : GSList *closures = NULL;
294 : :
295 : : /* We're in a little bit of a tricky situation here. We need to hold
296 : : * a lock while traversing the list, but we don't want to hold the
297 : : * lock while calling back into user code.
298 : : *
299 : : * We work around this by creating a bunch of GSettingsBackendClosure
300 : : * objects while holding the lock and dispatching them after. We
301 : : * never touch the list without holding the lock.
302 : : */
303 : 154 : g_mutex_lock (&backend->priv->lock);
304 : 320 : for (watch = backend->priv->watches; watch; watch = watch->next)
305 : : {
306 : : GSettingsBackendClosure *closure;
307 : 166 : GObject *target = g_weak_ref_get (&watch->target);
308 : :
309 : : /* If the target was destroyed in the meantime, just skip it here */
310 : 166 : if (!target)
311 : 0 : continue;
312 : :
313 : 166 : closure = g_slice_new (GSettingsBackendClosure);
314 : 166 : closure->context = watch->context;
315 : 166 : if (closure->context)
316 : 150 : g_main_context_ref (closure->context);
317 : 166 : closure->backend = g_object_ref (backend);
318 : 166 : closure->target = g_steal_pointer (&target);
319 : 166 : closure->function = G_STRUCT_MEMBER (void *, watch->vtable,
320 : : function_offset);
321 : 166 : closure->name = g_strdup (name);
322 : 166 : closure->origin_tag = origin_tag;
323 : 166 : closure->names = g_strdupv ((gchar **) names);
324 : :
325 : 166 : closures = g_slist_prepend (closures, closure);
326 : : }
327 : 154 : g_mutex_unlock (&backend->priv->lock);
328 : :
329 : 320 : while (closures)
330 : : {
331 : 166 : GSettingsBackendClosure *closure = closures->data;
332 : :
333 : 166 : if (closure->context)
334 : 150 : g_main_context_invoke (closure->context,
335 : : g_settings_backend_invoke_closure,
336 : : closure);
337 : : else
338 : 16 : g_settings_backend_invoke_closure (closure);
339 : :
340 : 166 : closures = g_slist_delete_link (closures, closures);
341 : : }
342 : 154 : }
343 : :
344 : : /**
345 : : * g_settings_backend_changed:
346 : : * @backend: a #GSettingsBackend implementation
347 : : * @key: the name of the key
348 : : * @origin_tag: the origin tag
349 : : *
350 : : * Signals that a single key has possibly changed. Backend
351 : : * implementations should call this if a key has possibly changed its
352 : : * value.
353 : : *
354 : : * @key must be a valid key (ie starting with a slash, not containing
355 : : * '//', and not ending with a slash).
356 : : *
357 : : * The implementation must call this function during any call to
358 : : * g_settings_backend_write(), before the call returns (except in the
359 : : * case that no keys are actually changed and it cares to detect this
360 : : * fact). It may not rely on the existence of a mainloop for
361 : : * dispatching the signal later.
362 : : *
363 : : * The implementation may call this function at any other time it likes
364 : : * in response to other events (such as changes occurring outside of the
365 : : * program). These calls may originate from a mainloop or may originate
366 : : * in response to any other action (including from calls to
367 : : * g_settings_backend_write()).
368 : : *
369 : : * In the case that this call is in response to a call to
370 : : * g_settings_backend_write() then @origin_tag must be set to the same
371 : : * value that was passed to that call.
372 : : *
373 : : * Since: 2.26
374 : : **/
375 : : void
376 : 127 : g_settings_backend_changed (GSettingsBackend *backend,
377 : : const gchar *key,
378 : : gpointer origin_tag)
379 : : {
380 : 127 : g_return_if_fail (G_IS_SETTINGS_BACKEND (backend));
381 : 127 : g_return_if_fail (is_key (key));
382 : :
383 : 127 : g_settings_backend_dispatch_signal (backend,
384 : : G_STRUCT_OFFSET (GSettingsListenerVTable,
385 : : changed),
386 : : key, origin_tag, NULL);
387 : : }
388 : :
389 : : /**
390 : : * g_settings_backend_keys_changed:
391 : : * @backend: a #GSettingsBackend implementation
392 : : * @path: the path containing the changes
393 : : * @items: (array zero-terminated=1): the %NULL-terminated list of changed keys
394 : : * @origin_tag: the origin tag
395 : : *
396 : : * Signals that a list of keys have possibly changed. Backend
397 : : * implementations should call this if keys have possibly changed their
398 : : * values.
399 : : *
400 : : * @path must be a valid path (ie starting and ending with a slash and
401 : : * not containing '//'). Each string in @items must form a valid key
402 : : * name when @path is prefixed to it (ie: each item must not start or
403 : : * end with '/' and must not contain '//').
404 : : *
405 : : * The meaning of this signal is that any of the key names resulting
406 : : * from the contatenation of @path with each item in @items may have
407 : : * changed.
408 : : *
409 : : * The same rules for when notifications must occur apply as per
410 : : * g_settings_backend_changed(). These two calls can be used
411 : : * interchangeably if exactly one item has changed (although in that
412 : : * case g_settings_backend_changed() is definitely preferred).
413 : : *
414 : : * For efficiency reasons, the implementation should strive for @path to
415 : : * be as long as possible (ie: the longest common prefix of all of the
416 : : * keys that were changed) but this is not strictly required.
417 : : *
418 : : * Since: 2.26
419 : : */
420 : : void
421 : 19 : g_settings_backend_keys_changed (GSettingsBackend *backend,
422 : : const gchar *path,
423 : : gchar const * const *items,
424 : : gpointer origin_tag)
425 : : {
426 : 19 : g_return_if_fail (G_IS_SETTINGS_BACKEND (backend));
427 : 19 : g_return_if_fail (is_path (path));
428 : :
429 : : /* XXX: should do stricter checking (ie: inspect each item) */
430 : 19 : g_return_if_fail (items != NULL);
431 : :
432 : 19 : g_settings_backend_dispatch_signal (backend,
433 : : G_STRUCT_OFFSET (GSettingsListenerVTable,
434 : : keys_changed),
435 : : path, origin_tag, items);
436 : : }
437 : :
438 : : /**
439 : : * g_settings_backend_path_changed:
440 : : * @backend: a #GSettingsBackend implementation
441 : : * @path: the path containing the changes
442 : : * @origin_tag: the origin tag
443 : : *
444 : : * Signals that all keys below a given path may have possibly changed.
445 : : * Backend implementations should call this if an entire path of keys
446 : : * have possibly changed their values.
447 : : *
448 : : * @path must be a valid path (ie starting and ending with a slash and
449 : : * not containing '//').
450 : : *
451 : : * The meaning of this signal is that any of the key which has a name
452 : : * starting with @path may have changed.
453 : : *
454 : : * The same rules for when notifications must occur apply as per
455 : : * g_settings_backend_changed(). This call might be an appropriate
456 : : * reasponse to a 'reset' call but implementations are also free to
457 : : * explicitly list the keys that were affected by that call if they can
458 : : * easily do so.
459 : : *
460 : : * For efficiency reasons, the implementation should strive for @path to
461 : : * be as long as possible (ie: the longest common prefix of all of the
462 : : * keys that were changed) but this is not strictly required. As an
463 : : * example, if this function is called with the path of "/" then every
464 : : * single key in the application will be notified of a possible change.
465 : : *
466 : : * Since: 2.26
467 : : */
468 : : void
469 : 0 : g_settings_backend_path_changed (GSettingsBackend *backend,
470 : : const gchar *path,
471 : : gpointer origin_tag)
472 : : {
473 : 0 : g_return_if_fail (G_IS_SETTINGS_BACKEND (backend));
474 : 0 : g_return_if_fail (is_path (path));
475 : :
476 : 0 : g_settings_backend_dispatch_signal (backend,
477 : : G_STRUCT_OFFSET (GSettingsListenerVTable,
478 : : path_changed),
479 : : path, origin_tag, NULL);
480 : : }
481 : :
482 : : /**
483 : : * g_settings_backend_writable_changed:
484 : : * @backend: a #GSettingsBackend implementation
485 : : * @key: the name of the key
486 : : *
487 : : * Signals that the writability of a single key has possibly changed.
488 : : *
489 : : * Since GSettings performs no locking operations for itself, this call
490 : : * will always be made in response to external events.
491 : : *
492 : : * Since: 2.26
493 : : **/
494 : : void
495 : 0 : g_settings_backend_writable_changed (GSettingsBackend *backend,
496 : : const gchar *key)
497 : : {
498 : 0 : g_return_if_fail (G_IS_SETTINGS_BACKEND (backend));
499 : 0 : g_return_if_fail (is_key (key));
500 : :
501 : 0 : g_settings_backend_dispatch_signal (backend,
502 : : G_STRUCT_OFFSET (GSettingsListenerVTable,
503 : : writable_changed),
504 : : key, NULL, NULL);
505 : : }
506 : :
507 : : /**
508 : : * g_settings_backend_path_writable_changed:
509 : : * @backend: a #GSettingsBackend implementation
510 : : * @path: the name of the path
511 : : *
512 : : * Signals that the writability of all keys below a given path may have
513 : : * changed.
514 : : *
515 : : * Since GSettings performs no locking operations for itself, this call
516 : : * will always be made in response to external events.
517 : : *
518 : : * Since: 2.26
519 : : **/
520 : : void
521 : 8 : g_settings_backend_path_writable_changed (GSettingsBackend *backend,
522 : : const gchar *path)
523 : : {
524 : 8 : g_return_if_fail (G_IS_SETTINGS_BACKEND (backend));
525 : 8 : g_return_if_fail (is_path (path));
526 : :
527 : 8 : g_settings_backend_dispatch_signal (backend,
528 : : G_STRUCT_OFFSET (GSettingsListenerVTable,
529 : : path_writable_changed),
530 : : path, NULL, NULL);
531 : : }
532 : :
533 : : typedef struct
534 : : {
535 : : const gchar **keys;
536 : : GVariant **values;
537 : : gint prefix_len;
538 : : gchar *prefix;
539 : : } FlattenState;
540 : :
541 : : static gboolean
542 : 18 : g_settings_backend_flatten_one (gpointer key,
543 : : gpointer value,
544 : : gpointer user_data)
545 : : {
546 : 18 : FlattenState *state = user_data;
547 : 18 : const gchar *skey = key;
548 : : gint i;
549 : :
550 : 18 : g_return_val_if_fail (is_key (key), TRUE);
551 : :
552 : : /* calculate longest common prefix */
553 : 18 : if (state->prefix == NULL)
554 : : {
555 : : gchar *last_byte;
556 : :
557 : : /* first key? just take the prefix up to the last '/' */
558 : 17 : state->prefix = g_strdup (skey);
559 : 17 : last_byte = strrchr (state->prefix, '/') + 1;
560 : 17 : state->prefix_len = last_byte - state->prefix;
561 : 17 : *last_byte = '\0';
562 : : }
563 : : else
564 : : {
565 : : /* find the first character that does not match. we will
566 : : * definitely find one because the prefix ends in '/' and the key
567 : : * does not. also: no two keys in the tree are the same.
568 : : */
569 : 8 : for (i = 0; state->prefix[i] == skey[i]; i++);
570 : :
571 : : /* check if we need to shorten the prefix */
572 : 1 : if (state->prefix[i] != '\0')
573 : : {
574 : : /* find the nearest '/', terminate after it */
575 : 0 : while (state->prefix[i - 1] != '/')
576 : 0 : i--;
577 : :
578 : 0 : state->prefix[i] = '\0';
579 : 0 : state->prefix_len = i;
580 : : }
581 : : }
582 : :
583 : :
584 : : /* save the entire item into the array.
585 : : * the prefixes will be removed later.
586 : : */
587 : 18 : *state->keys++ = key;
588 : :
589 : 18 : if (state->values)
590 : 0 : *state->values++ = value;
591 : :
592 : 18 : return FALSE;
593 : : }
594 : :
595 : : /**
596 : : * g_settings_backend_flatten_tree:
597 : : * @tree: a #GTree containing the changes
598 : : * @path: (out): the location to save the path
599 : : * @keys: (out) (transfer container) (array zero-terminated=1): the
600 : : * location to save the relative keys
601 : : * @values: (out) (optional) (transfer container) (array zero-terminated=1):
602 : : * the location to save the values, or %NULL
603 : : *
604 : : * Calculate the longest common prefix of all keys in a tree and write
605 : : * out an array of the key names relative to that prefix and,
606 : : * optionally, the value to store at each of those keys.
607 : : *
608 : : * You must free the value returned in @path, @keys and @values using
609 : : * g_free(). You should not attempt to free or unref the contents of
610 : : * @keys or @values.
611 : : *
612 : : * Since: 2.26
613 : : **/
614 : : void
615 : 17 : g_settings_backend_flatten_tree (GTree *tree,
616 : : gchar **path,
617 : : const gchar ***keys,
618 : : GVariant ***values)
619 : : {
620 : 17 : FlattenState state = { 0, };
621 : : gsize nnodes;
622 : :
623 : 17 : nnodes = g_tree_nnodes (tree);
624 : :
625 : 17 : *keys = state.keys = g_new (const gchar *, nnodes + 1);
626 : 17 : state.keys[nnodes] = NULL;
627 : :
628 : 17 : if (values != NULL)
629 : : {
630 : 0 : *values = state.values = g_new (GVariant *, nnodes + 1);
631 : 0 : state.values[nnodes] = NULL;
632 : : }
633 : :
634 : 17 : g_tree_foreach (tree, g_settings_backend_flatten_one, &state);
635 : 17 : g_return_if_fail (*keys + nnodes == state.keys);
636 : :
637 : 17 : *path = state.prefix;
638 : 35 : while (nnodes--)
639 : 18 : *--state.keys += state.prefix_len;
640 : : }
641 : :
642 : : /**
643 : : * g_settings_backend_changed_tree:
644 : : * @backend: a #GSettingsBackend implementation
645 : : * @tree: a #GTree containing the changes
646 : : * @origin_tag: the origin tag
647 : : *
648 : : * This call is a convenience wrapper. It gets the list of changes from
649 : : * @tree, computes the longest common prefix and calls
650 : : * g_settings_backend_changed().
651 : : *
652 : : * Since: 2.26
653 : : **/
654 : : void
655 : 17 : g_settings_backend_changed_tree (GSettingsBackend *backend,
656 : : GTree *tree,
657 : : gpointer origin_tag)
658 : : {
659 : : const gchar **keys;
660 : : gchar *path;
661 : :
662 : 17 : g_return_if_fail (G_IS_SETTINGS_BACKEND (backend));
663 : :
664 : 17 : g_settings_backend_flatten_tree (tree, &path, &keys, NULL);
665 : :
666 : : #ifdef DEBUG_CHANGES
667 : : {
668 : : gint i;
669 : :
670 : : g_print ("----\n");
671 : : g_print ("changed_tree(): prefix %s\n", path);
672 : : for (i = 0; keys[i]; i++)
673 : : g_print (" %s\n", keys[i]);
674 : : g_print ("----\n");
675 : : }
676 : : #endif
677 : :
678 : 17 : g_settings_backend_keys_changed (backend, path, keys, origin_tag);
679 : 17 : g_free (path);
680 : 17 : g_free (keys);
681 : : }
682 : :
683 : : /*< private >
684 : : * g_settings_backend_read:
685 : : * @backend: a #GSettingsBackend implementation
686 : : * @key: the key to read
687 : : * @expected_type: a #GVariantType
688 : : * @default_value: if the default value should be returned
689 : : *
690 : : * Reads a key. This call will never block.
691 : : *
692 : : * If the key exists, the value associated with it will be returned.
693 : : * If the key does not exist, %NULL will be returned.
694 : : *
695 : : * The returned value will be of the type given in @expected_type. If
696 : : * the backend stored a value of a different type then %NULL will be
697 : : * returned.
698 : : *
699 : : * If @default_value is %TRUE then this gets the default value from the
700 : : * backend (ie: the one that the backend would contain if
701 : : * g_settings_reset() were called).
702 : : *
703 : : * Returns: (nullable) (transfer full): the value that was read, or %NULL
704 : : */
705 : : GVariant *
706 : 212 : g_settings_backend_read (GSettingsBackend *backend,
707 : : const gchar *key,
708 : : const GVariantType *expected_type,
709 : : gboolean default_value)
710 : : {
711 : : GVariant *value;
712 : :
713 : 212 : value = G_SETTINGS_BACKEND_GET_CLASS (backend)
714 : 212 : ->read (backend, key, expected_type, default_value);
715 : :
716 : 212 : if (value != NULL)
717 : 142 : value = g_variant_take_ref (value);
718 : :
719 : 212 : if G_UNLIKELY (value && !g_variant_is_of_type (value, expected_type))
720 : : {
721 : 0 : g_variant_unref (value);
722 : 0 : value = NULL;
723 : : }
724 : :
725 : 212 : return value;
726 : : }
727 : :
728 : : /*< private >
729 : : * g_settings_backend_read_user_value:
730 : : * @backend: a #GSettingsBackend implementation
731 : : * @key: the key to read
732 : : * @expected_type: a #GVariantType
733 : : *
734 : : * Reads the 'user value' of a key.
735 : : *
736 : : * This is the value of the key that the user has control over and has
737 : : * set for themselves. Put another way: if the user did not set the
738 : : * value for themselves, then this will return %NULL (even if the
739 : : * sysadmin has provided a default value).
740 : : *
741 : : * Returns: (nullable) (transfer full): the value that was read, or %NULL
742 : : */
743 : : GVariant *
744 : 3 : g_settings_backend_read_user_value (GSettingsBackend *backend,
745 : : const gchar *key,
746 : : const GVariantType *expected_type)
747 : : {
748 : : GVariant *value;
749 : :
750 : 3 : value = G_SETTINGS_BACKEND_GET_CLASS (backend)
751 : 3 : ->read_user_value (backend, key, expected_type);
752 : :
753 : 3 : if (value != NULL)
754 : 2 : value = g_variant_take_ref (value);
755 : :
756 : 3 : if G_UNLIKELY (value && !g_variant_is_of_type (value, expected_type))
757 : : {
758 : 0 : g_variant_unref (value);
759 : 0 : value = NULL;
760 : : }
761 : :
762 : 3 : return value;
763 : : }
764 : :
765 : : /*< private >
766 : : * g_settings_backend_write:
767 : : * @backend: a #GSettingsBackend implementation
768 : : * @key: the name of the key
769 : : * @value: a #GVariant value to write to this key
770 : : * @origin_tag: the origin tag
771 : : *
772 : : * Writes exactly one key.
773 : : *
774 : : * This call does not fail. During this call a
775 : : * #GSettingsBackend::changed signal will be emitted if the value of the
776 : : * key has changed. The updated key value will be visible to any signal
777 : : * callbacks.
778 : : *
779 : : * One possible method that an implementation might deal with failures is
780 : : * to emit a second "changed" signal (either during this call, or later)
781 : : * to indicate that the affected keys have suddenly "changed back" to their
782 : : * old values.
783 : : *
784 : : * If @value has a floating reference, it will be sunk.
785 : : *
786 : : * Returns: %TRUE if the write succeeded, %FALSE if the key was not writable
787 : : */
788 : : gboolean
789 : 121 : g_settings_backend_write (GSettingsBackend *backend,
790 : : const gchar *key,
791 : : GVariant *value,
792 : : gpointer origin_tag)
793 : : {
794 : : gboolean success;
795 : :
796 : 121 : g_variant_ref_sink (value);
797 : 121 : success = G_SETTINGS_BACKEND_GET_CLASS (backend)
798 : 121 : ->write (backend, key, value, origin_tag);
799 : 121 : g_variant_unref (value);
800 : :
801 : 121 : return success;
802 : : }
803 : :
804 : : /*< private >
805 : : * g_settings_backend_write_tree:
806 : : * @backend: a #GSettingsBackend implementation
807 : : * @tree: a #GTree containing key-value pairs to write
808 : : * @origin_tag: the origin tag
809 : : *
810 : : * Writes one or more keys. This call will never block.
811 : : *
812 : : * The key of each item in the tree is the key name to write to and the
813 : : * value is a #GVariant to write. The proper type of #GTree for this
814 : : * call can be created with g_settings_backend_create_tree(). This call
815 : : * might take a reference to the tree; you must not modified the #GTree
816 : : * after passing it to this call.
817 : : *
818 : : * This call does not fail. During this call a #GSettingsBackend::changed
819 : : * signal will be emitted if any keys have been changed. The new values of
820 : : * all updated keys will be visible to any signal callbacks.
821 : : *
822 : : * One possible method that an implementation might deal with failures is
823 : : * to emit a second "changed" signal (either during this call, or later)
824 : : * to indicate that the affected keys have suddenly "changed back" to their
825 : : * old values.
826 : : */
827 : : gboolean
828 : 14 : g_settings_backend_write_tree (GSettingsBackend *backend,
829 : : GTree *tree,
830 : : gpointer origin_tag)
831 : : {
832 : 28 : return G_SETTINGS_BACKEND_GET_CLASS (backend)
833 : 14 : ->write_tree (backend, tree, origin_tag);
834 : : }
835 : :
836 : : /*< private >
837 : : * g_settings_backend_reset:
838 : : * @backend: a #GSettingsBackend implementation
839 : : * @key: the name of a key
840 : : * @origin_tag: the origin tag
841 : : *
842 : : * "Resets" the named key to its "default" value (ie: after system-wide
843 : : * defaults, mandatory keys, etc. have been taken into account) or possibly
844 : : * unsets it.
845 : : */
846 : : void
847 : 14 : g_settings_backend_reset (GSettingsBackend *backend,
848 : : const gchar *key,
849 : : gpointer origin_tag)
850 : : {
851 : 14 : G_SETTINGS_BACKEND_GET_CLASS (backend)
852 : 14 : ->reset (backend, key, origin_tag);
853 : 14 : }
854 : :
855 : : /*< private >
856 : : * g_settings_backend_get_writable:
857 : : * @backend: a #GSettingsBackend implementation
858 : : * @key: the name of a key
859 : : *
860 : : * Finds out if a key is available for writing to. This is the
861 : : * interface through which 'lockdown' is implemented. Locked down
862 : : * keys will have %FALSE returned by this call.
863 : : *
864 : : * You should not write to locked-down keys, but if you do, the
865 : : * implementation will deal with it.
866 : : *
867 : : * Returns: %TRUE if the key is writable
868 : : */
869 : : gboolean
870 : 38 : g_settings_backend_get_writable (GSettingsBackend *backend,
871 : : const gchar *key)
872 : : {
873 : 76 : return G_SETTINGS_BACKEND_GET_CLASS (backend)
874 : 38 : ->get_writable (backend, key);
875 : : }
876 : :
877 : : /*< private >
878 : : * g_settings_backend_unsubscribe:
879 : : * @backend: a #GSettingsBackend
880 : : * @name: a key or path to subscribe to
881 : : *
882 : : * Reverses the effect of a previous call to
883 : : * g_settings_backend_subscribe().
884 : : */
885 : : void
886 : 71 : g_settings_backend_unsubscribe (GSettingsBackend *backend,
887 : : const char *name)
888 : : {
889 : 71 : G_SETTINGS_BACKEND_GET_CLASS (backend)
890 : 71 : ->unsubscribe (backend, name);
891 : 71 : }
892 : :
893 : : /*< private >
894 : : * g_settings_backend_subscribe:
895 : : * @backend: a #GSettingsBackend
896 : : * @name: a key or path to subscribe to
897 : : *
898 : : * Requests that change signals be emitted for events on @name.
899 : : */
900 : : void
901 : 63 : g_settings_backend_subscribe (GSettingsBackend *backend,
902 : : const gchar *name)
903 : : {
904 : 63 : G_SETTINGS_BACKEND_GET_CLASS (backend)
905 : 63 : ->subscribe (backend, name);
906 : 63 : }
907 : :
908 : : static void
909 : 22 : g_settings_backend_finalize (GObject *object)
910 : : {
911 : 22 : GSettingsBackend *backend = G_SETTINGS_BACKEND (object);
912 : :
913 : 22 : g_mutex_clear (&backend->priv->lock);
914 : :
915 : 22 : G_OBJECT_CLASS (g_settings_backend_parent_class)
916 : 22 : ->finalize (object);
917 : 22 : }
918 : :
919 : : static void
920 : 122 : ignore_subscription (GSettingsBackend *backend,
921 : : const gchar *key)
922 : : {
923 : 122 : }
924 : :
925 : : static GVariant *
926 : 2 : g_settings_backend_real_read_user_value (GSettingsBackend *backend,
927 : : const gchar *key,
928 : : const GVariantType *expected_type)
929 : : {
930 : 2 : return g_settings_backend_read (backend, key, expected_type, FALSE);
931 : : }
932 : :
933 : : static void
934 : 24 : g_settings_backend_init (GSettingsBackend *backend)
935 : : {
936 : 24 : backend->priv = g_settings_backend_get_instance_private (backend);
937 : 24 : g_mutex_init (&backend->priv->lock);
938 : 24 : }
939 : :
940 : : static void
941 : 7 : g_settings_backend_class_init (GSettingsBackendClass *class)
942 : : {
943 : 7 : GObjectClass *gobject_class = G_OBJECT_CLASS (class);
944 : :
945 : 7 : class->subscribe = ignore_subscription;
946 : 7 : class->unsubscribe = ignore_subscription;
947 : :
948 : 7 : class->read_user_value = g_settings_backend_real_read_user_value;
949 : :
950 : 7 : gobject_class->finalize = g_settings_backend_finalize;
951 : 7 : }
952 : :
953 : : static void
954 : 20 : g_settings_backend_variant_unref0 (gpointer data)
955 : : {
956 : 20 : if (data != NULL)
957 : 13 : g_variant_unref (data);
958 : 20 : }
959 : :
960 : : /*< private >
961 : : * g_settings_backend_create_tree:
962 : : *
963 : : * This is a convenience function for creating a tree that is compatible
964 : : * with g_settings_backend_write(). It merely calls g_tree_new_full()
965 : : * with strcmp(), g_free() and g_variant_unref().
966 : : *
967 : : * Returns: a new #GTree
968 : : */
969 : : GTree *
970 : 25 : g_settings_backend_create_tree (void)
971 : : {
972 : 25 : return g_tree_new_full ((GCompareDataFunc) strcmp, NULL,
973 : : g_free, g_settings_backend_variant_unref0);
974 : : }
975 : :
976 : : static gboolean
977 : 4 : g_settings_backend_verify (gpointer impl)
978 : : {
979 : 4 : GSettingsBackend *backend = impl;
980 : :
981 : 8 : if (strcmp (G_OBJECT_TYPE_NAME (backend), "GMemorySettingsBackend") == 0 &&
982 : 4 : g_strcmp0 (g_getenv ("GSETTINGS_BACKEND"), "memory") != 0)
983 : : {
984 : 0 : g_message ("Using the 'memory' GSettings backend. Your settings "
985 : : "will not be saved or shared with other applications.");
986 : : }
987 : :
988 : 4 : g_settings_has_backend = TRUE;
989 : 4 : return TRUE;
990 : : }
991 : :
992 : : /* We need to cache the default #GSettingsBackend for the entire process
993 : : * lifetime, especially if the backend is #GMemorySettingsBackend: it needs to
994 : : * keep the in-memory settings around even while there are no #GSettings
995 : : * instances alive. */
996 : : static GSettingsBackend *settings_backend_default_singleton = NULL; /* (owned) (atomic) */
997 : :
998 : : /**
999 : : * g_settings_backend_get_default:
1000 : : *
1001 : : * Returns the default #GSettingsBackend. It is possible to override
1002 : : * the default by setting the `GSETTINGS_BACKEND` environment variable
1003 : : * to the name of a settings backend.
1004 : : *
1005 : : * The user gets a reference to the backend.
1006 : : *
1007 : : * Returns: (not nullable) (transfer full): the default #GSettingsBackend,
1008 : : * which will be a dummy (memory) settings backend if no other settings
1009 : : * backend is available.
1010 : : *
1011 : : * Since: 2.28
1012 : : */
1013 : : GSettingsBackend *
1014 : 56 : g_settings_backend_get_default (void)
1015 : : {
1016 : 56 : if (g_once_init_enter_pointer (&settings_backend_default_singleton))
1017 : : {
1018 : : GSettingsBackend *singleton;
1019 : :
1020 : 4 : singleton = _g_io_module_get_default (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME,
1021 : : "GSETTINGS_BACKEND",
1022 : : g_settings_backend_verify);
1023 : :
1024 : 4 : g_once_init_leave_pointer (&settings_backend_default_singleton, singleton);
1025 : : }
1026 : :
1027 : 56 : return g_object_ref (settings_backend_default_singleton);
1028 : : }
1029 : :
1030 : : /*< private >
1031 : : * g_settings_backend_get_permission:
1032 : : * @backend: a #GSettingsBackend
1033 : : * @path: a path
1034 : : *
1035 : : * Gets the permission object associated with writing to keys below
1036 : : * @path on @backend.
1037 : : *
1038 : : * If this is not implemented in the backend, then a %TRUE
1039 : : * #GSimplePermission is returned.
1040 : : *
1041 : : * Returns: (not nullable) (transfer full): a non-%NULL #GPermission.
1042 : : * Free with g_object_unref()
1043 : : */
1044 : : GPermission *
1045 : 0 : g_settings_backend_get_permission (GSettingsBackend *backend,
1046 : : const gchar *path)
1047 : : {
1048 : 0 : GSettingsBackendClass *class = G_SETTINGS_BACKEND_GET_CLASS (backend);
1049 : :
1050 : 0 : if (class->get_permission)
1051 : 0 : return class->get_permission (backend, path);
1052 : :
1053 : 0 : return g_simple_permission_new (TRUE);
1054 : : }
1055 : :
1056 : : /*< private >
1057 : : * g_settings_backend_sync_default:
1058 : : *
1059 : : * Syncs the default backend.
1060 : : */
1061 : : void
1062 : 43 : g_settings_backend_sync_default (void)
1063 : : {
1064 : 43 : if (g_settings_has_backend)
1065 : : {
1066 : : GSettingsBackendClass *class;
1067 : : GSettingsBackend *backend;
1068 : :
1069 : 2 : backend = g_settings_backend_get_default ();
1070 : 2 : class = G_SETTINGS_BACKEND_GET_CLASS (backend);
1071 : :
1072 : 2 : if (class->sync)
1073 : 0 : class->sync (backend);
1074 : :
1075 : 2 : g_object_unref (backend);
1076 : : }
1077 : 43 : }
|