View | Details | Raw Unified | Return to bug 247039 | Differences between
and this patch

Collapse All | Expand All

(-)b/devel/glib20/Makefile (-1 / +1 lines)
Lines 3-9 Link Here
3
3
4
PORTNAME=	glib
4
PORTNAME=	glib
5
PORTVERSION=	2.56.3
5
PORTVERSION=	2.56.3
6
PORTREVISION=	7
6
PORTREVISION=	8
7
PORTEPOCH=	1
7
PORTEPOCH=	1
8
CATEGORIES=	devel
8
CATEGORIES=	devel
9
MASTER_SITES=	GNOME
9
MASTER_SITES=	GNOME
(-)b/devel/glib20/files/patch-keyfile (+582 lines)
Added Link Here
1
https://gitlab.gnome.org/GNOME/glib/-/merge_requests/450
2
https://gitlab.gnome.org/GNOME/glib/-/merge_requests/603
3
https://gitlab.gnome.org/GNOME/glib/-/merge_requests/974
4
5
--- gio/giomodule.c.orig	2018-09-21 09:29:23 UTC
6
+++ gio/giomodule.c
7
@@ -1136,6 +1136,7 @@ _g_io_modules_ensure_loaded (void)
8
       /* Initialize types from built-in "modules" */
9
       g_type_ensure (g_null_settings_backend_get_type ());
10
       g_type_ensure (g_memory_settings_backend_get_type ());
11
+      g_type_ensure (g_keyfile_settings_backend_get_type ());
12
 #if defined(HAVE_INOTIFY_INIT1)
13
       g_type_ensure (g_inotify_file_monitor_get_type ());
14
 #endif
15
--- gio/gkeyfilesettingsbackend.c.orig	2018-08-15 16:22:08 UTC
16
+++ gio/gkeyfilesettingsbackend.c
17
@@ -21,14 +21,20 @@
18
 
19
 #include "config.h"
20
 
21
+#include <glib.h>
22
+#include <glibintl.h>
23
+
24
 #include <stdio.h>
25
 #include <string.h>
26
 
27
 #include "gfile.h"
28
 #include "gfileinfo.h"
29
+#include "gfileenumerator.h"
30
 #include "gfilemonitor.h"
31
 #include "gsimplepermission.h"
32
-#include "gsettingsbackend.h"
33
+#include "gsettingsbackendinternal.h"
34
+#include "giomodule-priv.h"
35
+#include "gportalsupport.h"
36
 
37
 
38
 #define G_TYPE_KEYFILE_SETTINGS_BACKEND      (g_keyfile_settings_backend_get_type ())
39
@@ -41,6 +47,13 @@
40
 
41
 typedef GSettingsBackendClass GKeyfileSettingsBackendClass;
42
 
43
+typedef enum {
44
+  PROP_FILENAME = 1,
45
+  PROP_ROOT_PATH,
46
+  PROP_ROOT_GROUP,
47
+  PROP_DEFAULTS_DIR
48
+} GKeyfileSettingsBackendProperty;
49
+
50
 typedef struct
51
 {
52
   GSettingsBackend   parent_instance;
53
@@ -48,6 +61,9 @@ typedef struct
54
   GKeyFile          *keyfile;
55
   GPermission       *permission;
56
   gboolean           writable;
57
+  char              *defaults_dir;
58
+  GKeyFile          *system_keyfile;
59
+  GHashTable        *system_locks; /* Used as a set, owning the strings it contains */
60
 
61
   gchar             *prefix;
62
   gint               prefix_len;
63
@@ -61,11 +77,19 @@ typedef struct
64
   GFileMonitor      *dir_monitor;
65
 } GKeyfileSettingsBackend;
66
 
67
-static GType g_keyfile_settings_backend_get_type (void);
68
-G_DEFINE_TYPE (GKeyfileSettingsBackend,
69
-               g_keyfile_settings_backend,
70
-               G_TYPE_SETTINGS_BACKEND)
71
+#ifdef G_OS_WIN32
72
+#define EXTENSION_PRIORITY 10
73
+#else
74
+#define EXTENSION_PRIORITY (glib_should_use_portal () ? 110 : 10)
75
+#endif
76
 
