diff options
author | Philip Withnall <philip@tecnocode.co.uk> | 2018-08-21 15:41:51 +0000 |
---|---|---|
committer | Philip Withnall <philip@tecnocode.co.uk> | 2018-08-21 15:41:51 +0000 |
commit | a060755f30e5c89882b160e7f284eee003a960ec (patch) | |
tree | 1765b9bdae5258808f30b421b3c95b9b15e69eef /service | |
parent | e960b50696b95f4b035787e9cbceaa549c172c91 (diff) | |
parent | 8d76d4881f14af8a78029a89b43ce99cc558a65f (diff) | |
download | dconf-a060755f30e5c89882b160e7f284eee003a960ec.tar.gz |
Merge branch '1454-gvdb-corruption' into 'master'
service: Allow opening corrupt GVDB files when writing
See merge request GNOME/dconf!8
Diffstat (limited to 'service')
-rw-r--r-- | service/dconf-gvdb-utils.c | 40 | ||||
-rw-r--r-- | service/dconf-gvdb-utils.h | 2 | ||||
-rw-r--r-- | service/dconf-writer.c | 2 | ||||
-rw-r--r-- | service/dconf-writer.h | 3 | ||||
-rw-r--r-- | service/meson.build | 28 |
5 files changed, 60 insertions, 15 deletions
diff --git a/service/dconf-gvdb-utils.c b/service/dconf-gvdb-utils.c index 099a9f3..93a4719 100644 --- a/service/dconf-gvdb-utils.c +++ b/service/dconf-gvdb-utils.c @@ -26,12 +26,15 @@ #include "../gvdb/gvdb-builder.h" #include "../gvdb/gvdb-reader.h" +#include <errno.h> +#include <glib.h> +#include <glib/gstdio.h> #include <string.h> DConfChangeset * -dconf_gvdb_utils_read_file (const gchar *filename, - gboolean *file_missing, - GError **error) +dconf_gvdb_utils_read_and_back_up_file (const gchar *filename, + gboolean *file_missing, + GError **error) { DConfChangeset *database; GError *my_error = NULL; @@ -57,7 +60,36 @@ dconf_gvdb_utils_read_file (const gchar *filename, /* Otherwise, we should report errors to prevent ourselves from * overwriting the database in other situations... */ - if (my_error) + 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; diff --git a/service/dconf-gvdb-utils.h b/service/dconf-gvdb-utils.h index 5b3e3a9..7076781 100644 --- a/service/dconf-gvdb-utils.h +++ b/service/dconf-gvdb-utils.h @@ -23,7 +23,7 @@ #include "../common/dconf-changeset.h" -DConfChangeset * dconf_gvdb_utils_read_file (const gchar *filename, +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, diff --git a/service/dconf-writer.c b/service/dconf-writer.c index 00d34fe..5fb3467 100644 --- a/service/dconf-writer.c +++ b/service/dconf-writer.c @@ -107,7 +107,7 @@ dconf_writer_real_begin (DConfWriter *writer, { gboolean missing; - writer->priv->commited_values = dconf_gvdb_utils_read_file (writer->priv->filename, &missing, error); + writer->priv->commited_values = dconf_gvdb_utils_read_and_back_up_file (writer->priv->filename, &missing, error); if (!writer->priv->commited_values) return FALSE; diff --git a/service/dconf-writer.h b/service/dconf-writer.h index a41f115..17360c9 100644 --- a/service/dconf-writer.h +++ b/service/dconf-writer.h @@ -20,7 +20,9 @@ #ifndef __dconf_writer_h__ #define __dconf_writer_h__ +#include <glib.h> #include <gio/gio.h> +#include <gobject/gobject.h> #include "../common/dconf-changeset.h" #include "dconf-generated.h" @@ -65,6 +67,7 @@ struct _DConfWriter DConfWriterPrivate *priv; }; +G_DEFINE_AUTOPTR_CLEANUP_FUNC (DConfWriter, g_object_unref) GType dconf_writer_get_type (void); diff --git a/service/meson.build b/service/meson.build index 618cbd5..35ee23a 100644 --- a/service/meson.build +++ b/service/meson.build @@ -11,35 +11,45 @@ configure_file( install_dir: dbus_session_service_dir, ) -sources = [ +lib_sources = [ 'dconf-blame.c', 'dconf-gvdb-utils.c', 'dconf-keyfile-writer.c', 'dconf-service.c', 'dconf-shm-writer.c', 'dconf-writer.c', +] +sources = [ 'main.c', ] -sources += gnome.gdbus_codegen( +lib_sources += gnome.gdbus_codegen( 'dconf-generated', dconf_namespace + '.xml', interface_prefix: dconf_namespace + '.', namespace: 'DConfDBus', ) -service_deps = [ - gio_unix_dep, - libdconf_common_dep, - libdconf_shm_dep, - libgvdb_dep, -] +libdconf_service = static_library( + 'dconf-service', + sources: lib_sources, + include_directories: top_inc, + c_args: dconf_c_args, + dependencies: gio_unix_dep, + link_with: [ + libdconf_common, + libdconf_shm, + libgvdb, + ], +) executable( 'dconf-service', sources, include_directories: top_inc, - dependencies: service_deps, + c_args: dconf_c_args, + dependencies: gio_unix_dep, + link_with: libdconf_service, install: true, install_dir: dconf_libexecdir, ) |