diff options
author | Ryan Lortie <desrt@desrt.ca> | 2012-10-23 10:14:43 +0200 |
---|---|---|
committer | Ryan Lortie <desrt@desrt.ca> | 2013-01-03 09:02:58 -0500 |
commit | 81521e8c1fef4911901278bff90746d2b3cc6ebf (patch) | |
tree | b6ca49e74eab56472d6ab06e134730907cec5288 /service | |
parent | a2bad17d26b596ef46fd2e9c60b9e0163a51012d (diff) | |
download | dconf-wip/nfs-client.tar.gz |
wip: NFS on the library sidewip/nfs-client
Diffstat (limited to 'service')
-rw-r--r-- | service/dconf-nfs-writer.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/service/dconf-nfs-writer.c b/service/dconf-nfs-writer.c new file mode 100644 index 0000000..69675ef --- /dev/null +++ b/service/dconf-nfs-writer.c @@ -0,0 +1,182 @@ +/* + * Copyright © 2010 Codethink 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ryan Lortie <desrt@desrt.ca> + */ + +#include "dconf-writer.h" + +#include "../gvdb/gvdb-reader.h" + +#include <sys/fcntl.h> +#include <errno.h> + +typedef DConfWriterClass DConfNfsWriterClass; + +typedef struct +{ + DConfWriter parent_instance; + + gchar *lockfile; + gchar *filename; + gint lock_fd; +} DConfNfsWriter; + +G_DEFINE_TYPE (DConfNfsWriter, dconf_nfs_writer, DCONF_TYPE_WRITER) + +static void +dconf_nfs_writer_constructed (GObject *object) +{ + DConfNfsWriter *nfs = (DConfNfsWriter *) object; + DConfWriter *writer = DCONF_WRITER (object); + + G_OBJECT_CLASS (dconf_nfs_writer_parent_class)->constructed (object); + + nfs->filename = g_build_filename (g_get_user_config_dir (), "dconf", writer->name, NULL); +} + +static DConfChangeset * +dconf_nfs_writer_diff (DConfNfsWriter *nfs, + GHashTable *old, + GError **error) +{ + DConfChangeset *changeset; + GvdbTable *new; + GBytes *bytes; + + { + gchar *contents; + gsize size; + + if (!g_file_get_contents (nfs->filename, &contents, &size, error)) + return NULL; + + bytes = g_bytes_new_take (contents, size); + } + + new = gvdb_table_new (bytes, FALSE, error); + + g_bytes_unref (bytes); + + if (new == NULL) + return NULL; +} + +static gboolean +dconf_nfs_writer_begin (DConfWriter *writer, + GError **error) +{ + DConfNfsWriter *nfs = (DConfNfsWriter *) writer; + DConfChangeset *changeset; + struct flock lock; + gint fd; + + nfs->lock_fd = open (nfs->lockfile, O_CREAT | O_WRONLY, 0600); + + if (nfs->lock_fd == -1) + { + gint saved_errno = errno; + + g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (saved_errno), + "Cannot open dconf lockfile %s: %s", nfs->lockfile, g_strerror (saved_errno)); + goto out; + } + + lock.l_whence = SEEK_SET; + lock.l_type = F_WRLCK; + lock.l_start = 0; + lock.l_len = 0; + + if (fcntl (nfs->lock_fd, F_SETLKW, &lock) != 0) + { + gint saved_errno = errno; + + g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (saved_errno), + "Unable to lock dconf lockfile %s: %s", nfs->lockfile, g_strerror (saved_errno)); + goto out; + } + + if (!DCONF_WRITER_CLASS (dconf_nfs_writer_parent_class)->begin (writer, error)) + goto out; + + changeset = dconf_nfs_writer_diff (nfs, writer->uncommited_values, error); + if (changeset == NULL) + goto out; + + if (!dconf_changeset_is_empty (changeset)) + dconf_writer_change (writer, changeset, "(updated from nfs home directory)"); + + dconf_changeset_unref (changeset); + + return TRUE; + +out: + if (writer->uncommited_values) + DCONF_WRITER_CLASS (dconf_nfs_writer_parent_class)->end (writer); + + if (nfs->lock_fd != -1) + { + close (nfs->lock_fd); + nfs->lock_fd = -1; + } + + return FALSE; +} + +static gboolean +dconf_nfs_writer_commit (DConfWriter *writer, + GError **error) +{ + return DCONF_WRITER_CLASS (dconf_nfs_writer_parent_class)->commit (writer, error); +} + +static void +dconf_nfs_writer_end (DConfWriter *writer) +{ + DConfNfsWriter *nfs = (DConfNfsWriter *) writer; + + DCONF_WRITER_CLASS (dconf_nfs_writer_parent_class)->end (writer); + + if (nfs->lock_fd != -1) + { + close (nfs->lock_fd); + nfs->lock_fd = -1; + } +} + +static void +dconf_nfs_writer_init (DConfNfsWriter *nfs) +{ + dconf_writer_set_native (DCONF_WRITER (nfs), FALSE); + + nfs->lock_fd = -1; +} + +static void +dconf_nfs_writer_class_init (DConfNfsWriterClass *class) +{ + class->begin = dconf_nfs_writer_begin; + class->commit = dconf_nfs_writer_commit; + class->end = dconf_nfs_writer_end; +} + +DConfWriter * +dconf_nfs_writer_new (const gchar *name) +{ + return g_object_new (dconf_nfs_writer_get_type (), NULL); +} |