[patch] Auto session bus launch from libdbus, take 2
Havoc Pennington
hp at redhat.com
Sat Sep 16 16:06:23 PDT 2006
Hi,
Here is a patch to add a guaranteed machine uuid on any system that has
libdbus installed.
The only large problem with this dbus-uuidgen is that it uses the static
version of libdbus that has the private string, random bytes, etc.
utility functions exported, so the executable is a couple hundred K for
no good reason.
Not committing this yet since I'm not sure how it interacts with 1.0,
plus it could use some review.
Unrelated, I realized that on an embedded system someone could make
dbus-daemon use the shared libdbus by removing the
private-symbol-stripping - that would give 100K or so of disk savings.
Just in case any list lurkers could use that space ;-)
Havoc
-------------- next part --------------
Index: ChangeLog
===================================================================
RCS file: /cvs/dbus/dbus/ChangeLog,v
retrieving revision 1.1127
diff -u -p -r1.1127 ChangeLog
--- ChangeLog 16 Sep 2006 19:24:07 -0000 1.1127
+++ ChangeLog 16 Sep 2006 22:59:46 -0000
@@ -1,5 +1,11 @@
2006-09-16 Havoc Pennington <hp at redhat.com>
+ * tools/dbus-uuidgen.c: add a machine uuid generator command,
+ which can go in postinstall scripts and ensure we have a unique
+ machine id on any system running dbus.
+
+2006-09-16 Havoc Pennington <hp at redhat.com>
+
* dbus/dbus-transport.c (_dbus_transport_open): modify to delegate
to _dbus_transport_open_platform_specific,
_dbus_transport_open_socket,
Index: tools/Makefile.am
===================================================================
RCS file: /cvs/dbus/dbus/tools/Makefile.am,v
retrieving revision 1.20
diff -u -p -r1.20 Makefile.am
--- tools/Makefile.am 8 Aug 2006 21:30:31 -0000 1.20
+++ tools/Makefile.am 16 Sep 2006 22:59:47 -0000
@@ -1,6 +1,6 @@
-INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_X_CFLAGS) -DDBUS_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" -DDBUS_COMPILATION -DDBUS_DAEMONDIR=\"@DBUS_DAEMONDIR@\"
+INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_X_CFLAGS) -DDBUS_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" -DDBUS_COMPILATION -DDBUS_DAEMONDIR=\"@DBUS_DAEMONDIR@\" -DDBUS_CONFIG_DIR=\""$(sysconfdir)/dbus-1"\"
-bin_PROGRAMS=dbus-send dbus-monitor dbus-launch dbus-cleanup-sockets
+bin_PROGRAMS=dbus-send dbus-monitor dbus-launch dbus-cleanup-sockets dbus-uuidgen
dbus_send_SOURCES= \
dbus-print-message.c \
@@ -18,11 +18,15 @@ dbus_launch_SOURCES= \
dbus_cleanup_sockets_SOURCES= \
dbus-cleanup-sockets.c
+dbus_uuidgen_SOURCES= \
+ dbus-uuidgen.c
+
dbus_send_LDADD= $(top_builddir)/dbus/libdbus-1.la
dbus_monitor_LDADD= $(top_builddir)/dbus/libdbus-1.la
+dbus_uuidgen_LDADD= $(top_builddir)/dbus/libdbus-convenience.la
dbus_launch_LDADD= $(DBUS_X_LIBS)
-man_MANS = dbus-send.1 dbus-monitor.1 dbus-launch.1 dbus-cleanup-sockets.1
+man_MANS = dbus-send.1 dbus-monitor.1 dbus-launch.1 dbus-cleanup-sockets.1 dbus-uuidgen.1
EXTRA_DIST = $(man_MANS) run-with-tmp-session-bus.sh
CLEANFILES = \
run-with-tmp-session-bus.conf
Index: tools/dbus-cleanup-sockets.1
===================================================================
RCS file: /cvs/dbus/dbus/tools/dbus-cleanup-sockets.1,v
retrieving revision 1.2
diff -u -p -r1.2 dbus-cleanup-sockets.1
--- tools/dbus-cleanup-sockets.1 3 Aug 2006 20:34:36 -0000 1.2
+++ tools/dbus-cleanup-sockets.1 16 Sep 2006 22:59:47 -0000
@@ -11,8 +11,8 @@ dbus-cleanup-sockets \- clean up leftove
.SH DESCRIPTION
-The \fIdbus-cleanup-sockets\fP command cleans up sockets used for
-D-Bus connections. See http://www.freedesktop.org/software/dbus/ for
+The \fIdbus-cleanup-sockets\fP command cleans up unused D-Bus
+connection sockets. See http://www.freedesktop.org/software/dbus/ for
more information about the big picture.
.PP
@@ -21,6 +21,19 @@ in the standard default socket directory
per-user-login-session message bus; this is usually /tmp.
Optionally, you can pass a different directory on the command line.
+.PP
+On Linux, this program is essentially useless, because D-Bus defaults
+to using "abstract sockets" that exist only in memory and don't have a
+corresponding file in /tmp.
+
+.PP
+On most other flavors of UNIX, it's possible for the socket files to
+leak when programs using D-Bus exit abnormally or without closing
+their D-Bus connections. Thus, it might be interesting to run
+dbus-cleanup-sockets in a cron job to mop up any leaked sockets.
+Or you can just ignore the leaked sockets, they aren't really hurting
+anything, other than cluttering the output of "ls /tmp"
+
.SH AUTHOR
dbus-cleanup-sockets was adapted by Havoc Pennington from
linc-cleanup-sockets written by Michael Meeks.
Index: tools/dbus-uuidgen.1
===================================================================
RCS file: tools/dbus-uuidgen.1
diff -N tools/dbus-uuidgen.1
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tools/dbus-uuidgen.1 16 Sep 2006 22:59:47 -0000
@@ -0,0 +1,62 @@
+.\"
+.\" dbus-uuidgen manual page.
+.\" Copyright (C) 2006 Red Hat, Inc.
+.\"
+.TH dbus-uuidgen 1
+.SH NAME
+dbus-uuidgen \- Utility to generate UUIDs
+.SH SYNOPSIS
+.PP
+.B dbus-uuidgen [\-\-version] [\-\-ensure[=FILENAME]] [\-\-get[=FILENAME]]
+
+.SH DESCRIPTION
+
+The \fIdbus-uuidgen\fP command generates a universally unique ID. It
+is similar to the "uuidgen" command found on many systems already, but
+D-Bus can't rely on that command existing everywhere.
+
+.PP
+See http://www.freedesktop.org/software/dbus/ for more information
+about D-Bus.
+
+.PP
+The primary usage of \fIdbus-uuidgen\fP is to run in the post-install
+script of a D-Bus package with the "--ensure" option. This
+will ensure that /etc/dbus-1/machine-id (or
+a specified file) exists and has the uuid in it.
+It won't overwrite an existing uuid, since this id should remain fixed
+for a single machine.
+
+.PP
+If you run the command with no options it just prints a new uuid.
+
+.PP
+If you run it with --get, it prints the machine uuid by default, or
+the uuid in the specified file if you specify a file.
+
+.SH OPTIONS
+The following options are supported:
+.TP
+.I "--get[=FILENAME]"
+If a filename is not given, defaults to sysconfdir/dbus-1/machine-id
+(sysconfdir is usually /etc). If this file exists and is valid, the
+uuid in the file is printed on stdout. Otherwise, the command exits
+with a nonzero status.
+
+.TP
+.I "--ensure[=FILENAME]"
+If a filename is not given, defaults to sysconfdir/dbus-1/machine-id
+(sysconfdir is usually /etc). If this file exists then it will be
+validated, and a failure code returned if it contains the wrong thing.
+If the file does not exist, it will be created with a new uuid in it.
+
+.TP
+.I "--version"
+Print the version of dbus-uuidgen
+
+.SH AUTHOR
+See http://www.freedesktop.org/software/dbus/doc/AUTHORS
+
+.SH BUGS
+Please send bug reports to the D-Bus mailing list or bug tracker,
+see http://www.freedesktop.org/software/dbus/
Index: tools/dbus-uuidgen.c
===================================================================
RCS file: tools/dbus-uuidgen.c
diff -N tools/dbus-uuidgen.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tools/dbus-uuidgen.c 16 Sep 2006 22:59:47 -0000
@@ -0,0 +1,269 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-uuidgen.c Utility program to create UUIDs
+ *
+ * Copyright (C) 2006 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dbus/dbus-sysdeps.h>
+#include <dbus/dbus-string.h>
+
+static void
+delete_leading_whitespace (DBusString *str)
+{
+ int i;
+
+ _dbus_string_skip_white (str, 0, &i);
+
+ if (i > 0)
+ _dbus_string_delete (str, 0, i);
+}
+
+static void
+usage (char *name, int ecode)
+{
+ if (name == NULL)
+ name = "dbus-uuidgen";
+
+ fprintf (stderr, "Usage: %s [--ensure[=FILENAME]] [--get[=FILENAME]]\n", name);
+ exit (ecode);
+}
+
+static void
+version (void)
+{
+ printf ("D-Bus UUID Generator %s\n"
+ "Copyright (C) 2006 Red Hat, Inc.\n"
+ "This is free software; see the source for copying conditions.\n"
+ "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
+ VERSION);
+ exit (0);
+}
+
+/* should not modify str if it returns false */
+static dbus_bool_t
+get_arg(const char *arg,
+ const char *option,
+ DBusString *str)
+{
+ const char *fn;
+
+ if (strlen(arg) < strlen(option))
+ return FALSE;
+
+ fn = arg + strlen(option);
+
+ if (!(*fn == '=' || *fn == ' ' || *fn == '\0'))
+ {
+ usage (NULL, 1);
+ }
+
+ if (*fn == '=')
+ ++fn;
+
+ while (*fn == ' ' && *fn != '\0')
+ ++fn;
+
+ if (*fn != '\0')
+ {
+ _dbus_string_init_const (str, fn);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int i;
+ DBusString filename;
+ DBusString contents;
+ dbus_bool_t ensure_uuid;
+ dbus_bool_t get_uuid;
+
+ ensure_uuid = FALSE;
+ get_uuid = FALSE;
+
+ _dbus_string_init_const (&filename, DBUS_CONFIG_DIR "/machine-id");
+
+ for (i = 1; i < argc; i++)
+ {
+ char *arg = argv[i];
+
+ if (strncmp (arg, "--ensure", strlen("--ensure")) == 0)
+ {
+ get_arg (arg, "--ensure", &filename);
+ ensure_uuid = TRUE;
+ }
+ else if (strncmp (arg, "--get", strlen("--get")) == 0)
+ {
+ get_arg (arg, "--get", &filename);
+ get_uuid = TRUE;
+ }
+ else if (strcmp (arg, "--help") == 0)
+ usage (argv[0], 0);
+ else if (strcmp (arg, "--version") == 0)
+ version ();
+ else
+ usage (argv[0], 1);
+ }
+
+ if (get_uuid && ensure_uuid)
+ {
+ fprintf (stderr, "Can't specify both --get-for-machine and --ensure-for-machine\n");
+ exit (1);
+ }
+
+ /* Don't cut-and-paste this string code as an example, none of it
+ * checks for out of memory or frees anything.
+ */
+
+ _dbus_string_init (&contents);
+ if ((get_uuid || ensure_uuid) && _dbus_file_get_contents (&contents, &filename, NULL))
+ {
+
+ /* If the file exists and is valid we exit successfully;
+ * if it exists but contains junk, we don't overwrite
+ * it (don't want to lose data) but we also exit with
+ * a failure code.
+ */
+
+ DBusString decoded;
+ int end;
+
+ delete_leading_whitespace (&contents);
+ _dbus_string_init (&decoded);
+
+ /* this function will allow the last hex pair to be just one
+ * character instead of 2, so it isn't 100% as strict as
+ * it should be for this.
+ */
+ _dbus_string_hex_decode (&contents, 0, &end, &decoded, 0);
+
+ if (end == 0)
+ {
+ fprintf (stderr, "File '%s' contains something other than a valid hex-encoded uuid\n",
+ _dbus_string_get_const_data (&filename));
+ exit (1);
+ }
+
+ _dbus_string_delete (&contents, 0, end);
+ delete_leading_whitespace (&contents);
+
+ if (_dbus_string_get_length (&contents) > 0)
+ {
+ fprintf (stderr, "File '%s' contains trailing stuff that is not a valid hex-encoded uuid: '%s'\n",
+ _dbus_string_get_const_data (&filename),
+ _dbus_string_get_const_data (&contents));
+ exit (1);
+ }
+
+ if (_dbus_string_get_length (&decoded) != 16)
+ {
+ fprintf (stderr, "File '%s' contains %d hex-encoded bytes instead of 16\n",
+ _dbus_string_get_const_data (&filename),
+ _dbus_string_get_length (&decoded));
+ exit (1);
+ }
+
+ if (get_uuid)
+ {
+ DBusString encoded;
+ _dbus_string_init (&encoded);
+ _dbus_string_hex_encode (&decoded, 0, &encoded, 0);
+
+ printf ("%s\n", _dbus_string_get_const_data (&encoded));
+ }
+
+ /* don't bother to free all the strings */
+
+ exit (0);
+ }
+ else if (get_uuid)
+ {
+ fprintf (stderr, "No valid uuid in file '%s'\n",
+ _dbus_string_get_const_data (&filename));
+ exit (1);
+ }
+ else
+ {
+ DBusString bytes;
+ DBusString encoded;
+ DBusError error;
+ long tv_sec;
+ union {
+ dbus_uint32_t number;
+ unsigned char bytes[4];
+ } val32;
+
+ _dbus_string_init (&bytes);
+ _dbus_get_current_time (&tv_sec, NULL);
+ val32.number = tv_sec;
+
+ _dbus_string_append_4_aligned (&bytes, val32.bytes);
+
+ if (!_dbus_generate_random_bytes (&bytes, 12))
+ {
+ fprintf (stderr, "Failed to generate random bytes for uuid");
+ exit (1);
+ }
+
+ _dbus_string_init (&encoded);
+
+ _dbus_string_hex_encode (&bytes, 0, &encoded, 0);
+
+ if (ensure_uuid)
+ {
+ /* FIXME this is racy; we need a save_file_exclusively
+ * function. But in practice this should be fine.
+ *
+ * - first be sure we can create the file and it
+ * doesn't exist by creating it empty with O_EXCL
+ * - then create it by creating a temporary file and
+ * overwriting atomically with rename()
+ */
+ dbus_error_init (&error);
+ if (!_dbus_create_file_exclusively (&filename, &error))
+ {
+ fprintf (stderr, "Could not create uuid file '%s': %s\n",
+ _dbus_string_get_const_data (&filename),
+ error.message);
+ exit (1);
+ }
+
+ if (!_dbus_string_save_to_file (&encoded, &filename, &error))
+ {
+ fprintf (stderr, "Failed to save new uuid to '%s': %s\n",
+ _dbus_string_get_const_data (&filename),
+ error.message);
+ exit (1);
+ }
+ }
+ else
+ {
+ printf ("%s\n",
+ _dbus_string_get_const_data (&encoded));
+ }
+
+ exit (0);
+ }
+}
More information about the dbus
mailing list