summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog61
-rwxr-xr-xautogen.sh2
-rw-r--r--bus/connection.c2
-rw-r--r--bus/dispatch.c84
-rw-r--r--configure.in4
-rw-r--r--dbus/Makefile.am6
-rw-r--r--dbus/dbus-connection.c169
-rw-r--r--dbus/dbus-connection.h4
-rw-r--r--dbus/dbus-internals.c252
-rw-r--r--dbus/dbus-internals.h33
-rw-r--r--dbus/dbus-protocol.h2
-rw-r--r--dbus/dbus-server-protected.h10
-rw-r--r--dbus/dbus-server.c28
-rw-r--r--dbus/dbus-string-private.h12
-rw-r--r--dbus/dbus-string-util.c37
-rw-r--r--dbus/dbus-string.c92
-rw-r--r--dbus/dbus-string.h4
-rw-r--r--dbus/dbus-sysdeps-unix.c32
-rw-r--r--dbus/dbus-sysdeps.c2
-rw-r--r--dbus/dbus-sysdeps.h7
-rw-r--r--dbus/dbus-threads.c3
-rw-r--r--dbus/dbus-uuidgen.c123
-rw-r--r--dbus/dbus-uuidgen.h47
-rw-r--r--doc/dbus-specification.xml33
-rw-r--r--tools/Makefile.am8
-rw-r--r--tools/dbus-cleanup-sockets.117
-rw-r--r--tools/dbus-launch-x11.c2
-rw-r--r--tools/dbus-launch.c59
-rw-r--r--tools/dbus-uuidgen.191
-rw-r--r--tools/dbus-uuidgen.c161
-rwxr-xr-xtools/run-with-tmp-session-bus.sh8
31 files changed, 1262 insertions, 133 deletions
diff --git a/ChangeLog b/ChangeLog
index 55a88c88..d9bf6aa7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,64 @@
+2006-09-30 Havoc Pennington <hp@redhat.com>
+
+ * configure.in (LT_CURRENT, LT_AGE): increment current and age to
+ reflect addition of interfaces.
+
+ * doc/dbus-specification.xml: describe a new
+ org.freedesktop.DBus.Peer.GetMachineId method
+
+ * dbus/dbus-string.c (_dbus_string_skip_white_reverse): new function
+ (_dbus_string_skip_white, _dbus_string_skip_blank): use new
+ DBUS_IS_ASCII_BLANK, DBUS_IS_ASCII_WHITE macros and fix assertion
+ at end of skip_white
+ (_dbus_string_chop_white): new function
+
+ * bus/connection.c (bus_connections_setup_connection): call
+ dbus_connection_set_route_peer_messages.
+
+ * dbus/dbus-connection.c
+ (_dbus_connection_peer_filter_unlocked_no_update): modify to
+ support a GetMachineId method.
+
+ Also, support a new flag to let the bus pass peer methods through
+ to apps on the bus, which can be set with
+ dbus_connection_set_route_peer_messages.
+
+ Finally, handle and return an error for anything unknown on the
+ Peer interface, which will allow us to extend the Peer interface
+ in the future without fear that we're now intercepting something
+ apps were wanting to see.
+
+ * tools/dbus-uuidgen.c: a thin wrapper around the functions in
+ dbus/dbus-uuidgen.c
+
+ * dbus/dbus-uuidgen.c: implement the bulk of the dbus-uuidgen
+ binary here, since most of the code is already in libdbus
+
+ * dbus/dbus-sysdeps.c (_dbus_read_local_machine_uuid): read the
+ uuid from the system config file
+
+ * dbus/dbus-internals.c (_dbus_generate_uuid, _dbus_uuid_encode)
+ (_dbus_read_uuid_file_without_creating)
+ (_dbus_create_uuid_file_exclusively, _dbus_read_uuid_file): new
+ uuid-related functions, partly factored out from dbus-server.c
+
+ * dbus/dbus-sysdeps.c (_dbus_error_from_errno): convert EEXIST to
+ DBUS_ERROR_FILE_EXISTS instead of EEXIST
+
+ * dbus/dbus-protocol.h (DBUS_ERROR_FILE_EXISTS): add file exists error
+
+ * tools/dbus-cleanup-sockets.1: explain what the point of this
+ thing is a bit more
+
+ * autogen.sh (run_configure): add --config-cache to default
+ configure args
+
+ * dbus/dbus-internals.h (_DBUS_ASSERT_ERROR_IS_SET): disable the
+ error set/clear assertions when DBUS_DISABLE_CHECKS is defined
+
+ * tools/dbus-launch.c (main): if xdisplay hasn't been opened,
+ don't try to save address, fixes crash in make check
+
2006-09-30 Thiago Macieira <thiago@kde.org>
* configure.in: add DBUS_BINDIR as a #define to C source code.
diff --git a/autogen.sh b/autogen.sh
index 6435fd5e..76561338 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -83,7 +83,7 @@ for arg in $*; do
done
if $run_configure; then
- $srcdir/configure --enable-maintainer-mode "$@"
+ $srcdir/configure --enable-maintainer-mode --config-cache "$@"
echo
echo "Now type 'make' to compile $PROJECT."
else
diff --git a/bus/connection.c b/bus/connection.c
index a7f3c1e9..df888f47 100644
--- a/bus/connection.c
+++ b/bus/connection.c
@@ -564,6 +564,8 @@ bus_connections_setup_connection (BusConnections *connections,
return FALSE;
}
+ dbus_connection_set_route_peer_messages (connection, TRUE);
+
retval = FALSE;
dbus_error_init (&error);
diff --git a/bus/dispatch.c b/bus/dispatch.c
index e1dd001f..d8b6ffb4 100644
--- a/bus/dispatch.c
+++ b/bus/dispatch.c
@@ -2941,6 +2941,87 @@ check_existent_ping (BusContext *context,
* but the correct thing may include OOM errors.
*/
static dbus_bool_t
+check_existent_get_machine_id (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ const char *machine_id;
+
+ message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
+ "/org/freedesktop/TestSuite",
+ "org.freedesktop.DBus.Peer",
+ "GetMachineId");
+
+ if (message == NULL)
+ return TRUE;
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ bus_test_run_everything (context);
+
+ /* Note: if this test is run in OOM mode, it will block when the bus
+ * doesn't send a reply due to OOM.
+ */
+ block_connection_until_message_from_bus (context, connection, "reply from running GetMachineId");
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Failed to pop message! Should have been reply from GetMachineId message\n");
+ return FALSE;
+ }
+
+ if (dbus_message_get_reply_serial (message) != serial)
+ {
+ _dbus_warn ("Wrong reply serial\n");
+ dbus_message_unref (message);
+ return FALSE;
+ }
+
+ if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
+ {
+ _dbus_warn ("Unexpected message return during GetMachineId\n");
+ dbus_message_unref (message);
+ return FALSE;
+ }
+
+ machine_id = NULL;
+ if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &machine_id, DBUS_TYPE_INVALID))
+ {
+ _dbus_warn ("Did not get a machine ID in reply to GetMachineId\n");
+ dbus_message_unref (message);
+ return FALSE;
+ }
+
+ if (machine_id == NULL || strlen (machine_id) != 32)
+ {
+ _dbus_warn ("Machine id looks bogus: '%s'\n", machine_id ? machine_id : "null");
+ dbus_message_unref (message);
+ return FALSE;
+ }
+
+ /* We can't check that the machine id is correct because during make check it is
+ * just made up for each process separately
+ */
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ return TRUE;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
check_existent_service_auto_start (BusContext *context,
DBusConnection *connection)
{
@@ -3115,6 +3196,9 @@ check_existent_service_auto_start (BusContext *context,
if (!check_existent_ping (context, connection))
goto out;
+ if (!check_existent_get_machine_id (context, connection))
+ goto out;
+
if (!check_existent_hello_from_self (context, connection))
goto out;
diff --git a/configure.in b/configure.in
index 0c70bb31..bfe50d6b 100644
--- a/configure.in
+++ b/configure.in
@@ -25,7 +25,7 @@ AM_MAINTAINER_MODE
#
## increment if the interface has additions, changes, removals.
-LT_CURRENT=4
+LT_CURRENT=5
## increment any time the source changes; set to
## 0 if you increment CURRENT
@@ -34,7 +34,7 @@ LT_REVISION=0
## increment if any interfaces have been added; set to 0
## if any interfaces have been changed or removed. removal has
## precedence over adding, so set to 0 if both happened.
-LT_AGE=1
+LT_AGE=2
AC_SUBST(LT_CURRENT)
AC_SUBST(LT_REVISION)
diff --git a/dbus/Makefile.am b/dbus/Makefile.am
index 84ee5609..ba326c14 100644
--- a/dbus/Makefile.am
+++ b/dbus/Makefile.am
@@ -1,5 +1,7 @@
-INCLUDES=-I$(top_builddir) -I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) -DDBUS_COMPILATION
+configdir=$(sysconfdir)/dbus-1
+
+INCLUDES=-I$(top_builddir) -I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) -DDBUS_COMPILATION -DDBUS_MACHINE_UUID_FILE=\""$(configdir)/machine-id"\"
dbusincludedir=$(includedir)/dbus-1.0/dbus
dbusarchincludedir=$(libdir)/dbus-1.0/include/dbus
@@ -80,6 +82,8 @@ DBUS_LIB_SOURCES= \
dbus-transport-socket.h \
dbus-transport-unix.c \
dbus-transport-unix.h \
+ dbus-uuidgen.c \
+ dbus-uuidgen.h \
dbus-watch.c \
dbus-watch.h
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index d60816c3..254eb008 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -1,7 +1,7 @@
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-connection.c DBusConnection object
*
- * Copyright (C) 2002, 2003, 2004, 2005 Red Hat Inc.
+ * Copyright (C) 2002-2006 Red Hat Inc.
*
* Licensed under the Academic Free License version 2.1
*
@@ -246,6 +246,8 @@ struct DBusConnection
unsigned int io_path_acquired : 1; /**< Someone has transport io path (can use the transport to read/write messages) */
unsigned int exit_on_disconnect : 1; /**< If #TRUE, exit after handling disconnect signal */
+
+ unsigned int route_peer_messages : 1; /**< If #TRUE, if org.freedesktop.DBus.Peer messages have a bus name, don't handle them automatically */
#ifndef DBUS_DISABLE_CHECKS
unsigned int have_connection_lock : 1; /**< Used to check locking */
@@ -1175,6 +1177,8 @@ _dbus_connection_new_for_transport (DBusTransport *transport)
connection->objects = objects;
connection->exit_on_disconnect = FALSE;
connection->shareable = FALSE;
+ connection->route_peer_messages = FALSE;
+
#ifndef DBUS_DISABLE_CHECKS
connection->generation = _dbus_current_generation;
#endif
@@ -3575,15 +3579,20 @@ dbus_connection_get_dispatch_status (DBusConnection *connection)
}
/**
-* Filter funtion for handling the Peer standard interface
-**/
+ * Filter funtion for handling the Peer standard interface.
+ */
static DBusHandlerResult
_dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
DBusMessage *message)
{
- if (dbus_message_is_method_call (message,
- DBUS_INTERFACE_PEER,
- "Ping"))
+ if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
+ {
+ /* This means we're letting the bus route this message */
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+ else if (dbus_message_is_method_call (message,
+ DBUS_INTERFACE_PEER,
+ "Ping"))
{
DBusMessage *ret;
dbus_bool_t sent;
@@ -3601,9 +3610,68 @@ _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
return DBUS_HANDLER_RESULT_HANDLED;
}
-
-
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ else if (dbus_message_is_method_call (message,
+ DBUS_INTERFACE_PEER,
+ "GetMachineId"))
+ {
+ DBusMessage *ret;
+ dbus_bool_t sent;
+ DBusString uuid;
+
+ ret = dbus_message_new_method_return (message);
+ if (ret == NULL)
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+ sent = FALSE;
+ _dbus_string_init (&uuid);
+ if (_dbus_get_local_machine_uuid_encoded (&uuid))
+ {
+ const char *v_STRING = _dbus_string_get_const_data (&uuid);
+ if (dbus_message_append_args (ret,
+ DBUS_TYPE_STRING, &v_STRING,
+ DBUS_TYPE_INVALID))
+ {
+ sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
+ }
+ }
+ _dbus_string_free (&uuid);
+
+ dbus_message_unref (ret);
+
+ if (!sent)
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
+ {
+ /* We need to bounce anything else with this interface, otherwise apps
+ * could start extending the interface and when we added extensions
+ * here to DBusConnection we'd break those apps.
+ */
+
+ DBusMessage *ret;
+ dbus_bool_t sent;
+
+ ret = dbus_message_new_error (message,
+ DBUS_ERROR_UNKNOWN_METHOD,
+ "Unknown method invoked on org.freedesktop.DBus.Peer interface");
+ if (ret == NULL)
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+ sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
+
+ dbus_message_unref (ret);
+
+ if (!sent)
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ else
+ {
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
}
/**
@@ -4409,6 +4477,35 @@ dbus_connection_set_unix_user_function (DBusConnection *connection,
}
/**
+ *
+ * Normally #DBusConnection automatically handles all messages to the
+ * org.freedesktop.DBus.Peer interface. However, the message bus wants
+ * to be able to route methods on that interface through the bus and
+ * to other applications. If routing peer messages is enabled, then
+ * messages with the org.freedesktop.DBus.Peer interface that also
+ * have a bus destination name set will not be automatically
+ * handled by the #DBusConnection and instead will be dispatched
+ * normally to the application.
+ *
+ *
+ * If a normal application sets this flag, it can break things badly.
+ * So don't set this unless you are the message bus.
+ *
+ * @param connection the connection
+ * @param value #TRUE to pass through org.freedesktop.DBus.Peer messages with a bus name set
+ */
+void
+dbus_connection_set_route_peer_messages (DBusConnection *connection,
+ dbus_bool_t value)
+{
+ _dbus_return_if_fail (connection != NULL);
+
+ CONNECTION_LOCK (connection);
+ connection->route_peer_messages = TRUE;
+ CONNECTION_UNLOCK (connection);
+}
+
+/**
* Adds a message filter. Filters are handlers that are run on all
* incoming messages, prior to the objects registered with
* dbus_connection_register_object_path(). Filters are run in the
@@ -4968,4 +5065,58 @@ dbus_connection_get_outgoing_size (DBusConnection *connection)
return res;
}
+/**
+ * Obtains the machine UUID of the machine this process is running on.
+ *
+ * The returned string must be freed with dbus_free().
+ *
+ * This UUID is guaranteed to remain the same until the next reboot
+ * (unless the sysadmin foolishly changes it and screws themselves).
+ * It will usually remain the same across reboots also, but hardware
+ * configuration changes or rebuilding the machine could break that.
+ *
+ * The idea is that two processes with the same machine ID should be
+ * able to use shared memory, UNIX domain sockets, process IDs, and other
+ * features of the OS that require both processes to be running
+ * on the same OS kernel instance.
+ *
+ * The machine ID can also be used to create unique per-machine
+ * instances. For example, you could use it in bus names or
+ * X selection names.
+ *
+ * The machine ID is preferred over the machine hostname, because
+ * the hostname is frequently set to "localhost.localdomain" and
+ * may also change at runtime.
+ *
+ * You can get the machine ID of a remote application by invoking the
+ * method GetMachineId from interface org.freedesktop.DBus.Peer.
+ *
+ * If the remote application has the same machine ID as the one
+ * returned by this function, then the remote application is on the
+ * same machine as your application.
+ *
+ * @returns a 32-byte-long hex-encoded UUID string, or #NULL if insufficient memory
+ */
+char*
+dbus_get_local_machine_id (void)
+{
+ DBusString uuid;
+ char *s;
+
+ s = NULL;
+ _dbus_string_init (&uuid);
+ if (!_dbus_get_local_machine_uuid_encoded (&uuid) ||
+ !_dbus_string_steal_data (&uuid, &s))
+ {
+ _dbus_string_free (&uuid);
+ return FALSE;
+ }
+ else
+ {
+ _dbus_string_free (&uuid);
+ return s;
+ }
+
+}
+
/** @} */
diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h
index ed90a7f6..1e78c1f3 100644
--- a/dbus/dbus-connection.h
+++ b/dbus/dbus-connection.h
@@ -151,6 +151,8 @@ void dbus_connection_set_unix_user_function (DBusConnection
DBusAllowUnixUserFunction function,
void *data,
DBusFreeFunction free_data_function);
+void dbus_connection_set_route_peer_messages (DBusConnection *connection,
+ dbus_bool_t value);
int dbus_watch_get_fd (DBusWatch *watch);
@@ -258,6 +260,8 @@ dbus_bool_t dbus_connection_get_unix_fd (DBusConnection
dbus_bool_t dbus_connection_get_socket (DBusConnection *connection,
int *fd);
+char* dbus_get_local_machine_id (void);
+
DBUS_END_DECLS
#endif /* DBUS_CONNECTION_H */
diff --git a/dbus/dbus-internals.c b/dbus/dbus-internals.c
index 8567ebb5..707b4005 100644
--- a/dbus/dbus-internals.c
+++ b/dbus/dbus-internals.c
@@ -413,6 +413,258 @@ _dbus_string_array_contains (const char **array,
return FALSE;
}
+/**
+ * Generates a new UUID. If you change how this is done,
+ * there's some text about it in the spec that should also change.
+ *
+ * @param uuid the uuid to initialize
+ */
+void
+_dbus_generate_uuid (DBusGUID *uuid)
+{
+ long now;
+ char *p;
+ int ts_size;
+
+ _dbus_get_current_time (&now, NULL);
+
+ uuid->as_uint32s[0] = now;
+
+ ts_size = sizeof (uuid->as_uint32s[0]);
+ p = ((char*)uuid->as_bytes) + ts_size;
+
+ _dbus_generate_random_bytes_buffer (p,
+ sizeof (uuid->as_bytes) - ts_size);
+}
+
+/**
+ * Hex-encode a UUID.
+ *
+ * @param uuid the uuid
+ * @param encoded string to append hex uuid to
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_uuid_encode (const DBusGUID *uuid,
+ DBusString *encoded)
+{
+ DBusString binary;
+ _dbus_string_init_const_len (&binary, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
+ return _dbus_string_hex_encode (&binary, 0, encoded, _dbus_string_get_length (encoded));
+}
+
+static dbus_bool_t
+_dbus_read_uuid_file_without_creating (const DBusString *filename,
+ DBusGUID *uuid,
+ DBusError *error)
+{
+ DBusString contents;
+ DBusString decoded;
+ int end;
+
+ _dbus_string_init (&contents);
+ _dbus_string_init (&decoded);
+
+ if (!_dbus_file_get_contents (&contents, filename, error))
+ goto error;
+
+ _dbus_string_chop_white (&contents);
+
+ if (_dbus_string_get_length (&contents) != DBUS_UUID_LENGTH_HEX)
+ {
+ dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
+ "UUID file '%s' should contain a hex string of length %d, not length %d, with no other text",
+ _dbus_string_get_const_data (filename),
+ DBUS_UUID_LENGTH_HEX,
+ _dbus_string_get_length (&contents));
+ goto error;
+ }
+
+ if (!_dbus_string_hex_decode (&contents, 0, &end, &decoded, 0))
+ {
+ _DBUS_SET_OOM (error);
+ goto error;
+ }
+
+ if (end == 0)
+ {
+ dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
+ "UUID file '%s' contains invalid hex data",
+ _dbus_string_get_const_data (filename));
+ goto error;
+ }
+
+ if (_dbus_string_get_length (&decoded) != DBUS_UUID_LENGTH_BYTES)
+ {
+ dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
+ "UUID file '%s' contains %d bytes of hex-encoded data instead of %d",
+ _dbus_string_get_const_data (filename),
+ _dbus_string_get_length (&decoded),
+ DBUS_UUID_LENGTH_BYTES);
+ goto error;
+ }
+
+ _dbus_string_copy_to_buffer (&decoded, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
+
+ _dbus_string_free (&decoded);
+ _dbus_string_free (&contents);
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ return TRUE;
+
+ error:
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ _dbus_string_free (&contents);
+ _dbus_string_free (&decoded);
+ return FALSE;
+}
+
+static dbus_bool_t
+_dbus_create_uuid_file_exclusively (const DBusString *filename,
+ DBusGUID *uuid,
+ DBusError *error)
+{
+ DBusString encoded;
+
+ _dbus_string_init (&encoded);
+
+ _dbus_generate_uuid (uuid);
+
+ if (!_dbus_uuid_encode (uuid, &encoded))
+ {
+ _DBUS_SET_OOM (error);
+ goto error;
+ }
+
+ /* FIXME this is racy; we need a save_file_exclusively
+ * function. But in practice this should be fine for now.
+ *
+ * - 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()
+ */
+ if (!_dbus_create_file_exclusively (filename, error))
+ goto error;
+
+ if (!_dbus_string_append_byte (&encoded, '\n'))
+ {
+ _DBUS_SET_OOM (error);
+ goto error;
+ }
+
+ if (!_dbus_string_save_to_file (&encoded, filename, error))
+ goto error;
+
+
+ _dbus_string_free (&encoded);
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+ return TRUE;
+
+ error:
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ _dbus_string_free (&encoded);
+ return FALSE;
+}
+
+/**
+ * Reads (and optionally writes) a uuid to a file. Initializes the uuid
+ * unless an error is returned.
+ *
+ * @param filename the name of the file
+ * @param uuid uuid to be initialized with the loaded uuid
+ * @param create_if_not_found #TRUE to create a new uuid and save it if the file doesn't exist
+ * @param error the error return
+ * @returns #FALSE if the error is set
+ */
+dbus_bool_t
+_dbus_read_uuid_file (const DBusString *filename,
+ DBusGUID *uuid,
+ dbus_bool_t create_if_not_found,
+ DBusError *error)
+{
+ DBusError read_error;
+
+ dbus_error_init (&read_error);
+
+ if (_dbus_read_uuid_file_without_creating (filename, uuid, &read_error))
+ return TRUE;
+
+ if (!create_if_not_found)
+ {
+ dbus_move_error (&read_error, error);
+ return FALSE;
+ }
+
+ /* If the file exists and contains junk, we want to keep that error
+ * message instead of overwriting it with a "file exists" error
+ * message when we try to write
+ */
+ if (dbus_error_has_name (&read_error, DBUS_ERROR_INVALID_FILE_CONTENT))
+ {
+ dbus_move_error (&read_error, error);
+ return FALSE;
+ }
+ else
+ {
+ dbus_error_free (&read_error);
+ return _dbus_create_uuid_file_exclusively (filename, uuid, error);
+ }
+}
+
+_DBUS_DEFINE_GLOBAL_LOCK (machine_uuid);
+static int machine_uuid_initialized_generation = 0;
+static DBusGUID machine_uuid;
+
+/**
+ * Gets the hex-encoded UUID of the machine this function is
+ * executed on. This UUID is guaranteed to be the same for a given
+ * machine at least until it next reboots, though it also
+ * makes some effort to be the same forever, it may change if the
+ * machine is reconfigured or its hardware is modified.
+ *
+ * @param uuid_str string to append hex-encoded machine uuid to
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_get_local_machine_uuid_encoded (DBusString *uuid_str)
+{
+ dbus_bool_t ok;
+
+ _DBUS_LOCK (machine_uuid);
+ if (machine_uuid_initialized_generation != _dbus_current_generation)
+ {
+ DBusError error;
+ dbus_error_init (&error);
+ if (!_dbus_read_local_machine_uuid (&machine_uuid, FALSE,
+ &error))
+ {
+#ifndef DBUS_BUILD_TESTS
+ /* For the test suite, we may not be installed so just continue silently
+ * here. But in a production build, we want to be nice and loud about
+ * this.
+ */
+ _dbus_warn ("D-Bus library appears to be incorrectly set up; failed to read machine uuid: %s\n",
+ error.message);
+ _dbus_warn ("See the manual page for dbus-uuidgen to correct this issue.\n");
+ _dbus_warn ("Continuing with a bogus made-up machine UUID, which may cause problems.");
+#endif
+
+ dbus_error_free (&error);
+
+ _dbus_generate_uuid (&machine_uuid);
+ }
+ }
+
+ ok = _dbus_uuid_encode (&machine_uuid, uuid_str);
+
+ _DBUS_UNLOCK (machine_uuid);
+
+ return ok;
+}
+
#ifdef DBUS_BUILD_TESTS
/**
* Returns a string describing the given name.
diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h
index 520d6dfe..204ac1f9 100644
--- a/dbus/dbus-internals.h
+++ b/dbus/dbus-internals.h
@@ -157,8 +157,16 @@ extern const char _dbus_return_if_fail_warning_format[];
#define _DBUS_STRUCT_OFFSET(struct_type, member) \
((long) ((unsigned char*) &((struct_type*) 0)->member))
+#ifdef DBUS_DISABLE_CHECKS
+/* this is an assert and not an error, but in the typical --disable-checks case (you're trying
+ * to really minimize code size), disabling these assertions makes sense.
+ */
+#define _DBUS_ASSERT_ERROR_IS_SET(error)
+#define _DBUS_ASSERT_ERROR_IS_CLEAR(error)
+#else
#define _DBUS_ASSERT_ERROR_IS_SET(error) _dbus_assert ((error) == NULL || dbus_error_is_set ((error)))
#define _DBUS_ASSERT_ERROR_IS_CLEAR(error) _dbus_assert ((error) == NULL || !dbus_error_is_set ((error)))
+#endif
#define _dbus_return_if_error_is_set(error) _dbus_return_if_fail ((error) == NULL || !dbus_error_is_set ((error)))
#define _dbus_return_val_if_error_is_set(error, val) _dbus_return_val_if_fail ((error) == NULL || !dbus_error_is_set ((error)), (val))
@@ -288,7 +296,8 @@ _DBUS_DECLARE_GLOBAL_LOCK (message_cache);
_DBUS_DECLARE_GLOBAL_LOCK (shared_connections);
_DBUS_DECLARE_GLOBAL_LOCK (win_fds);
_DBUS_DECLARE_GLOBAL_LOCK (sid_atom_cache);
-#define _DBUS_N_GLOBAL_LOCKS (13)
+_DBUS_DECLARE_GLOBAL_LOCK (machine_uuid);
+#define _DBUS_N_GLOBAL_LOCKS (14)
dbus_bool_t _dbus_threads_init_debug (void);
@@ -300,6 +309,28 @@ void _dbus_set_bad_address (DBusError *error,
const char *address_problem_field,
const char *address_problem_other);
+#define DBUS_UUID_LENGTH_BYTES 16
+#define DBUS_UUID_LENGTH_HEX (DBUS_UUID_LENGTH_BYTES * 2)
+
+/**
+ * A globally unique ID ; we have one for each DBusServer, and also one for each
+ * machine with libdbus installed on it.
+ */
+union DBusGUID
+{
+ dbus_uint32_t as_uint32s[DBUS_UUID_LENGTH_BYTES / 4];
+ char as_bytes[DBUS_UUID_LENGTH_BYTES];
+};
+
+void _dbus_generate_uuid (DBusGUID *uuid);
+dbus_bool_t _dbus_uuid_encode (const DBusGUID *uuid,
+ DBusString *encoded);
+dbus_bool_t _dbus_read_uuid_file (const DBusString *filename,
+ DBusGUID *uuid,
+ dbus_bool_t create_if_not_found,
+ DBusError *error);
+
+dbus_bool_t _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str);
DBUS_END_DECLS
diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h
index 3fb5e495..4cfb6d16 100644
--- a/dbus/dbus-protocol.h
+++ b/dbus/dbus-protocol.h
@@ -242,6 +242,7 @@ extern "C" {
#define DBUS_ERROR_DISCONNECTED "org.freedesktop.DBus.Error.Disconnected"
#define DBUS_ERROR_INVALID_ARGS "org.freedesktop.DBus.Error.InvalidArgs"
#define DBUS_ERROR_FILE_NOT_FOUND "org.freedesktop.DBus.Error.FileNotFound"
+#define DBUS_ERROR_FILE_EXISTS "org.freedesktop.DBus.Error.FileExists"
#define DBUS_ERROR_UNKNOWN_METHOD "org.freedesktop.DBus.Error.UnknownMethod"
#define DBUS_ERROR_TIMED_OUT "org.freedesktop.DBus.Error.TimedOut"
#define DBUS_ERROR_MATCH_RULE_NOT_FOUND "org.freedesktop.DBus.Error.MatchRuleNotFound"
@@ -253,6 +254,7 @@ extern "C" {
#define DBUS_ERROR_SPAWN_FAILED "org.freedesktop.DBus.Error.Spawn.Failed"
#define DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN "org.freedesktop.DBus.Error.UnixProcessIdUnknown"
#define DBUS_ERROR_INVALID_SIGNATURE "org.freedesktop.DBus.Error.InvalidSignature"
+#define DBUS_ERROR_INVALID_FILE_CONTENT "org.freedesktop.DBus.Error.InvalidFileContent"
#define DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"
#define DBUS_INTROSPECT_1_0_XML_NAMESPACE "http://www.freedesktop.org/standards/dbus"
diff --git a/dbus/dbus-server-protected.h b/dbus/dbus-server-protected.h
index 6bbcebaf..3846c8c0 100644
--- a/dbus/dbus-server-protected.h
+++ b/dbus/dbus-server-protected.h
@@ -37,16 +37,6 @@
DBUS_BEGIN_DECLS
typedef struct DBusServerVTable DBusServerVTable;
-typedef union DBusGUID DBusGUID;
-
-/**
- * A server's globally unique ID
- */
-union DBusGUID
-{
- dbus_uint32_t as_uint32s[4];
- unsigned char as_bytes[16];
-};
/**
* Virtual table to be implemented by all server "subclasses"
diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c
index 883b361b..3b9ee341 100644
--- a/dbus/dbus-server.c
+++ b/dbus/dbus-server.c
@@ -53,24 +53,6 @@
* @{
*/
-static void
-init_guid (DBusGUID *guid)
-{
- long now;
- char *p;
- int ts_size;
-
- _dbus_get_current_time (&now, NULL);
-
- guid->as_uint32s[0] = now;
-
- ts_size = sizeof (guid->as_uint32s[0]);
- p = ((char*)guid->as_bytes) + ts_size;
-
- _dbus_generate_random_bytes_buffer (p,
- sizeof (guid->as_bytes) - ts_size);
-}
-
/* this is a little fragile since it assumes the address doesn't
* already have a guid, but it shouldn't
*/
@@ -116,8 +98,6 @@ _dbus_server_init_base (DBusServer *server,
const DBusServerVTable *vtable,
const DBusString *address)
{
- DBusString guid_raw;
-
server->vtable = vtable;
server->refcount.value = 1;
@@ -128,13 +108,9 @@ _dbus_server_init_base (DBusServer *server,
if (!_dbus_string_init (&server->guid_hex))
return FALSE;
- init_guid (&server->guid);
+ _dbus_generate_uuid (&server->guid);
- _dbus_string_init_const_len (&guid_raw, (signed char*) server->guid.as_bytes,
- sizeof (server->guid.as_bytes));
- if (!_dbus_string_hex_encode (&guid_raw, 0,
- &server->guid_hex,
- _dbus_string_get_length (&server->guid_hex)))
+ if (!_dbus_uuid_encode (&server->guid, &server->guid_hex))
goto failed;
server->address = copy_address_with_guid_appended (address,
diff --git a/dbus/dbus-string-private.h b/dbus/dbus-string-private.h
index fbdde70a..65f62794 100644
--- a/dbus/dbus-string-private.h
+++ b/dbus/dbus-string-private.h
@@ -107,6 +107,18 @@ typedef struct
#define DBUS_CONST_STRING_PREAMBLE(str) const DBusRealString *real = (DBusRealString*) str; \
DBUS_GENERIC_STRING_PREAMBLE (real)
+/**
+ * Checks for ASCII blank byte
+ * @param c the byte
+ */
+#define DBUS_IS_ASCII_BLANK(c) ((c) == ' ' || (c) == '\t')
+
+/**
+ * Checks for ASCII whitespace byte
+ * @param c the byte
+ */
+#define DBUS_IS_ASCII_WHITE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r')
+
/** @} */
DBUS_END_DECLS
diff --git a/dbus/dbus-string-util.c b/dbus/dbus-string-util.c
index ddb9d750..260ef875 100644
--- a/dbus/dbus-string-util.c
+++ b/dbus/dbus-string-util.c
@@ -111,43 +111,6 @@ _dbus_string_find_byte_backward (const DBusString *str,
return i >= 0;
}
-/**
- * Skips whitespace from start, storing the first non-whitespace in *end.
- * (whitespace is space, tab, newline, CR).
- *
- * @param str the string
- * @param start where to start
- * @param end where to store the first non-whitespace byte index
- */
-void
-_dbus_string_skip_white (const DBusString *str,
- int start,
- int *end)
-{
- int i;
- DBUS_CONST_STRING_PREAMBLE (str);
- _dbus_assert (start <= real->len);
- _dbus_assert (start >= 0);
-
- i = start;
- while (i < real->len)
- {
- if (!(real->str[i] == ' ' ||
- real->str[i] == '\n' ||
- real->str[i] == '\r' ||
- real->str[i] == '\t'))
- break;
-
- ++i;
- }
-
- _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
- real->str[i] == '\t'));
-
- if (end)
- *end = i;
-}
-
/** @} */
#ifdef DBUS_BUILD_TESTS
diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c
index e35b9e1a..86cb986f 100644
--- a/dbus/dbus-string.c
+++ b/dbus/dbus-string.c
@@ -1924,20 +1924,84 @@ _dbus_string_skip_blank (const DBusString *str,
i = start;
while (i < real->len)
{
- if (!(real->str[i] == ' ' ||
- real->str[i] == '\t'))
+ if (!DBUS_IS_ASCII_BLANK (real->str[i]))
break;
++i;
}
- _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
- real->str[i] == '\t'));
+ _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i]));
if (end)
*end = i;
}
+
+/**
+ * Skips whitespace from start, storing the first non-whitespace in *end.
+ * (whitespace is space, tab, newline, CR).
+ *
+ * @param str the string
+ * @param start where to start
+ * @param end where to store the first non-whitespace byte index
+ */
+void
+_dbus_string_skip_white (const DBusString *str,
+ int start,
+ int *end)
+{
+ int i;
+ DBUS_CONST_STRING_PREAMBLE (str);
+ _dbus_assert (start <= real->len);
+ _dbus_assert (start >= 0);
+
+ i = start;
+ while (i < real->len)
+ {
+ if (!DBUS_IS_ASCII_WHITE (real->str[i]))
+ break;
+
+ ++i;
+ }
+
+ _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i])));
+
+ if (end)
+ *end = i;
+}
+
+/**
+ * Skips whitespace from end, storing the start index of the trailing
+ * whitespace in *start. (whitespace is space, tab, newline, CR).
+ *
+ * @param str the string
+ * @param end where to start scanning backward
+ * @param start where to store the start of whitespace chars
+ */
+void
+_dbus_string_skip_white_reverse (const DBusString *str,
+ int end,
+ int *start)
+{
+ int i;
+ DBUS_CONST_STRING_PREAMBLE (str);
+ _dbus_assert (end <= real->len);
+ _dbus_assert (end >= 0);
+
+ i = end;
+ while (i > 0)
+ {
+ if (!DBUS_IS_ASCII_WHITE (real->str[i-1]))
+ break;
+ --i;
+ }
+
+ _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1]))));
+
+ if (start)
+ *start = i;
+}
+
/**
* Assigns a newline-terminated or \\r\\n-terminated line from the front
* of the string to the given dest string. The dest string's previous
@@ -2043,6 +2107,26 @@ _dbus_string_delete_leading_blanks (DBusString *str)
#endif
/**
+ * Deletes leading and trailing whitespace
+ *
+ * @param str the string
+ */
+void
+_dbus_string_chop_white(DBusString *str)
+{
+ int i;
+
+ _dbus_string_skip_white (str, 0, &i);
+
+ if (i > 0)
+ _dbus_string_delete (str, 0, i);
+
+ _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i);
+
+ _dbus_string_set_length (str, i);
+}
+
+/**
* Tests two DBusString for equality.
*
* @todo memcmp is probably faster
diff --git a/dbus/dbus-string.h b/dbus/dbus-string.h
index 854ed941..47fd1b41 100644
--- a/dbus/dbus-string.h
+++ b/dbus/dbus-string.h
@@ -233,6 +233,9 @@ void _dbus_string_skip_blank (const DBusString *str,
void _dbus_string_skip_white (const DBusString *str,
int start,
int *end);
+void _dbus_string_skip_white_reverse (const DBusString *str,
+ int end,
+ int *start);
dbus_bool_t _dbus_string_equal (const DBusString *a,
const DBusString *b);
dbus_bool_t _dbus_string_equal_c_str (const DBusString *a,
@@ -253,6 +256,7 @@ dbus_bool_t _dbus_string_pop_line (DBusString *source,
DBusString *dest);
void _dbus_string_delete_first_word (DBusString *str);
void _dbus_string_delete_leading_blanks (DBusString *str);
+void _dbus_string_chop_white (DBusString *str);
dbus_bool_t _dbus_string_append_byte_as_hex (DBusString *str,
int byte);
dbus_bool_t _dbus_string_hex_encode (const DBusString *source,
diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c
index c0540175..d0538010 100644
--- a/dbus/dbus-sysdeps-unix.c
+++ b/dbus/dbus-sysdeps-unix.c
@@ -2297,10 +2297,12 @@ _dbus_get_autolaunch_address (DBusString *address, DBusError *error)
pid_t pid;
int ret;
int status;
- int orig_len = _dbus_string_get_length (address);
+ int orig_len;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
+ orig_len = _dbus_string_get_length (address);
+
#define READ_END 0
#define WRITE_END 1
if (pipe (address_pipe) < 0)
@@ -2388,6 +2390,34 @@ _dbus_get_autolaunch_address (DBusString *address, DBusError *error)
return TRUE;
}
+/**
+ * Reads the uuid of the machine we're running on from
+ * the dbus configuration. Optionally try to create it
+ * (only root can do this usually).
+ *
+ * On UNIX, reads a file that gets created by dbus-uuidgen
+ * in a post-install script. On Windows, if there's a standard
+ * machine uuid we could just use that, but I can't find one
+ * with the right properties (the hardware profile guid can change
+ * without rebooting I believe). If there's no standard one
+ * we might want to use the registry instead of a file for
+ * this, and I'm not sure how we'd ensure the uuid gets created.
+ *
+ * @param guid to init with the machine's uuid
+ * @param create_if_not_found try to create the uuid if it doesn't exist
+ * @param error the error return
+ * @returns #FALSE if the error is set
+ */
+dbus_bool_t
+_dbus_read_local_machine_uuid (DBusGUID *machine_id,
+ dbus_bool_t create_if_not_found,
+ DBusError *error)
+{
+ DBusString filename;
+ _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
+ return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
+}
+
/** @} end of sysdeps */
/* tests in dbus-sysdeps-util.c */
diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c
index d09f33e6..2db45900 100644
--- a/dbus/dbus-sysdeps.c
+++ b/dbus/dbus-sysdeps.c
@@ -919,7 +919,7 @@ _dbus_error_from_errno (int error_number)
#endif
#ifdef EEXIST
case EEXIST:
- return DBUS_ERROR_FILE_NOT_FOUND;
+ return DBUS_ERROR_FILE_EXISTS;
#endif
#ifdef ENOENT
case ENOENT:
diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h
index 3541a721..7db23e57 100644
--- a/dbus/dbus-sysdeps.h
+++ b/dbus/dbus-sysdeps.h
@@ -379,6 +379,13 @@ dbus_bool_t _dbus_parse_uid (const DBusString *uid_str,
dbus_bool_t _dbus_get_autolaunch_address (DBusString *address,
DBusError *error);
+typedef union DBusGUID DBusGUID;
+
+dbus_bool_t _dbus_read_local_machine_uuid (DBusGUID *machine_id,
+ dbus_bool_t create_if_not_found,
+ DBusError *error);
+
+
DBUS_END_DECLS
#endif /* DBUS_SYSDEPS_H */
diff --git a/dbus/dbus-threads.c b/dbus/dbus-threads.c
index 8c7eb5ef..c4ccd66e 100644
--- a/dbus/dbus-threads.c
+++ b/dbus/dbus-threads.c
@@ -450,7 +450,8 @@ init_locks (void)
LOCK_ADDR (shutdown_funcs),
LOCK_ADDR (system_users),
LOCK_ADDR (message_cache),
- LOCK_ADDR (shared_connections)
+ LOCK_ADDR (shared_connections),
+ LOCK_ADDR (machine_uuid)
#undef LOCK_ADDR
};
diff --git a/dbus/dbus-uuidgen.c b/dbus/dbus-uuidgen.c
new file mode 100644
index 00000000..8da83960
--- /dev/null
+++ b/dbus/dbus-uuidgen.c
@@ -0,0 +1,123 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-uuidgen.c The guts of the dbus-uuidgen binary live in libdbus, in this file.
+ *
+ * Copyright (C) 2006 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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 "dbus-uuidgen.h"
+#include "dbus-internals.h"
+#include "dbus-string.h"
+#include "dbus-protocol.h"
+
+#ifdef DBUS_WIN
+#error "dbus-uuidgen should not be needed on Windows"
+#endif
+
+/**
+ * @defgroup DBusInternalsUuidgen dbus-uuidgen implementation
+ * @ingroup DBusInternals
+ * @brief Functions for dbus-uuidgen binary
+ *
+ * These are not considered part of the ABI, and if you call them
+ * you will get screwed by future changes.
+ *
+ * @{
+ */
+
+static dbus_bool_t
+return_uuid (DBusGUID *uuid,
+ char **uuid_p,
+ DBusError *error)
+{
+ if (uuid_p)
+ {
+ DBusString encoded;
+ _dbus_string_init (&encoded);
+ if (!_dbus_uuid_encode (uuid, &encoded) ||
+ !_dbus_string_steal_data (&encoded, uuid_p))
+ {
+ _DBUS_SET_OOM (error);
+ _dbus_string_free (&encoded);
+ return FALSE;
+ }
+ _dbus_string_free (&encoded);
+ }
+ return TRUE;
+}
+
+/**
+ * For use by the dbus-uuidgen binary ONLY, do not call this.
+ * We can and will change this function without modifying
+ * the libdbus soname.
+ *
+ * @param filename the file or #NULL for the machine ID file
+ * @param uuid_p out param to return the uuid
+ * @param create_if_not_found whether to create it if not already there
+ * @param error error return
+ * @param returns #FALSE if error is set
+ */
+dbus_bool_t
+dbus_internal_do_not_use_get_uuid (const char *filename,
+ char **uuid_p,
+ dbus_bool_t create_if_not_found,
+ DBusError *error)
+{
+ DBusGUID uuid;
+
+ if (filename)
+ {
+ DBusString filename_str;
+ _dbus_string_init_const (&filename_str, filename);
+ if (!_dbus_read_uuid_file (&filename_str, &uuid, create_if_not_found, error))
+ goto error;
+ }
+ else
+ {
+ if (!_dbus_read_local_machine_uuid (&uuid, create_if_not_found, error))
+ goto error;
+ }
+
+ if (!return_uuid(&uuid, uuid_p, error))
+ goto error;
+
+ return TRUE;
+
+ error:
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ return FALSE;
+}
+
+/**
+ * For use by the dbus-uuidgen binary ONLY, do not call this.
+ * We can and will change this function without modifying
+ * the libdbus soname.
+ *
+ * @param uuid_p out param to return the uuid
+ * @param returns #FALSE if no memory
+ */
+dbus_bool_t
+dbus_internal_do_not_use_create_uuid (char **uuid_p)
+{
+ DBusGUID uuid;
+
+ _dbus_generate_uuid (&uuid);
+ return return_uuid (&uuid, uuid_p, NULL);
+}
+
+/** @} */
diff --git a/dbus/dbus-uuidgen.h b/dbus/dbus-uuidgen.h
new file mode 100644
index 00000000..2b5b28fe
--- /dev/null
+++ b/dbus/dbus-uuidgen.h
@@ -0,0 +1,47 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-uuidgen.h The guts of the dbus-uuidgen binary live in libdbus, in this file.
+ *
+ * Copyright (C) 2006 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+#ifdef DBUS_INSIDE_DBUS_H
+#error "You can't include dbus-uuidgen.h in the public header dbus.h"
+#endif
+
+#ifndef DBUS_UUIDGEN_H
+#define DBUS_UUIDGEN_H
+
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-errors.h>
+
+DBUS_BEGIN_DECLS
+
+dbus_bool_t dbus_internal_do_not_use_get_uuid (const char *filename,
+ char **uuid_p,
+ dbus_bool_t create_if_not_found,
+ DBusError *error);
+dbus_bool_t dbus_internal_do_not_use_ensure_uuid (const char *filename,
+ char **uuid_p,
+ DBusError *error);
+dbus_bool_t dbus_internal_do_not_use_create_uuid (char **uuid_p);
+
+
+DBUS_END_DECLS
+
+#endif /* DBUS_UUIDGEN_H */
diff --git a/doc/dbus-specification.xml b/doc/dbus-specification.xml
index d8e9911f..41d3fb9b 100644
--- a/doc/dbus-specification.xml
+++ b/doc/dbus-specification.xml
@@ -2290,9 +2290,10 @@
<title><literal>org.freedesktop.DBus.Peer</literal></title>
<para>
The <literal>org.freedesktop.DBus.Peer</literal> interface
- has one method:
+ has two methods:
<programlisting>
org.freedesktop.DBus.Peer.Ping ()
+ org.freedesktop.DBus.Peer.GetMachineId (out STRING machine_uuid)
</programlisting>
</para>
<para>
@@ -2300,9 +2301,33 @@
<literal>org.freedesktop.DBus.Peer.Ping</literal>, an application should do
nothing other than reply with a <literal>METHOD_RETURN</literal> as
usual. It does not matter which object path a ping is sent to. The
- reference implementation should simply handle this method on behalf of
- all objects, though it doesn't yet. (The point is, you're really pinging
- the peer process, not a specific object.)
+ reference implementation handles this method automatically.
+ </para>
+ <para>
+ On receipt of the <literal>METHOD_CALL</literal> message
+ <literal>org.freedesktop.DBus.Peer.GetMachineId</literal>, an application should
+ reply with a <literal>METHOD_RETURN</literal> containing a hex-encoded
+ UUID representing the identity of the machine the process is running on.
+ This UUID must be the same for all processes on a single system at least
+ until that system next reboots. It should be the same across reboots
+ if possible, but may change due to reconfiguration or hardware changes.
+ It does not matter which object path a GetMachineId is sent to. The
+ reference implementation handles this method automatically.
+ </para>
+ <para>
+ The UUID must contain 128 bits of data and be hex-encoded (meaning, the hex
+ string contains 32 ASCII characters). The hex-encoded string may not contain
+ hyphens or other non-hex-digit characters, and it must be exactly 32 characters long.
+ To generate a UUID, the recommended algorithm is to put the current time in seconds
+ since the UNIX epoch in the last 32 bits of the UUID, and to put randomly-generated bits
+ in the first 96 bits of the UUID.
+ </para>
+ <para>
+ The UUID is intended to be per-instance-of-the-operating-system, so may represent
+ a virtual machine running on a hypervisor, rather than a physical machine.
+ Basically if two processes see the same UUID, they should also see the same
+ shared memory, UNIX domain sockets, process IDs, and other features that require
+ a running OS kernel in common between the processes.
</para>
</sect2>
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 05c3618e..a3d786c4 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,6 +1,6 @@
INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_X_CFLAGS) -DDBUS_LOCALEDIR=\"@EXPANDED_DATADIR@/locale\" -DDBUS_COMPILATION -DDBUS_DAEMONDIR=\"@DBUS_DAEMONDIR@\"
-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 \
@@ -19,11 +19,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-1.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
diff --git a/tools/dbus-cleanup-sockets.1 b/tools/dbus-cleanup-sockets.1
index e093ab0f..ca669f49 100644
--- a/tools/dbus-cleanup-sockets.1
+++ b/tools/dbus-cleanup-sockets.1
@@ -11,8 +11,8 @@ dbus-cleanup-sockets \- clean up leftover sockets in a directory
.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 for the
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.
diff --git a/tools/dbus-launch-x11.c b/tools/dbus-launch-x11.c
index ac356219..67aef04d 100644
--- a/tools/dbus-launch-x11.c
+++ b/tools/dbus-launch-x11.c
@@ -33,7 +33,7 @@
#include <X11/Xlib.h>
#include <X11/Xatom.h>
-Display *xdisplay;
+Display *xdisplay = NULL;
static Atom selection_atom;
static Atom address_atom;
static Atom pid_atom;
diff --git a/tools/dbus-launch.c b/tools/dbus-launch.c
index fb993e4e..1589c168 100644
--- a/tools/dbus-launch.c
+++ b/tools/dbus-launch.c
@@ -799,7 +799,7 @@ main (int argc, char **argv)
fprintf (stderr,
"Failed to execute message bus daemon %s: %s. Will try again without full path.\n",
DBUS_DAEMONDIR"/dbus-daemon", strerror (errno));
-
+
/*
* If it failed, try running without full PATH. Note this is needed
* because the build process builds the run-with-tmp-session-bus.conf
@@ -902,33 +902,36 @@ main (int argc, char **argv)
close (bus_pid_to_launcher_pipe[READ_END]);
#ifdef DBUS_BUILD_X11
- ret2 = x11_save_address (bus_address, bus_pid, &wid);
- if (ret2 == 0)
- {
- /* another window got added. Return its address */
- char *address;
- pid_t pid;
- long wid;
-
- if (x11_get_address (&address, &pid, &wid) && address != NULL)
- {
- verbose ("dbus-daemon is already running. Returning existing parameters.\n");
- print_variables (address, pid, wid, c_shell_syntax,
- bourne_shell_syntax, binary_syntax);
- free (address);
-
- bus_pid_to_kill = bus_pid;
- kill_bus_and_exit (0);
- }
-
- /* if failed, fall through */
- }
- if (ret2 <= 0)
- {
- fprintf (stderr, "Error saving bus information.\n");
- bus_pid_to_kill = bus_pid;
- kill_bus_and_exit (1);
- }
+ if (xdisplay != NULL)
+ {
+ ret2 = x11_save_address (bus_address, bus_pid, &wid);
+ if (ret2 == 0)
+ {
+ /* another window got added. Return its address */
+ char *address;
+ pid_t pid;
+ long wid;
+
+ if (x11_get_address (&address, &pid, &wid) && address != NULL)
+ {
+ verbose ("dbus-daemon is already running. Returning existing parameters.\n");
+ print_variables (address, pid, wid, c_shell_syntax,
+ bourne_shell_syntax, binary_syntax);
+ free (address);
+
+ bus_pid_to_kill = bus_pid;
+ kill_bus_and_exit (0);
+ }
+
+ /* if failed, fall through */
+ }
+ if (ret2 <= 0)
+ {
+ fprintf (stderr, "Error saving bus information.\n");
+ bus_pid_to_kill = bus_pid;
+ kill_bus_and_exit (1);
+ }
+ }
#endif
/* Forward the pid to the babysitter */
diff --git a/tools/dbus-uuidgen.1 b/tools/dbus-uuidgen.1
new file mode 100644
index 00000000..7b533723
--- /dev/null
+++ b/tools/dbus-uuidgen.1
@@ -0,0 +1,91 @@
+.\"
+.\" 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 or reads a universally unique ID.
+
+.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 like this:
+.nf
+ dbus-uuidgen --ensure
+.fi
+
+.PP
+This will ensure that /etc/dbus-1/machine-id exists and has the uuid in it.
+It won't overwrite an existing uuid, since this id should remain fixed
+for a single machine until the next reboot at least.
+
+.PP
+The important properties of the machine UUID are that 1) it remains
+unchanged until the next reboot and 2) it is different for any two
+running instances of the OS kernel. That is, if two processes see the
+same UUID, they should also see the same shared memory, UNIX domain
+sockets, local X displays, localhost.localdomain resolution, process
+IDs, and so forth.
+
+.PP
+If you run \fIdbus-uuidgen\fP with no options it just prints a new uuid made
+up out of thin air. This is similar to the regular "uuidgen" command.
+
+.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.
+
+.PP
+The D-Bus UUID has no relationship to RFC 4122 and does not generate
+UUIDs compatible with that spec.
+
+.PP
+If you try to change an existing /etc/dbus-1/machine-id on a running
+system, it will probably result in bad things happening. Don't try
+to change this file. Also, don't make it the same on two different
+systems; it needs to be different anytime there are two different
+kernels running.
+
+.PP
+If you need to share /etc between two different kernels, a possible solution
+is to symlink the machine ID to /var, and run "dbus-uuidgen
+--ensure=/var/whatever" from an early boot script or the system
+message bus boot script.
+
+.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.
+On success, prints no output.
+
+.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/
diff --git a/tools/dbus-uuidgen.c b/tools/dbus-uuidgen.c
new file mode 100644
index 00000000..569bdb07
--- /dev/null
+++ b/tools/dbus-uuidgen.c
@@ -0,0 +1,161 @@
+/* -*- 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-uuidgen.h>
+#include <dbus/dbus.h>
+
+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);
+}
+
+static dbus_bool_t
+get_arg (const char *arg,
+ const char *option,
+ const char **value_p)
+{
+ 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')
+ {
+ *value_p = fn;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int i;
+ const char *filename;
+ dbus_bool_t ensure_uuid;
+ dbus_bool_t get_uuid;
+ DBusError error;
+
+ ensure_uuid = FALSE;
+ get_uuid = FALSE;
+
+ filename = NULL;
+
+ 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 and --ensure\n");
+ exit (1);
+ }
+
+ dbus_error_init (&error);
+
+ if (get_uuid || ensure_uuid)
+ {
+ char *uuid;
+ if (dbus_internal_do_not_use_get_uuid (filename, &uuid, ensure_uuid, &error))
+ {
+ if (get_uuid) /* print nothing on --ensure */
+ printf ("%s\n", uuid);
+ dbus_free (uuid);
+ }
+ }
+ else
+ {
+ char *uuid;
+ if (dbus_internal_do_not_use_create_uuid (&uuid))
+ {
+ printf ("%s\n", uuid);
+ dbus_free (uuid);
+ }
+ else
+ {
+ dbus_set_error (&error, DBUS_ERROR_NO_MEMORY, "No memory");
+ }
+ }
+
+ if (dbus_error_is_set (&error))
+ {
+ fprintf (stderr, "%s\n", error.message);
+ dbus_error_free (&error);
+ exit (1);
+ }
+ else
+ {
+ exit (0);
+ }
+}
diff --git a/tools/run-with-tmp-session-bus.sh b/tools/run-with-tmp-session-bus.sh
index 880924b7..b72a56a5 100755
--- a/tools/run-with-tmp-session-bus.sh
+++ b/tools/run-with-tmp-session-bus.sh
@@ -34,7 +34,11 @@ cat $DBUS_TOP_BUILDDIR/bus/session.conf | \
echo "Created configuration file $CONFIG_FILE" >&2
-export PATH=$DBUS_TOP_BUILDDIR/bus:$PATH
+if ! test -e "$DBUS_TOP_BUILDDIR"/bus/dbus-daemon ; then
+ die "$DBUS_TOP_BUILDDIR/bus/dbus-daemon does not exist"
+fi
+
+export PATH="$DBUS_TOP_BUILDDIR"/bus:$PATH
## the libtool script found by the path search should already do this, but
export LD_LIBRARY_PATH=$DBUS_TOP_BUILDDIR/dbus/.libs:$LD_LIBRARY_PATH
@@ -46,7 +50,7 @@ echo "Running $DBUS_TOP_BUILDDIR/tools/dbus-launch --sh-syntax --config-file=$CO
eval `$DBUS_TOP_BUILDDIR/tools/dbus-launch --sh-syntax --config-file=$CONFIG_FILE`
if test -z "$DBUS_SESSION_BUS_PID" ; then
- die "Failed to launch message bus for introspection generation to run"
+ die "Failed to launch message bus for test script to run"
fi
echo "Started bus pid $DBUS_SESSION_BUS_PID at $DBUS_SESSION_BUS_ADDRESS" >&2