From 658af7018a349eb925503f920a3c6b5a948b0cc1 Mon Sep 17 00:00:00 2001 From: Daniel Playfair Cal Date: Mon, 6 Jan 2020 12:29:12 +1100 Subject: move dconf-gvdb-utils from service into common --- common/dconf-gvdb-utils.c | 219 +++++++++++++++++++++++++++++++++++++++++++++ common/dconf-gvdb-utils.h | 33 +++++++ common/meson.build | 5 +- service/dconf-gvdb-utils.c | 219 --------------------------------------------- service/dconf-gvdb-utils.h | 33 ------- service/dconf-writer.c | 2 +- service/meson.build | 7 +- 7 files changed, 259 insertions(+), 259 deletions(-) create mode 100644 common/dconf-gvdb-utils.c create mode 100644 common/dconf-gvdb-utils.h delete mode 100644 service/dconf-gvdb-utils.c delete mode 100644 service/dconf-gvdb-utils.h diff --git a/common/dconf-gvdb-utils.c b/common/dconf-gvdb-utils.c new file mode 100644 index 0000000..e70e2dc --- /dev/null +++ b/common/dconf-gvdb-utils.c @@ -0,0 +1,219 @@ +/* + * Copyright © 2010 Codethink Limited + * Copyright © 2012 Canonical Limited + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * Author: Ryan Lortie + */ + +#include "config.h" + +#include "dconf-gvdb-utils.h" + +#include "./dconf-paths.h" +#include "../gvdb/gvdb-builder.h" +#include "../gvdb/gvdb-reader.h" + +#include +#include +#include +#include + +DConfChangeset * +dconf_gvdb_utils_read_and_back_up_file (const gchar *filename, + gboolean *file_missing, + GError **error) +{ + DConfChangeset *database; + GError *my_error = NULL; + GvdbTable *table = NULL; + gchar *contents; + gsize size; + + if (g_file_get_contents (filename, &contents, &size, &my_error)) + { + GBytes *bytes; + + bytes = g_bytes_new_take (contents, size); + table = gvdb_table_new_from_bytes (bytes, FALSE, &my_error); + g_bytes_unref (bytes); + } + + /* It is perfectly fine if the file does not exist -- then it's + * just empty. + */ + if (g_error_matches (my_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) + g_clear_error (&my_error); + + /* Otherwise, we should report errors to prevent ourselves from + * overwriting the database in other situations... + */ + if (g_error_matches (my_error, G_FILE_ERROR, G_FILE_ERROR_INVAL)) + { + /* Move the database to a backup file, warn and continue with a new + * database. The alternative is erroring out and exiting the daemon, + * which leaves the user’s session essentially unusable. + * + * The code to find an unused backup filename is racy, but this is an + * error handling path. Who cares. */ + g_autofree gchar *backup_filename = NULL; + guint i; + + for (i = 0; + i < G_MAXUINT && + (backup_filename == NULL || g_file_test (backup_filename, G_FILE_TEST_EXISTS)); + i++) + { + g_free (backup_filename); + backup_filename = g_strdup_printf ("%s~%u", filename, i); + } + + if (g_rename (filename, backup_filename) != 0) + g_warning ("Error renaming corrupt database from ‘%s’ to ‘%s’: %s", + filename, backup_filename, g_strerror (errno)); + else + g_warning ("Database ‘%s’ was corrupt: moved it to ‘%s’ and created an empty replacement", + filename, backup_filename); + + g_clear_error (&my_error); + } + else if (my_error) + { + g_propagate_prefixed_error (error, my_error, "Cannot open dconf database: "); + return NULL; + } + + /* Only allocate once we know we are in a non-error situation */ + database = dconf_changeset_new_database (NULL); + + /* Fill the table up with the initial state */ + if (table != NULL) + { + gchar **names; + gsize n_names; + gsize i; + + names = gvdb_table_get_names (table, &n_names); + for (i = 0; i < n_names; i++) + { + if (dconf_is_key (names[i], NULL)) + { + GVariant *value; + + value = gvdb_table_get_value (table, names[i]); + + if (value != NULL) + { + dconf_changeset_set (database, names[i], value); + g_variant_unref (value); + } + } + + g_free (names[i]); + } + + gvdb_table_free (table); + g_free (names); + } + + if (file_missing) + *file_missing = (table == NULL); + + return database; +} + +static GvdbItem * +dconf_gvdb_utils_get_parent (GHashTable *table, + const gchar *key) +{ + GvdbItem *grandparent, *parent; + gchar *parent_name; + gint len; + + if (g_str_equal (key, "/")) + return NULL; + + len = strlen (key); + if (key[len - 1] == '/') + len--; + + while (key[len - 1] != '/') + len--; + + parent_name = g_strndup (key, len); + parent = g_hash_table_lookup (table, parent_name); + + if (parent == NULL) + { + parent = gvdb_hash_table_insert (table, parent_name); + + grandparent = dconf_gvdb_utils_get_parent (table, parent_name); + + if (grandparent != NULL) + gvdb_item_set_parent (parent, grandparent); + } + + g_free (parent_name); + + return parent; +} + +static gboolean +dconf_gvdb_utils_add_key (const gchar *path, + GVariant *value, + gpointer user_data) +{ + GHashTable *gvdb = user_data; + GvdbItem *item; + + g_assert (g_hash_table_lookup (gvdb, path) == NULL); + item = gvdb_hash_table_insert (gvdb, path); + gvdb_item_set_parent (item, dconf_gvdb_utils_get_parent (gvdb, path)); + gvdb_item_set_value (item, value); + + return TRUE; +} + +gboolean +dconf_gvdb_utils_write_file (const gchar *filename, + DConfChangeset *database, + GError **error) +{ + GHashTable *gvdb; + gboolean success; + + gvdb = gvdb_hash_table_new (NULL, NULL); + dconf_changeset_all (database, dconf_gvdb_utils_add_key, gvdb); + success = gvdb_table_write_contents (gvdb, filename, FALSE, error); + + if (!success) + { + gchar *dirname; + + /* Maybe it failed because the directory doesn't exist. Try + * again, after mkdir(). + */ + dirname = g_path_get_dirname (filename); + g_mkdir_with_parents (dirname, 0700); + g_free (dirname); + + g_clear_error (error); + success = gvdb_table_write_contents (gvdb, filename, FALSE, error); + } + + g_hash_table_unref (gvdb); + + return success; +} diff --git a/common/dconf-gvdb-utils.h b/common/dconf-gvdb-utils.h new file mode 100644 index 0000000..8d73133 --- /dev/null +++ b/common/dconf-gvdb-utils.h @@ -0,0 +1,33 @@ +/* + * Copyright © 2010 Codethink Limited + * Copyright © 2012 Canonical Limited + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * Author: Ryan Lortie + */ + +#ifndef __dconf_gvdb_utils_h__ +#define __dconf_gvdb_utils_h__ + +#include "./dconf-changeset.h" + +DConfChangeset * dconf_gvdb_utils_read_and_back_up_file (const gchar *filename, + gboolean *file_missing, + GError **error); +gboolean dconf_gvdb_utils_write_file (const gchar *filename, + DConfChangeset *database, + GError **error); + +#endif /* __dconf_gvdb_utils_h__ */ diff --git a/common/meson.build b/common/meson.build index befa9bc..e736ea8 100644 --- a/common/meson.build +++ b/common/meson.build @@ -15,18 +15,19 @@ sources = files( 'dconf-changeset.c', 'dconf-error.c', 'dconf-paths.c', + 'dconf-gvdb-utils.c', ) libdconf_common = static_library( 'dconf-common', sources: sources, include_directories: top_inc, - dependencies: glib_dep, + dependencies: [glib_dep, libgvdb_dep], c_args: dconf_c_args, pic: true, ) libdconf_common_dep = declare_dependency( - dependencies: glib_dep, + dependencies: [glib_dep, libgvdb_dep], link_with: libdconf_common, ) diff --git a/service/dconf-gvdb-utils.c b/service/dconf-gvdb-utils.c deleted file mode 100644 index d77ae97..0000000 --- a/service/dconf-gvdb-utils.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright © 2010 Codethink Limited - * Copyright © 2012 Canonical Limited - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the licence, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - * - * Author: Ryan Lortie - */ - -#include "config.h" - -#include "dconf-gvdb-utils.h" - -#include "../common/dconf-paths.h" -#include "../gvdb/gvdb-builder.h" -#include "../gvdb/gvdb-reader.h" - -#include -#include -#include -#include - -DConfChangeset * -dconf_gvdb_utils_read_and_back_up_file (const gchar *filename, - gboolean *file_missing, - GError **error) -{ - DConfChangeset *database; - GError *my_error = NULL; - GvdbTable *table = NULL; - gchar *contents; - gsize size; - - if (g_file_get_contents (filename, &contents, &size, &my_error)) - { - GBytes *bytes; - - bytes = g_bytes_new_take (contents, size); - table = gvdb_table_new_from_bytes (bytes, FALSE, &my_error); - g_bytes_unref (bytes); - } - - /* It is perfectly fine if the file does not exist -- then it's - * just empty. - */ - if (g_error_matches (my_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) - g_clear_error (&my_error); - - /* Otherwise, we should report errors to prevent ourselves from - * overwriting the database in other situations... - */ - if (g_error_matches (my_error, G_FILE_ERROR, G_FILE_ERROR_INVAL)) - { - /* Move the database to a backup file, warn and continue with a new - * database. The alternative is erroring out and exiting the daemon, - * which leaves the user’s session essentially unusable. - * - * The code to find an unused backup filename is racy, but this is an - * error handling path. Who cares. */ - g_autofree gchar *backup_filename = NULL; - guint i; - - for (i = 0; - i < G_MAXUINT && - (backup_filename == NULL || g_file_test (backup_filename, G_FILE_TEST_EXISTS)); - i++) - { - g_free (backup_filename); - backup_filename = g_strdup_printf ("%s~%u", filename, i); - } - - if (g_rename (filename, backup_filename) != 0) - g_warning ("Error renaming corrupt database from ‘%s’ to ‘%s’: %s", - filename, backup_filename, g_strerror (errno)); - else - g_warning ("Database ‘%s’ was corrupt: moved it to ‘%s’ and created an empty replacement", - filename, backup_filename); - - g_clear_error (&my_error); - } - else if (my_error) - { - g_propagate_prefixed_error (error, my_error, "Cannot open dconf database: "); - return NULL; - } - - /* Only allocate once we know we are in a non-error situation */ - database = dconf_changeset_new_database (NULL); - - /* Fill the table up with the initial state */ - if (table != NULL) - { - gchar **names; - gsize n_names; - gsize i; - - names = gvdb_table_get_names (table, &n_names); - for (i = 0; i < n_names; i++) - { - if (dconf_is_key (names[i], NULL)) - { - GVariant *value; - - value = gvdb_table_get_value (table, names[i]); - - if (value != NULL) - { - dconf_changeset_set (database, names[i], value); - g_variant_unref (value); - } - } - - g_free (names[i]); - } - - gvdb_table_free (table); - g_free (names); - } - - if (file_missing) - *file_missing = (table == NULL); - - return database; -} - -static GvdbItem * -dconf_gvdb_utils_get_parent (GHashTable *table, - const gchar *key) -{ - GvdbItem *grandparent, *parent; - gchar *parent_name; - gint len; - - if (g_str_equal (key, "/")) - return NULL; - - len = strlen (key); - if (key[len - 1] == '/') - len--; - - while (key[len - 1] != '/') - len--; - - parent_name = g_strndup (key, len); - parent = g_hash_table_lookup (table, parent_name); - - if (parent == NULL) - { - parent = gvdb_hash_table_insert (table, parent_name); - - grandparent = dconf_gvdb_utils_get_parent (table, parent_name); - - if (grandparent != NULL) - gvdb_item_set_parent (parent, grandparent); - } - - g_free (parent_name); - - return parent; -} - -static gboolean -dconf_gvdb_utils_add_key (const gchar *path, - GVariant *value, - gpointer user_data) -{ - GHashTable *gvdb = user_data; - GvdbItem *item; - - g_assert (g_hash_table_lookup (gvdb, path) == NULL); - item = gvdb_hash_table_insert (gvdb, path); - gvdb_item_set_parent (item, dconf_gvdb_utils_get_parent (gvdb, path)); - gvdb_item_set_value (item, value); - - return TRUE; -} - -gboolean -dconf_gvdb_utils_write_file (const gchar *filename, - DConfChangeset *database, - GError **error) -{ - GHashTable *gvdb; - gboolean success; - - gvdb = gvdb_hash_table_new (NULL, NULL); - dconf_changeset_all (database, dconf_gvdb_utils_add_key, gvdb); - success = gvdb_table_write_contents (gvdb, filename, FALSE, error); - - if (!success) - { - gchar *dirname; - - /* Maybe it failed because the directory doesn't exist. Try - * again, after mkdir(). - */ - dirname = g_path_get_dirname (filename); - g_mkdir_with_parents (dirname, 0700); - g_free (dirname); - - g_clear_error (error); - success = gvdb_table_write_contents (gvdb, filename, FALSE, error); - } - - g_hash_table_unref (gvdb); - - return success; -} diff --git a/service/dconf-gvdb-utils.h b/service/dconf-gvdb-utils.h deleted file mode 100644 index 7076781..0000000 --- a/service/dconf-gvdb-utils.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright © 2010 Codethink Limited - * Copyright © 2012 Canonical Limited - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the licence, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - * - * Author: Ryan Lortie - */ - -#ifndef __dconf_gvdb_utils_h__ -#define __dconf_gvdb_utils_h__ - -#include "../common/dconf-changeset.h" - -DConfChangeset * dconf_gvdb_utils_read_and_back_up_file (const gchar *filename, - gboolean *file_missing, - GError **error); -gboolean dconf_gvdb_utils_write_file (const gchar *filename, - DConfChangeset *database, - GError **error); - -#endif /* __dconf_gvdb_utils_h__ */ diff --git a/service/dconf-writer.c b/service/dconf-writer.c index 4d054c8..438c77b 100644 --- a/service/dconf-writer.c +++ b/service/dconf-writer.c @@ -23,7 +23,7 @@ #include "dconf-writer.h" #include "../shm/dconf-shm.h" -#include "dconf-gvdb-utils.h" +#include "../common/dconf-gvdb-utils.h" #include "dconf-generated.h" #include "dconf-blame.h" diff --git a/service/meson.build b/service/meson.build index 19fe670..51e3090 100644 --- a/service/meson.build +++ b/service/meson.build @@ -12,7 +12,6 @@ configure_file( lib_sources = [ 'dconf-blame.c', - 'dconf-gvdb-utils.c', 'dconf-keyfile-writer.c', 'dconf-service.c', 'dconf-shm-writer.c', @@ -36,7 +35,7 @@ libdconf_service = static_library( sources: lib_sources, include_directories: top_inc, c_args: dconf_c_args, - dependencies: gio_unix_dep, + dependencies: [gio_unix_dep, libdconf_common_dep], link_with: [ libdconf_common, libdconf_shm, @@ -46,7 +45,7 @@ libdconf_service = static_library( libdconf_service_dep = declare_dependency( link_with: libdconf_service, - dependencies: gio_unix_dep, + dependencies: [gio_unix_dep, libdconf_common_dep], sources: dconf_generated, ) @@ -55,7 +54,7 @@ dconf_service = executable( sources, include_directories: top_inc, c_args: dconf_c_args, - dependencies: gio_unix_dep, + dependencies: [gio_unix_dep, libdconf_common_dep], link_with: libdconf_service, install: true, install_dir: dconf_libexecdir, -- cgit v1.2.1