X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dbus%2Fdbus-bus.c;h=3824b3f8368385d3ce3b0b72c25b8589ab5c9cc1;hb=7d9239c9c78cb6d0b9c282376fcf3cda1de23209;hp=234282680768998a15b310b3b98cce8ade9f791f;hpb=eaefe03a8891b84e3f9e1f99f9098d65567e3092;p=platform%2Fupstream%2Fdbus.git diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c index 2342826..3824b3f 100644 --- a/dbus/dbus-bus.c +++ b/dbus/dbus-bus.c @@ -1,8 +1,9 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* dbus-bus.c Convenience functions for communicating with the bus. * * Copyright (C) 2003 CodeFactory AB * Copyright (C) 2003 Red Hat, Inc. + * Copyright (C) 2013 Samsung Electronics * * Licensed under the Academic Free License version 2.1 * @@ -18,18 +19,26 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ +#include #include "dbus-bus.h" #include "dbus-protocol.h" #include "dbus-internals.h" #include "dbus-message.h" #include "dbus-marshal-validate.h" +#include "dbus-misc.h" #include "dbus-threads-internal.h" #include "dbus-connection-internal.h" -#include +#include "dbus-string.h" +#ifdef ENABLE_KDBUS_TRANSPORT +#include "dbus-transport-kdbus.h" +#include +#include +#include +#endif /** * @defgroup DBusBus Message bus APIs @@ -94,19 +103,6 @@ static DBusBusType activation_bus_type = DBUS_BUS_STARTER; static dbus_bool_t initialized = FALSE; -/** - * Lock for globals in this file - */ -_DBUS_DEFINE_GLOBAL_LOCK (bus); - -/** - * Global lock covering all BusData on any connection. The bet is - * that some lock contention is better than more memory - * for a per-connection lock, but it's tough to imagine it mattering - * either way. - */ -_DBUS_DEFINE_GLOBAL_LOCK (bus_datas); - static void addresses_shutdown_func (void *data) { @@ -124,6 +120,8 @@ addresses_shutdown_func (void *data) } activation_bus_type = DBUS_BUS_STARTER; + + initialized = FALSE; } static dbus_bool_t @@ -144,6 +142,72 @@ get_from_env (char **connection_p, } } +#ifdef ENABLE_KDBUS_TRANSPORT +void dbus_bus_set_bus_connection_address(DBusBusType address_type, char* address) +{ + if(bus_connection_addresses[address_type] != NULL) + free(bus_connection_addresses[address_type]); + bus_connection_addresses[address_type] = address; +} +#endif + +static dbus_bool_t +init_session_address (void) +{ + dbus_bool_t retval; + + retval = FALSE; + + /* First, look in the environment. This is the normal case on + * freedesktop.org/Unix systems. */ + get_from_env (&bus_connection_addresses[DBUS_BUS_SESSION], + "DBUS_SESSION_BUS_ADDRESS"); + if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL) + { + dbus_bool_t supported; + DBusString addr; + DBusError error = DBUS_ERROR_INIT; + + if (!_dbus_string_init (&addr)) + return FALSE; + + supported = FALSE; + /* So it's not in the environment - let's try a platform-specific method. + * On MacOS, this involves asking launchd. On Windows (not specified yet) + * we might do a COM lookup. + * Ignore errors - if we failed, fall back to autolaunch. */ + retval = _dbus_lookup_session_address (&supported, &addr, &error); + if (supported && retval) + { + retval =_dbus_string_steal_data (&addr, &bus_connection_addresses[DBUS_BUS_SESSION]); + } + else if (supported && !retval) + { + if (dbus_error_is_set(&error)) + _dbus_warn ("Dynamic session lookup supported but failed: %s\n", error.message); + else + _dbus_warn ("Dynamic session lookup supported but failed silently\n"); + } + _dbus_string_free (&addr); + } + else + retval = TRUE; + + if (!retval) + return FALSE; + + /* We have a hard-coded (but compile-time-configurable) fallback address for + * the session bus. */ + if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL) + bus_connection_addresses[DBUS_BUS_SESSION] = + _dbus_strdup (DBUS_SESSION_BUS_CONNECT_ADDRESS); + + if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL) + return FALSE; + + return TRUE; +} + static dbus_bool_t init_connections_unlocked (void) { @@ -196,17 +260,9 @@ init_connections_unlocked (void) { _dbus_verbose ("Filling in session bus address...\n"); - if (!get_from_env (&bus_connection_addresses[DBUS_BUS_SESSION], - "DBUS_SESSION_BUS_ADDRESS")) + if (!init_session_address ()) return FALSE; - if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL) - bus_connection_addresses[DBUS_BUS_SESSION] = - _dbus_strdup (DBUS_SESSION_BUS_DEFAULT_ADDRESS); - - if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL) - return FALSE; - _dbus_verbose (" \"%s\"\n", bus_connection_addresses[DBUS_BUS_SESSION] ? bus_connection_addresses[DBUS_BUS_SESSION] : "none set"); } @@ -254,10 +310,10 @@ init_connections_unlocked (void) * the above code will work right */ - if (!_dbus_setenv ("DBUS_ACTIVATION_ADDRESS", NULL)) + if (!dbus_setenv ("DBUS_ACTIVATION_ADDRESS", NULL)) return FALSE; - if (!_dbus_setenv ("DBUS_ACTIVATION_BUS_TYPE", NULL)) + if (!dbus_setenv ("DBUS_ACTIVATION_BUS_TYPE", NULL)) return FALSE; if (!_dbus_register_shutdown_func (addresses_shutdown_func, @@ -278,7 +334,11 @@ bus_data_free (void *data) if (bd->is_well_known) { int i; - _DBUS_LOCK (bus); + + if (!_DBUS_LOCK (bus)) + _dbus_assert_not_reached ("global locks should have been initialized " + "when we attached bus data"); + /* We may be stored in more than one slot */ /* This should now be impossible - these slots are supposed to * be cleared on disconnect, so should not need to be cleared on @@ -349,8 +409,13 @@ void _dbus_bus_notify_shared_connection_disconnected_unlocked (DBusConnection *connection) { int i; - - _DBUS_LOCK (bus); + + if (!_DBUS_LOCK (bus)) + { + /* If it was in bus_connections, we would have initialized global locks + * when we added it. So, it can't be. */ + return; + } /* We are expecting to have the connection saved in only one of these * slots, but someone could in a pathological case set system and session @@ -382,15 +447,21 @@ internal_bus_get (DBusBusType type, _dbus_return_val_if_fail (type >= 0 && type < N_BUS_TYPES, NULL); _dbus_return_val_if_error_is_set (error, NULL); - _DBUS_LOCK (bus); + connection = NULL; - if (!init_connections_unlocked ()) + if (!_DBUS_LOCK (bus)) { - _DBUS_UNLOCK (bus); _DBUS_SET_OOM (error); + /* do not "goto out", that would try to unlock */ return NULL; } + if (!init_connections_unlocked ()) + { + _DBUS_SET_OOM (error); + goto out; + } + /* We want to use the activation address even if the * activating bus is the session or system bus, * per the spec. @@ -410,9 +481,7 @@ internal_bus_get (DBusBusType type, { connection = bus_connections[type]; dbus_connection_ref (connection); - - _DBUS_UNLOCK (bus); - return connection; + goto out; } address = bus_connection_addresses[address_type]; @@ -420,8 +489,7 @@ internal_bus_get (DBusBusType type, { dbus_set_error (error, DBUS_ERROR_FAILED, "Unable to determine the address of the message bus (try 'man dbus-launch' and 'man dbus-daemon' for help)"); - _DBUS_UNLOCK (bus); - return NULL; + goto out; } if (private) @@ -431,25 +499,15 @@ internal_bus_get (DBusBusType type, if (!connection) { - _DBUS_ASSERT_ERROR_IS_SET (error); - _DBUS_UNLOCK (bus); - return NULL; + goto out; } - /* By default we're bound to the lifecycle of - * the message bus. - */ - dbus_connection_set_exit_on_disconnect (connection, - TRUE); - if (!dbus_bus_register (connection, error)) { - _DBUS_ASSERT_ERROR_IS_SET (error); _dbus_connection_close_possibly_shared (connection); dbus_connection_unref (connection); - - _DBUS_UNLOCK (bus); - return NULL; + connection = NULL; + goto out; } if (!private) @@ -461,17 +519,27 @@ internal_bus_get (DBusBusType type, bus_connections[type] = connection; } - _DBUS_LOCK (bus_datas); + /* By default we're bound to the lifecycle of + * the message bus. + */ + dbus_connection_set_exit_on_disconnect (connection, + TRUE); + + if (!_DBUS_LOCK (bus_datas)) + _dbus_assert_not_reached ("global locks were initialized already"); + bd = ensure_bus_data (connection); _dbus_assert (bd != NULL); /* it should have been created on register, so OOM not possible */ bd->is_well_known = TRUE; _DBUS_UNLOCK (bus_datas); - - _DBUS_UNLOCK (bus); +out: + /* Return a reference to the caller, or NULL with error set. */ + if (connection == NULL) + _DBUS_ASSERT_ERROR_IS_SET (error); - /* Return a reference to the caller */ + _DBUS_UNLOCK (bus); return connection; } @@ -506,7 +574,7 @@ internal_bus_get (DBusBusType type, * * @param type bus type * @param error address where an error can be returned. - * @returns a #DBusConnection with new ref + * @returns a #DBusConnection with new ref or #NULL on error */ DBusConnection * dbus_bus_get (DBusBusType type, @@ -601,7 +669,7 @@ dbus_bus_register (DBusConnection *connection, DBusError *error) { DBusMessage *message, *reply; - char *name; + char *name = NULL; BusData *bd; dbus_bool_t retval; @@ -609,71 +677,74 @@ dbus_bus_register (DBusConnection *connection, _dbus_return_val_if_error_is_set (error, FALSE); retval = FALSE; + message = NULL; + reply = NULL; - _DBUS_LOCK (bus_datas); + if (!_DBUS_LOCK (bus_datas)) + { + _DBUS_SET_OOM (error); + /* do not "goto out", that would try to unlock */ + return FALSE; + } bd = ensure_bus_data (connection); if (bd == NULL) { _DBUS_SET_OOM (error); - _DBUS_UNLOCK (bus_datas); - return FALSE; + goto out; } if (bd->unique_name != NULL) { _dbus_verbose ("Ignoring attempt to register the same DBusConnection %s with the message bus a second time.\n", bd->unique_name); - _DBUS_UNLOCK (bus_datas); - /* Success! */ - return TRUE; + retval = TRUE; + goto out; } - message = dbus_message_new_method_call (DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS, - "Hello"); - + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "Hello"); if (!message) - { - _DBUS_SET_OOM (error); + { + _DBUS_SET_OOM (error); + goto out; + } - _DBUS_UNLOCK (bus_datas); - return FALSE; - } - reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error); - dbus_message_unref (message); - if (reply == NULL) - goto out; + goto out; else if (dbus_set_error_from_message (error, reply)) - goto out; + goto out; else if (!dbus_message_get_args (reply, error, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID)) - goto out; - + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID)) + goto out; + bd->unique_name = _dbus_strdup (name); + if (bd->unique_name == NULL) { _DBUS_SET_OOM (error); goto out; } - + retval = TRUE; out: + _DBUS_UNLOCK (bus_datas); + + if (message) + dbus_message_unref (message); + if (reply) dbus_message_unref (reply); if (!retval) _DBUS_ASSERT_ERROR_IS_SET (error); - _DBUS_UNLOCK (bus_datas); - return retval; } @@ -717,22 +788,27 @@ dbus_bus_set_unique_name (DBusConnection *connection, const char *unique_name) { BusData *bd; - dbus_bool_t success; + dbus_bool_t success = FALSE; _dbus_return_val_if_fail (connection != NULL, FALSE); _dbus_return_val_if_fail (unique_name != NULL, FALSE); - _DBUS_LOCK (bus_datas); - + if (!_DBUS_LOCK (bus_datas)) + { + /* do not "goto out", that would try to unlock */ + return FALSE; + } + bd = ensure_bus_data (connection); if (bd == NULL) - return FALSE; + goto out; _dbus_assert (bd->unique_name == NULL); bd->unique_name = _dbus_strdup (unique_name); success = bd->unique_name != NULL; - + +out: _DBUS_UNLOCK (bus_datas); return success; @@ -760,20 +836,26 @@ const char* dbus_bus_get_unique_name (DBusConnection *connection) { BusData *bd; - const char *unique_name; + const char *unique_name = NULL; _dbus_return_val_if_fail (connection != NULL, NULL); - _DBUS_LOCK (bus_datas); - + if (!_DBUS_LOCK (bus_datas)) + { + /* We'd have initialized locks when we gave it its unique name, if it + * had one. Don't "goto out", that would try to unlock. */ + return NULL; + } + bd = ensure_bus_data (connection); if (bd == NULL) - return NULL; + goto out; unique_name = bd->unique_name; +out: _DBUS_UNLOCK (bus_datas); - + return unique_name; } @@ -865,6 +947,85 @@ dbus_bus_get_unix_user (DBusConnection *connection, return (unsigned long) uid; } +/** + * Asks the bus to return its globally unique ID, as described in the + * D-Bus specification. For the session bus, this is useful as a way + * to uniquely identify each user session. For the system bus, + * probably the bus ID is not useful; instead, use the machine ID + * since it's accessible without necessarily connecting to the bus and + * may be persistent beyond a single bus instance (across reboots for + * example). See dbus_get_local_machine_id(). + * + * In addition to an ID for each bus and an ID for each machine, there is + * an ID for each address that the bus is listening on; that can + * be retrieved with dbus_connection_get_server_id(), though it is + * probably not very useful. + * + * @param connection the connection + * @param error location to store the error + * @returns the bus ID or #NULL if error is set + */ +char* +dbus_bus_get_id (DBusConnection *connection, + DBusError *error) +{ + DBusMessage *message, *reply; + char *id; + const char *v_STRING; + + _dbus_return_val_if_fail (connection != NULL, NULL); + _dbus_return_val_if_error_is_set (error, NULL); + + message = dbus_message_new_method_call (DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "GetId"); + + if (message == NULL) + { + _DBUS_SET_OOM (error); + return NULL; + } + + reply = dbus_connection_send_with_reply_and_block (connection, message, -1, + error); + + dbus_message_unref (message); + + if (reply == NULL) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + return NULL; + } + + if (dbus_set_error_from_message (error, reply)) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + dbus_message_unref (reply); + return NULL; + } + + v_STRING = NULL; + if (!dbus_message_get_args (reply, error, + DBUS_TYPE_STRING, &v_STRING, + DBUS_TYPE_INVALID)) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + dbus_message_unref (reply); + return NULL; + } + + id = _dbus_strdup (v_STRING); /* may be NULL */ + + dbus_message_unref (reply); + + if (id == NULL) + _DBUS_SET_OOM (error); + + /* FIXME it might be nice to cache the ID locally */ + + return id; +} /** * Asks the bus to assign the given name to this connection by invoking @@ -974,65 +1135,63 @@ dbus_bus_request_name (DBusConnection *connection, unsigned int flags, DBusError *error) { - DBusMessage *message, *reply; - dbus_uint32_t result; - - _dbus_return_val_if_fail (connection != NULL, 0); - _dbus_return_val_if_fail (name != NULL, 0); - _dbus_return_val_if_fail (_dbus_check_is_valid_bus_name (name), 0); - _dbus_return_val_if_error_is_set (error, 0); - - message = dbus_message_new_method_call (DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS, - "RequestName"); - - if (message == NULL) - { - _DBUS_SET_OOM (error); - return -1; - } - - if (!dbus_message_append_args (message, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_UINT32, &flags, - DBUS_TYPE_INVALID)) - { - dbus_message_unref (message); - _DBUS_SET_OOM (error); - return -1; - } - - reply = dbus_connection_send_with_reply_and_block (connection, message, -1, - error); - - dbus_message_unref (message); - - if (reply == NULL) - { - _DBUS_ASSERT_ERROR_IS_SET (error); - return -1; - } - - if (dbus_set_error_from_message (error, reply)) - { - _DBUS_ASSERT_ERROR_IS_SET (error); - dbus_message_unref (reply); - return -1; - } - - if (!dbus_message_get_args (reply, error, - DBUS_TYPE_UINT32, &result, - DBUS_TYPE_INVALID)) - { - _DBUS_ASSERT_ERROR_IS_SET (error); - dbus_message_unref (reply); - return -1; - } - - dbus_message_unref (reply); - - return result; + dbus_uint32_t result; + DBusMessage *message, *reply; + + _dbus_return_val_if_fail (connection != NULL, 0); + _dbus_return_val_if_fail (name != NULL, 0); + _dbus_return_val_if_fail (_dbus_check_is_valid_bus_name (name), 0); + _dbus_return_val_if_error_is_set (error, 0); + + message = dbus_message_new_method_call (DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "RequestName"); + if (message == NULL) + { + _DBUS_SET_OOM (error); + return -1; + } + + if (!dbus_message_append_args (message, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_UINT32, &flags, + DBUS_TYPE_INVALID)) + { + dbus_message_unref (message); + _DBUS_SET_OOM (error); + return -1; + } + + reply = dbus_connection_send_with_reply_and_block (connection, message, -1, + error); + + dbus_message_unref (message); + + if (reply == NULL) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + return -1; + } + + if (dbus_set_error_from_message (error, reply)) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + dbus_message_unref (reply); + return -1; + } + + if (!dbus_message_get_args (reply, error, + DBUS_TYPE_UINT32, &result, + DBUS_TYPE_INVALID)) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + dbus_message_unref (reply); + return -1; + } + + dbus_message_unref (reply); + return result; } @@ -1301,11 +1460,17 @@ send_no_return_values (DBusConnection *connection, * If you pass #NULL for the error, this function will not * block; the match thus won't be added until you flush the * connection, and if there's an error adding the match - * (only possible error is lack of resources in the bus), - * you won't find out about it. + * you won't find out about it. This is generally acceptable, since the + * possible errors (including a lack of resources in the bus, the connection + * having exceeded its quota of active match rules, or the match rule being + * unparseable) are generally unrecoverable. * * If you pass non-#NULL for the error this function will - * block until it gets a reply. + * block until it gets a reply. This may be useful when using match rule keys + * introduced in recent versions of D-Bus, like 'arg0namespace', to allow the + * application to fall back to less efficient match rules supported by older + * versions of the daemon if the running version is not new enough; or when + * using user-supplied rules rather than rules hard-coded at compile time. * * Normal API conventions would have the function return * a boolean value indicating whether the error was set, @@ -1345,6 +1510,13 @@ send_no_return_values (DBusConnection *connection, * * Currently there is no way to match against non-string arguments. * + * A specialised form of wildcard matching on arguments is + * supported for path-like namespaces. If your argument match has + * a 'path' suffix (eg: "arg0path='/some/path/'") then it is + * considered a match if the argument exactly matches the given + * string or if one of them ends in a '/' and is a prefix of the + * other. + * * Matching on interface is tricky because method call * messages only optionally specify the interface. * If a message omits the interface, then it will NOT match @@ -1374,32 +1546,32 @@ dbus_bus_add_match (DBusConnection *connection, const char *rule, DBusError *error) { - DBusMessage *msg; + DBusMessage *msg; - _dbus_return_if_fail (rule != NULL); + _dbus_return_if_fail (rule != NULL); - msg = dbus_message_new_method_call (DBUS_SERVICE_DBUS, + msg = dbus_message_new_method_call (DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "AddMatch"); - if (msg == NULL) - { - _DBUS_SET_OOM (error); - return; - } + if (msg == NULL) + { + _DBUS_SET_OOM (error); + return; + } - if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, &rule, - DBUS_TYPE_INVALID)) - { - dbus_message_unref (msg); - _DBUS_SET_OOM (error); - return; - } + if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, &rule, + DBUS_TYPE_INVALID)) + { + dbus_message_unref (msg); + _DBUS_SET_OOM (error); + return; + } - send_no_return_values (connection, msg, error); + send_no_return_values (connection, msg, error); - dbus_message_unref (msg); + dbus_message_unref (msg); } /** @@ -1424,26 +1596,26 @@ dbus_bus_remove_match (DBusConnection *connection, const char *rule, DBusError *error) { - DBusMessage *msg; + DBusMessage *msg; - _dbus_return_if_fail (rule != NULL); - - msg = dbus_message_new_method_call (DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS, - "RemoveMatch"); + _dbus_return_if_fail (rule != NULL); - if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, &rule, - DBUS_TYPE_INVALID)) - { - dbus_message_unref (msg); - _DBUS_SET_OOM (error); - return; - } + msg = dbus_message_new_method_call (DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "RemoveMatch"); - send_no_return_values (connection, msg, error); + if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, &rule, + DBUS_TYPE_INVALID)) + { + dbus_message_unref (msg); + _DBUS_SET_OOM (error); + return; + } - dbus_message_unref (msg); + send_no_return_values (connection, msg, error); + + dbus_message_unref (msg); } /** @} */