summaryrefslogtreecommitdiffstats
path: root/dbus
diff options
context:
space:
mode:
Diffstat (limited to 'dbus')
-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
18 files changed, 772 insertions, 91 deletions
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 */