diff options
Diffstat (limited to 'dbus')
-rw-r--r-- | dbus/Makefile.am | 6 | ||||
-rw-r--r-- | dbus/dbus-connection.c | 169 | ||||
-rw-r--r-- | dbus/dbus-connection.h | 4 | ||||
-rw-r--r-- | dbus/dbus-internals.c | 252 | ||||
-rw-r--r-- | dbus/dbus-internals.h | 33 | ||||
-rw-r--r-- | dbus/dbus-protocol.h | 2 | ||||
-rw-r--r-- | dbus/dbus-server-protected.h | 10 | ||||
-rw-r--r-- | dbus/dbus-server.c | 28 | ||||
-rw-r--r-- | dbus/dbus-string-private.h | 12 | ||||
-rw-r--r-- | dbus/dbus-string-util.c | 37 | ||||
-rw-r--r-- | dbus/dbus-string.c | 92 | ||||
-rw-r--r-- | dbus/dbus-string.h | 4 | ||||
-rw-r--r-- | dbus/dbus-sysdeps-unix.c | 32 | ||||
-rw-r--r-- | dbus/dbus-sysdeps.c | 2 | ||||
-rw-r--r-- | dbus/dbus-sysdeps.h | 7 | ||||
-rw-r--r-- | dbus/dbus-threads.c | 3 | ||||
-rw-r--r-- | dbus/dbus-uuidgen.c | 123 | ||||
-rw-r--r-- | dbus/dbus-uuidgen.h | 47 |
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 */ |