77
+G_DEFINE_TYPE_WITH_CODE (GKeyfileSettingsBackend,
78
+                         g_keyfile_settings_backend,
79
+                         G_TYPE_SETTINGS_BACKEND,
80
+                         _g_io_modules_ensure_extension_points_registered ();
81
+                         g_io_extension_point_implement (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME,
82
+                                                         g_define_type_id, "keyfile", EXTENSION_PRIORITY))
83
+
84
 static void
85
 compute_checksum (guint8        *digest,
86
                   gconstpointer  contents,
87
@@ -184,17 +208,47 @@ get_from_keyfile (GKeyfileSettingsBackend *kfsb,
88
   if (convert_path (kfsb, key, &group, &name))
89
     {
90
       gchar *str;
91
+      gchar *sysstr;
92
 
93
       g_assert (*name);
94
 
95
+      sysstr = g_key_file_get_value (kfsb->system_keyfile, group, name, NULL);
96
       str = g_key_file_get_value (kfsb->keyfile, group, name, NULL);
97
+      if (sysstr &&
98
+          (g_hash_table_contains (kfsb->system_locks, key) ||
99
+           str == NULL))
100
+        {
101
+          g_free (str);
102
+          str = g_steal_pointer (&sysstr);
103
+        }
104
 
105
       if (str)
106
         {
107
           return_value = g_variant_parse (type, str, NULL, NULL, NULL);
108
+          if (return_value == NULL &&
109
+              g_variant_type_equal (type, G_VARIANT_TYPE_STRING) &&
110
+              str[0] != '\"')
111
+            {
112
+              GString *s = g_string_sized_new (strlen (str) + 2);
113
+              char *p = str;
114
+
115
+              g_string_append_c (s, '\"');
116
+              while (*p)
117
+                {
118
+                  if (*p == '\"')
119
+                    g_string_append_c (s, '\\');
120
+                  g_string_append_c (s, *p);
121
+                  p++;
122
+                }
123
+              g_string_append_c (s, '\"');
124
+              return_value = g_variant_parse (type, s->str, NULL, NULL, NULL);
125
+              g_string_free (s, TRUE);
126
+            }
127
           g_free (str);
128
         }
129
 
130
+      g_free (sysstr);
131
+
132
       g_free (group);
133
       g_free (name);
134
     }
135
@@ -209,6 +263,9 @@ set_to_keyfile (GKeyfileSettingsBackend *kfsb,
136
 {
137
   gchar *group, *name;
138
 
139
+  if (g_hash_table_contains (kfsb->system_locks, key))
140
+    return FALSE;
141
+
142
   if (convert_path (kfsb, key, &group, &name))
143
     {
144
       if (value)
145
@@ -287,7 +344,8 @@ g_keyfile_settings_backend_check_one (gpointer key,
146
 {
147
   WriteManyData *data = user_data;
148
 
149
-  return data->failed = !path_is_valid (data->kfsb, key);
150
+  return data->failed = g_hash_table_contains (data->kfsb->system_locks, key) ||
151
+                        !path_is_valid (data->kfsb, key);
152
 }
153
 
154
 static gboolean
155
@@ -355,7 +413,9 @@ g_keyfile_settings_backend_get_writable (GSettingsBack
156
 {
157
   GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (backend);
158
 
159
-  return kfsb->writable && path_is_valid (kfsb, name);
160
+  return kfsb->writable &&
161
+         !g_hash_table_contains (kfsb->system_locks, name) &&
162
+         path_is_valid (kfsb, name);
163
 }
164
 
165
 static GPermission *
166
@@ -501,6 +561,9 @@ g_keyfile_settings_backend_finalize (GObject *object)
167
 
168
   g_key_file_free (kfsb->keyfile);
169
   g_object_unref (kfsb->permission);
170
+  g_key_file_unref (kfsb->system_keyfile);
171
+  g_hash_table_unref (kfsb->system_locks);
172
+  g_free (kfsb->defaults_dir);
173
 
174
   g_file_monitor_cancel (kfsb->file_monitor);
175
   g_object_unref (kfsb->file_monitor);
176
@@ -523,25 +586,6 @@ g_keyfile_settings_backend_init (GKeyfileSettingsBacke
177
 }
178
 
179
 static void
180
-g_keyfile_settings_backend_class_init (GKeyfileSettingsBackendClass *class)
181
-{
182
-  GObjectClass *object_class = G_OBJECT_CLASS (class);
183
-
184
-  object_class->finalize = g_keyfile_settings_backend_finalize;
185
-
186
-  class->read = g_keyfile_settings_backend_read;
187
-  class->write = g_keyfile_settings_backend_write;
188
-  class->write_tree = g_keyfile_settings_backend_write_tree;
189
-  class->reset = g_keyfile_settings_backend_reset;
190
-  class->get_writable = g_keyfile_settings_backend_get_writable;
191
-  class->get_permission = g_keyfile_settings_backend_get_permission;
192
-  /* No need to implement subscribed/unsubscribe: the only point would be to
193
-   * stop monitoring the file when there's no GSettings anymore, which is no
194
-   * big win.
195
-   */
196
-}
197
-
198
-static void
199
 file_changed (GFileMonitor      *monitor,
200
               GFile             *file,
201
               GFile             *other_file,
202
@@ -567,6 +611,282 @@ dir_changed (GFileMonitor       *monitor,
203
   g_keyfile_settings_backend_keyfile_writable (kfsb);
204
 }
205
 
206
+static void
207
+load_system_settings (GKeyfileSettingsBackend *kfsb)
208
+{
209
+  GError *error = NULL;
210
+  const char *dir = "/etc/glib-2.0/settings";
211
+  char *path;
212
+  char *contents;
213
+
214
+  kfsb->system_keyfile = g_key_file_new ();
215
+  kfsb->system_locks = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
216
+
217
+  if (kfsb->defaults_dir)
218
+    dir = kfsb->defaults_dir;
219
+
220
+  path = g_build_filename (dir, "defaults", NULL);
221
+
222
+  /* The defaults are in the same keyfile format that we use for the settings.
223
+   * It can be produced from a dconf database using: dconf dump
224
+   */
225
+  if (!g_key_file_load_from_file (kfsb->system_keyfile, path, G_KEY_FILE_NONE, &error))
226
+    {
227
+      if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
228
+        g_warning ("Failed to read %s: %s", path, error->message);
229
+      g_clear_error (&error);
230
+    }
231
+  else
232
+    g_debug ("Loading default settings from %s", path);
233
+
234
+  g_free (path);
235
+
236
+  path = g_build_filename (dir, "locks", NULL);
237
+
238
+  /* The locks file is a text file containing a list paths to lock, one per line.
239
+   * It can be produced from a dconf database using: dconf list-locks
240
+   */
241
+  if (!g_file_get_contents (path, &contents, NULL, &error))
242
+    {
243
+      if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
244
+        g_warning ("Failed to read %s: %s", path, error->message);
245
+      g_clear_error (&error);
246
+    }
247
+  else
248
+    {
249
+      char **lines;
250
+      gsize i;
251
+
252
+      g_debug ("Loading locks from %s", path);
253
+
254
+      lines = g_strsplit (contents, "\n", 0);
255
+      for (i = 0; lines[i]; i++)
256
+        {
257
+          char *line = lines[i];
258
+          if (line[0] == '#' || line[0] == '\0')
259
+            {
260
+              g_free (line);
261
+              continue;
262
+            }
263
+
264
+          g_debug ("Locking key %s", line);
265
+          g_hash_table_add (kfsb->system_locks, g_steal_pointer (&line));
266
+        }
267
+
268
+      g_free (lines);
269
+    }
270
+  g_free (contents);
271
+
272
+  g_free (path);
273
+}
274
+
275
+static void
276
+g_keyfile_settings_backend_constructed (GObject *object)
277
+{
278
+  GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (object);
279
+
280
+  if (kfsb->file == NULL)
281
+    {
282
+      char *filename = g_build_filename (g_get_user_config_dir (),
283
+                                         "glib-2.0", "settings", "keyfile",
284
+                                         NULL);
285
+      kfsb->file = g_file_new_for_path (filename);
286
+      g_free (filename);
287
+    }
288
+
289
+  if (kfsb->prefix == NULL)
290
+    {
291
+      kfsb->prefix = g_strdup ("/");
292
+      kfsb->prefix_len = 1;
293
+    }
294
+  
295
+  kfsb->keyfile = g_key_file_new ();
296
+  kfsb->permission = g_simple_permission_new (TRUE);
297
+
298
+  kfsb->dir = g_file_get_parent (kfsb->file);
299
+  g_file_make_directory_with_parents (kfsb->dir, NULL, NULL);
300
+
301
+  kfsb->file_monitor = g_file_monitor (kfsb->file, G_FILE_MONITOR_NONE, NULL, NULL);
302
+  kfsb->dir_monitor = g_file_monitor (kfsb->dir, G_FILE_MONITOR_NONE, NULL, NULL);
303
+
304
+  compute_checksum (kfsb->digest, NULL, 0);
305
+
306
+  g_signal_connect (kfsb->file_monitor, "changed",
307
+                    G_CALLBACK (file_changed), kfsb);
308
+  g_signal_connect (kfsb->dir_monitor, "changed",
309
+                    G_CALLBACK (dir_changed), kfsb);
310
+
311
+  g_keyfile_settings_backend_keyfile_writable (kfsb);
312
+  g_keyfile_settings_backend_keyfile_reload (kfsb);
313
+
314
+  load_system_settings (kfsb);
315
+}
316
+
317
+static void
318
+g_keyfile_settings_backend_set_property (GObject      *object,
319
+                                         guint         prop_id,
320
+                                         const GValue *value,
321
+                                         GParamSpec   *pspec)
322
+{
323
+  GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (object);
324
+
325
+  switch ((GKeyfileSettingsBackendProperty)prop_id)
326
+    {
327
+    case PROP_FILENAME:
328
+      /* Construct only. */
329
+      g_assert (kfsb->file == NULL);
330
+      kfsb->file = g_file_new_for_path (g_value_get_string (value));
331
+      break;
332
+
333
+    case PROP_ROOT_PATH:
334
+      /* Construct only. */
335
+      g_assert (kfsb->prefix == NULL);
336
+      kfsb->prefix = g_value_dup_string (value);
337
+      if (kfsb->prefix)
338
+        kfsb->prefix_len = strlen (kfsb->prefix);
339
+      break;
340
+
341
+    case PROP_ROOT_GROUP:
342
+      /* Construct only. */
343
+      g_assert (kfsb->root_group == NULL);
344
+      kfsb->root_group = g_value_dup_string (value);
345
+      if (kfsb->root_group)
346
+        kfsb->root_group_len = strlen (kfsb->root_group);
347
+      break;
348
+
349
+    case PROP_DEFAULTS_DIR:
350
+      /* Construct only. */
351
+      g_assert (kfsb->defaults_dir == NULL);
352
+      kfsb->defaults_dir = g_value_dup_string (value);
353
+      break;
354
+
355
+    default:
356
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
357
+      break;
358
+    }
359
+}
360
+
361
+static void
362
+g_keyfile_settings_backend_get_property (GObject    *object,
363
+                                         guint       prop_id,
364
+                                         GValue     *value,
365
+                                         GParamSpec *pspec)
366
+{
367
+  GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (object);
368
+
369
+  switch ((GKeyfileSettingsBackendProperty)prop_id)
370
+    {
371
+    case PROP_FILENAME:
372
+      g_value_set_string (value, g_file_peek_path (kfsb->file));
373
+      break;
374
+
375
+    case PROP_ROOT_PATH:
376
+      g_value_set_string (value, kfsb->prefix);
377
+      break;
378
+
379
+    case PROP_ROOT_GROUP:
380
+      g_value_set_string (value, kfsb->root_group);
381
+      break;
382
+
383
+    case PROP_DEFAULTS_DIR:
384
+      g_value_set_string (value, kfsb->defaults_dir);
385
+      break;
386
+
387
+    default:
388
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
389
+      break;
390
+    }
391
+}
392
+
393
+static void
394
+g_keyfile_settings_backend_class_init (GKeyfileSettingsBackendClass *class)
395
+{
396
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
397
+
398
+  object_class->finalize = g_keyfile_settings_backend_finalize;
399
+  object_class->constructed = g_keyfile_settings_backend_constructed;
400
+  object_class->get_property = g_keyfile_settings_backend_get_property;
401
+  object_class->set_property = g_keyfile_settings_backend_set_property;
402
+
403
+  class->read = g_keyfile_settings_backend_read;
404
+  class->write = g_keyfile_settings_backend_write;
405
+  class->write_tree = g_keyfile_settings_backend_write_tree;
406
+  class->reset = g_keyfile_settings_backend_reset;
407
+  class->get_writable = g_keyfile_settings_backend_get_writable;
408
+  class->get_permission = g_keyfile_settings_backend_get_permission;
409
+  /* No need to implement subscribed/unsubscribe: the only point would be to
410
+   * stop monitoring the file when there's no GSettings anymore, which is no
411
+   * big win.
412
+   */
413
+
414
+  /**
415
+   * GKeyfileSettingsBackend:filename:
416
+   *
417
+   * The location where the settings are stored on disk.
418
+   *
419
+   * Defaults to `$XDG_CONFIG_HOME/glib-2.0/settings/keyfile`.
420
+   */
421
+  g_object_class_install_property (object_class,
422
+                                   PROP_FILENAME,
423
+                                   g_param_spec_string ("filename",
424
+                                                        P_("Filename"),
425
+                                                        P_("The filename"),
426
+                                                        NULL,
427
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
428
+                                                        G_PARAM_STATIC_STRINGS));
429
+
430
+  /**
431
+   * GKeyfileSettingsBackend:root-path:
432
+   *
433
+   * All settings read to or written from the backend must fall under the
434
+   * path given in @root_path (which must start and end with a slash and
435
+   * not contain two consecutive slashes).  @root_path may be "/".
436
+   * 
437
+   * Defaults to "/".
438
+   */
439
+  g_object_class_install_property (object_class,
440
+                                   PROP_ROOT_PATH,
441
+                                   g_param_spec_string ("root-path",
442
+                                                        P_("Root path"),
443
+                                                        P_("The root path"),
444
+                                                        NULL,
445
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
446
+                                                        G_PARAM_STATIC_STRINGS));
447
+
448
+  /**
449
+   * GKeyfileSettingsBackend:root-group:
450
+   *
451
+   * If @root_group is non-%NULL then it specifies the name of the keyfile
452
+   * group used for keys that are written directly below the root path.
453
+   *
454
+   * Defaults to NULL.
455
+   */
456
+  g_object_class_install_property (object_class,
457
+                                   PROP_ROOT_GROUP,
458
+                                   g_param_spec_string ("root-group",
459
+                                                        P_("Root group"),
460
+                                                        P_("The root group"),
461
+                                                        NULL,
462
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
463
+                                                        G_PARAM_STATIC_STRINGS));
464
+
465
+  /**
466
+   * GKeyfileSettingsBackend:default-dir:
467
+   *
468
+   * The directory where the system defaults and locks are located.
469
+   *
470
+   * Defaults to `/etc/glib-2.0/settings`.
471
+   */
472
+  g_object_class_install_property (object_class,
473
+                                   PROP_DEFAULTS_DIR,
474
+                                   g_param_spec_string ("defaults-dir",
475
+                                                        P_("Default dir"),
476
+                                                        P_("Defaults dir"),
477
+                                                        NULL,
478
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
479
+                                                        G_PARAM_STATIC_STRINGS));
480
+}
481
+
482
 /**
483
  * g_keyfile_settings_backend_new:
484
  * @filename: the filename of the keyfile
485
@@ -619,6 +939,11 @@ dir_changed (GFileMonitor       *monitor,
486
  * characters in your path names or '=' in your key names you may be in
487
  * trouble.
488
  *
489
+ * The backend reads default values from a keyfile called `defaults` in
490
+ * the directory specified by the #GKeyfileSettingsBackend:defaults-dir property,
491
+ * and a list of locked keys from a text file with the name `locks` in
492
+ * the same location.
493
+ *
494
  * Returns: (transfer full): a keyfile-backed #GSettingsBackend
495
  **/
496
 GSettingsBackend *
497
@@ -626,43 +951,15 @@ g_keyfile_settings_backend_new (const gchar *filename,
498
                                 const gchar *root_path,
499
                                 const gchar *root_group)
500
 {
501
-  GKeyfileSettingsBackend *kfsb;
502
-
503
   g_return_val_if_fail (filename != NULL, NULL);
504
   g_return_val_if_fail (root_path != NULL, NULL);
505
   g_return_val_if_fail (g_str_has_prefix (root_path, "/"), NULL);
506
   g_return_val_if_fail (g_str_has_suffix (root_path, "/"), NULL);
507
   g_return_val_if_fail (strstr (root_path, "//") == NULL, NULL);
508
 
509
-  kfsb = g_object_new (G_TYPE_KEYFILE_SETTINGS_BACKEND, NULL);
510
-  kfsb->keyfile = g_key_file_new ();
511
-  kfsb->permission = g_simple_permission_new (TRUE);
512
-
513
-  kfsb->file = g_file_new_for_path (filename);
514
-  kfsb->dir = g_file_get_parent (kfsb->file);
515
-  g_file_make_directory_with_parents (kfsb->dir, NULL, NULL);
516
-
517
-  kfsb->file_monitor = g_file_monitor (kfsb->file, 0, NULL, NULL);
518
-  kfsb->dir_monitor = g_file_monitor (kfsb->dir, 0, NULL, NULL);
519
-
520
-  kfsb->prefix_len = strlen (root_path);
521
-  kfsb->prefix = g_strdup (root_path);
522
-
523
-  if (root_group)
524
-    {
525
-      kfsb->root_group_len = strlen (root_group);
526
-      kfsb->root_group = g_strdup (root_group);
527
-    }
528
-
529
-  compute_checksum (kfsb->digest, NULL, 0);
530
-
531
-  g_signal_connect (kfsb->file_monitor, "changed",
532
-                    G_CALLBACK (file_changed), kfsb);
533
-  g_signal_connect (kfsb->dir_monitor, "changed",
534
-                    G_CALLBACK (dir_changed), kfsb);
535
-
536
-  g_keyfile_settings_backend_keyfile_writable (kfsb);
537
-  g_keyfile_settings_backend_keyfile_reload (kfsb);
538
-
539
-  return G_SETTINGS_BACKEND (kfsb);
540
+  return G_SETTINGS_BACKEND (g_object_new (G_TYPE_KEYFILE_SETTINGS_BACKEND,
541
+                                           "filename", filename,
542
+                                           "root-path", root_path,
543
+                                           "root-group", root_group,
544
+                                           NULL));
545
 }
546
--- gio/gsettingsbackendinternal.h.orig	2018-08-15 16:22:08 UTC
547
+++ gio/gsettingsbackendinternal.h
548
@@ -87,6 +87,8 @@ GType                   g_null_settings_backend_get_ty
549
 
550
 GType                   g_memory_settings_backend_get_type              (void);
551
 
552
+GType                   g_keyfile_settings_backend_get_type             (void);
553
+
554
 #ifdef HAVE_COCOA
555
 GType                   g_nextstep_settings_backend_get_type            (void);
556
 #endif
557
--- gio/tests/gsettings.c.orig	2018-09-21 09:29:23 UTC
558
+++ gio/tests/gsettings.c
559
@@ -1716,6 +1716,23 @@ test_keyfile (void)
560
   g_assert_cmpstr (str, ==, "howdy");
561
   g_free (str);
562
 
563
+  /* Now check setting a string without quotes */
564
+  called = FALSE;
565
+  g_signal_connect (settings, "changed::greeting", G_CALLBACK (key_changed_cb), &called);
566
+
567
+  g_key_file_set_string (keyfile, "tests", "greeting", "he\"l🤗uń");
568
+  g_free (data);
569
+  data = g_key_file_to_data (keyfile, &len, NULL);
570
+  g_file_set_contents ("keyfile/gsettings.store", data, len, &error);
571
+  g_assert_no_error (error);
572
+  while (!called)
573
+    g_main_context_iteration (NULL, FALSE);
574
+  g_signal_handlers_disconnect_by_func (settings, key_changed_cb, &called);
575
+
576
+  str = g_settings_get_string (settings, "greeting");
577
+  g_assert_cmpstr (str, ==, "he\"l🤗uń");
578
+  g_free (str);
579
+
580
   g_settings_set (settings, "farewell", "s", "cheerio");
581
   
582
   called = FALSE;

Return to bug 247039