[dconf] add 'dconf-update' utility
- From: Ryan Lortie <ryanl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dconf] add 'dconf-update' utility
- Date: Sun, 18 Jul 2010 23:40:56 +0000 (UTC)
commit 46bed217bae3ffb796d9acde4c830ee3bc587852
Author: Ryan Lortie <desrt desrt ca>
Date: Sun Jul 18 19:37:48 2010 -0400
add 'dconf-update' utility
This utility scans /etc/dconf/db/ looking for directories named *.d.
For each directory name.d that it finds, it reads each file contained
within as a keyfile containing a list of keys to populate a dconf
database with.
That database is then written to 'name' (ie: the directory name with the
'.d' removed), the old file is invalidated, and a signal is sent over
the system DBus to indicate the change.
This tool facilitates updating of dconf databases by sysadmins who
prefer to follow the 'drop a text file here' approach to system
management.
bin/.gitignore | 3 +
bin/Makefile.am | 8 ++-
bin/dconf-update.vala | 143 +++++++++++++++++++++++++++++++++++++++++++++++++
bin/fixes.vapi | 4 ++
bin/gvdb.vapi | 21 +++++++
5 files changed, 177 insertions(+), 2 deletions(-)
---
diff --git a/bin/.gitignore b/bin/.gitignore
index 042fec5..08c4537 100644
--- a/bin/.gitignore
+++ b/bin/.gitignore
@@ -1 +1,4 @@
dconf
+dconf-update
+dconf-update.c
+*.stamp
diff --git a/bin/Makefile.am b/bin/Makefile.am
index d771ce4..5544f82 100644
--- a/bin/Makefile.am
+++ b/bin/Makefile.am
@@ -1,6 +1,10 @@
AM_CFLAGS = -std=c89 -Wall -Wmissing-prototypes -Wwrite-strings
-INCLUDES = -I$(top_srcdir)/common -I$(top_srcdir)/engine -I$(top_srcdir)/client $(gio_CFLAGS)
+INCLUDES = -I$(top_srcdir)/common -I$(top_srcdir)/engine -I$(top_srcdir)/client -I$(top_srcdir)/gvdb $(gio_CFLAGS)
-bin_PROGRAMS = dconf
+bin_PROGRAMS = dconf dconf-update
dconf_LDADD = ../client/libdconf.la $(gio_LIBS)
+
+dconf_update_VALAFLAGS = --pkg=posix --pkg=gio-2.0
+dconf_update_LDADD = $(gio_LIBS)
+dconf_update_SOURCES = dconf-update.vala ../gvdb/gvdb-builder.c gvdb.vapi fixes.vapi
diff --git a/bin/dconf-update.vala b/bin/dconf-update.vala
new file mode 100644
index 0000000..9a81140
--- /dev/null
+++ b/bin/dconf-update.vala
@@ -0,0 +1,143 @@
+unowned Gvdb.Item get_parent (Gvdb.HashTable table, string name) {
+ unowned Gvdb.Item parent;
+
+ int end = 0;
+
+ for (int i = 0; name[i] != '\0'; i++) {
+ if (name[i - 1] == '/') {
+ end = i;
+ }
+ }
+
+ var parent_name = name.ndup (end);
+ parent = table.lookup (parent_name);
+
+ if (parent == null) {
+ parent = table.insert (parent_name);
+ parent.set_parent (get_parent (table, parent_name));
+ }
+
+ return parent;
+}
+
+Gvdb.HashTable read_directory (string dirname) throws GLib.Error {
+ var table = new Gvdb.HashTable ();
+ unowned string? name;
+
+ table.insert ("/");
+
+ var dir = Dir.open (dirname);
+ while ((name = dir.read_name ()) != null) {
+ var filename = Path.build_filename (dirname, name);
+
+ var kf = new KeyFile ();
+
+ try {
+ kf.load_from_file (filename, KeyFileFlags.NONE);
+ } catch (GLib.Error e) {
+ stderr.printf ("%s: %s\n", filename, e.message);
+ continue;
+ }
+
+ foreach (var group in kf.get_groups ()) {
+ if (group.has_prefix ("/") || group.has_suffix ("/") || group.str ("//") != null) {
+ stderr.printf ("%s: ignoring invalid group name: %s\n", filename, group);
+ continue;
+ }
+
+ foreach (var key in kf.get_keys (group)) {
+ if (key.str ("/") != null) {
+ stderr.printf ("%s: [%s]: ignoring invalid key name: %s\n", filename, group, key);
+ continue;
+ }
+
+ var path = "/" + group + "/" + key;
+
+ if (table.lookup (path) != null) {
+ stderr.printf ("%s: [%s]: %s: ignoring duplicate definition of key %s\n",
+ filename, group, key, path);
+ continue;
+ }
+
+ var text = kf.get_value (group, key);
+
+ try {
+ var value = Variant.parse (null, text);
+ unowned Gvdb.Item item = table.insert (path);
+ item.set_parent (get_parent (table, path));
+ item.set_value (value);
+ } catch (VariantParseError e) {
+ stderr.printf ("%s: [%s]: %s: skipping invalid value: %s (%s)\n",
+ filename, group, key, text, e.message);
+ }
+ }
+ }
+ }
+
+ return table;
+}
+
+void maybe_update_from_directory (string dirname) throws GLib.Error {
+ Posix.Stat dir_buf;
+
+ if (Posix.stat (dirname, out dir_buf) == 0 && Posix.S_ISDIR (dir_buf.st_mode)) {
+ Posix.Stat file_buf;
+
+ var filename = dirname.ndup (dirname.length - 2);
+
+ if (Posix.stat (filename, out file_buf) == 0 && file_buf.st_mtime > dir_buf.st_mtime) {
+ return;
+ }
+
+ var table = read_directory (dirname);
+
+ var fd = Posix.open (filename, Posix.O_WRONLY);
+
+ if (fd < 0 && errno != Posix.EEXIST) {
+ var saved_error = errno;
+ throw new FileError.FAILED ("Can not open '%s' for replacement: %s", filename, strerror (saved_error));
+ }
+
+ table.write_contents (filename);
+
+ if (fd >= 0) {
+ Posix.write (fd, "\0\0\0\0\0\0\0\0", 8);
+ Posix.close (fd);
+ }
+
+ try {
+ var system_bus = Bus.get_sync (BusType.SYSTEM);
+ system_bus.emit_signal (null, "/" + Path.get_basename (filename), "ca.desrt.dconf.Writer", "Notify",
+ new Variant ("(tsas)", (uint64) 0, "/", new VariantBuilder (STRING_ARRAY)));
+ flush_the_bus (system_bus);
+ } catch {
+ /* if we can't, ... don't. */
+ }
+ }
+}
+
+void update_all (string dirname) throws GLib.Error {
+ unowned string? name;
+
+ var dir = Dir.open (dirname);
+
+ while ((name = dir.read_name ()) != null) {
+ if (name.has_suffix (".d")) {
+ try {
+ maybe_update_from_directory (Path.build_filename (dirname, name));
+ } catch (GLib.Error e) {
+ stderr.printf ("%s\n", e.message);
+ }
+ }
+ }
+}
+
+void main () {
+ try {
+ update_all ("/etc/dconf/db");
+ } catch (GLib.Error e) {
+ stderr.printf ("fatal: %s\n", e.message);
+ }
+}
+
+// vim:noet ts=4 sw=4
diff --git a/bin/fixes.vapi b/bin/fixes.vapi
new file mode 100644
index 0000000..ada6ab6
--- /dev/null
+++ b/bin/fixes.vapi
@@ -0,0 +1,4 @@
+[CCode (cname = "g_dbus_connection_flush_sync")]
+void flush_the_bus (GLib.DBusConnection connection, GLib.Cancellable? cancellable = null) throws GLib.Error;
+[CCode (cname = "G_VARIANT_TYPE_STRING_ARRAY")]
+public static GLib.VariantType STRING_ARRAY;
diff --git a/bin/gvdb.vapi b/bin/gvdb.vapi
new file mode 100644
index 0000000..1848c1d
--- /dev/null
+++ b/bin/gvdb.vapi
@@ -0,0 +1,21 @@
+[CCode (cheader_filename = "gvdb-builder.h")]
+namespace Gvdb {
+ [Compact]
+ [CCode (cname = "GHashTable")]
+ class HashTable : GLib.HashTable<string, Item> {
+ public HashTable (HashTable? parent = null, string? key = null);
+ public unowned Item insert (string key);
+ public void insert_string (string key, string value);
+ [CCode (cname = "gvdb_table_write_contents")]
+ public void write_contents (string filename, bool byteswap = false) throws GLib.Error;
+ }
+
+ [Compact]
+ class Item {
+ public void set_value (GLib.Variant value);
+ public void set_hash_table (HashTable table);
+ public void set_parent (Item parent);
+ }
+}
+
+// vim:noet ts=4 sw=4
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]