summaryrefslogtreecommitdiff
path: root/shm
diff options
context:
space:
mode:
authorRyan Lortie <desrt@desrt.ca>2012-07-08 14:41:33 -0400
committerRyan Lortie <desrt@desrt.ca>2012-07-08 14:52:03 -0400
commitdd9c1a0cad35082724bba59235af031246c06ce5 (patch)
treed87fae1e6ce41e19ca1b8506424c1801faf8cc7a /shm
parent4228ef3194fff11dcdcdce0b61aa0474fffb066d (diff)
downloaddconf-dd9c1a0cad35082724bba59235af031246c06ce5.tar.gz
clean up and factor out the 'shm' code
Remove the shm code from the engine and the service and put it in a separate convenience library in shm/. Remove the vestigial shmdir weirdness from the service (since shmdir is now always relative to XDG_RUNTIME_DIR and has been for some time). The purpose of this is so that dconf-engine can be properly unit-tested. dconf-engine now has five points of contact with the world (excluding the users of the engine themselves): - the DCONF_PROFILE environment variable - fopen() of profile files - shm - gvdb - dbus The environment variable is quite easily controlled. fopen() is intercepted in the engine testcase with a interpose of the libc symbol. With this commit now each of dbus, gvdb and shm are implemented in separate utility modules that can be mocked from the testcases.
Diffstat (limited to 'shm')
-rw-r--r--shm/.gitignore2
-rw-r--r--shm/Makefile.am12
-rw-r--r--shm/dconf-shm.c138
-rw-r--r--shm/dconf-shm.h34
4 files changed, 186 insertions, 0 deletions
diff --git a/shm/.gitignore b/shm/.gitignore
new file mode 100644
index 0000000..16d8712
--- /dev/null
+++ b/shm/.gitignore
@@ -0,0 +1,2 @@
+libdconf-shm.a
+libdconf-shm-shared.a
diff --git a/shm/Makefile.am b/shm/Makefile.am
new file mode 100644
index 0000000..b3068cb
--- /dev/null
+++ b/shm/Makefile.am
@@ -0,0 +1,12 @@
+include $(top_srcdir)/Makefile.gtester
+
+noinst_LIBRARIES = libdconf-shm.a libdconf-shm-shared.a
+libdconf_shm_a_CFLAGS = -Wall
+INCLUDES = $(glib_CFLAGS)
+
+libdconf_shm_a_SOURCES = \
+ dconf-shm.h \
+ dconf-shm.c
+
+libdconf_shm_shared_a_CFLAGS = -fPIC -DPIC $(libdconf_shm_a_CFLAGS)
+libdconf_shm_shared_a_SOURCES = $(libdconf_shm_a_SOURCES)
diff --git a/shm/dconf-shm.c b/shm/dconf-shm.c
new file mode 100644
index 0000000..62439a0
--- /dev/null
+++ b/shm/dconf-shm.c
@@ -0,0 +1,138 @@
+/*
+ * 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, 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-shm.h"
+
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+static gchar *
+dconf_shm_get_shmdir (void)
+{
+ static gchar *shmdir;
+
+ if (g_once_init_enter (&shmdir))
+ g_once_init_leave (&shmdir, g_build_filename (g_get_user_runtime_dir (), "dconf", NULL));
+
+ return shmdir;
+}
+
+void
+dconf_shm_close (guint8 *shm)
+{
+ if (shm)
+ munmap (shm, 1);
+}
+
+guint8 *
+dconf_shm_open (const gchar *name)
+{
+ const gchar *shmdir;
+ gchar *filename;
+ void *memory;
+ gint fd;
+
+ shmdir = dconf_shm_get_shmdir ();
+ filename = g_build_filename (shmdir, name, NULL);
+ memory = NULL;
+ fd = -1;
+
+ if (g_mkdir_with_parents (shmdir, 0700) != 0)
+ {
+ g_critical ("unable to create directory '%s': %s. dconf will not work properly.", shmdir, g_strerror (errno));
+ goto out;
+ }
+
+ fd = open (filename, O_RDWR | O_CREAT, 0600);
+ if (fd == -1)
+ {
+ g_critical ("unable to create file '%s': %s. dconf will not work properly.", filename, g_strerror (errno));
+ goto out;
+ }
+
+ if (ftruncate (fd, 1) != 0)
+ {
+ g_critical ("failed to allocate file '%s': %s. dconf will not work properly.", filename, g_strerror (errno));
+ goto out;
+ }
+
+ memory = mmap (NULL, 1, PROT_READ, MAP_SHARED, fd, 0);
+ g_assert (memory != NULL);
+
+ if (memory == MAP_FAILED)
+ {
+ g_critical ("failed to mmap file '%s': %s. dconf will not work properly.", filename, g_strerror (errno));
+ memory = NULL;
+ goto out;
+ }
+
+ out:
+ g_free (filename);
+ close (fd);
+
+ return memory;
+}
+
+void
+dconf_shm_flag (const gchar *name)
+{
+ const gchar *shmdir;
+ gchar *filename;
+ gint fd;
+
+ shmdir = dconf_shm_get_shmdir ();
+ filename = g_build_filename (shmdir, name, NULL);
+
+ fd = open (filename, O_WRONLY);
+ if (fd >= 0)
+ {
+ guint8 *shm;
+
+ /* Easiest thing to do here would be write(fd, "\1", 1); but this
+ * causes problems on kernels (ie: OpenBSD) that don't sync up
+ * their filesystem cache with mmap()ed regions.
+ *
+ * Using mmap() works everywhere.
+ */
+ shm = mmap (NULL, 1, PROT_WRITE, MAP_SHARED, fd, 0);
+
+ if (shm != MAP_FAILED)
+ {
+ *shm = 1;
+
+ munmap (shm, 1);
+ }
+ else
+ g_warning ("failed to invalidate mmap file '%s': %s.", filename, g_strerror (errno));
+
+ close (fd);
+
+ unlink (filename);
+ }
+
+ else if (errno != ENOENT)
+ unlink (filename);
+
+ g_free (filename);
+}
diff --git a/shm/dconf-shm.h b/shm/dconf-shm.h
new file mode 100644
index 0000000..407375a
--- /dev/null
+++ b/shm/dconf-shm.h
@@ -0,0 +1,34 @@
+/*
+ * 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>
+ */
+
+#ifndef __dconf_shm_h__
+#define __dconf_shm_h__
+
+#include <glib.h>
+
+G_GNUC_INTERNAL
+guint8 * dconf_shm_open (const gchar *name);
+G_GNUC_INTERNAL
+void dconf_shm_close (guint8 *shm);
+G_GNUC_INTERNAL
+void dconf_shm_flag (const gchar *name);
+
+#endif /* __dconf_shm_h__ */