summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2003-03-13 00:56:43 +0000
committerHavoc Pennington <hp@redhat.com>2003-03-13 00:56:43 +0000
commit29560adcc79a259a0be3511c056ee7453aa26c04 (patch)
tree57e72dd26b5876da48379e5ff910c63e66cb7001
parent799a3ff443f5357ae7857ebe989a7f92f7bd84df (diff)
2003-03-12 Havoc Pennington <hp@redhat.com>
Mega-patch that gets the message bus daemon initially handling out-of-memory. Work still needed. Also lots of random moving stuff to DBusError instead of ResultCode. * dbus/dbus-list.c (_dbus_list_length_is_one): new function * dbus/dbus-connection.c (dbus_connection_send_with_reply_and_block): use DBusError * dbus/dbus-bus.c: adapt to API changes, make it use DBusError not DBusResultCode * dbus/dbus-connection.c (dbus_connection_send): drop the result code here, as the only failure possible is OOM. * bus/connection.c (bus_connection_disconnect): rename bus_connection_disconnected as it's a notification only * bus/driver.c (bus_driver_handle_acquire_service): don't free "name" on get_args failure, should be done by get_args; don't disconnect client for bad args, just return an error. (bus_driver_handle_service_exists): ditto * bus/services.c (bus_services_list): NULL-terminate returned array * bus/driver.c (bus_driver_send_service_lost) (bus_driver_send_service_acquired): send messages from driver to a specific client to the client's unique name, not to the broadcast service. * dbus/dbus-message.c (decode_header_data): reject messages that contain no name field (_dbus_message_get_client_serial): rename to dbus_message_get_serial and make public (_dbus_message_set_serial): rename from set_client_serial (_dbus_message_set_reply_serial): make public (_dbus_message_get_reply_serial): make public * bus/connection.c (bus_connection_foreach): allow stopping iteration by returning FALSE from foreach function. * dbus/dbus-connection.c (dbus_connection_send_preallocated) (dbus_connection_free_preallocated_send) (dbus_connection_preallocate_send): new API for sending a message without possibility of malloc failure. (dbus_connection_send_message): rename to just dbus_connection_send (and same for whole function family) * dbus/dbus-errors.c (dbus_error_free): make this reinit the error * dbus/dbus-sysdeps.c (_dbus_exit): new function * bus/activation.c: handle/return errors * dbus/dbus-errors.h: add more DBUS_ERROR #define * dbus/dbus-sysdeps.c (_dbus_directory_open) (_dbus_file_get_contents) (_dbus_directory_get_next_file): use DBusError instead of DBusResultCode (_dbus_result_from_errno): move to this file
-rw-r--r--ChangeLog62
-rw-r--r--bus/activation.c231
-rw-r--r--bus/activation.h5
-rw-r--r--bus/connection.c422
-rw-r--r--bus/connection.h26
-rw-r--r--bus/desktop-file.c180
-rw-r--r--bus/dispatch.c281
-rw-r--r--bus/dispatch.h6
-rw-r--r--bus/driver.c680
-rw-r--r--bus/driver.h31
-rw-r--r--bus/main.c13
-rw-r--r--bus/services.c165
-rw-r--r--bus/services.h21
-rw-r--r--bus/utils.c2
-rw-r--r--bus/utils.h5
-rw-r--r--dbus/dbus-address.c4
-rw-r--r--dbus/dbus-auth-script.c12
-rw-r--r--dbus/dbus-auth.c25
-rw-r--r--dbus/dbus-bus.c124
-rw-r--r--dbus/dbus-bus.h8
-rw-r--r--dbus/dbus-connection.c220
-rw-r--r--dbus/dbus-connection.h34
-rw-r--r--dbus/dbus-errors.c44
-rw-r--r--dbus/dbus-errors.h16
-rw-r--r--dbus/dbus-internals.c107
-rw-r--r--dbus/dbus-internals.h5
-rw-r--r--dbus/dbus-keyring.c12
-rw-r--r--dbus/dbus-list.c18
-rw-r--r--dbus/dbus-list.h2
-rw-r--r--dbus/dbus-message-builder.c11
-rw-r--r--dbus/dbus-message-internal.h17
-rw-r--r--dbus/dbus-message.c217
-rw-r--r--dbus/dbus-message.h39
-rw-r--r--dbus/dbus-sha.c16
-rw-r--r--dbus/dbus-sysdeps.c321
-rw-r--r--dbus/dbus-sysdeps.h30
-rw-r--r--glib/test-dbus-glib.c20
-rw-r--r--glib/test-thread-client.c9
-rw-r--r--test/bus-test.c56
-rw-r--r--test/data/valid-messages/dict-simple.message3
-rw-r--r--test/data/valid-messages/dict.message5
-rw-r--r--test/data/valid-messages/lots-of-arguments.message3
-rw-r--r--test/data/valid-messages/no-padding.message4
-rw-r--r--test/data/valid-messages/simplest-manual.message3
-rw-r--r--test/data/valid-messages/simplest.message3
-rw-r--r--test/echo-client.c8
-rw-r--r--test/unbase64.c10
-rw-r--r--test/watch.c8
48 files changed, 2605 insertions, 939 deletions
diff --git a/ChangeLog b/ChangeLog
index 36f27b9e..c7bc4362 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,65 @@
+2003-03-12 Havoc Pennington <hp@redhat.com>
+
+ Mega-patch that gets the message bus daemon initially handling
+ out-of-memory. Work still needed. Also lots of random
+ moving stuff to DBusError instead of ResultCode.
+
+ * dbus/dbus-list.c (_dbus_list_length_is_one): new function
+
+ * dbus/dbus-connection.c
+ (dbus_connection_send_with_reply_and_block): use DBusError
+
+ * dbus/dbus-bus.c: adapt to API changes, make it use DBusError not
+ DBusResultCode
+
+ * dbus/dbus-connection.c (dbus_connection_send): drop the result
+ code here, as the only failure possible is OOM.
+
+ * bus/connection.c (bus_connection_disconnect):
+ rename bus_connection_disconnected as it's a notification only
+
+ * bus/driver.c (bus_driver_handle_acquire_service): don't free
+ "name" on get_args failure, should be done by get_args;
+ don't disconnect client for bad args, just return an error.
+ (bus_driver_handle_service_exists): ditto
+
+ * bus/services.c (bus_services_list): NULL-terminate returned array
+
+ * bus/driver.c (bus_driver_send_service_lost)
+ (bus_driver_send_service_acquired): send messages from driver to a
+ specific client to the client's unique name, not to the broadcast
+ service.
+
+ * dbus/dbus-message.c (decode_header_data): reject messages that
+ contain no name field
+ (_dbus_message_get_client_serial): rename to
+ dbus_message_get_serial and make public
+ (_dbus_message_set_serial): rename from set_client_serial
+ (_dbus_message_set_reply_serial): make public
+ (_dbus_message_get_reply_serial): make public
+
+ * bus/connection.c (bus_connection_foreach): allow stopping
+ iteration by returning FALSE from foreach function.
+
+ * dbus/dbus-connection.c (dbus_connection_send_preallocated)
+ (dbus_connection_free_preallocated_send)
+ (dbus_connection_preallocate_send): new API for sending a message
+ without possibility of malloc failure.
+ (dbus_connection_send_message): rename to just
+ dbus_connection_send (and same for whole function family)
+
+ * dbus/dbus-errors.c (dbus_error_free): make this reinit the error
+
+ * dbus/dbus-sysdeps.c (_dbus_exit): new function
+
+ * bus/activation.c: handle/return errors
+
+ * dbus/dbus-errors.h: add more DBUS_ERROR #define
+
+ * dbus/dbus-sysdeps.c (_dbus_directory_open) (_dbus_file_get_contents)
+ (_dbus_directory_get_next_file): use DBusError instead of DBusResultCode
+ (_dbus_result_from_errno): move to this file
+
2003-03-10 Anders Carlsson <andersca@codefactory.se>
* dbus/dbus-marshal.c:
diff --git a/bus/activation.c b/bus/activation.c
index b5cec44a..4e428bde 100644
--- a/bus/activation.c
+++ b/bus/activation.c
@@ -59,18 +59,24 @@ bus_activation_entry_free (BusActivationEntry *entry)
}
static dbus_bool_t
-add_desktop_file_entry (BusDesktopFile *desktop_file)
+add_desktop_file_entry (BusDesktopFile *desktop_file,
+ DBusError *error)
{
char *name, *exec;
BusActivationEntry *entry;
+
+ name = NULL;
+ exec = NULL;
+ entry = NULL;
if (!bus_desktop_file_get_string (desktop_file,
DBUS_SERVICE_SECTION,
DBUS_SERVICE_NAME,
&name))
{
- _dbus_verbose ("No \""DBUS_SERVICE_NAME"\" key in .service file\n");
- return FALSE;
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "No \""DBUS_SERVICE_NAME"\" key in .service file\n");
+ goto failed;
}
if (!bus_desktop_file_get_string (desktop_file,
@@ -78,57 +84,104 @@ add_desktop_file_entry (BusDesktopFile *desktop_file)
DBUS_SERVICE_EXEC,
&exec))
{
- _dbus_verbose ("No \""DBUS_SERVICE_EXEC"\" key in .service file\n");
-
- dbus_free (name);
- return FALSE;
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "No \""DBUS_SERVICE_EXEC"\" key in .service file\n");
+ goto failed;
}
+ /* FIXME we need a better-defined algorithm for which service file to
+ * pick than "whichever one is first in the directory listing"
+ */
if (_dbus_hash_table_lookup_string (activation_entries, name))
{
- _dbus_verbose ("Service %s already exists in activation entry list\n", name);
- dbus_free (name);
- dbus_free (exec);
-
- return FALSE;
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Service %s already exists in activation entry list\n", name);
+ goto failed;
+ }
+
+ entry = dbus_new0 (BusActivationEntry, 1);
+ if (entry == NULL)
+ {
+ BUS_SET_OOM (error);
+ goto failed;
}
- BUS_HANDLE_OOM (entry = dbus_malloc0 (sizeof (BusActivationEntry)));
entry->name = name;
entry->exec = exec;
- BUS_HANDLE_OOM (_dbus_hash_table_insert_string (activation_entries, entry->name, entry));
+ if (!_dbus_hash_table_insert_string (activation_entries, entry->name, entry))
+ {
+ BUS_SET_OOM (error);
+ goto failed;
+ }
_dbus_verbose ("Added \"%s\" to list of services\n", entry->name);
return TRUE;
+
+ failed:
+ dbus_free (name);
+ dbus_free (exec);
+ dbus_free (entry);
+
+ return FALSE;
}
-static void
-load_directory (const char *directory)
+/* warning: this doesn't fully "undo" itself on failure, i.e. doesn't strip
+ * hash entries it already added.
+ */
+static dbus_bool_t
+load_directory (const char *directory,
+ DBusError *error)
{
DBusDirIter *iter;
DBusString dir, filename;
- DBusResultCode result;
-
+ DBusString full_path;
+ BusDesktopFile *desktop_file;
+ DBusError tmp_error;
+
_dbus_string_init_const (&dir, directory);
+
+ iter = NULL;
+ desktop_file = NULL;
- iter = _dbus_directory_open (&dir, &result);
- if (iter == NULL)
+ if (!_dbus_string_init (&filename, _DBUS_INT_MAX))
{
- _dbus_verbose ("Failed to open directory %s: &s\n", directory,
- result);
- return;
+ BUS_SET_OOM (error);
+ return FALSE;
}
- BUS_HANDLE_OOM (_dbus_string_init (&filename, _DBUS_INT_MAX));
+ if (!_dbus_string_init (&full_path, _DBUS_INT_MAX))
+ {
+ BUS_SET_OOM (error);
+ _dbus_string_free (&filename);
+ return FALSE;
+ }
+
+ /* from this point it's safe to "goto failed" */
+
+ iter = _dbus_directory_open (&dir, error);
+ if (iter == NULL)
+ {
+ _dbus_verbose ("Failed to open directory %s: %s\n",
+ directory, error ? error->message : "unknown");
+ goto failed;
+ }
/* Now read the files */
- while (_dbus_directory_get_next_file (iter, &filename, &result))
+ dbus_error_init (&tmp_error);
+ while (_dbus_directory_get_next_file (iter, &filename, &tmp_error))
{
- DBusString full_path;
- BusDesktopFile *desktop_file;
- DBusError error;
+ _dbus_assert (!dbus_error_is_set (&tmp_error));
+
+ _dbus_string_set_length (&full_path, 0);
+
+ if (!_dbus_string_append (&full_path, directory) ||
+ !_dbus_concat_dir_and_file (&full_path, &filename))
+ {
+ BUS_SET_OOM (error);
+ goto failed;
+ }
if (!_dbus_string_ends_with_c_str (&filename, ".service"))
{
@@ -136,71 +189,133 @@ load_directory (const char *directory)
_dbus_string_get_const_data (&filename, &filename_c);
_dbus_verbose ("Skipping non-.service file %s\n",
filename_c);
- continue;
+ continue;
}
- BUS_HANDLE_OOM (_dbus_string_init (&full_path, _DBUS_INT_MAX));
- BUS_HANDLE_OOM (_dbus_string_append (&full_path, directory));
-
- BUS_HANDLE_OOM (_dbus_concat_dir_and_file (&full_path, &filename));
+ desktop_file = bus_desktop_file_load (&full_path, &tmp_error);
- desktop_file = bus_desktop_file_load (&full_path, &error);
-
- if (!desktop_file)
+ if (desktop_file == NULL)
{
const char *full_path_c;
_dbus_string_get_const_data (&full_path, &full_path_c);
_dbus_verbose ("Could not load %s: %s\n", full_path_c,
- error.message);
- dbus_error_free (&error);
- _dbus_string_free (&full_path);
+ tmp_error.message);
+
+ if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
+ {
+ dbus_move_error (&tmp_error, error);
+ goto failed;
+ }
+
+ dbus_error_free (&tmp_error);
continue;
}
- if (!add_desktop_file_entry (desktop_file))
+ if (!add_desktop_file_entry (desktop_file, &tmp_error))
{
const char *full_path_c;
+ bus_desktop_file_free (desktop_file);
+ desktop_file = NULL;
+
_dbus_string_get_const_data (&full_path, &full_path_c);
- _dbus_verbose ("Could not add %s to activation entry list.\n", full_path_c);
+ _dbus_verbose ("Could not add %s to activation entry list: %s\n",
+ full_path_c, tmp_error.message);
+
+ if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
+ {
+ dbus_move_error (&tmp_error, error);
+ goto failed;
+ }
+
+ dbus_error_free (&tmp_error);
+ continue;
}
+ else
+ {
+ bus_desktop_file_free (desktop_file);
+ desktop_file = NULL;
+ continue;
+ }
+ }
- bus_desktop_file_free (desktop_file);
- _dbus_string_free (&full_path);
+ if (dbus_error_is_set (&tmp_error))
+ {
+ dbus_move_error (&tmp_error, error);
+ goto failed;
}
+
+ return TRUE;
+
+ failed:
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+
+ if (iter != NULL)
+ _dbus_directory_close (iter);
+ if (desktop_file)
+ bus_desktop_file_free (desktop_file);
+ _dbus_string_free (&filename);
+ _dbus_string_free (&full_path);
+
+ return FALSE;
}
-
-void
-bus_activation_init (const char *address,
- const char **directories)
+dbus_bool_t
+bus_activation_init (const char *address,
+ const char **directories,
+ DBusError *error)
{
int i;
+ _dbus_assert (server_address == NULL);
+ _dbus_assert (activation_entries == NULL);
+
/* FIXME: We should split up the server addresses. */
- BUS_HANDLE_OOM (server_address = _dbus_strdup (address));
+ server_address = _dbus_strdup (address);
+ if (server_address == NULL)
+ {
+ BUS_SET_OOM (error);
+ goto failed;
+ }
- BUS_HANDLE_OOM (activation_entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
- (DBusFreeFunction)bus_activation_entry_free));
-
- i = 0;
+ activation_entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
+ (DBusFreeFunction)bus_activation_entry_free);
+ if (activation_entries == NULL)
+ {
+ BUS_SET_OOM (error);
+ goto failed;
+ }
/* Load service files */
+ i = 0;
while (directories[i] != NULL)
{
- load_directory (directories[i]);
- i++;
+ if (!load_directory (directories[i], error))
+ goto failed;
+ ++i;
}
+
+ return TRUE;
+
+ failed:
+ dbus_free (server_address);
+ if (activation_entries)
+ _dbus_hash_table_unref (activation_entries);
+
+ return FALSE;
}
static void
child_setup (void *data)
{
- /* FIXME: Check return value in case of OOM */
- _dbus_setenv ("DBUS_ADDRESS", server_address);
+ /* If no memory, we simply have the child exit, so it won't try
+ * to connect to the wrong thing.
+ */
+ if (!_dbus_setenv ("DBUS_ADDRESS", server_address))
+ _dbus_exit (1);
}
dbus_bool_t
@@ -220,6 +335,10 @@ bus_activation_activate_service (const char *service_name,
return FALSE;
}
+ /* FIXME we need to support a full command line, not just a single
+ * argv[0]
+ */
+
/* Now try to spawn the process */
argv[0] = entry->exec;
argv[1] = NULL;
diff --git a/bus/activation.h b/bus/activation.h
index 5f29871e..e7a9cdfc 100644
--- a/bus/activation.h
+++ b/bus/activation.h
@@ -26,8 +26,9 @@
#include <dbus/dbus.h>
-void bus_activation_init (const char *address,
- const char **paths);
+dbus_bool_t bus_activation_init (const char *address,
+ const char **paths,
+ DBusError *error);
dbus_bool_t bus_activation_activate_service (const char *service_name,
DBusError *error);
diff --git a/bus/connection.c b/bus/connection.c
index 40bbc325..ff671c58 100644
--- a/bus/connection.c
+++ b/bus/connection.c
@@ -24,34 +24,79 @@
#include "dispatch.h"
#include "loop.h"
#include "services.h"
+#include "utils.h"
#include <dbus/dbus-list.h>
+static void bus_connection_remove_transactions (DBusConnection *connection);
+
static int connection_data_slot;
static DBusList *connections = NULL;
typedef struct
{
+ DBusConnection *connection;
DBusList *services_owned;
-
char *name;
+ DBusList *transaction_messages; /**< Stuff we need to send as part of a transaction */
+ DBusMessage *oom_message;
+ DBusPreallocatedSend *oom_preallocated;
} BusConnectionData;
#define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot))
void
-bus_connection_disconnect (DBusConnection *connection)
+bus_connection_disconnected (DBusConnection *connection)
{
BusConnectionData *d;
BusService *service;
-
+
_dbus_warn ("Disconnected\n");
d = BUS_CONNECTION_DATA (connection);
_dbus_assert (d != NULL);
- /* Drop any service ownership */
- while ((service = _dbus_list_get_last (&d->services_owned)))
- bus_service_remove_owner (service, connection);
+ /* Drop any service ownership. FIXME Unfortunately, this requires
+ * memory allocation and there doesn't seem to be a good way to
+ * handle it other than sleeping; we can't "fail" the operation of
+ * disconnecting a client, and preallocating a broadcast "service is
+ * now gone" message for every client-service pair seems kind of
+ * involved. Probably we need to do that though, and also
+ * extend BusTransaction to be able to revert generic
+ * stuff, not just sending a message (so we can e.g. revert
+ * removal of service owners).
+ */
+ {
+ BusTransaction *transaction;
+ DBusError error;
+
+ dbus_error_init (&error);
+
+ transaction = NULL;
+ while (transaction == NULL)
+ {
+ transaction = bus_transaction_new ();
+ bus_wait_for_memory ();
+ }
+
+ while ((service = _dbus_list_get_last (&d->services_owned)))
+ {
+ retry:
+ if (!bus_service_remove_owner (service, connection,
+ transaction, &error))
+ {
+ if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+ {
+ dbus_error_free (&error);
+ bus_wait_for_memory ();
+ goto retry;
+ }
+ else
+ _dbus_assert_not_reached ("Removing service owner failed for non-memory-related reason");
+ }
+ }
+
+ bus_transaction_execute_and_free (transaction);
+ }
bus_dispatch_remove_connection (connection);
@@ -60,12 +105,14 @@ bus_connection_disconnect (DBusConnection *connection)
NULL, NULL,
connection,
NULL);
+
+ bus_connection_remove_transactions (connection);
dbus_connection_set_data (connection,
connection_data_slot,
NULL, NULL);
- _dbus_list_remove (&connections, connection);
+ _dbus_list_remove (&connections, connection);
dbus_connection_unref (connection);
}
@@ -106,7 +153,14 @@ free_connection_data (void *data)
/* services_owned should be NULL since we should be disconnected */
_dbus_assert (d->services_owned == NULL);
+ /* similarly */
+ _dbus_assert (d->transaction_messages == NULL);
+ if (d->oom_preallocated)
+ dbus_connection_free_preallocated_send (d->connection, d->oom_preallocated);
+ if (d->oom_message)
+ dbus_message_unref (d->oom_message);
+
dbus_free (d->name);
dbus_free (d);
@@ -132,6 +186,8 @@ bus_connection_setup (DBusConnection *connection)
if (d == NULL)
return FALSE;
+
+ d->connection = connection;
if (!dbus_connection_set_data (connection,
connection_data_slot,
@@ -163,6 +219,88 @@ bus_connection_setup (DBusConnection *connection)
return TRUE;
}
+/**
+ * Checks whether the connection is registered with the message bus.
+ *
+ * @param connection the connection
+ * @returns #TRUE if we're an active message bus participant
+ */
+dbus_bool_t
+bus_connection_is_active (DBusConnection *connection)
+{
+ BusConnectionData *d;
+
+ d = BUS_CONNECTION_DATA (connection);
+
+ return d != NULL && d->name != NULL;
+}
+
+dbus_bool_t
+bus_connection_preallocate_oom_error (DBusConnection *connection)
+{
+ DBusMessage *message;
+ DBusPreallocatedSend *preallocated;
+ BusConnectionData *d;
+
+ d = BUS_CONNECTION_DATA (connection);
+
+ _dbus_assert (d != NULL);
+
+ if (d->oom_preallocated != NULL)
+ return TRUE;
+
+ preallocated = dbus_connection_preallocate_send (connection);
+ if (preallocated == NULL)
+ return FALSE;
+
+ message = dbus_message_new (DBUS_SERVICE_DBUS,
+ DBUS_ERROR_NO_MEMORY);
+ if (message == NULL)
+ {
+ dbus_connection_free_preallocated_send (connection, preallocated);
+ return FALSE;
+ }
+
+ /* set reply serial to placeholder value just so space is already allocated
+ * for it.
+ */
+ if (!dbus_message_set_reply_serial (message, 14))
+ {
+ dbus_connection_free_preallocated_send (connection, preallocated);
+ dbus_message_unref (message);
+ return FALSE;
+ }
+
+ d->oom_message = message;
+ d->oom_preallocated = preallocated;
+
+ return TRUE;
+}
+
+void
+bus_connection_send_oom_error (DBusConnection *connection,
+ DBusMessage *in_reply_to)
+{
+ BusConnectionData *d;
+
+ d = BUS_CONNECTION_DATA (connection);
+
+ _dbus_assert (d != NULL);
+ _dbus_assert (d->oom_message != NULL);
+
+ /* should always succeed since we set it to a placeholder earlier */
+ if (!dbus_message_set_reply_serial (d->oom_message,
+ dbus_message_get_serial (in_reply_to)))
+ _dbus_assert_not_reached ("Failed to set reply serial for preallocated oom message");
+
+ dbus_connection_send_preallocated (connection, d->oom_preallocated,
+ d->oom_message, NULL);
+
+ dbus_message_unref (d->oom_message);
+ d->oom_message = NULL;
+ d->oom_preallocated = NULL;
+}
+
dbus_bool_t
bus_connection_add_owned_service (DBusConnection *connection,
BusService *service)
@@ -223,9 +361,277 @@ bus_connection_get_name (DBusConnection *connection)
return d->name;
}
+/**
+ * Calls function on each connection; if the function returns
+ * #FALSE, stops iterating.
+ *
+ * @param function the function
+ * @param data data to pass to it as a second arg
+ */
void
bus_connection_foreach (BusConnectionForeachFunction function,
void *data)
{
- _dbus_list_foreach (&connections, (DBusForeachFunction)function, data);
+ DBusList *link;
+
+ link = _dbus_list_get_first_link (&connections);
+ while (link != NULL)
+ {
+ DBusConnection *connection = link->data;
+ DBusList *next = _dbus_list_get_next_link (&connections, link);
+
+ if (!(* function) (connection, data))
+ break;
+
+ link = next;
+ }
+}
+
+typedef struct
+{
+ BusTransaction *transaction;
+ DBusMessage *message;
+ DBusPreallocatedSend *preallocated;
+} MessageToSend;
+
+struct BusTransaction
+{
+ DBusList *connections;
+
+};
+
+static void
+message_to_send_free (DBusConnection *connection,
+ MessageToSend *to_send)
+{
+ if (to_send->message)
+ dbus_message_unref (to_send->message);
+
+ if (to_send->preallocated)
+ dbus_connection_free_preallocated_send (connection, to_send->preallocated);
+
+ dbus_free (to_send);
+}
+
+BusTransaction*
+bus_transaction_new (void)
+{
+ BusTransaction *transaction;
+
+ transaction = dbus_new0 (BusTransaction, 1);
+ if (transaction == NULL)
+ return NULL;
+
+ return transaction;
+}
+
+dbus_bool_t
+bus_transaction_send_message (BusTransaction *transaction,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ MessageToSend *to_send;
+ BusConnectionData *d;
+ DBusList *link;
+
+ if (!dbus_connection_get_is_connected (connection))
+ return TRUE; /* silently ignore disconnected connections */
+
+ d = BUS_CONNECTION_DATA (connection);
+ _dbus_assert (d != NULL);
+
+ to_send = dbus_new (MessageToSend, 1);
+ if (to_send == NULL)
+ {
+ return FALSE;
+ }
+
+ to_send->preallocated = dbus_connection_preallocate_send (connection);
+ if (to_send->preallocated == NULL)
+ {
+ dbus_free (to_send);
+ return FALSE;
+ }
+
+ dbus_message_ref (message);
+ to_send->message = message;
+ to_send->transaction = transaction;
+
+ if (!_dbus_list_prepend (&d->transaction_messages, to_send))
+ {
+ message_to_send_free (connection, to_send);
+ return FALSE;
+ }
+
+ /* See if we already had this connection in the list
+ * for this transaction. If we have a pending message,
+ * then we should already be in transaction->connections
+ */
+ link = _dbus_list_get_first_link (&d->transaction_messages);
+ _dbus_assert (link->data == to_send);
+ link = _dbus_list_get_next_link (&d->transaction_messages, link);
+ while (link != NULL)
+ {
+ MessageToSend *m = link->data;
+ DBusList *next = _dbus_list_get_next_link (&d->transaction_messages, link);
+
+ if (m->transaction == transaction)
+ break;
+
+ link = next;
+ }
+
+ if (link == NULL)
+ {
+ if (!_dbus_list_prepend (&transaction->connections, connection))
+ {
+ _dbus_list_remove (&d->transaction_messages, to_send);
+ message_to_send_free (connection, to_send);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+connection_cancel_transaction (DBusConnection *connection,
+ BusTransaction *transaction)
+{
+ DBusList *link;
+ BusConnectionData *d;
+
+ d = BUS_CONNECTION_DATA (connection);
+ _dbus_assert (d != NULL);
+
+ link = _dbus_list_get_first_link (&d->transaction_messages);
+ while (link != NULL)
+ {
+ MessageToSend *m = link->data;
+ DBusList *next = _dbus_list_get_next_link (&d->transaction_messages, link);
+
+ if (m->transaction == transaction)
+ {
+ _dbus_list_remove_link (&d->transaction_messages,
+ link);
+
+ message_to_send_free (connection, m);
+ }
+
+ link = next;
+ }
+}
+
+void
+bus_transaction_cancel_and_free (BusTransaction *transaction)
+{
+ DBusConnection *connection;
+
+ while ((connection = _dbus_list_pop_first (&transaction->connections)))
+ connection_cancel_transaction (connection, transaction);
+
+ _dbus_assert (transaction->connections == NULL);
+
+ dbus_free (transaction);
+}
+
+static void
+connection_execute_transaction (DBusConnection *connection,
+ BusTransaction *transaction)
+{
+ DBusList *link;
+ BusConnectionData *d;
+
+ d = BUS_CONNECTION_DATA (connection);
+ _dbus_assert (d != NULL);
+
+ /* Send the queue in order (FIFO) */
+ link = _dbus_list_get_last_link (&d->transaction_messages);
+ while (link != NULL)
+ {
+ MessageToSend *m = link->data;
+ DBusList *prev = _dbus_list_get_prev_link (&d->transaction_messages, link);
+
+ if (m->transaction == transaction)
+ {
+ _dbus_list_remove_link (&d->transaction_messages,
+ link);
+
+ dbus_connection_send_preallocated (connection,
+ m->preallocated,
+ m->message,
+ NULL);
+
+ m->preallocated = NULL; /* so we don't double-free it */
+
+ message_to_send_free (connection, m);
+ }
+
+ link = prev;
+ }
+}
+
+void
+bus_transaction_execute_and_free (BusTransaction *transaction)
+{
+ /* For each connection in transaction->connections
+ * send the messages
+ */
+ DBusConnection *connection;
+
+ while ((connection = _dbus_list_pop_first (&transaction->connections)))
+ connection_execute_transaction (connection, transaction);
+
+ _dbus_assert (transaction->connections == NULL);
+
+ dbus_free (transaction);
+}
+
+static void
+bus_connection_remove_transactions (DBusConnection *connection)
+{
+ MessageToSend *to_send;
+ BusConnectionData *d;
+
+ d = BUS_CONNECTION_DATA (connection);
+ _dbus_assert (d != NULL);
+
+ while ((to_send = _dbus_list_get_first (&d->transaction_messages)))
+ {
+ /* only has an effect for the first MessageToSend listing this transaction */
+ _dbus_list_remove (&to_send->transaction->connections,
+ connection);
+
+ _dbus_list_remove (&d->transaction_messages, to_send);
+ message_to_send_free (connection, to_send);
+ }
+}
+
+/**
+ * Converts the DBusError to a message reply
+ */
+dbus_bool_t
+bus_transaction_send_error_reply (BusTransaction *transaction,
+ DBusConnection *connection,
+ const DBusError *error,
+ DBusMessage *in_reply_to)
+{
+ DBusMessage *reply;
+
+ _dbus_assert (error != NULL);
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+
+ reply = dbus_message_new_error_reply (in_reply_to,
+ error->name,
+ error->message);
+ if (reply == NULL)
+ return FALSE;
+
+ if (!bus_transaction_send_message (transaction, connection, reply))
+ {
+ dbus_message_unref (reply);
+ return FALSE;
+ }
+
+ return TRUE;
}
diff --git a/bus/connection.h b/bus/connection.h
index 04ab1f08..a7a448a1 100644
--- a/bus/connection.h
+++ b/bus/connection.h
@@ -27,13 +27,19 @@
#include <dbus/dbus.h>
#include "services.h"
-typedef void (* BusConnectionForeachFunction) (DBusConnection *connection,
- void *data);
+typedef dbus_bool_t (* BusConnectionForeachFunction) (DBusConnection *connection,
+ void *data);
dbus_bool_t bus_connection_init (void);
dbus_bool_t bus_connection_setup (DBusConnection *connection);
+dbus_bool_t bus_connection_is_active (DBusConnection *connection);
+
+dbus_bool_t bus_connection_preallocate_oom_error (DBusConnection *connection);
+void bus_connection_send_oom_error (DBusConnection *connection,
+ DBusMessage *in_reply_to);
+
/* called by services.c */
dbus_bool_t bus_connection_add_owned_service (DBusConnection *connection,
BusService *service);
@@ -47,8 +53,20 @@ const char *bus_connection_get_name (DBusConnection *connection);
void bus_connection_foreach (BusConnectionForeachFunction function,
void *data);
-/* called by dispatch.c */
-void bus_connection_disconnect (DBusConnection *connection);
+/* called by dispatch.c when the connection is dropped */
+void bus_connection_disconnected (DBusConnection *connection);
+
+/* transaction API so we can send or not send a block of messages as a whole */
+BusTransaction* bus_transaction_new (void);
+dbus_bool_t bus_transaction_send_message (BusTransaction *transaction,
+ DBusConnection *connection,
+ DBusMessage *message);
+dbus_bool_t bus_transaction_send_error_reply (BusTransaction *transaction,
+ DBusConnection *connection,
+ const DBusError *error,
+ DBusMessage *in_reply_to);
+void bus_transaction_cancel_and_free (BusTransaction *transaction);
+void bus_transaction_execute_and_free (BusTransaction *transaction);
#endif /* BUS_CONNECTION_H */
diff --git a/bus/desktop-file.c b/bus/desktop-file.c
index 0ab6afc8..65a0d76f 100644
--- a/bus/desktop-file.c
+++ b/bus/desktop-file.c
@@ -125,7 +125,7 @@ bus_desktop_file_free (BusDesktopFile *desktop_file)
dbus_free (desktop_file);
}
-static void
+static dbus_bool_t
grow_lines_in_section (BusDesktopFileSection *section)
{
BusDesktopFileLine *lines;
@@ -137,14 +137,19 @@ grow_lines_in_section (BusDesktopFileSection *section)
else
new_n_lines = section->n_allocated_lines*2;
- BUS_HANDLE_OOM (lines = dbus_realloc (section->lines,
- sizeof (BusDesktopFileLine) * new_n_lines));
- section->lines = lines;
+ lines = dbus_realloc (section->lines,
+ sizeof (BusDesktopFileLine) * new_n_lines);
+
+ if (lines == NULL)
+ return FALSE;
+ section->lines = lines;
section->n_allocated_lines = new_n_lines;
+
+ return TRUE;
}
-static void
+static dbus_bool_t
grow_sections (BusDesktopFile *desktop_file)
{
int new_n_sections;
@@ -155,21 +160,36 @@ grow_sections (BusDesktopFile *desktop_file)
else
new_n_sections = desktop_file->n_allocated_sections*2;
- BUS_HANDLE_OOM (sections = dbus_realloc (desktop_file->sections,
- sizeof (BusDesktopFileSection) * new_n_sections));
+ sections = dbus_realloc (desktop_file->sections,
+ sizeof (BusDesktopFileSection) * new_n_sections);
+ if (sections == NULL)
+ return FALSE;
+
desktop_file->sections = sections;
desktop_file->n_allocated_sections = new_n_sections;
+
+ return TRUE;
}
static char *
-unescape_string (const DBusString *str, int pos, int end_pos)
+unescape_string (BusDesktopFileParser *parser,
+ const DBusString *str,
+ int pos,
+ int end_pos,
+ DBusError *error)
{
char *retval, *q;
/* len + 1 is enough, because unescaping never makes the
- * string longer */
- BUS_HANDLE_OOM (retval = dbus_malloc (end_pos - pos + 1));
+ * string longer
+ */
+ retval = dbus_malloc (end_pos - pos + 1);
+ if (retval == NULL)
+ {
+ BUS_SET_OOM (error);
+ return NULL;
+ }
q = retval;
@@ -179,6 +199,8 @@ unescape_string (const DBusString *str, int pos, int end_pos)
{
/* Found an embedded null */
dbus_free (retval);
+ report_error (parser, "Text to be unescaped contains embedded nul",
+ BUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error);
return NULL;
}
@@ -190,6 +212,8 @@ unescape_string (const DBusString *str, int pos, int end_pos)
{
/* Escape at end of string */
dbus_free (retval);
+ report_error (parser, "Text to be unescaped ended in \\",
+ BUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error);
return NULL;
}
@@ -213,7 +237,9 @@ unescape_string (const DBusString *str, int pos, int end_pos)
default:
/* Invalid escape code */
dbus_free (retval);
- return NULL;
+ report_error (parser, "Text to be unescaped had invalid escape sequence",
+ BUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error);
+ return NULL;
}
pos++;
}
@@ -235,20 +261,34 @@ new_section (BusDesktopFile *desktop_file,
const char *name)
{
int n;
+ char *name_copy;
if (desktop_file->n_allocated_sections == desktop_file->n_sections)
- grow_sections (desktop_file);
-
- n = desktop_file->n_sections++;
+ {
+ if (!grow_sections (desktop_file))
+ return NULL;
+ }
- BUS_HANDLE_OOM (desktop_file->sections[n].section_name = _dbus_strdup (name));
+ name_copy = _dbus_strdup (name);
+ if (name_copy == NULL)
+ return NULL;
+
+ n = desktop_file->n_sections + 1;
+ desktop_file->sections[n].section_name = name_copy;
desktop_file->sections[n].n_lines = 0;
desktop_file->sections[n].lines = NULL;
desktop_file->sections[n].n_allocated_lines = 0;
- grow_lines_in_section (&desktop_file->sections[n]);
+ if (!grow_lines_in_section (&desktop_file->sections[n]))
+ {
+ dbus_free (desktop_file->sections[n].section_name);
+ desktop_file->sections[n].section_name = NULL;
+ return NULL;
+ }
+ desktop_file->n_sections = n;
+
return &desktop_file->sections[n];
}
@@ -277,7 +317,10 @@ new_line (BusDesktopFileParser *parser)
section = &parser->desktop_file->sections[parser->current_section];
if (section->n_allocated_lines == section->n_lines)
- grow_lines_in_section (section);
+ {
+ if (!grow_lines_in_section (section))
+ return NULL;
+ }
line = &section->lines[section->n_lines++];
@@ -358,11 +401,12 @@ parse_section_start (BusDesktopFileParser *parser, DBusError *error)
return FALSE;
}
- section_name = unescape_string (&parser->data, parser->pos + 1, line_end - 1);
+ section_name = unescape_string (parser,
+ &parser->data, parser->pos + 1, line_end - 1,
+ error);
if (section_name == NULL)
{
- report_error (parser, "Invalid escaping in section name", BUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error);
parser_free (parser);
return FALSE;
}
@@ -450,20 +494,39 @@ parse_key_value (BusDesktopFileParser *parser, DBusError *error)
value_start = p;
- value = unescape_string (&parser->data, value_start, line_end);
+ value = unescape_string (parser, &parser->data, value_start, line_end, error);
if (value == NULL)
{
- report_error (parser, "Invalid escaping in value", BUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error);
parser_free (parser);
return FALSE;
}
line = new_line (parser);
-
- BUS_HANDLE_OOM (_dbus_string_init (&key, key_end - key_start));
- BUS_HANDLE_OOM (_dbus_string_copy_len (&parser->data, key_start, key_end - key_start,
- &key, 0));
- BUS_HANDLE_OOM (_dbus_string_steal_data (&key, &tmp));
+ if (line == NULL)
+ {
+ parser_free (parser);
+ return FALSE;
+ }
+
+ if (!_dbus_string_init (&key, key_end - key_start))
+ {
+ parser_free (parser);
+ return FALSE;
+ }
+
+ if (!_dbus_string_copy_len (&parser->data, key_start, key_end - key_start,
+ &key, 0))
+ {
+ parser_free (parser);
+ return FALSE;
+ }
+
+ if (!_dbus_string_steal_data (&key, &tmp))
+ {
+ parser_free (parser);
+ return FALSE;
+ }
+
_dbus_string_free (&key);
line->key = tmp;
@@ -491,11 +554,11 @@ report_error (BusDesktopFileParser *parser,
section_name = parser->desktop_file->sections[parser->current_section].section_name;
if (section_name)
- BUS_HANDLE_OOM (dbus_set_error (error, error_name,
- "Error in section %s at line %d: %s\n", section_name, parser->line_num, message));
+ dbus_set_error (error, error_name,
+ "Error in section %s at line %d: %s\n", section_name, parser->line_num, message);
else
- BUS_HANDLE_OOM (dbus_set_error (error, error_name,
- "Error at line %d: %s\n", parser->line_num, message));
+ dbus_set_error (error, error_name,
+ "Error at line %d: %s\n", parser->line_num, message);
}
#if 0
@@ -519,39 +582,52 @@ dump_desktop_file (BusDesktopFile *file)
}
#endif
-BusDesktopFile *
+BusDesktopFile*
bus_desktop_file_load (DBusString *filename,
DBusError *error)
{
DBusString str;
- DBusResultCode result_code;
BusDesktopFileParser parser;
+ DBusStat sb;
- /* FIXME: Check file size so we don't try to load a ridicously large file. */
+ /* Clearly there's a race here, but it's just to make it unlikely
+ * that we do something silly, we still handle doing it below.
+ */
+ if (!_dbus_stat (filename, &sb, error))
+ return NULL;
- BUS_HANDLE_OOM (_dbus_string_init (&str, _DBUS_INT_MAX));
+ if (sb.size > _DBUS_ONE_KILOBYTE * 128)
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Desktop file size (%ld bytes) is too large", (long) sb.size);
+ return NULL;
+ }
- BUS_HANDLE_OOM ((result_code = _dbus_file_get_contents (&str, filename)) !=
- DBUS_RESULT_NO_MEMORY);
+ if (!_dbus_string_init (&str, _DBUS_INT_MAX))
+ return NULL;
- if (result_code != DBUS_RESULT_SUCCESS)
+ if (!_dbus_file_get_contents (&str, filename, error))
{
_dbus_string_free (&str);
-
- /* FIXME: Set error */
return NULL;
}
if (!_dbus_string_validate_utf8 (&str, 0, _dbus_string_get_length (&str)))
{
_dbus_string_free (&str);
-
- /* FIXME: Set error */
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "invalid UTF-8");
+ return NULL;
+ }
+
+ parser.desktop_file = dbus_new0 (BusDesktopFile, 1);
+ if (parser.desktop_file == NULL)
+ {
+ _dbus_string_free (&str);
+ BUS_SET_OOM (error);
return NULL;
}
- BUS_HANDLE_OOM (parser.desktop_file = dbus_malloc0 (sizeof (BusDesktopFile)));
-
parser.data = str;
parser.line_num = 1;
parser.pos = 0;
@@ -563,7 +639,10 @@ bus_desktop_file_load (DBusString *filename,
if (_dbus_string_get_byte (&parser.data, parser.pos) == '[')
{
if (!parse_section_start (&parser, error))
- return NULL;
+ {
+ _dbus_string_free (&parser.data);
+ return NULL;
+ }
}
else if (is_blank_line (&parser) ||
_dbus_string_get_byte (&parser.data, parser.pos) == '#')
@@ -571,7 +650,10 @@ bus_desktop_file_load (DBusString *filename,
else
{
if (!parse_key_value (&parser, error))
- return NULL;
+ {
+ _dbus_string_free (&parser.data);
+ return NULL;
+ }
}
}
@@ -661,7 +743,13 @@ bus_desktop_file_get_string (BusDesktopFile *desktop_file,
if (!bus_desktop_file_get_raw (desktop_file, section, keyname, &raw))
return FALSE;
- BUS_HANDLE_OOM (*val = _dbus_strdup (raw));
+ *val = _dbus_strdup (raw);
+
+ /* FIXME we don't distinguish "key not found" from "out of memory" here,
+ * which is broken.
+ */
+ if (*val == NULL)
+ return FALSE;
return TRUE;
}
diff --git a/bus/dispatch.c b/bus/dispatch.c
index 76e10a9f..d9fe81ac 100644
--- a/bus/dispatch.c
+++ b/bus/dispatch.c
@@ -30,23 +30,110 @@
static int message_handler_slot;
-static void
+typedef struct
+{
+ DBusMessage *message;
+ BusTransaction *transaction;
+ DBusError *error;
+} SendMessageData;
+
+static dbus_bool_t
send_one_message (DBusConnection *connection, void *data)
{
- /* Only send messages to registered connections */
- if (bus_connection_get_name (connection) == NULL)
- return;
+ SendMessageData *d = data;
- BUS_HANDLE_OOM (dbus_connection_send_message (connection, data, NULL, NULL));
+ if (!bus_connection_is_active (connection))
+ return TRUE;
+
+ if (!bus_transaction_send_message (d->transaction,
+ connection,
+ d->message))
+ {
+ BUS_SET_OOM (d->error);
+ return FALSE;
+ }
+
+ return TRUE;
}
-void
-bus_dispatch_broadcast_message (DBusMessage *message)
+dbus_bool_t
+bus_dispatch_broadcast_message (BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
{
- _dbus_assert (dbus_message_get_sender (message) != NULL);
-
- bus_connection_foreach (send_one_message, message);
+ DBusError tmp_error;
+ SendMessageData d;
+ _dbus_assert (dbus_message_get_sender (message) != NULL);
+
+ dbus_error_init (&tmp_error);
+ d.message = message;
+ d.transaction = transaction;
+ d.error = &tmp_error;
+ bus_connection_foreach (send_one_message, &d);
+
+ if (dbus_error_is_set (&tmp_error))
+ {
+ dbus_move_error (&tmp_error, error);
+ return FALSE;
+ }
+ else
+ return TRUE;
+}
+
+static dbus_bool_t
+send_service_nonexistent_error (BusTransaction *transaction,
+ DBusConnection *connection,
+ const char *service_name,
+ DBusMessage *in_reply_to,
+ DBusError *error)
+{
+ DBusMessage *error_reply;
+ DBusString error_message;
+ const char *error_str;
+
+ /* Trying to send a message to a non-existant service,
+ * bounce back an error message.
+ */
+
+ if (!_dbus_string_init (&error_message, _DBUS_INT_MAX))
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ if (!_dbus_string_append (&error_message, "Service \"") ||
+ !_dbus_string_append (&error_message, service_name) ||
+ !_dbus_string_append (&error_message, "does not exist"))
+ {
+ _dbus_string_free (&error_message);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ _dbus_string_get_const_data (&error_message, &error_str);
+ error_reply = dbus_message_new_error_reply (in_reply_to,
+ DBUS_ERROR_SERVICE_DOES_NOT_EXIST,
+ error_str);
+
+ _dbus_string_free (&error_message);
+
+ if (error_reply == NULL)
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ if (!bus_transaction_send_message (transaction, connection, error_reply))
+ {
+ dbus_message_unref (error_reply);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ dbus_message_unref (error_reply);
+
+ return TRUE;
}
static DBusHandlerResult
@@ -56,76 +143,164 @@ bus_dispatch_message_handler (DBusMessageHandler *handler,
void *user_data)
{
const char *sender, *service_name, *message_name;
+ DBusError error;
+ BusTransaction *transaction;
+
+ transaction = NULL;
+ dbus_error_init (&error);
- /* Assign a sender to the message */
- sender = bus_connection_get_name (connection);
- BUS_HANDLE_OOM (dbus_message_set_sender (message, sender));
+ /* If we can't even allocate an OOM error, we just go to sleep
+ * until we can.
+ */
+ while (!bus_connection_preallocate_oom_error (connection))
+ bus_wait_for_memory ();
+
+ /* Ref connection in case we disconnect it at some point in here */
+ dbus_connection_ref (connection);
service_name = dbus_message_get_service (message);
message_name = dbus_message_get_name (message);
+
+ _dbus_assert (message_name != NULL); /* DBusMessageLoader is supposed to check this */
+
+ /* If service_name is NULL, this is a message to the bus daemon, not intended
+ * to actually go "on the bus"; e.g. a peer-to-peer ping. Handle these
+ * immediately, especially disconnection messages.
+ */
+ if (service_name == NULL)
+ {
+ if (strcmp (message_name, DBUS_MESSAGE_LOCAL_DISCONNECT) == 0)
+ bus_connection_disconnected (connection);
+
+ /* DBusConnection also handles some of these automatically, we leave
+ * it to do so.
+ */
+ goto out;
+ }
+
+ _dbus_assert (service_name != NULL); /* this message is intended for bus routing */
- /* TODO: Crashes if service_name == NULL */
+ /* Create our transaction */
+ transaction = bus_transaction_new ();
+ if (transaction == NULL)
+ {
+ BUS_SET_OOM (&error);
+ goto out;
+ }
- /* See if the message is to the driver */
- if (message_name && strcmp (message_name, DBUS_MESSAGE_LOCAL_DISCONNECT) == 0)
+ /* Assign a sender to the message */
+ if (bus_connection_is_active (connection))
{
- bus_connection_disconnect (connection);
+ sender = bus_connection_get_name (connection);
+ _dbus_assert (sender != NULL);
+
+ if (!dbus_message_set_sender (message, sender))
+ {
+ BUS_SET_OOM (&error);
+ goto out;
+ }
}
- else if (strcmp (service_name, DBUS_SERVICE_DBUS) == 0)
+
+ if (strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
{
- bus_driver_handle_message (connection, message);
+ if (!bus_driver_handle_message (connection, transaction, message, &error))
+ goto out;
}
- else if (sender == NULL)
+ else if (!bus_connection_is_active (connection)) /* clients must talk to bus driver first */
{
_dbus_verbose ("Received message from non-registered client. Disconnecting.\n");
dbus_connection_disconnect (connection);
}
- else if (strcmp (service_name, DBUS_SERVICE_BROADCAST) == 0)
+ /* FIXME what if we un-special-case this service and just have a flag
+ * on services that all service owners will get messages to it, not just
+ * the primary owner.
+ */
+ else if (strcmp (service_name, DBUS_SERVICE_BROADCAST) == 0) /* spam! */
{
- bus_dispatch_broadcast_message (message);
+ if (!bus_dispatch_broadcast_message (transaction, message, &error))
+ goto out;
}
- else
+ else /* route to named service */
{
DBusString service_string;
BusService *service;
_dbus_string_init_const (&service_string, service_name);
- service = bus_service_lookup (&service_string, FALSE);
-
- if (!service)
- {
- DBusMessage *error_reply;
- DBusString error_message;
- const char *error_str;
-
- /* Trying to send a message to a non-existant service,
- bounce back an error message. */
-
- BUS_HANDLE_OOM (_dbus_string_init (&error_message, _DBUS_INT_MAX));
-
- BUS_HANDLE_OOM (_dbus_string_append (&error_message, "Service \""));
- BUS_HANDLE_OOM (_dbus_string_append (&error_message, service_name));
- BUS_HANDLE_OOM (_dbus_string_append (&error_message, "does not exist"));
+ service = bus_service_lookup (&service_string);
- _dbus_string_get_const_data (&error_message, &error_str);
- BUS_HANDLE_OOM (error_reply = dbus_message_new_error_reply (message, DBUS_ERROR_SERVICE_DOES_NOT_EXIST,
- error_str));
- _dbus_string_free (&error_message);
+ if (service == NULL)
+ {
+ if (!send_service_nonexistent_error (transaction, connection,
+ service_name,
+ message, &error))
+ goto out;
+ }
+ else
+ {
+ _dbus_assert (bus_service_get_primary_owner (service) != NULL);
+
+ /* Dispatch the message */
+ if (!bus_transaction_send_message (transaction,
+ bus_service_get_primary_owner (service),
+ message))
+ {
+ BUS_SET_OOM (&error);
+ goto out;
+ }
+ }
+ }
+
+ out:
+ if (dbus_error_is_set (&error))
+ {
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ /* If we disconnected it, we won't bother to send it any error
+ * messages.
+ */
+ }
+ else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+ {
+ bus_connection_send_oom_error (connection, message);
- /* Dispatch the message */
- BUS_HANDLE_OOM (dbus_connection_send_message (connection, error_reply, NULL, NULL));
- dbus_message_unref (error_reply);
- }
+ /* cancel transaction due to OOM */
+ if (transaction != NULL)
+ {
+ bus_transaction_cancel_and_free (transaction);
+ transaction = NULL;
+ }
+ }
else
- {
- _dbus_assert (bus_service_get_primary_owner (service) != NULL);
+ {
+ /* Try to send the real error, if no mem to do that, send
+ * the OOM error
+ */
+ _dbus_assert (transaction != NULL);
+
+ if (!bus_transaction_send_error_reply (transaction, connection,
+ &error, message))
+ {
+ bus_connection_send_oom_error (connection, message);
+
+ /* cancel transaction due to OOM */
+ if (transaction != NULL)
+ {
+ bus_transaction_cancel_and_free (transaction);
+ transaction = NULL;
+ }
+ }
+ }
- /* Dispatch the message */
- BUS_HANDLE_OOM (dbus_connection_send_message (bus_service_get_primary_owner (service),
- message, NULL, NULL));
- }
+ dbus_error_free (&error);
}
+ if (transaction != NULL)
+ {
+ bus_transaction_execute_and_free (transaction);
+ }
+
+ dbus_connection_unref (connection);
+
return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
}
diff --git a/bus/dispatch.h b/bus/dispatch.h
index 2fe3479c..c24170dc 100644
--- a/bus/dispatch.h
+++ b/bus/dispatch.h
@@ -25,10 +25,12 @@
#define BUS_DISPATCH_H
#include <dbus/dbus.h>
+#include "connection.h"
dbus_bool_t bus_dispatch_add_connection (DBusConnection *connection);
void bus_dispatch_remove_connection (DBusConnection *connection);
-void bus_dispatch_broadcast_message (DBusMessage *message);
-
+dbus_bool_t bus_dispatch_broadcast_message (BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error);
#endif /* BUS_DISPATCH_H */
diff --git a/bus/driver.c b/bus/driver.c
index 80478e45..46985594 100644
--- a/bus/driver.c
+++ b/bus/driver.c
@@ -31,79 +31,171 @@
#include <dbus/dbus-internals.h>
#include <string.h>
-static void bus_driver_send_welcome_message (DBusConnection *connection,
- DBusMessage *hello_message);
-
-void
-bus_driver_send_service_deleted (const char *service_name)
+static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection,
+ DBusMessage *hello_message,
+ BusTransaction *transaction,
+ DBusError *error);
+
+dbus_bool_t
+bus_driver_send_service_deleted (const char *service_name,
+ BusTransaction *transaction,
+ DBusError *error)
{
DBusMessage *message;
-
+ dbus_bool_t retval;
+
_dbus_verbose ("sending service deleted: %s\n", service_name);
- BUS_HANDLE_OOM (message = dbus_message_new (DBUS_SERVICE_BROADCAST,
- DBUS_MESSAGE_SERVICE_DELETED));
+ message = dbus_message_new (DBUS_SERVICE_BROADCAST,
+ DBUS_MESSAGE_SERVICE_DELETED);
+ if (message == NULL)
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
- BUS_HANDLE_OOM (dbus_message_set_sender (message, DBUS_SERVICE_DBUS));
+ if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS) ||
+ !dbus_message_append_args (message,
+ DBUS_TYPE_STRING, service_name,
+ 0))
+ {
+ dbus_message_unref (message);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
- BUS_HANDLE_OOM (dbus_message_append_args (message,
- DBUS_TYPE_STRING, service_name,
- 0));
- bus_dispatch_broadcast_message (message);
- dbus_message_unref (message);
+ retval = bus_dispatch_broadcast_message (transaction, message, error);
+ dbus_message_unref (message);
+
+ return retval;
}
-void
-bus_driver_send_service_created (const char *service_name)
+dbus_bool_t
+bus_driver_send_service_created (const char *service_name,
+ BusTransaction *transaction,
+ DBusError *error)
{
DBusMessage *message;
-
- BUS_HANDLE_OOM (message = dbus_message_new (DBUS_SERVICE_BROADCAST,
- DBUS_MESSAGE_SERVICE_CREATED));
+ dbus_bool_t retval;
+
+ message = dbus_message_new (DBUS_SERVICE_BROADCAST,
+ DBUS_MESSAGE_SERVICE_CREATED);
+ if (message == NULL)
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
- BUS_HANDLE_OOM (dbus_message_set_sender (message, DBUS_SERVICE_DBUS));
+ if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
+ {
+ dbus_message_unref (message);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
- BUS_HANDLE_OOM (dbus_message_append_args (message,
- DBUS_TYPE_STRING, service_name,
- 0));
- bus_dispatch_broadcast_message (message);
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_STRING, service_name,
+ 0))
+ {
+ dbus_message_unref (message);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ retval = bus_dispatch_broadcast_message (transaction, message, error);
dbus_message_unref (message);
+
+ return retval;
}
-void
+dbus_bool_t
bus_driver_send_service_lost (DBusConnection *connection,
- const char *service_name)
+ const char *service_name,
+ BusTransaction *transaction,
+ DBusError *error)
{
DBusMessage *message;
- BUS_HANDLE_OOM (message = dbus_message_new (DBUS_SERVICE_BROADCAST,
- DBUS_MESSAGE_SERVICE_LOST));
+ message = dbus_message_new (bus_connection_get_name (connection),
+ DBUS_MESSAGE_SERVICE_LOST);
+ if (message == NULL)
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
- BUS_HANDLE_OOM (dbus_message_set_sender (message, DBUS_SERVICE_DBUS));
- BUS_HANDLE_OOM (dbus_message_append_args (message,
- DBUS_TYPE_STRING, service_name,
- 0));
- BUS_HANDLE_OOM (dbus_connection_send_message (connection, message, NULL, NULL));
+ if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
+ {
+ dbus_message_unref (message);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
- dbus_message_unref (message);
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_STRING, service_name,
+ 0))
+ {
+ dbus_message_unref (message);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ if (!bus_transaction_send_message (transaction, connection, message))
+ {
+ dbus_message_unref (message);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+ else
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
}
-void
+dbus_bool_t
bus_driver_send_service_acquired (DBusConnection *connection,
- const char *service_name)
+ const char *service_name,
+ BusTransaction *transaction,
+ DBusError *error)
{
DBusMessage *message;
- BUS_HANDLE_OOM (message = dbus_message_new (DBUS_SERVICE_BROADCAST,
- DBUS_MESSAGE_SERVICE_ACQUIRED));
+ message = dbus_message_new (bus_connection_get_name (connection),
+ DBUS_MESSAGE_SERVICE_ACQUIRED);
+ if (message == NULL)
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
- BUS_HANDLE_OOM (dbus_message_set_sender (message, DBUS_SERVICE_DBUS));
- BUS_HANDLE_OOM (dbus_message_append_args (message,
- DBUS_TYPE_STRING, service_name,
- 0));
- BUS_HANDLE_OOM (dbus_connection_send_message (connection, message, NULL, NULL));
+ if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
+ {
+ dbus_message_unref (message);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
- dbus_message_unref (message);
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_STRING, service_name,
+ 0))
+ {
+ dbus_message_unref (message);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ if (!bus_transaction_send_message (transaction, connection, message))
+ {
+ dbus_message_unref (message);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+ else
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
}
static dbus_bool_t
@@ -154,7 +246,7 @@ create_unique_client_name (DBusString *str)
next_minor_number += 1;
/* Check if a client with the name exists */
- if (bus_service_lookup (str, FALSE) == NULL)
+ if (bus_service_lookup (str) == NULL)
break;
/* drop the number again, try the next one. */
@@ -164,35 +256,65 @@ create_unique_client_name (DBusString *str)
return TRUE;
}
-static void
+static dbus_bool_t
bus_driver_handle_hello (DBusConnection *connection,
- DBusMessage *message)
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
{
DBusString unique_name;
BusService *service;
+ dbus_bool_t retval;
+
+ if (!_dbus_string_init (&unique_name, _DBUS_INT_MAX))
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
- BUS_HANDLE_OOM (_dbus_string_init (&unique_name, _DBUS_INT_MAX));
- BUS_HANDLE_OOM (create_unique_client_name (&unique_name));
+ retval = FALSE;
+
+ if (!create_unique_client_name (&unique_name))
+ {
+ BUS_SET_OOM (error);
+ goto out_0;
+ }
- BUS_HANDLE_OOM (bus_connection_set_name (connection, &unique_name));
- BUS_HANDLE_OOM (dbus_message_set_sender (message,
- bus_connection_get_name (connection)));
+ if (!bus_connection_set_name (connection, &unique_name))
+ {
+ BUS_SET_OOM (error);
+ goto out_0;
+ }
+
+ if (!dbus_message_set_sender (message,
+ bus_connection_get_name (connection)))
+ {
+ BUS_SET_OOM (error);
+ goto out_0;
+ }
- BUS_HANDLE_OOM (bus_driver_send_welcome_message (connection, message));
+ if (!bus_driver_send_welcome_message (connection, message, transaction, error))
+ goto out_0;
/* Create the service */
- BUS_HANDLE_OOM (service = bus_service_lookup (&unique_name, TRUE));
- bus_service_set_prohibit_replacement (service, TRUE);
+ service = bus_service_ensure (&unique_name, connection, transaction, error);
+ if (service == NULL)
+ goto out_0;
- /* Add the connection as the owner */
- BUS_HANDLE_OOM (bus_service_add_owner (service, connection));
+ bus_service_set_prohibit_replacement (service, TRUE);
+ retval = TRUE;
+
+ out_0:
_dbus_string_free (&unique_name);
+ return retval;
}
-static void
+static dbus_bool_t
bus_driver_send_welcome_message (DBusConnection *connection,
- DBusMessage *hello_message)
+ DBusMessage *hello_message,
+ BusTransaction *transaction,
+ DBusError *error)
{
DBusMessage *welcome;
const char *name;
@@ -200,209 +322,330 @@ bus_driver_send_welcome_message (DBusConnection *connection,
name = bus_connection_get_name (connection);
_dbus_assert (name != NULL);
- BUS_HANDLE_OOM (welcome = dbus_message_new_reply (hello_message));
-
- BUS_HANDLE_OOM (dbus_message_set_sender (welcome, DBUS_SERVICE_DBUS));
-
- BUS_HANDLE_OOM (dbus_message_append_args (welcome,
- DBUS_TYPE_STRING, name,
- NULL));
+ welcome = dbus_message_new_reply (hello_message);
+ if (welcome == NULL)
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
- BUS_HANDLE_OOM (dbus_connection_send_message (connection, welcome, NULL, NULL));
+ if (!dbus_message_set_sender (welcome, DBUS_SERVICE_DBUS))
+ {
+ dbus_message_unref (welcome);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
- dbus_message_unref (welcome);
+ if (!dbus_message_append_args (welcome,
+ DBUS_TYPE_STRING, name,
+ NULL))
+ {
+ dbus_message_unref (welcome);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ if (!bus_transaction_send_message (transaction, connection, welcome))
+ {
+ dbus_message_unref (welcome);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+ else
+ {
+ dbus_message_unref (welcome);
+ return TRUE;
+ }
}
-static void
+static dbus_bool_t
bus_driver_handle_list_services (DBusConnection *connection,
- DBusMessage *message)
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
{
DBusMessage *reply;
- int len, i;
+ int len;
char **services;
- BUS_HANDLE_OOM (reply = dbus_message_new_reply (message));
-
- BUS_HANDLE_OOM (services = bus_services_list (&len));
-
- BUS_HANDLE_OOM (dbus_message_append_args (reply,
- DBUS_TYPE_STRING_ARRAY, services, len,
- 0));
-
- BUS_HANDLE_OOM (dbus_connection_send_message (connection, reply, NULL, NULL));
+ reply = dbus_message_new_reply (message);
+ if (reply == NULL)
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
- dbus_message_unref (reply);
+ services = bus_services_list (&len);
+ if (services == NULL)
+ {
+ dbus_message_unref (reply);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ if (!dbus_message_append_args (reply,
+ DBUS_TYPE_STRING_ARRAY, services, len,
+ 0))
+ {
+ dbus_free_string_array (services);
+ dbus_message_unref (reply);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
- if (services != NULL)
+ dbus_free_string_array (services);
+
+ if (!bus_transaction_send_message (transaction, connection, reply))
{
- for (i = 0; i < len; i++)
- dbus_free (services[i]);
- dbus_free (services);
+ dbus_message_unref (reply);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+ else
+ {
+ dbus_message_unref (reply);
+ return TRUE;
}
}
-static void
+static dbus_bool_t
bus_driver_handle_acquire_service (DBusConnection *connection,
- DBusMessage *message)
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
{
DBusMessage *reply;
- DBusResultCode result;
DBusString service_name;
BusService *service;
char *name;
int service_reply;
int flags;
+ dbus_bool_t retval;
+ DBusConnection *old_owner;
+ DBusConnection *current_owner;
- BUS_HANDLE_OOM ((result = dbus_message_get_args (message,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_UINT32, &flags,
- 0)) != DBUS_RESULT_NO_MEMORY);
+ if (!dbus_message_get_args (message,
+ error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_UINT32, &flags,
+ 0))
+ return FALSE;
- if (result != DBUS_RESULT_SUCCESS)
- {
- dbus_free (name);
- dbus_connection_disconnect (connection);
- return;
- }
+ _dbus_verbose ("Trying to own service %s with flags 0x%x\n", name, flags);
- _dbus_verbose ("Trying to own service %s with flags %d\n", name, flags);
+ retval = FALSE;
+ reply = NULL;
_dbus_string_init_const (&service_name, name);
- service = bus_service_lookup (&service_name, TRUE);
+
+ service = bus_service_lookup (&service_name);
- BUS_HANDLE_OOM ((reply = dbus_message_new_reply (message)));
+ if (service != NULL)
+ old_owner = bus_service_get_primary_owner (service);
+ else
+ old_owner = NULL;
- /*
- * Check if the service already has an owner
- */
- if (bus_service_get_primary_owner (service) != NULL)
- {
- if (bus_service_has_owner (service, connection))
- service_reply = DBUS_SERVICE_REPLY_ALREADY_OWNER;
- else if (!(flags & DBUS_SERVICE_FLAG_REPLACE_EXISTING))
- service_reply = DBUS_SERVICE_REPLY_SERVICE_EXISTS;
- else
- {
- if (bus_service_get_prohibit_replacement (service))
- {
-
- /* Queue the connection */
- BUS_HANDLE_OOM (bus_service_add_owner (service, connection));
-
- service_reply = DBUS_SERVICE_REPLY_IN_QUEUE;
- }
- else
- {
- DBusConnection *owner;
-
- /* We can replace the primary owner */
- owner = bus_service_get_primary_owner (service);
-
- /* We enqueue the new owner and remove the first one because
- * that will cause ServiceAcquired and ServiceLost messages to
- * be sent.
- */
- BUS_HANDLE_OOM (bus_service_add_owner (service, connection));
- bus_service_remove_owner (service, owner);
- _dbus_assert (connection == bus_service_get_primary_owner (service));
- service_reply = DBUS_SERVICE_REPLY_PRIMARY_OWNER;
- }
- }
+ reply = dbus_message_new_reply (message);
+ if (reply == NULL)
+ {
+ BUS_SET_OOM (error);
+ goto out;
}
- else
+
+ if (service == NULL)
{
+ service = bus_service_ensure (&service_name, connection, transaction, error);
+ if (service == NULL)
+ goto out;
+ }
+
+ current_owner = bus_service_get_primary_owner (service);
+
+ if (old_owner == NULL)
+ {
+ _dbus_assert (current_owner == connection);
+
bus_service_set_prohibit_replacement (service,
- (flags & DBUS_SERVICE_FLAG_PROHIBIT_REPLACEMENT));
+ (flags & DBUS_SERVICE_FLAG_PROHIBIT_REPLACEMENT));
+
+ service_reply = DBUS_SERVICE_REPLY_PRIMARY_OWNER;
+ }
+ else if (old_owner == connection)
+ service_reply = DBUS_SERVICE_REPLY_ALREADY_OWNER;
+ else if (!((flags & DBUS_SERVICE_FLAG_REPLACE_EXISTING)))
+ service_reply = DBUS_SERVICE_REPLY_SERVICE_EXISTS;
+ else if (bus_service_get_prohibit_replacement (service))
+ {
+ /* Queue the connection */
+ if (!bus_service_add_owner (service, connection,
+ transaction, error))
+ goto out;
- /* Broadcast service created message */
- bus_driver_send_service_created (bus_service_get_name (service));
+ service_reply = DBUS_SERVICE_REPLY_IN_QUEUE;
+ }
+ else
+ {
+ /* Replace the current owner */
+
+ /* We enqueue the new owner and remove the first one because
+ * that will cause ServiceAcquired and ServiceLost messages to
+ * be sent.
+ */
- BUS_HANDLE_OOM (bus_service_add_owner (service, connection));
-
+ /* FIXME this is broken, if the remove_owner fails
+ * we don't undo the add_owner
+ * (easiest fix is probably to move all this to
+ * services.c and have a single routine for it)
+ */
+
+ if (!bus_service_add_owner (service, connection,
+ transaction, error))
+ goto out;
+
+ if (!bus_service_remove_owner (service, old_owner,
+ transaction, error))
+ goto out;
+
+ _dbus_assert (connection == bus_service_get_primary_owner (service));
service_reply = DBUS_SERVICE_REPLY_PRIMARY_OWNER;
}
- BUS_HANDLE_OOM (dbus_message_append_args (reply, DBUS_TYPE_UINT32, service_reply, 0));
+ if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, service_reply, 0))
+ {
+ BUS_SET_OOM (error);
+ goto out;
+ }
- /* Send service reply */
- BUS_HANDLE_OOM (dbus_connection_send_message (connection, reply, NULL, NULL));
+ if (!bus_transaction_send_message (transaction, connection, reply))
+ {
+ BUS_SET_OOM (error);
+ goto out;
+ }
+
+ retval = TRUE;
+
+ out:
dbus_free (name);
- dbus_message_unref (reply);
-}
+ if (reply)
+ dbus_message_unref (reply);
+ return retval;
+}
-static void
+static dbus_bool_t
bus_driver_handle_service_exists (DBusConnection *connection,
- DBusMessage *message)
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
{
DBusMessage *reply;
- DBusResultCode result;
DBusString service_name;
BusService *service;
char *name;
+ dbus_bool_t retval;
- BUS_HANDLE_OOM ((result = dbus_message_get_args (message,
- DBUS_TYPE_STRING, &name,
- 0)) != DBUS_RESULT_NO_MEMORY);
- if (result != DBUS_RESULT_SUCCESS)
- {
- dbus_free (name);
- dbus_connection_disconnect (connection);
- return;
- }
+ if (!dbus_message_get_args (message, error,
+ DBUS_TYPE_STRING, &name,
+ 0))
+ return FALSE;
+ retval = FALSE;
+
_dbus_string_init_const (&service_name, name);
- service = bus_service_lookup (&service_name, FALSE);
+ service = bus_service_lookup (&service_name);
- BUS_HANDLE_OOM ((reply = dbus_message_new_reply (message)));
- BUS_HANDLE_OOM (dbus_message_set_sender (reply, DBUS_SERVICE_DBUS));
-
- BUS_HANDLE_OOM (dbus_message_append_args (reply,
- DBUS_TYPE_UINT32, service != NULL,
- 0));
- BUS_HANDLE_OOM (dbus_connection_send_message (connection, reply, NULL, NULL));
- dbus_message_unref (reply);
+ reply = dbus_message_new_reply (message);
+ if (reply == NULL)
+ {
+ BUS_SET_OOM (error);
+ goto out;
+ }
+
+ if (!dbus_message_set_sender (reply, DBUS_SERVICE_DBUS))
+ {
+ BUS_SET_OOM (error);
+ goto out;
+ }
+
+ if (!dbus_message_append_args (reply,
+ DBUS_TYPE_UINT32, service != NULL,
+ 0))
+ {
+ BUS_SET_OOM (error);
+ goto out;
+ }
+
+ if (!bus_transaction_send_message (transaction, connection, reply))
+ {
+ BUS_SET_OOM (error);
+ goto out;
+ }
+
+ retval = TRUE;
+
+ out:
+ if (reply)
+ dbus_message_unref (reply);
dbus_free (name);
+
+ return retval;
}
-static void
+static dbus_bool_t
bus_driver_handle_activate_service (DBusConnection *connection,
- DBusMessage *message)
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
{
- DBusResultCode result;
dbus_uint32_t flags;
char *name;
- DBusError error;
+ dbus_bool_t retval;
- BUS_HANDLE_OOM ((result = dbus_message_get_args (message,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_UINT32, &flags,
- 0)) != DBUS_RESULT_NO_MEMORY);
- if (result != DBUS_RESULT_SUCCESS)
- {
- dbus_free (name);
- dbus_connection_disconnect (connection);
- return;
- }
+ if (!dbus_message_get_args (message, error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_UINT32, &flags,
+ 0))
+ return FALSE;
- if (!bus_activation_activate_service (name, &error))
- {
- DBusMessage *error_reply;
-
- BUS_HANDLE_OOM (error_reply = dbus_message_new_error_reply (message,
- error.name, error.message));
- dbus_error_free (&error);
+ retval = FALSE;
- BUS_HANDLE_OOM (dbus_connection_send_message (connection, error_reply, NULL, NULL));
- dbus_message_unref (error_reply);
- }
+ if (!bus_activation_activate_service (name, error))
+ goto out;
+
+ retval = TRUE;
+
+ out:
+ dbus_free (name);
+ return retval;
}
-void
+/* For speed it might be useful to sort this in order of
+ * frequency of use (but doesn't matter with only a few items
+ * anyhow)
+ */
+struct
+{
+ const char *name;
+ dbus_bool_t (* handler) (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error);
+} message_handlers[] = {
+ { DBUS_MESSAGE_ACQUIRE_SERVICE, bus_driver_handle_acquire_service },
+ { DBUS_MESSAGE_ACTIVATE_SERVICE, bus_driver_handle_activate_service },
+ { DBUS_MESSAGE_HELLO, bus_driver_handle_hello },
+ { DBUS_MESSAGE_SERVICE_EXISTS, bus_driver_handle_service_exists },
+ { DBUS_MESSAGE_LIST_SERVICES, bus_driver_handle_list_services }
+};
+
+dbus_bool_t
bus_driver_handle_message (DBusConnection *connection,
- DBusMessage *message)
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
{
const char *name, *sender;
-
+ int i;
+
_dbus_verbose ("Driver got a message: %s\n",
dbus_message_get_name (message));
@@ -411,26 +654,39 @@ bus_driver_handle_message (DBusConnection *connection,
if (sender == NULL && (strcmp (name, DBUS_MESSAGE_HELLO) != 0))
{
- _dbus_verbose ("Trying to send a message without being registered. Disconnecting.\n");
+ dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+ "Client tried to send a message other than %s without being registered",
+ DBUS_MESSAGE_HELLO);
+
dbus_connection_disconnect (connection);
- return;
- }
-
- /* Now check names. */
- if (strcmp (name, DBUS_MESSAGE_HELLO) == 0)
- bus_driver_handle_hello (connection, message);
- else if (strcmp (name, DBUS_MESSAGE_LIST_SERVICES) == 0)
- bus_driver_handle_list_services (connection, message);
- else if (strcmp (name, DBUS_MESSAGE_ACQUIRE_SERVICE) == 0)
- bus_driver_handle_acquire_service (connection, message);
- else if (strcmp (name, DBUS_MESSAGE_SERVICE_EXISTS) == 0)
- bus_driver_handle_service_exists (connection, message);
- else if (strcmp (name, DBUS_MESSAGE_ACTIVATE_SERVICE) == 0)
- bus_driver_handle_activate_service (connection, message);
+ return FALSE;
+ }
+
+ i = 0;
+ while (i < _DBUS_N_ELEMENTS (message_handlers))
+ {
+ if (strcmp (message_handlers[i].name, name) == 0)
+ {
+ if ((* message_handlers[i].handler) (connection, transaction, message, error))
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ ++i;
+ }
+
+ dbus_set_error (error, DBUS_ERROR_UNKNOWN_MESSAGE,
+ "%s does not understand message %s",
+ DBUS_SERVICE_DBUS, name);
+
+ return FALSE;
}
void
bus_driver_remove_connection (DBusConnection *connection)
{
- /* Does nothing for now */
+ /* FIXME Does nothing for now, should unregister the connection
+ * with the bus driver.
+ */
}
diff --git a/bus/driver.h b/bus/driver.h
index 3019fe43..ac80c15f 100644
--- a/bus/driver.h
+++ b/bus/driver.h
@@ -25,17 +25,26 @@
#define BUS_DRIVER_H
#include <dbus/dbus.h>
+#include "connection.h"
-void bus_driver_remove_connection (DBusConnection *connection);
-void bus_driver_handle_message (DBusConnection *connection,
- DBusMessage *message);
-void bus_driver_send_service_deleted (const char *service_name);
-void bus_driver_send_service_lost (DBusConnection *connection,
- const char *service_name);
-void bus_driver_send_service_acquired (DBusConnection *connection,
- const char *service_name);
-void bus_driver_send_service_created (const char *service_name);
-
-
+void bus_driver_remove_connection (DBusConnection *connection);
+dbus_bool_t bus_driver_handle_message (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error);
+dbus_bool_t bus_driver_send_service_deleted (const char *service_name,
+ BusTransaction *transaction,
+ DBusError *error);
+dbus_bool_t bus_driver_send_service_lost (DBusConnection *connection,
+ const char *service_name,
+ BusTransaction *transaction,
+ DBusError *error);
+dbus_bool_t bus_driver_send_service_acquired (DBusConnection *connection,
+ const char *service_name,
+ BusTransaction *transaction,
+ DBusError *error);
+dbus_bool_t bus_driver_send_service_created (const char *service_name,
+ BusTransaction *transaction,
+ DBusError *error);
#endif /* BUS_DRIVER_H */
diff --git a/bus/main.c b/bus/main.c
index fdb6462e..56345c76 100644
--- a/bus/main.c
+++ b/bus/main.c
@@ -97,9 +97,18 @@ main (int argc, char **argv)
}
else
{
- char *paths[] = { argv[2], NULL };
+ const char *paths[] = { argv[2], NULL };
+ DBusError error;
- bus_activation_init (argv[1], paths);
+ dbus_error_init (&error);
+ if (!bus_activation_init (argv[1], paths,
+ &error))
+ {
+ _dbus_warn ("Could not initialize service activation: %s\n",
+ error.message);
+ dbus_error_free (&error);
+ return 1;
+ }
}
setup_server (server);
diff --git a/bus/services.c b/bus/services.c
index 497978d0..22302af4 100644
--- a/bus/services.c
+++ b/bus/services.c
@@ -21,31 +21,29 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
-#include "driver.h"
-#include "services.h"
-#include "connection.h"
#include <dbus/dbus-hash.h>
#include <dbus/dbus-list.h>
#include <dbus/dbus-mempool.h>
+#include "driver.h"
+#include "services.h"
+#include "connection.h"
+#include "utils.h"
+
struct BusService
{
char *name;
DBusList *owners;
-
- unsigned int prohibit_replacement:1;
+
+ unsigned int prohibit_replacement : 1;
};
static DBusHashTable *service_hash = NULL;
static DBusMemPool *service_pool = NULL;
-BusService*
-bus_service_lookup (const DBusString *service_name,
- dbus_bool_t create_if_not_found)
+static dbus_bool_t
+init_hash (void)
{
- const char *c_name;
- BusService *service;
-
if (service_hash == NULL)
{
service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
@@ -65,93 +63,182 @@ bus_service_lookup (const DBusString *service_name,
_dbus_mem_pool_free (service_pool);
service_pool = NULL;
}
- return NULL;
+ return FALSE;
}
}
+ return TRUE;
+}
+
+BusService*
+bus_service_lookup (const DBusString *service_name)
+{
+ const char *c_name;
+ BusService *service;
+
+ if (!init_hash ())
+ return NULL;
_dbus_string_get_const_data (service_name, &c_name);
service = _dbus_hash_table_lookup_string (service_hash,
c_name);
- if (service != NULL)
- return service;
- if (!create_if_not_found)
+ return service;
+}
+
+BusService*
+bus_service_ensure (const DBusString *service_name,
+ DBusConnection *owner_if_created,
+ BusTransaction *transaction,
+ DBusError *error)
+{
+ const char *c_name;
+ BusService *service;
+
+ _dbus_assert (owner_if_created != NULL);
+ _dbus_assert (transaction != NULL);
+
+ if (!init_hash ())
return NULL;
+ _dbus_string_get_const_data (service_name, &c_name);
+
+ service = _dbus_hash_table_lookup_string (service_hash,
+ c_name);
+ if (service != NULL)
+ return service;
+
service = _dbus_mem_pool_alloc (service_pool);
if (service == NULL)
- return NULL;
+ {
+ BUS_SET_OOM (error);
+ return NULL;
+ }
service->name = _dbus_strdup (c_name);
if (service->name == NULL)
{
_dbus_mem_pool_dealloc (service_pool, service);
+ BUS_SET_OOM (error);
return NULL;
}
+ if (!bus_driver_send_service_created (service->name, transaction, error))
+ {
+ dbus_free (service->name);
+ _dbus_mem_pool_dealloc (service_pool, service);
+ return NULL;
+ }
+
+ if (!bus_service_add_owner (service, owner_if_created,
+ transaction, error))
+ {
+ dbus_free (service->name);
+ _dbus_mem_pool_dealloc (service_pool, service);
+ return NULL;
+ }
+
if (!_dbus_hash_table_insert_string (service_hash,
service->name,
service))
{
+ _dbus_list_clear (&service->owners);
dbus_free (service->name);
_dbus_mem_pool_dealloc (service_pool, service);
+ BUS_SET_OOM (error);
return NULL;
}
-
- bus_driver_send_service_created (service->name);
return service;
}
dbus_bool_t
bus_service_add_owner (BusService *service,
- DBusConnection *owner)
+ DBusConnection *owner,
+ BusTransaction *transaction,
+ DBusError *error)
{
+ /* Send service acquired message first, OOM will result
+ * in cancelling the transaction
+ */
+ if (service->owners == NULL)
+ {
+ if (!bus_driver_send_service_acquired (owner, service->name, transaction, error))
+ return FALSE;
+ }
+
if (!_dbus_list_append (&service->owners,
owner))
- return FALSE;
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
if (!bus_connection_add_owned_service (owner, service))
{
_dbus_list_remove_last (&service->owners, owner);
+ BUS_SET_OOM (error);
return FALSE;
}
-
- /* Send service acquired message */
- if (bus_service_get_primary_owner (service) == owner)
- bus_driver_send_service_acquired (owner, service->name);
return TRUE;
}
-void
+dbus_bool_t
bus_service_remove_owner (BusService *service,
- DBusConnection *owner)
+ DBusConnection *owner,
+ BusTransaction *transaction,
+ DBusError *error)
{
+ /* We send out notifications before we do any work we
+ * might have to undo if the notification-sending failed
+ */
+
/* Send service lost message */
if (bus_service_get_primary_owner (service) == owner)
- bus_driver_send_service_lost (owner, service->name);
+ {
+ if (!bus_driver_send_service_lost (owner, service->name,
+ transaction, error))
+ return FALSE;
+ }
+
+ if (_dbus_list_length_is_one (&service->owners))
+ {
+ /* We are the only owner - send service deleted */
+ if (!bus_driver_send_service_deleted (service->name,
+ transaction, error))
+ return FALSE;
+ }
+ else
+ {
+ DBusList *link;
+ link = _dbus_list_get_first (&service->owners);
+ link = _dbus_list_get_next_link (&service->owners, link);
+
+ if (link != NULL)
+ {
+ /* This will be our new owner */
+ if (!bus_driver_send_service_acquired (link->data,
+ service->name,
+ transaction,
+ error))
+ return FALSE;
+ }
+ }
_dbus_list_remove_last (&service->owners, owner);
bus_connection_remove_owned_service (owner, service);
if (service->owners == NULL)
{
- /* Delete service */
- bus_driver_send_service_deleted (service->name);
-
+ /* Delete service (already sent message that it was deleted above) */
_dbus_hash_table_remove_string (service_hash, service->name);
dbus_free (service->name);
_dbus_mem_pool_dealloc (service_pool, service);
}
- else
- {
- /* Send service acquired to the new owner */
- bus_driver_send_service_acquired (bus_service_get_primary_owner (service),
- service->name);
- }
+
+ return TRUE;
}
DBusConnection*
@@ -192,7 +279,7 @@ bus_services_list (int *array_len)
DBusHashIter iter;
len = _dbus_hash_table_get_n_entries (service_hash);
- retval = dbus_new (char *, len);
+ retval = dbus_new (char *, len + 1);
if (retval == NULL)
return NULL;
@@ -210,6 +297,8 @@ bus_services_list (int *array_len)
i++;
}
+ retval[i] = NULL;
+
if (array_len)
*array_len = len;
@@ -227,8 +316,6 @@ void
bus_service_set_prohibit_replacement (BusService *service,
dbus_bool_t prohibit_replacement)
{
- _dbus_assert (service->owners == NULL);
-
service->prohibit_replacement = prohibit_replacement != FALSE;
}
diff --git a/bus/services.h b/bus/services.h
index 3f6b31a9..97583582 100644
--- a/bus/services.h
+++ b/bus/services.h
@@ -26,6 +26,10 @@
#include <dbus/dbus.h>
#include <dbus/dbus-string.h>
+#include "connection.h"
+
+/* forward decl that probably shouldn't be in this file */
+typedef struct BusTransaction BusTransaction;
/* Each service can have multiple owners; one owner is the "real
* owner" and the others are queued up. For example, if I have
@@ -38,12 +42,19 @@ typedef struct BusService BusService;
typedef void (* BusServiceForeachFunction) (BusService *service,
void *data);
-BusService* bus_service_lookup (const DBusString *service_name,
- dbus_bool_t create_if_not_found);
+BusService* bus_service_lookup (const DBusString *service_name);
+BusService* bus_service_ensure (const DBusString *service_name,
+ DBusConnection *owner_if_created,
+ BusTransaction *transaction,
+ DBusError *error);
dbus_bool_t bus_service_add_owner (BusService *service,
- DBusConnection *owner);
-void bus_service_remove_owner (BusService *service,
- DBusConnection *owner);
+ DBusConnection *owner,
+ BusTransaction *transaction,
+ DBusError *error);
+dbus_bool_t bus_service_remove_owner (BusService *service,
+ DBusConnection *owner,
+ BusTransaction *transaction,
+ DBusError *error);
dbus_bool_t bus_service_has_owner (BusService *service,
DBusConnection *owner);
DBusConnection* bus_service_get_primary_owner (BusService *service);
diff --git a/bus/utils.c b/bus/utils.c
index 8663b1e5..8b964cc4 100644
--- a/bus/utils.c
+++ b/bus/utils.c
@@ -25,6 +25,8 @@
#include "utils.h"
#include <dbus/dbus-sysdeps.h>
+const char bus_no_memory_message[] = "Memory allocation failure in message bus";
+
void
bus_wait_for_memory (void)
{
diff --git a/bus/utils.h b/bus/utils.h
index 5cbe2849..41eb5557 100644
--- a/bus/utils.h
+++ b/bus/utils.h
@@ -25,8 +25,9 @@
#ifndef BUS_UTILS_H
#define BUS_UTILS_H
-#define BUS_HANDLE_OOM(stat) (stat)
-
void bus_wait_for_memory (void);
+extern const char bus_no_memory_message[];
+#define BUS_SET_OOM(error) dbus_set_error ((error), DBUS_ERROR_NO_MEMORY, bus_no_memory_message)
+
#endif /* BUS_ACTIVATION_H */
diff --git a/dbus/dbus-address.c b/dbus/dbus-address.c
index fb8952b5..25179cea 100644
--- a/dbus/dbus-address.c
+++ b/dbus/dbus-address.c
@@ -27,9 +27,9 @@
#include "dbus-list.h"
/**
- * @defgroup DBusAddress address parsing
+ * @defgroup DBusAddress Address parsing
* @ingroup DBus
- * @brief Parsing addresses to DBus servers.
+ * @brief Parsing addresses of D-BUS servers.
*
* @{
*/
diff --git a/dbus/dbus-auth-script.c b/dbus/dbus-auth-script.c
index 732b4515..336d63e1 100644
--- a/dbus/dbus-auth-script.c
+++ b/dbus/dbus-auth-script.c
@@ -184,7 +184,7 @@ dbus_bool_t
_dbus_auth_script_run (const DBusString *filename)
{
DBusString file;
- DBusResultCode result;
+ DBusError error;
DBusString line;
dbus_bool_t retval;
int line_no;
@@ -213,14 +213,14 @@ _dbus_auth_script_run (const DBusString *filename)
_dbus_string_free (&line);
return FALSE;
}
-
- if ((result = _dbus_file_get_contents (&file, filename)) != DBUS_RESULT_SUCCESS)
- {
+
+ dbus_error_init (&error);
+ if (!_dbus_file_get_contents (&file, filename, &error)) {
const char *s;
_dbus_string_get_const_data (filename, &s);
_dbus_warn ("Getting contents of %s failed: %s\n",
- s, dbus_result_to_string (result));
-
+ s, error.message);
+ dbus_error_free (&error);
goto out;
}
diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c
index 516a51ae..8dfdc766 100644
--- a/dbus/dbus-auth.c
+++ b/dbus/dbus-auth.c
@@ -514,7 +514,7 @@ sha1_handle_first_client_response (DBusAuth *auth,
}
else
{
- _dbus_assert (dbus_error_is_set (&error));
+ _DBUS_ASSERT_ERROR_IS_SET (&error);
_dbus_verbose ("Error loading keyring: %s\n",
error.message);
if (send_rejected (auth))
@@ -535,7 +535,7 @@ sha1_handle_first_client_response (DBusAuth *auth,
auth->cookie_id = _dbus_keyring_get_best_key (auth->keyring, &error);
if (auth->cookie_id < 0)
{
- _dbus_assert (dbus_error_is_set (&error));
+ _DBUS_ASSERT_ERROR_IS_SET (&error);
_dbus_verbose ("Could not get a cookie ID to send to client: %s\n",
error.message);
if (send_rejected (auth))
@@ -844,7 +844,8 @@ handle_client_data_cookie_sha1_mech (DBusAuth *auth,
}
else
{
- _dbus_assert (dbus_error_is_set (&error));
+ _DBUS_ASSERT_ERROR_IS_SET (&error);
+
_dbus_verbose ("Error loading keyring: %s\n",
error.message);
@@ -2238,7 +2239,7 @@ process_test_subdir (const DBusString *test_base_dir,
DBusString filename;
DBusDirIter *dir;
dbus_bool_t retval;
- DBusResultCode result;
+ DBusError error;
retval = FALSE;
dir = NULL;
@@ -2258,22 +2259,23 @@ process_test_subdir (const DBusString *test_base_dir,
_dbus_string_free (&filename);
if (!_dbus_string_init (&filename, _DBUS_INT_MAX))
_dbus_assert_not_reached ("didn't allocate filename string\n");
-
- dir = _dbus_directory_open (&test_directory, &result);
+
+ dbus_error_init (&error);
+ dir = _dbus_directory_open (&test_directory, &error);
if (dir == NULL)
{
const char *s;
_dbus_string_get_const_data (&test_directory, &s);
_dbus_warn ("Could not open %s: %s\n", s,
- dbus_result_to_string (result));
+ error.message);
+ dbus_error_free (&error);
goto failed;
}
printf ("Testing:\n");
- result = DBUS_RESULT_SUCCESS;
next:
- while (_dbus_directory_get_next_file (dir, &filename, &result))
+ while (_dbus_directory_get_next_file (dir, &filename, &error))
{
DBusString full_path;
@@ -2311,12 +2313,13 @@ process_test_subdir (const DBusString *test_base_dir,
_dbus_string_free (&full_path);
}
- if (result != DBUS_RESULT_SUCCESS)
+ if (dbus_error_is_set (&error))
{
const char *s;
_dbus_string_get_const_data (&test_directory, &s);
_dbus_warn ("Could not get next file in %s: %s\n",
- s, dbus_result_to_string (result));
+ s, error.message);
+ dbus_error_free (&error);
goto failed;
}
diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c
index 99ef5ade..cc612a78 100644
--- a/dbus/dbus-bus.c
+++ b/dbus/dbus-bus.c
@@ -2,6 +2,7 @@
/* dbus-bus.c Convenience functions for communicating with the bus.
*
* Copyright (C) 2003 CodeFactory AB
+ * Copyright (C) 2003 Red Hat, Inc.
*
* Licensed under the Academic Free License version 1.2
*
@@ -23,29 +24,32 @@
#include "dbus-bus.h"
#include "dbus-protocol.h"
+#include "dbus-internals.h"
/**
- * @defgroup DBusBus Convenience functinos for communicating with the bus.
+ * @defgroup DBusBus Message bus APIs
* @ingroup DBus
- * @brief Convenience functinos for communicating with the bus.
+ * @brief Functions for communicating with the message bus
*
* @{
*/
/**
- * Registers a connection with the bus. This is needed to send messages
- * to other clients.
+ * Registers a connection with the bus. This must be the first
+ * thing an application does when connecting to the message bus.
*
- * @param connection The connection
- * @param result address where a result code can be returned.
- * @returns the service name of which the client is known as.
+ * @todo if we get an error reply, it has to be converted into
+ * DBusError and returned
+ *
+ * @param connection the connection
+ * @param error place to store errors
+ * @returns the client's unique service name, #NULL on error
*/
-char *
+char*
dbus_bus_register_client (DBusConnection *connection,
- DBusResultCode *result)
+ DBusError *error)
{
DBusMessage *message, *reply;
- DBusResultCode code;
char *name;
message = dbus_message_new (DBUS_SERVICE_DBUS,
@@ -53,56 +57,61 @@ dbus_bus_register_client (DBusConnection *connection,
if (!message)
{
- dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
+ _DBUS_SET_OOM (error);
return NULL;
}
- reply = dbus_connection_send_message_with_reply_and_block (connection, message, -1, result);
+ reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
dbus_message_unref (message);
- if (!reply)
- return NULL;
-
- code = dbus_message_get_args (reply,
- DBUS_TYPE_STRING, &name,
- 0);
- if (code != DBUS_RESULT_SUCCESS)
+ if (reply == NULL)
{
- dbus_set_result (result, code);
+ _DBUS_ASSERT_ERROR_IS_SET (error);
return NULL;
}
- dbus_set_result (result, DBUS_RESULT_SUCCESS);
-
+ if (!dbus_message_get_args (reply, error,
+ DBUS_TYPE_STRING, &name,
+ 0))
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ return NULL;
+ }
+
return name;
}
/**
* Asks the bus to try to acquire a certain service.
*
+ * @todo these docs are not complete, need to document the
+ * return value and flags
+ *
+ * @todo if we get an error reply, it has to be converted into
+ * DBusError and returned
+ *
* @param connection the connection
* @param service_name the service name
* @param flags flags
- * @param result address where a result code can be returned.
- * @returns a result code.
+ * @param error location to store the error
+ * @returns a result code, -1 if error is set
*/
int
dbus_bus_acquire_service (DBusConnection *connection,
const char *service_name,
unsigned int flags,
- DBusResultCode *result)
+ DBusError *error)
{
DBusMessage *message, *reply;
int service_result;
- DBusResultCode code;
message = dbus_message_new (DBUS_SERVICE_DBUS,
DBUS_MESSAGE_ACQUIRE_SERVICE);
- if (!message)
+ if (message == NULL)
{
- dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
+ _DBUS_SET_OOM (error);
return -1;
}
@@ -112,26 +121,28 @@ dbus_bus_acquire_service (DBusConnection *connection,
0))
{
dbus_message_unref (message);
- dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
+ _DBUS_SET_OOM (error);
return -1;
}
- reply = dbus_connection_send_message_with_reply_and_block (connection, message, -1, result);
+ reply = dbus_connection_send_with_reply_and_block (connection, message, -1,
+ error);
+
dbus_message_unref (message);
- if (!reply)
- return -1;
-
- code = dbus_message_get_args (reply,
- DBUS_TYPE_UINT32, &service_result,
- 0);
- if (code != DBUS_RESULT_SUCCESS)
+ if (reply == NULL)
{
- dbus_set_result (result, code);
+ _DBUS_ASSERT_ERROR_IS_SET (error);
return -1;
}
- dbus_set_result (result, DBUS_RESULT_SUCCESS);
+ if (!dbus_message_get_args (reply, error,
+ DBUS_TYPE_UINT32, &service_result,
+ 0))
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ return -1;
+ }
return service_result;
}
@@ -139,25 +150,26 @@ dbus_bus_acquire_service (DBusConnection *connection,
/**
* Checks whether a certain service exists.
*
+ * @todo the SERVICE_EXISTS message should use BOOLEAN not UINT32
+ *
* @param connection the connection
* @param service_name the service name
- * @param result address where a result code can be returned.
- * @returns #TRUE if the service exists, #FALSE otherwise.
+ * @param error location to store any errors
+ * @returns #TRUE if the service exists, #FALSE if not or on error
*/
dbus_bool_t
dbus_bus_service_exists (DBusConnection *connection,
const char *service_name,
- DBusResultCode *result)
+ DBusError *error)
{
DBusMessage *message, *reply;
unsigned int exists;
- DBusResultCode code;
message = dbus_message_new (DBUS_SERVICE_DBUS,
DBUS_MESSAGE_SERVICE_EXISTS);
- if (!message)
+ if (message == NULL)
{
- dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
+ _DBUS_SET_OOM (error);
return FALSE;
}
@@ -166,27 +178,27 @@ dbus_bus_service_exists (DBusConnection *connection,
0))
{
dbus_message_unref (message);
- dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
+ _DBUS_SET_OOM (error);
return FALSE;
}
- reply = dbus_connection_send_message_with_reply_and_block (connection, message, -1, result);
+ reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
dbus_message_unref (message);
- if (!reply)
- return FALSE;
+ if (reply == NULL)
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ return FALSE;
+ }
- code = dbus_message_get_args (reply,
- DBUS_TYPE_UINT32, &exists,
- 0);
- if (code != DBUS_RESULT_SUCCESS)
+ if (!dbus_message_get_args (reply, error,
+ DBUS_TYPE_UINT32, &exists,
+ 0))
{
- dbus_set_result (result, code);
+ _DBUS_ASSERT_ERROR_IS_SET (error);
return FALSE;
}
- dbus_set_result (result, DBUS_RESULT_SUCCESS);
-
return (exists != FALSE);
}
diff --git a/dbus/dbus-bus.h b/dbus/dbus-bus.h
index 0bd8dec8..d1c2bfd7 100644
--- a/dbus/dbus-bus.h
+++ b/dbus/dbus-bus.h
@@ -29,15 +29,15 @@
#include <dbus/dbus-connection.h>
-char * dbus_bus_register_client (DBusConnection *connection,
- DBusResultCode *result);
+char* dbus_bus_register_client (DBusConnection *connection,
+ DBusError *error);
int dbus_bus_acquire_service (DBusConnection *connection,
const char *service_name,
unsigned int flags,
- DBusResultCode *result);
+ DBusError *error);
dbus_bool_t dbus_bus_service_exists (DBusConnection *connection,
const char *service_name,
- DBusResultCode *result);
+ DBusError *error);
#endif /* DBUS_BUS_H */
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index 3611b871..bfc27e2a 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -187,7 +187,7 @@ _dbus_connection_queue_received_message (DBusConnection *connection,
return FALSE;
/* If this is a reply we're waiting on, remove timeout for it */
- reply_serial = _dbus_message_get_reply_serial (message);
+ reply_serial = dbus_message_get_reply_serial (message);
if (reply_serial != -1)
{
reply_handler_data = _dbus_hash_table_lookup_int (connection->pending_replies,
@@ -205,9 +205,11 @@ _dbus_connection_queue_received_message (DBusConnection *connection,
connection->n_incoming += 1;
_dbus_connection_wakeup_mainloop (connection);
-
- _dbus_verbose ("Incoming message %p added to queue, %d incoming\n",
- message, connection->n_incoming);
+
+ _dbus_assert (dbus_message_get_name (message) != NULL);
+ _dbus_verbose ("Incoming message %p (%s) added to queue, %d incoming\n",
+ message, dbus_message_get_name (message),
+ connection->n_incoming);
return TRUE;
}
@@ -963,54 +965,88 @@ dbus_connection_get_is_authenticated (DBusConnection *connection)
}
/**
- * Adds a message to the outgoing message queue. Does not block to
- * write the message to the network; that happens asynchronously. to
- * force the message to be written, call dbus_connection_flush().
+ * Preallocates resources needed to send a message, allowing the message
+ * to be sent without the possibility of memory allocation failure.
+ * Allows apps to create a future guarantee that they can send
+ * a message regardless of memory shortages.
*
- * If the function fails, it returns #FALSE and returns the
- * reason for failure via the result parameter.
- * The result parameter can be #NULL if you aren't interested
- * in the reason for the failure.
- *
- * @param connection the connection.
- * @param message the message to write.
- * @param client_serial return location for client serial.
- * @param result address where result code can be placed.
- * @returns #TRUE on success.
+ * @param connection the connection we're preallocating for.
+ * @returns the preallocated resources, or #NULL
*/
-dbus_bool_t
-dbus_connection_send_message (DBusConnection *connection,
- DBusMessage *message,
- dbus_int32_t *client_serial,
- DBusResultCode *result)
+DBusPreallocatedSend*
+dbus_connection_preallocate_send (DBusConnection *connection)
+{
+ /* we store "connection" in the link just to enforce via
+ * assertion that preallocated links are only used
+ * with the connection they were created for.
+ */
+ return (DBusPreallocatedSend*) _dbus_list_alloc_link (connection);
+}
+/**
+ * Frees preallocated message-sending resources from
+ * dbus_connection_preallocate_send(). Should only
+ * be called if the preallocated resources are not used
+ * to send a message.
+ *
+ * @param connection the connection
+ * @param preallocated the resources
+ */
+void
+dbus_connection_free_preallocated_send (DBusConnection *connection,
+ DBusPreallocatedSend *preallocated)
{
- dbus_int32_t serial;
+ DBusList *link = (DBusList*) preallocated;
+ _dbus_assert (link->data == connection);
+ _dbus_list_free_link (link);
+}
+/**
+ * Sends a message using preallocated resources. This function cannot fail.
+ * It works identically to dbus_connection_send() in other respects.
+ * Preallocated resources comes from dbus_connection_preallocate_send().
+ * This function "consumes" the preallocated resources, they need not
+ * be freed separately.
+ *
+ * @param connection the connection
+ * @param preallocated the preallocated resources
+ * @param message the message to send
+ * @param client_serial return location for client serial assigned to the message
+ */
+void
+dbus_connection_send_preallocated (DBusConnection *connection,
+ DBusPreallocatedSend *preallocated,
+ DBusMessage *message,
+ dbus_int32_t *client_serial)
+{
+ DBusList *link = (DBusList*) preallocated;
+ dbus_int32_t serial;
+
+ _dbus_assert (link->data == connection);
+ _dbus_assert (dbus_message_get_name (message) != NULL);
+
dbus_mutex_lock (connection->mutex);
- if (!_dbus_list_prepend (&connection->outgoing_messages,
- message))
- {
- dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
- dbus_mutex_unlock (connection->mutex);
- return FALSE;
- }
+ link->data = message;
+ _dbus_list_prepend_link (&connection->outgoing_messages,
+ link);
dbus_message_ref (message);
connection->n_outgoing += 1;
- _dbus_verbose ("Message %p added to outgoing queue, %d pending to send\n",
- message, connection->n_outgoing);
+ _dbus_verbose ("Message %p (%s) added to outgoing queue, %d pending to send\n",
+ message,
+ dbus_message_get_name (message),
+ connection->n_outgoing);
- if (_dbus_message_get_client_serial (message) == -1)
+ if (dbus_message_get_serial (message) == -1)
{
serial = _dbus_connection_get_next_client_serial (connection);
- _dbus_message_set_client_serial (message, serial);
+ _dbus_message_set_serial (message, serial);
}
if (client_serial)
- *client_serial = _dbus_message_get_client_serial (message);
+ *client_serial = dbus_message_get_serial (message);
_dbus_message_lock (message);
@@ -1021,8 +1057,43 @@ dbus_connection_send_message (DBusConnection *connection,
_dbus_connection_wakeup_mainloop (connection);
dbus_mutex_unlock (connection->mutex);
-
- return TRUE;
+}
+
+/**
+ * Adds a message to the outgoing message queue. Does not block to
+ * write the message to the network; that happens asynchronously. To
+ * force the message to be written, call dbus_connection_flush().
+ * Because this only queues the message, the only reason it can
+ * fail is lack of memory. Even if the connection is disconnected,
+ * no error will be returned.
+ *
+ * If the function fails, it returns #FALSE and returns the
+ * reason for failure via the result parameter.
+ * The result parameter can be #NULL if you aren't interested
+ * in the reason for the failure.
+ *
+ * @param connection the connection.
+ * @param message the message to write.
+ * @param client_serial return location for client serial.
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+dbus_connection_send (DBusConnection *connection,
+ DBusMessage *message,
+ dbus_int32_t *client_serial)
+{
+ DBusPreallocatedSend *preallocated;
+
+ preallocated = dbus_connection_preallocate_send (connection);
+ if (preallocated == NULL)
+ {
+ return FALSE;
+ }
+ else
+ {
+ dbus_connection_send_preallocated (connection, preallocated, message, client_serial);
+ return TRUE;
+ }
}
static void
@@ -1100,25 +1171,19 @@ reply_handler_data_free (ReplyHandlerData *data)
* you want a very short or very long timeout. There is no way to
* avoid a timeout entirely, other than passing INT_MAX for the
* timeout to postpone it indefinitely.
- *
- * @todo I think we should rename this function family
- * dbus_connection_send(), send_with_reply(), etc. (i.e.
- * drop the "message" part), the names are too long.
*
* @param connection the connection
* @param message the message to send
* @param reply_handler message handler expecting the reply, or #NULL
* @param timeout_milliseconds timeout in milliseconds or -1 for default
- * @param result return location for result code
* @returns #TRUE if the message is successfully queued, #FALSE if no memory.
*
*/
dbus_bool_t
-dbus_connection_send_message_with_reply (DBusConnection *connection,
- DBusMessage *message,
- DBusMessageHandler *reply_handler,
- int timeout_milliseconds,
- DBusResultCode *result)
+dbus_connection_send_with_reply (DBusConnection *connection,
+ DBusMessage *message,
+ DBusMessageHandler *reply_handler,
+ int timeout_milliseconds)
{
DBusTimeout *timeout;
ReplyHandlerData *data;
@@ -1132,10 +1197,7 @@ dbus_connection_send_message_with_reply (DBusConnection *connection,
data = dbus_new0 (ReplyHandlerData, 1);
if (!data)
- {
- dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
- return FALSE;
- }
+ return FALSE;
timeout = _dbus_timeout_new (timeout_milliseconds, reply_handler_timeout,
data, NULL);
@@ -1143,7 +1205,6 @@ dbus_connection_send_message_with_reply (DBusConnection *connection,
if (!timeout)
{
reply_handler_data_free (data);
- dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
return FALSE;
}
@@ -1155,8 +1216,6 @@ dbus_connection_send_message_with_reply (DBusConnection *connection,
reply_handler_data_free (data);
_dbus_timeout_unref (timeout);
dbus_mutex_unlock (connection->mutex);
-
- dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
return FALSE;
}
@@ -1171,17 +1230,15 @@ dbus_connection_send_message_with_reply (DBusConnection *connection,
{
dbus_mutex_unlock (connection->mutex);
reply_handler_data_free (data);
-
- dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
return FALSE;
}
data->connection_added = TRUE;
/* Assign a serial to the message */
- if (_dbus_message_get_client_serial (message) == -1)
+ if (dbus_message_get_serial (message) == -1)
{
serial = _dbus_connection_get_next_client_serial (connection);
- _dbus_message_set_client_serial (message, serial);
+ _dbus_message_set_serial (message, serial);
}
data->handler = reply_handler;
@@ -1195,8 +1252,6 @@ dbus_connection_send_message_with_reply (DBusConnection *connection,
{
dbus_mutex_unlock (connection->mutex);
reply_handler_data_free (data);
-
- dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
return FALSE;
}
@@ -1206,8 +1261,6 @@ dbus_connection_send_message_with_reply (DBusConnection *connection,
dbus_mutex_unlock (connection->mutex);
dbus_message_unref (reply);
reply_handler_data_free (data);
-
- dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
return FALSE;
}
@@ -1216,23 +1269,20 @@ dbus_connection_send_message_with_reply (DBusConnection *connection,
/* Insert the serial in the pending replies hash. */
if (!_dbus_hash_table_insert_int (connection->pending_replies, serial, data))
{
- dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
dbus_mutex_unlock (connection->mutex);
- reply_handler_data_free (data);
-
+ reply_handler_data_free (data);
return FALSE;
}
dbus_mutex_unlock (connection->mutex);
- if (!dbus_connection_send_message (connection, message, NULL, result))
+ if (!dbus_connection_send (connection, message, NULL))
{
/* This will free the handler data too */
_dbus_hash_table_remove_int (connection->pending_replies, serial);
return FALSE;
}
- dbus_set_result (result, DBUS_RESULT_SUCCESS);
return TRUE;
}
@@ -1242,9 +1292,9 @@ dbus_connection_send_message_with_reply (DBusConnection *connection,
* has been reached. This function is used to do non-reentrant "method calls."
* If a reply is received, it is returned, and removed from the incoming
* message queue. If it is not received, #NULL is returned and the
- * result is set to #DBUS_RESULT_NO_REPLY. If something else goes
+ * error is set to #DBUS_ERROR_NO_REPLY. If something else goes
* wrong, result is set to whatever is appropriate, such as
- * #DBUS_RESULT_NO_MEMORY.
+ * #DBUS_ERROR_NO_MEMORY or #DBUS_ERROR_DISCONNECTED.
*
* @todo could use performance improvements (it keeps scanning
* the whole message queue for example) and has thread issues,
@@ -1253,15 +1303,15 @@ dbus_connection_send_message_with_reply (DBusConnection *connection,
* @param connection the connection
* @param message the message to send
* @param timeout_milliseconds timeout in milliseconds or -1 for default
- * @param result return location for result code
+ * @param error return location for error message
* @returns the message that is the reply or #NULL with an error code if the
* function fails.
*/
DBusMessage *
-dbus_connection_send_message_with_reply_and_block (DBusConnection *connection,
- DBusMessage *message,
- int timeout_milliseconds,
- DBusResultCode *result)
+dbus_connection_send_with_reply_and_block (DBusConnection *connection,
+ DBusMessage *message,
+ int timeout_milliseconds,
+ DBusError *error)
{
dbus_int32_t client_serial;
DBusList *link;
@@ -1279,8 +1329,11 @@ dbus_connection_send_message_with_reply_and_block (DBusConnection *connectio
if (timeout_milliseconds > _DBUS_ONE_HOUR_IN_MILLISECONDS * 6)
timeout_milliseconds = _DBUS_ONE_HOUR_IN_MILLISECONDS * 6;
- if (!dbus_connection_send_message (connection, message, &client_serial, result))
- return NULL;
+ if (!dbus_connection_send (connection, message, &client_serial))
+ {
+ _DBUS_SET_OOM (error);
+ return NULL;
+ }
message = NULL;
@@ -1318,13 +1371,10 @@ dbus_connection_send_message_with_reply_and_block (DBusConnection *connectio
{
DBusMessage *reply = link->data;
- if (_dbus_message_get_reply_serial (reply) == client_serial)
+ if (dbus_message_get_reply_serial (reply) == client_serial)
{
_dbus_list_remove_link (&connection->incoming_messages, link);
dbus_message_ref (reply);
-
- if (result)
- *result = DBUS_RESULT_SUCCESS;
dbus_mutex_unlock (connection->mutex);
return reply;
@@ -1345,14 +1395,14 @@ dbus_connection_send_message_with_reply_and_block (DBusConnection *connectio
(end_tv_usec - tv_usec) / 1000;
_dbus_verbose ("%d milliseconds remain\n", timeout_milliseconds);
_dbus_assert (timeout_milliseconds > 0);
-
+
goto block_again; /* not expired yet */
}
-
+
if (dbus_connection_get_is_connected (connection))
- dbus_set_result (result, DBUS_RESULT_NO_REPLY);
+ dbus_set_error (error, DBUS_ERROR_NO_REPLY, "Message did not receive a reply");
else
- dbus_set_result (result, DBUS_RESULT_DISCONNECTED);
+ dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Disconnected prior to receiving a reply");
dbus_mutex_unlock (connection->mutex);
@@ -1631,7 +1681,7 @@ dbus_connection_dispatch_message (DBusConnection *connection)
result = DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- reply_serial = _dbus_message_get_reply_serial (message);
+ reply_serial = dbus_message_get_reply_serial (message);
reply_handler_data = _dbus_hash_table_lookup_int (connection->pending_replies,
reply_serial);
diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h
index fd631c6d..6b480136 100644
--- a/dbus/dbus-connection.h
+++ b/dbus/dbus-connection.h
@@ -37,6 +37,7 @@ typedef struct DBusConnection DBusConnection;
typedef struct DBusWatch DBusWatch;
typedef struct DBusTimeout DBusTimeout;
typedef struct DBusMessageHandler DBusMessageHandler;
+typedef struct DBusPreallocatedSend DBusPreallocatedSend;
typedef enum
{
@@ -85,19 +86,18 @@ DBusMessage* dbus_connection_pop_message (DBusConnection *connecti
dbus_bool_t dbus_connection_dispatch_message (DBusConnection *connection);
-dbus_bool_t dbus_connection_send_message (DBusConnection *connection,
- DBusMessage *message,
- dbus_int32_t *client_serial,
- DBusResultCode *result);
-dbus_bool_t dbus_connection_send_message_with_reply (DBusConnection *connection,
- DBusMessage *message,
- DBusMessageHandler *reply_handler,
- int timeout_milliseconds,
- DBusResultCode *result);
-DBusMessage *dbus_connection_send_message_with_reply_and_block (DBusConnection *connection,
- DBusMessage *message,
- int timeout_milliseconds,
- DBusResultCode *result);
+dbus_bool_t dbus_connection_send (DBusConnection *connection,
+ DBusMessage *message,
+ dbus_int32_t *client_serial);
+dbus_bool_t dbus_connection_send_with_reply (DBusConnection *connection,
+ DBusMessage *message,
+ DBusMessageHandler *reply_handler,
+ int timeout_milliseconds);
+DBusMessage *dbus_connection_send_with_reply_and_block (DBusConnection *connection,
+ DBusMessage *message,
+ int timeout_milliseconds,
+ DBusError *error);
+
void dbus_connection_set_watch_functions (DBusConnection *connection,
@@ -169,6 +169,14 @@ void dbus_connection_set_max_live_messages_size (DBusConnection *connection,
long size);
long dbus_connection_get_max_live_messages_size (DBusConnection *connection);
+DBusPreallocatedSend* dbus_connection_preallocate_send (DBusConnection *connection);
+void dbus_connection_free_preallocated_send (DBusConnection *connection,
+ DBusPreallocatedSend *preallocated);
+void dbus_connection_send_preallocated (DBusConnection *connection,
+ DBusPreallocatedSend *preallocated,
+ DBusMessage *message,
+ dbus_int32_t *client_serial);
+
DBUS_END_DECLS;
diff --git a/dbus/dbus-errors.c b/dbus/dbus-errors.c
index e57d3538..da49e2ea 100644
--- a/dbus/dbus-errors.c
+++ b/dbus/dbus-errors.c
@@ -44,9 +44,6 @@
* @endcode
*
* @todo add docs with DBusError
- *
- * @todo add dbus_error_is_set() to check
- * whether an error is set.
*
* @{
*/
@@ -138,11 +135,9 @@ dbus_result_to_string (DBusResultCode code)
}
/**
- * Initializes a DBusError structure.
- *
- * @todo calling dbus_error_init() in here is no good,
- * for the same reason a GError* has to be set to NULL
- * before you pass it in.
+ * Initializes a DBusError structure. Does not allocate
+ * any memory; the error only needs to be freed
+ * if it is set at some point.
*
* @param error the DBusError.
*/
@@ -164,7 +159,8 @@ dbus_error_init (DBusError *error)
}
/**
- * Frees an error created by dbus_error_init().
+ * Frees an error that's been set (or just initialized),
+ * then reinitializes the error as in dbus_error_init().
*
* @param error memory where the error is stored.
*/
@@ -177,6 +173,8 @@ dbus_error_free (DBusError *error)
if (!real->const_message)
dbus_free (real->message);
+
+ dbus_error_init (error);
}
/**
@@ -211,6 +209,32 @@ dbus_set_error_const (DBusError *error,
}
/**
+ * Moves an error src into dest, freeing src and
+ * overwriting dest. Both src and dest must be initialized.
+ * src is reinitialized to an empty error. dest may not
+ * contain an existing error. If the destination is
+ * #NULL, just frees and reinits the source error.
+ *
+ * @param src the source error
+ * @param dest the destination error or #NULL
+ */
+void
+dbus_move_error (DBusError *src,
+ DBusError *dest)
+{
+ _dbus_assert (!dbus_error_is_set (dest));
+
+ if (dest)
+ {
+ dbus_error_free (dest);
+ *dest = *src;
+ dbus_error_init (src);
+ }
+ else
+ dbus_error_free (src);
+}
+
+/**
* Checks whether the error is set and has the given
* name.
* @param error the error
@@ -246,7 +270,7 @@ dbus_error_has_name (const DBusError *error,
dbus_bool_t
dbus_error_is_set (const DBusError *error)
{
- _dbus_assert (error != NULL);
+ _dbus_assert (error != NULL);
_dbus_assert ((error->name != NULL && error->message != NULL) ||
(error->name == NULL && error->message == NULL));
return error->name != NULL;
diff --git a/dbus/dbus-errors.h b/dbus/dbus-errors.h
index e6b88465..63edbdbf 100644
--- a/dbus/dbus-errors.h
+++ b/dbus/dbus-errors.h
@@ -56,6 +56,20 @@ struct DBusError
#define DBUS_ERROR_NO_MEMORY "org.freedesktop.DBus.Error.NoMemory"
#define DBUS_ERROR_SERVICE_DOES_NOT_EXIST "org.freedesktop.DBus.Error.ServiceDoesNotExist"
#define DBUS_ERROR_NO_REPLY "org.freedesktop.DBus.Error.NoReply"
+#define DBUS_ERROR_IO_ERROR "org.freedesktop.DBus.Error.IOError"
+#define DBUS_ERROR_BAD_ADDRESS "org.freedesktop.DBus.Error.BadAddress"
+#define DBUS_ERROR_NOT_SUPPORTED "org.freedesktop.DBus.Error.NotSupported"
+#define DBUS_ERROR_LIMITS_EXCEEDED "org.freedesktop.DBus.Error.LimitsExceeded"
+#define DBUS_ERROR_ACCESS_DENIED "org.freedesktop.DBus.Error.AccessDenied"
+#define DBUS_ERROR_AUTH_FAILED "org.freedesktop.DBus.Error.AuthFailed"
+#define DBUS_ERROR_NO_SERVER "org.freedesktop.DBus.Error.NoServer"
+#define DBUS_ERROR_TIMEOUT "org.freedesktop.DBus.Error.Timeout"
+#define DBUS_ERROR_NO_NETWORK "org.freedesktop.DBus.Error.NoNetwork"
+#define DBUS_ERROR_ADDRESS_IN_USE "org.freedesktop.DBus.Error.AddressInUse"
+#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_UNKNOWN_MESSAGE "org.freedesktop.DBus.Error.UnknownMessage"
typedef enum
{
@@ -90,6 +104,8 @@ void dbus_set_error (DBusError *error,
void dbus_set_error_const (DBusError *error,
const char *name,
const char *message);
+void dbus_move_error (DBusError *src,
+ DBusError *dest);
dbus_bool_t dbus_error_has_name (const DBusError *error,
const char *name);
dbus_bool_t dbus_error_is_set (const DBusError *error);
diff --git a/dbus/dbus-internals.c b/dbus/dbus-internals.c
index 8dedb56a..acd6d72f 100644
--- a/dbus/dbus-internals.c
+++ b/dbus/dbus-internals.c
@@ -1,7 +1,7 @@
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-internals.c random utility stuff (internal to D-BUS implementation)
*
- * Copyright (C) 2002 Red Hat, Inc.
+ * Copyright (C) 2002, 2003 Red Hat, Inc.
*
* Licensed under the Academic Free License version 1.2
*
@@ -128,6 +128,13 @@
*/
/**
+ * Fixed "out of memory" error message, just to avoid
+ * making up a different string every time and wasting
+ * space.
+ */
+const char _dbus_no_memory_message[] = "Not enough memory";
+
+/**
* Prints a warning message to stderr.
*
* @param format printf-style format string.
@@ -181,104 +188,6 @@ _dbus_verbose_real (const char *format,
}
/**
- * Converts a UNIX errno into a DBusResultCode.
- *
- * @todo should cover more errnos, specifically those
- * from open().
- *
- * @param error_number the errno.
- * @returns the result code.
- */
-DBusResultCode
-_dbus_result_from_errno (int error_number)
-{
- switch (error_number)
- {
- case 0:
- return DBUS_RESULT_SUCCESS;
-
-#ifdef EPROTONOSUPPORT
- case EPROTONOSUPPORT:
- return DBUS_RESULT_NOT_SUPPORTED;
-#endif
-#ifdef EAFNOSUPPORT
- case EAFNOSUPPORT:
- return DBUS_RESULT_NOT_SUPPORTED;
-#endif
-#ifdef ENFILE
- case ENFILE:
- return DBUS_RESULT_LIMITS_EXCEEDED; /* kernel out of memory */
-#endif
-#ifdef EMFILE
- case EMFILE:
- return DBUS_RESULT_LIMITS_EXCEEDED;
-#endif
-#ifdef EACCES
- case EACCES:
- return DBUS_RESULT_ACCESS_DENIED;
-#endif
-#ifdef EPERM
- case EPERM:
- return DBUS_RESULT_ACCESS_DENIED;
-#endif
-#ifdef ENOBUFS
- case ENOBUFS:
- return DBUS_RESULT_NO_MEMORY;
-#endif
-#ifdef ENOMEM
- case ENOMEM:
- return DBUS_RESULT_NO_MEMORY;
-#endif
-#ifdef EINVAL
- case EINVAL:
- return DBUS_RESULT_FAILED;
-#endif
-#ifdef EBADF
- case EBADF:
- return DBUS_RESULT_FAILED;
-#endif
-#ifdef EFAULT
- case EFAULT:
- return DBUS_RESULT_FAILED;
-#endif
-#ifdef ENOTSOCK
- case ENOTSOCK:
- return DBUS_RESULT_FAILED;
-#endif
-#ifdef EISCONN
- case EISCONN:
- return DBUS_RESULT_FAILED;
-#endif
-#ifdef ECONNREFUSED
- case ECONNREFUSED:
- return DBUS_RESULT_NO_SERVER;
-#endif
-#ifdef ETIMEDOUT
- case ETIMEDOUT:
- return DBUS_RESULT_TIMEOUT;
-#endif
-#ifdef ENETUNREACH
- case ENETUNREACH:
- return DBUS_RESULT_NO_NETWORK;
-#endif
-#ifdef EADDRINUSE
- case EADDRINUSE:
- return DBUS_RESULT_ADDRESS_IN_USE;
-#endif
-#ifdef EEXIST
- case EEXIST:
- return DBUS_RESULT_FILE_NOT_FOUND;
-#endif
-#ifdef ENOENT
- case ENOENT:
- return DBUS_RESULT_FILE_NOT_FOUND;
-#endif
- }
-
- return DBUS_RESULT_FAILED;
-}
-
-/**
* Duplicates a string. Result must be freed with
* dbus_free(). Returns #NULL if memory allocation fails.
* If the string to be duplicated is #NULL, returns #NULL.
diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h
index 19a5cdc3..2576982d 100644
--- a/dbus/dbus-internals.h
+++ b/dbus/dbus-internals.h
@@ -94,6 +94,8 @@ do {
#define _DBUS_STRUCT_OFFSET(struct_type, member) \
((long) ((unsigned char*) &((struct_type*) 0)->member))
+#define _DBUS_ASSERT_ERROR_IS_SET(error) _dbus_assert ((error) == NULL || dbus_error_is_set ((error)))
+
/* This alignment thing is from ORBit2 */
/* Align a value upward to a boundary, expressed as a number of bytes.
* E.g. align to an 8-byte boundary with argument of 8.
@@ -146,6 +148,9 @@ void _dbus_verbose_bytes_of_string (const DBusString *str,
const char* _dbus_type_to_string (int type);
+extern const char _dbus_no_memory_message[];
+#define _DBUS_SET_OOM(error) dbus_set_error ((error), DBUS_ERROR_NO_MEMORY, _dbus_no_memory_message)
+
#ifdef DBUS_BUILD_TESTS
/* Memory debugging */
void _dbus_set_fail_alloc_counter (int until_next_fail);
diff --git a/dbus/dbus-keyring.c b/dbus/dbus-keyring.c
index c5c6a0b5..db432be8 100644
--- a/dbus/dbus-keyring.c
+++ b/dbus/dbus-keyring.c
@@ -399,6 +399,7 @@ _dbus_keyring_reload (DBusKeyring *keyring,
int n_keys;
int i;
long now;
+ DBusError tmp_error;
if (!_dbus_string_init (&contents, _DBUS_INT_MAX))
{
@@ -434,14 +435,15 @@ _dbus_keyring_reload (DBusKeyring *keyring,
have_lock = TRUE;
}
- result = _dbus_file_get_contents (&contents,
- &keyring->filename);
-
- if (result != DBUS_RESULT_SUCCESS)
+ dbus_error_init (&tmp_error);
+ if (!_dbus_file_get_contents (&contents,
+ &keyring->filename,
+ &tmp_error))
{
_dbus_verbose ("Failed to load keyring file: %s\n",
- dbus_result_to_string (result));
+ tmp_error.message);
/* continue with empty keyring file, so we recreate it */
+ dbus_error_free (&tmp_error);
}
if (!_dbus_string_validate_ascii (&contents, 0,
diff --git a/dbus/dbus-list.c b/dbus/dbus-list.c
index 7b306924..d0ca8dfa 100644
--- a/dbus/dbus-list.c
+++ b/dbus/dbus-list.c
@@ -678,6 +678,19 @@ _dbus_list_foreach (DBusList **list,
}
}
+/**
+ * Check whether length is exactly one.
+ *
+ * @param list the list
+ * @returns #TRUE if length is exactly one
+ */
+dbus_bool_t
+_dbus_list_length_is_one (DBusList **list)
+{
+ return (*list != NULL &&
+ (*list)->next == *list);
+}
+
/** @} */
#ifdef DBUS_BUILD_TESTS
@@ -713,6 +726,11 @@ verify_list (DBusList **list)
while (link != *list);
_dbus_assert (length == _dbus_list_get_length (list));
+
+ if (length == 1)
+ _dbus_assert (_dbus_list_length_is_one (list));
+ else
+ _dbus_assert (!_dbus_list_length_is_one (list));
}
static dbus_bool_t
diff --git a/dbus/dbus-list.h b/dbus/dbus-list.h
index 2c55c6bc..3f23f2ec 100644
--- a/dbus/dbus-list.h
+++ b/dbus/dbus-list.h
@@ -73,6 +73,8 @@ void _dbus_list_append_link (DBusList **list,
void _dbus_list_prepend_link (DBusList **list,
DBusList *link);
+dbus_bool_t _dbus_list_length_is_one (DBusList **list);
+
void _dbus_list_foreach (DBusList **list,
DBusForeachFunction function,
void *data);
diff --git a/dbus/dbus-message-builder.c b/dbus/dbus-message-builder.c
index 54b5de70..e34e1b55 100644
--- a/dbus/dbus-message-builder.c
+++ b/dbus/dbus-message-builder.c
@@ -314,7 +314,7 @@ _dbus_message_data_load (DBusString *dest,
const DBusString *filename)
{
DBusString file;
- DBusResultCode result;
+ DBusError error;
DBusString line;
dbus_bool_t retval;
int line_no;
@@ -340,14 +340,15 @@ _dbus_message_data_load (DBusString *dest,
_dbus_string_get_const_data (filename, &s);
_dbus_verbose ("Loading %s\n", s);
}
-
- if ((result = _dbus_file_get_contents (&file, filename)) != DBUS_RESULT_SUCCESS)
+
+ dbus_error_init (&error);
+ if (!_dbus_file_get_contents (&file, filename, &error))
{
const char *s;
_dbus_string_get_const_data (filename, &s);
_dbus_warn ("Getting contents of %s failed: %s\n",
- s, dbus_result_to_string (result));
-
+ s, error.message);
+ dbus_error_free (&error);
goto out;
}
diff --git a/dbus/dbus-message-internal.h b/dbus/dbus-message-internal.h
index 44ce62a3..86796da9 100644
--- a/dbus/dbus-message-internal.h
+++ b/dbus/dbus-message-internal.h
@@ -34,17 +34,12 @@ void _dbus_message_get_network_data (DBusMessage *message,
const DBusString **header,
const DBusString **body);
-void _dbus_message_lock (DBusMessage *message);
-void _dbus_message_unlock (DBusMessage *message);
-void _dbus_message_set_client_serial (DBusMessage *message,
- dbus_int32_t client_serial);
-dbus_int32_t _dbus_message_get_client_serial (DBusMessage *message);
-dbus_bool_t _dbus_message_set_reply_serial (DBusMessage *message,
- dbus_int32_t reply_serial);
-dbus_int32_t _dbus_message_get_reply_serial (DBusMessage *message);
-void _dbus_message_add_size_counter (DBusMessage *message,
- DBusCounter *counter);
-
+void _dbus_message_lock (DBusMessage *message);
+void _dbus_message_unlock (DBusMessage *message);
+void _dbus_message_set_serial (DBusMessage *message,
+ dbus_int32_t serial);
+void _dbus_message_add_size_counter (DBusMessage *message,
+ DBusCounter *counter);
DBusMessageLoader* _dbus_message_loader_new (void);
void _dbus_message_loader_ref (DBusMessageLoader *loader);
diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
index a25480cb..6a3c6618 100644
--- a/dbus/dbus-message.c
+++ b/dbus/dbus-message.c
@@ -532,28 +532,22 @@ set_string_field (DBusMessage *message,
}
/**
- * Sets the client serial of a message.
+ * Sets the serial number of a message.
* This can only be done once on a message.
- *
- * @todo client_serial should be called simply
- * "serial"; it's in outgoing messages for both
- * the client and the server, it's only client-specific
- * in the message bus case. It's more like origin_serial
- * or something.
*
* @param message the message
- * @param client_serial the client serial
+ * @param serial the serial
*/
void
-_dbus_message_set_client_serial (DBusMessage *message,
- dbus_int32_t client_serial)
+_dbus_message_set_serial (DBusMessage *message,
+ dbus_int32_t serial)
{
_dbus_assert (!message->locked);
- _dbus_assert (_dbus_message_get_client_serial (message) < 0);
+ _dbus_assert (dbus_message_get_serial (message) < 0);
set_int_field (message, FIELD_CLIENT_SERIAL,
- client_serial);
- message->client_serial = client_serial;
+ serial);
+ message->client_serial = serial;
}
/**
@@ -565,7 +559,7 @@ _dbus_message_set_client_serial (DBusMessage *message,
* @returns #FALSE if not enough memory
*/
dbus_bool_t
-_dbus_message_set_reply_serial (DBusMessage *message,
+dbus_message_set_reply_serial (DBusMessage *message,
dbus_int32_t reply_serial)
{
_dbus_assert (!message->locked);
@@ -581,19 +575,15 @@ _dbus_message_set_reply_serial (DBusMessage *message,
}
/**
- * Returns the client serial of a message or
- * -1 if none has been specified.
- *
- * @todo see note in _dbus_message_set_client_serial()
- * about how client_serial is a misnomer
- *
- * @todo this function should be public, after renaming it.
+ * Returns the serial of a message or -1 if none has been specified.
+ * The message's serial number is provided by the application sending
+ * the message and is used to identify replies to this message.
*
* @param message the message
* @returns the client serial
*/
dbus_int32_t
-_dbus_message_get_client_serial (DBusMessage *message)
+dbus_message_get_serial (DBusMessage *message)
{
return message->client_serial;
}
@@ -606,7 +596,7 @@ _dbus_message_get_client_serial (DBusMessage *message)
* @returns the reply serial
*/
dbus_int32_t
-_dbus_message_get_reply_serial (DBusMessage *message)
+dbus_message_get_reply_serial (DBusMessage *message)
{
return message->reply_serial;
}
@@ -845,8 +835,8 @@ dbus_message_new_reply (DBusMessage *original_message)
if (message == NULL)
return NULL;
- if (!_dbus_message_set_reply_serial (message,
- _dbus_message_get_client_serial (original_message)))
+ if (!dbus_message_set_reply_serial (message,
+ dbus_message_get_serial (original_message)))
{
dbus_message_unref (message);
return NULL;
@@ -881,8 +871,8 @@ dbus_message_new_error_reply (DBusMessage *original_message,
if (message == NULL)
return NULL;
- if (!_dbus_message_set_reply_serial (message,
- _dbus_message_get_client_serial (original_message)))
+ if (!dbus_message_set_reply_serial (message,
+ dbus_message_get_serial (original_message)))
{
dbus_message_unref (message);
return NULL;
@@ -1542,12 +1532,14 @@ dbus_message_append_dict (DBusMessage *message,
* stored. The list is terminated with 0.
*
* @param message the message
+ * @param error error to be filled in on failure
* @param first_arg_type the first argument type
* @param ... location for first argument value, then list of type-location pairs
- * @returns result code
+ * @returns #FALSE if the error was set
*/
-DBusResultCode
+dbus_bool_t
dbus_message_get_args (DBusMessage *message,
+ DBusError *error,
int first_arg_type,
...)
{
@@ -1555,7 +1547,7 @@ dbus_message_get_args (DBusMessage *message,
va_list var_args;
va_start (var_args, first_arg_type);
- retval = dbus_message_get_args_valist (message, first_arg_type, var_args);
+ retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
va_end (var_args);
return retval;
@@ -1575,22 +1567,31 @@ dbus_message_get_args (DBusMessage *message,
*
* @see dbus_message_get_args
* @param message the message
+ * @param error error to be filled in
* @param first_arg_type type of the first argument
* @param var_args return location for first argument, followed by list of type/location pairs
- * @returns result code
+ * @returns #FALSE if error was set
*/
-DBusResultCode
+dbus_bool_t
dbus_message_get_args_valist (DBusMessage *message,
+ DBusError *error,
int first_arg_type,
va_list var_args)
{
int spec_type, msg_type, i;
DBusMessageIter *iter;
-
+ dbus_bool_t retval;
+
iter = dbus_message_get_args_iter (message);
if (iter == NULL)
- return DBUS_RESULT_NO_MEMORY;
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+ "No memory to get message arguments");
+ return FALSE;
+ }
+
+ retval = FALSE;
spec_type = first_arg_type;
i = 0;
@@ -1601,13 +1602,13 @@ dbus_message_get_args_valist (DBusMessage *message,
if (msg_type != spec_type)
{
- _dbus_verbose ("Argument %d is specified to be of type \"%s\", but "
- "is actually of type \"%s\"\n", i,
- _dbus_type_to_string (spec_type),
- _dbus_type_to_string (msg_type));
- dbus_message_iter_unref (iter);
+ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+ "Argument %d is specified to be of type \"%s\", but "
+ "is actually of type \"%s\"\n", i,
+ _dbus_type_to_string (spec_type),
+ _dbus_type_to_string (msg_type));
- return DBUS_RESULT_INVALID_ARGS;
+ goto out;
}
switch (spec_type)
@@ -1661,7 +1662,11 @@ dbus_message_get_args_valist (DBusMessage *message,
*ptr = dbus_message_iter_get_string (iter);
if (!*ptr)
- return DBUS_RESULT_NO_MEMORY;
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+ "No memory for argument %d", i);
+ goto out;
+ }
break;
}
@@ -1675,8 +1680,11 @@ dbus_message_get_args_valist (DBusMessage *message,
len = va_arg (var_args, int *);
if (!dbus_message_iter_get_boolean_array (iter, ptr, len))
- return DBUS_RESULT_NO_MEMORY;
-
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+ "No memory for argument %d", i);
+ goto out;
+ }
break;
}
@@ -1689,7 +1697,11 @@ dbus_message_get_args_valist (DBusMessage *message,
len = va_arg (var_args, int *);
if (!dbus_message_iter_get_int32_array (iter, ptr, len))
- return DBUS_RESULT_NO_MEMORY;
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+ "No memory for argument %d", i);
+ goto out;
+ }
break;
}
@@ -1703,7 +1715,11 @@ dbus_message_get_args_valist (DBusMessage *message,
len = va_arg (var_args, int *);
if (!dbus_message_iter_get_uint32_array (iter, ptr, len))
- return DBUS_RESULT_NO_MEMORY;
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+ "No memory for argument %d", i);
+ goto out;
+ }
break;
}
@@ -1717,8 +1733,11 @@ dbus_message_get_args_valist (DBusMessage *message,
len = va_arg (var_args, int *);
if (!dbus_message_iter_get_double_array (iter, ptr, len))
- return DBUS_RESULT_NO_MEMORY;
-
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+ "No memory for argument %d", i);
+ goto out;
+ }
break;
}
@@ -1731,8 +1750,11 @@ dbus_message_get_args_valist (DBusMessage *message,
len = va_arg (var_args, int *);
if (!dbus_message_iter_get_byte_array (iter, ptr, len))
- return DBUS_RESULT_NO_MEMORY;
-
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+ "No memory for argument %d", i);
+ goto out;
+ }
break;
}
case DBUS_TYPE_STRING_ARRAY:
@@ -1744,7 +1766,11 @@ dbus_message_get_args_valist (DBusMessage *message,
len = va_arg (var_args, int *);
if (!dbus_message_iter_get_string_array (iter, ptr, len))
- return DBUS_RESULT_NO_MEMORY;
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+ "No memory for argument %d", i);
+ goto out;
+ }
break;
}
case DBUS_TYPE_DICT:
@@ -1754,7 +1780,11 @@ dbus_message_get_args_valist (DBusMessage *message,
dict = va_arg (var_args, DBusDict **);
if (!dbus_message_iter_get_dict (iter, dict))
- return DBUS_RESULT_NO_MEMORY;
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+ "No memory for argument %d", i);
+ goto out;
+ }
break;
}
default:
@@ -1763,17 +1793,20 @@ dbus_message_get_args_valist (DBusMessage *message,
spec_type = va_arg (var_args, int);
if (spec_type != 0 && !dbus_message_iter_next (iter))
- {
- _dbus_verbose ("More fields than exist in the message were specified or field is corrupt\n");
+ {
+ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+ "Message has only %d arguments, but more were expected", i);
+ goto out;
+ }
- dbus_message_iter_unref (iter);
- return DBUS_RESULT_INVALID_ARGS;
- }
i++;
}
-
+
+ retval = TRUE;
+
+ out:
dbus_message_iter_unref (iter);
- return DBUS_RESULT_SUCCESS;
+ return retval;
}
/**
@@ -2318,6 +2351,10 @@ dbus_message_name_is (DBusMessage *message,
* DBusTransport implementation. The DBusTransport then hands off
* the loaded messages to a DBusConnection, making the messages
* visible to the application.
+ *
+ * @todo write tests for break-loader that a) randomly delete header
+ * fields and b) set string fields to zero-length and other funky
+ * values.
*
*/
@@ -2624,6 +2661,13 @@ decode_header_data (const DBusString *data,
}
}
+ if (fields[FIELD_NAME].offset < 0)
+ {
+ _dbus_verbose ("No %s field provided\n",
+ DBUS_HEADER_FIELD_NAME);
+ return FALSE;
+ }
+
if (message_padding)
*message_padding = header_len - pos;
@@ -2970,13 +3014,13 @@ check_message_handling (DBusMessage *message)
retval = FALSE;
iter = NULL;
- client_serial = _dbus_message_get_client_serial (message);
+ client_serial = dbus_message_get_serial (message);
- /* can't use set_client_serial due to the assertions at the start of it */
+ /* can't use set_serial due to the assertions at the start of it */
set_int_field (message, FIELD_CLIENT_SERIAL,
client_serial);
-
- if (client_serial != _dbus_message_get_client_serial (message))
+
+ if (client_serial != dbus_message_get_serial (message))
{
_dbus_warn ("get/set cycle for client_serial did not succeed\n");
goto failed;
@@ -3215,14 +3259,15 @@ dbus_internal_do_not_use_load_message_file (const DBusString *filename,
if (is_raw)
{
- DBusResultCode result;
+ DBusError error;
- result = _dbus_file_get_contents (data, filename);
- if (result != DBUS_RESULT_SUCCESS)
+ dbus_error_init (&error);
+ if (!_dbus_file_get_contents (data, filename, &error))
{
const char *s;
_dbus_string_get_const_data (filename, &s);
- _dbus_warn ("Could not load message file %s\n", s);
+ _dbus_warn ("Could not load message file %s: %s\n", s, error.message);
+ dbus_error_free (&error);
goto failed;
}
}
@@ -3397,7 +3442,7 @@ process_test_subdir (const DBusString *test_base_dir,
DBusString filename;
DBusDirIter *dir;
dbus_bool_t retval;
- DBusResultCode result;
+ DBusError error;
retval = FALSE;
dir = NULL;
@@ -3417,22 +3462,23 @@ process_test_subdir (const DBusString *test_base_dir,
_dbus_string_free (&filename);
if (!_dbus_string_init (&filename, _DBUS_INT_MAX))
_dbus_assert_not_reached ("didn't allocate filename string\n");
-
- dir = _dbus_directory_open (&test_directory, &result);
+
+ dbus_error_init (&error);
+ dir = _dbus_directory_open (&test_directory, &error);
if (dir == NULL)
{
const char *s;
_dbus_string_get_const_data (&test_directory, &s);
_dbus_warn ("Could not open %s: %s\n", s,
- dbus_result_to_string (result));
+ error.message);
+ dbus_error_free (&error);
goto failed;
}
printf ("Testing:\n");
- result = DBUS_RESULT_SUCCESS;
next:
- while (_dbus_directory_get_next_file (dir, &filename, &result))
+ while (_dbus_directory_get_next_file (dir, &filename, &error))
{
DBusString full_path;
dbus_bool_t is_raw;
@@ -3480,12 +3526,13 @@ process_test_subdir (const DBusString *test_base_dir,
_dbus_string_free (&full_path);
}
- if (result != DBUS_RESULT_SUCCESS)
+ if (dbus_error_is_set (&error))
{
const char *s;
_dbus_string_get_const_data (&test_directory, &s);
_dbus_warn ("Could not get next file in %s: %s\n",
- s, dbus_result_to_string (result));
+ s, error.message);
+ dbus_error_free (&error);
goto failed;
}
@@ -3563,7 +3610,7 @@ _dbus_message_test (const char *test_data_dir)
/* Test the vararg functions */
message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
- _dbus_message_set_client_serial (message, 1);
+ _dbus_message_set_serial (message, 1);
dbus_message_append_args (message,
DBUS_TYPE_INT32, -0x12345678,
DBUS_TYPE_STRING, "Test string",
@@ -3574,13 +3621,13 @@ _dbus_message_test (const char *test_data_dir)
_dbus_string_get_length (&message->header));
_dbus_verbose_bytes_of_string (&message->body, 0,
_dbus_string_get_length (&message->body));
-
- if (dbus_message_get_args (message,
- DBUS_TYPE_INT32, &our_int,
- DBUS_TYPE_STRING, &our_str,
- DBUS_TYPE_DOUBLE, &our_double,
- DBUS_TYPE_BOOLEAN, &our_bool,
- 0) != DBUS_RESULT_SUCCESS)
+
+ if (!dbus_message_get_args (message, NULL,
+ DBUS_TYPE_INT32, &our_int,
+ DBUS_TYPE_STRING, &our_str,
+ DBUS_TYPE_DOUBLE, &our_double,
+ DBUS_TYPE_BOOLEAN, &our_bool,
+ 0))
_dbus_assert_not_reached ("Could not get arguments");
if (our_int != -0x12345678)
@@ -3599,8 +3646,8 @@ _dbus_message_test (const char *test_data_dir)
dbus_message_unref (message);
message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
- _dbus_message_set_client_serial (message, 1);
- _dbus_message_set_reply_serial (message, 0x12345678);
+ _dbus_message_set_serial (message, 1);
+ dbus_message_set_reply_serial (message, 0x12345678);
dbus_message_append_string (message, "Test string");
dbus_message_append_int32 (message, -0x12345678);
@@ -3645,7 +3692,7 @@ _dbus_message_test (const char *test_data_dir)
if (!message)
_dbus_assert_not_reached ("received a NULL message");
- if (_dbus_message_get_reply_serial (message) != 0x12345678)
+ if (dbus_message_get_reply_serial (message) != 0x12345678)
_dbus_assert_not_reached ("reply serial fields differ");
message_iter_test (message);
diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h
index 4ea63060..d30a0a3d 100644
--- a/dbus/dbus-message.h
+++ b/dbus/dbus-message.h
@@ -48,17 +48,21 @@ DBusMessage *dbus_message_new_from_message (const DBusMessage *message);
void dbus_message_ref (DBusMessage *message);
void dbus_message_unref (DBusMessage *message);
-const char* dbus_message_get_name (DBusMessage *message);
-const char* dbus_message_get_service (DBusMessage *message);
-dbus_bool_t dbus_message_set_sender (DBusMessage *message,
- const char *sender);
-const char* dbus_message_get_sender (DBusMessage *message);
-void dbus_message_set_is_error (DBusMessage *message,
- dbus_bool_t is_error_reply);
-dbus_bool_t dbus_message_get_is_error (DBusMessage *message);
+const char* dbus_message_get_name (DBusMessage *message);
+const char* dbus_message_get_service (DBusMessage *message);
+dbus_bool_t dbus_message_set_sender (DBusMessage *message,
+ const char *sender);
+const char* dbus_message_get_sender (DBusMessage *message);
+void dbus_message_set_is_error (DBusMessage *message,
+ dbus_bool_t is_error_reply);
+dbus_bool_t dbus_message_get_is_error (DBusMessage *message);
+dbus_bool_t dbus_message_name_is (DBusMessage *message,
+ const char *name);
+dbus_int32_t dbus_message_get_serial (DBusMessage *message);
+dbus_bool_t dbus_message_set_reply_serial (DBusMessage *message,
+ dbus_int32_t reply_serial);
+dbus_int32_t dbus_message_get_reply_serial (DBusMessage *message);
-dbus_bool_t dbus_message_name_is (DBusMessage *message,
- const char *name);
dbus_bool_t dbus_message_append_args (DBusMessage *message,
int first_arg_type,
@@ -99,13 +103,14 @@ dbus_bool_t dbus_message_append_dict (DBusMessage *message,
DBusDict *dict);
DBusMessageIter *dbus_message_get_args_iter (DBusMessage *message);
-DBusResultCode dbus_message_get_args (DBusMessage *message,
- int first_arg_type,
- ...);
-DBusResultCode dbus_message_get_args_valist (DBusMessage *message,
- int first_arg_type,
- va_list var_args);
-
+dbus_bool_t dbus_message_get_args (DBusMessage *message,
+ DBusError *error,
+ int first_arg_type,
+ ...);
+dbus_bool_t dbus_message_get_args_valist (DBusMessage *message,
+ DBusError *error,
+ int first_arg_type,
+ va_list var_args);
void dbus_message_iter_ref (DBusMessageIter *iter);
diff --git a/dbus/dbus-sha.c b/dbus/dbus-sha.c
index 2f73e363..8f047122 100644
--- a/dbus/dbus-sha.c
+++ b/dbus/dbus-sha.c
@@ -752,6 +752,7 @@ process_test_data (const char *test_data_dir)
int line_no;
dbus_bool_t retval;
int success_count;
+ DBusError error;
retval = FALSE;
@@ -784,21 +785,24 @@ process_test_data (const char *test_data_dir)
if (!_dbus_concat_dir_and_file (&results_file, &tmp))
_dbus_assert_not_reached ("no memory");
- if (_dbus_file_get_contents (&tests, &tests_file) != DBUS_RESULT_SUCCESS)
+ dbus_error_init (&error);
+ if (!_dbus_file_get_contents (&tests, &tests_file, &error))
{
const char *s;
_dbus_string_get_const_data (&tests_file, &s);
- fprintf (stderr, "could not load test data file %s\n",
- s);
+ fprintf (stderr, "could not load test data file %s: %s\n",
+ s, error.message);
+ dbus_error_free (&error);
goto out;
}
- if (_dbus_file_get_contents (&results, &results_file) != DBUS_RESULT_SUCCESS)
+ if (!_dbus_file_get_contents (&results, &results_file, &error))
{
const char *s;
_dbus_string_get_const_data (&results_file, &s);
- fprintf (stderr, "could not load results data file %s\n",
- s);
+ fprintf (stderr, "could not load results data file %s: %s\n",
+ s, error.message);
+ dbus_error_free (&error);
goto out;
}
diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c
index d096ce3e..5d0be321 100644
--- a/dbus/dbus-sysdeps.c
+++ b/dbus/dbus-sysdeps.c
@@ -1,7 +1,7 @@
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-sysdeps.c Wrappers around system/libc features (internal to D-BUS implementation)
*
- * Copyright (C) 2002 Red Hat, Inc.
+ * Copyright (C) 2002, 2003 Red Hat, Inc.
*
* Licensed under the Academic Free License version 1.2
*
@@ -1604,11 +1604,13 @@ _dbus_get_current_time (long *tv_sec,
*
* @param str the string to append to
* @param filename filename to load
- * @returns result
+ * @param error place to set an error
+ * @returns #FALSE if error was set
*/
-DBusResultCode
+dbus_bool_t
_dbus_file_get_contents (DBusString *str,
- const DBusString *filename)
+ const DBusString *filename,
+ DBusError *error)
{
int fd;
struct stat sb;
@@ -1621,28 +1623,32 @@ _dbus_file_get_contents (DBusString *str,
/* O_BINARY useful on Cygwin */
fd = open (filename_c, O_RDONLY | O_BINARY);
if (fd < 0)
- return _dbus_result_from_errno (errno);
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "%s", _dbus_strerror (errno));
+ return FALSE;
+ }
if (fstat (fd, &sb) < 0)
{
- DBusResultCode result;
-
- result = _dbus_result_from_errno (errno); /* prior to close() */
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "%s", _dbus_strerror (errno));
_dbus_verbose ("fstat() failed: %s",
_dbus_strerror (errno));
close (fd);
- return result;
+ return FALSE;
}
if (sb.st_size > _DBUS_ONE_MEGABYTE)
{
- _dbus_verbose ("File size %lu is too large.\n",
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "File size %lu is too large.\n",
(unsigned long) sb.st_size);
close (fd);
- return DBUS_RESULT_FAILED;
+ return FALSE;
}
total = 0;
@@ -1657,34 +1663,35 @@ _dbus_file_get_contents (DBusString *str,
sb.st_size - total);
if (bytes_read <= 0)
{
- DBusResultCode result;
-
- result = _dbus_result_from_errno (errno); /* prior to close() */
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "%s", _dbus_strerror (errno));
_dbus_verbose ("read() failed: %s",
_dbus_strerror (errno));
close (fd);
_dbus_string_set_length (str, orig_len);
- return result;
+ return FALSE;
}
else
total += bytes_read;
}
close (fd);
- return DBUS_RESULT_SUCCESS;
+ return TRUE;
}
else if (sb.st_size != 0)
{
_dbus_verbose ("Can only open regular files at the moment.\n");
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Not a regular file");
close (fd);
- return DBUS_RESULT_FAILED;
+ return FALSE;
}
else
{
close (fd);
- return DBUS_RESULT_SUCCESS;
+ return TRUE;
}
}
@@ -1972,12 +1979,12 @@ struct DBusDirIter
* Open a directory to iterate over.
*
* @param filename the directory name
- * @param result return location for error code if #NULL returned
+ * @param error exception return object or #NULL
* @returns new iterator, or #NULL on error
*/
DBusDirIter*
_dbus_directory_open (const DBusString *filename,
- DBusResultCode *result)
+ DBusError *error)
{
DIR *d;
DBusDirIter *iter;
@@ -1988,15 +1995,16 @@ _dbus_directory_open (const DBusString *filename,
d = opendir (filename_c);
if (d == NULL)
{
- dbus_set_result (result, _dbus_result_from_errno (errno));
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "%s", _dbus_strerror (errno));
return NULL;
}
-
iter = dbus_new0 (DBusDirIter, 1);
if (iter == NULL)
{
closedir (d);
- dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+ "Could not allocate memory for directory iterator");
return NULL;
}
@@ -2006,39 +2014,38 @@ _dbus_directory_open (const DBusString *filename,
}
/**
- * Get next file in the directory. Will not return "." or ".."
- * on UNIX. If an error occurs, the contents of "filename"
- * are undefined. #DBUS_RESULT_SUCCESS is always returned
- * in result if no error occurs.
+ * Get next file in the directory. Will not return "." or ".." on
+ * UNIX. If an error occurs, the contents of "filename" are
+ * undefined. The error is never set if the function succeeds.
*
* @todo for thread safety, I think we have to use
* readdir_r(). (GLib has the same issue, should file a bug.)
*
* @param iter the iterator
* @param filename string to be set to the next file in the dir
- * @param result return location for error, or #DBUS_RESULT_SUCCESS
+ * @param error return location for error
* @returns #TRUE if filename was filled in with a new filename
*/
dbus_bool_t
_dbus_directory_get_next_file (DBusDirIter *iter,
DBusString *filename,
- DBusResultCode *result)
+ DBusError *error)
{
/* we always have to put something in result, since return
* value means whether there's a filename and doesn't
* reliably indicate whether an error was set.
*/
struct dirent *ent;
-
- dbus_set_result (result, DBUS_RESULT_SUCCESS);
again:
errno = 0;
ent = readdir (iter->d);
if (ent == NULL)
{
- dbus_set_result (result,
- _dbus_result_from_errno (errno));
+ if (errno != 0)
+ dbus_set_error (error,
+ _dbus_error_from_errno (errno),
+ "%s", _dbus_strerror (errno));
return FALSE;
}
else if (ent->d_name[0] == '.' &&
@@ -2050,7 +2057,8 @@ _dbus_directory_get_next_file (DBusDirIter *iter,
_dbus_string_set_length (filename, 0);
if (!_dbus_string_append (filename, ent->d_name))
{
- dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+ "No memory to read directory entry");
return FALSE;
}
else
@@ -2501,4 +2509,249 @@ _dbus_fd_set_close_on_exec (int fd)
fcntl (fd, F_SETFD, val);
}
+
+/**
+ * Converts a UNIX errno into a DBusResultCode.
+ *
+ * @todo should cover more errnos, specifically those
+ * from open().
+ *
+ * @param error_number the errno.
+ * @returns the result code.
+ */
+DBusResultCode
+_dbus_result_from_errno (int error_number)
+{
+ switch (error_number)
+ {
+ case 0:
+ return DBUS_RESULT_SUCCESS;
+
+#ifdef EPROTONOSUPPORT
+ case EPROTONOSUPPORT:
+ return DBUS_RESULT_NOT_SUPPORTED;
+#endif
+#ifdef EAFNOSUPPORT
+ case EAFNOSUPPORT:
+ return DBUS_RESULT_NOT_SUPPORTED;
+#endif
+#ifdef ENFILE
+ case ENFILE:
+ return DBUS_RESULT_LIMITS_EXCEEDED; /* kernel out of memory */
+#endif
+#ifdef EMFILE
+ case EMFILE:
+ return DBUS_RESULT_LIMITS_EXCEEDED;
+#endif
+#ifdef EACCES
+ case EACCES:
+ return DBUS_RESULT_ACCESS_DENIED;
+#endif
+#ifdef EPERM
+ case EPERM:
+ return DBUS_RESULT_ACCESS_DENIED;
+#endif
+#ifdef ENOBUFS
+ case ENOBUFS:
+ return DBUS_RESULT_NO_MEMORY;
+#endif
+#ifdef ENOMEM
+ case ENOMEM:
+ return DBUS_RESULT_NO_MEMORY;
+#endif
+#ifdef EINVAL
+ case EINVAL:
+ return DBUS_RESULT_FAILED;
+#endif
+#ifdef EBADF
+ case EBADF:
+ return DBUS_RESULT_FAILED;
+#endif
+#ifdef EFAULT
+ case EFAULT:
+ return DBUS_RESULT_FAILED;
+#endif
+#ifdef ENOTSOCK
+ case ENOTSOCK:
+ return DBUS_RESULT_FAILED;
+#endif
+#ifdef EISCONN
+ case EISCONN:
+ return DBUS_RESULT_FAILED;
+#endif
+#ifdef ECONNREFUSED
+ case ECONNREFUSED:
+ return DBUS_RESULT_NO_SERVER;
+#endif
+#ifdef ETIMEDOUT
+ case ETIMEDOUT:
+ return DBUS_RESULT_TIMEOUT;
+#endif
+#ifdef ENETUNREACH
+ case ENETUNREACH:
+ return DBUS_RESULT_NO_NETWORK;
+#endif
+#ifdef EADDRINUSE
+ case EADDRINUSE:
+ return DBUS_RESULT_ADDRESS_IN_USE;
+#endif
+#ifdef EEXIST
+ case EEXIST:
+ return DBUS_RESULT_FILE_NOT_FOUND;
+#endif
+#ifdef ENOENT
+ case ENOENT:
+ return DBUS_RESULT_FILE_NOT_FOUND;
+#endif
+ }
+
+ return DBUS_RESULT_FAILED;
+}
+
+/**
+ * Converts a UNIX errno into a #DBusError name.
+ *
+ * @todo should cover more errnos, specifically those
+ * from open().
+ *
+ * @param error_number the errno.
+ * @returns an error name
+ */
+const char*
+_dbus_error_from_errno (int error_number)
+{
+ switch (error_number)
+ {
+ case 0:
+ return DBUS_ERROR_FAILED;
+
+#ifdef EPROTONOSUPPORT
+ case EPROTONOSUPPORT:
+ return DBUS_ERROR_NOT_SUPPORTED;
+#endif
+#ifdef EAFNOSUPPORT
+ case EAFNOSUPPORT:
+ return DBUS_ERROR_NOT_SUPPORTED;
+#endif
+#ifdef ENFILE
+ case ENFILE:
+ return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
+#endif
+#ifdef EMFILE
+ case EMFILE:
+ return DBUS_ERROR_LIMITS_EXCEEDED;
+#endif
+#ifdef EACCES
+ case EACCES:
+ return DBUS_ERROR_ACCESS_DENIED;
+#endif
+#ifdef EPERM
+ case EPERM:
+ return DBUS_ERROR_ACCESS_DENIED;
+#endif
+#ifdef ENOBUFS
+ case ENOBUFS:
+ return DBUS_ERROR_NO_MEMORY;
+#endif
+#ifdef ENOMEM
+ case ENOMEM:
+ return DBUS_ERROR_NO_MEMORY;
+#endif
+#ifdef EINVAL
+ case EINVAL:
+ return DBUS_ERROR_FAILED;
+#endif
+#ifdef EBADF
+ case EBADF:
+ return DBUS_ERROR_FAILED;
+#endif
+#ifdef EFAULT
+ case EFAULT:
+ return DBUS_ERROR_FAILED;
+#endif
+#ifdef ENOTSOCK
+ case ENOTSOCK:
+ return DBUS_ERROR_FAILED;
+#endif
+#ifdef EISCONN
+ case EISCONN:
+ return DBUS_ERROR_FAILED;
+#endif
+#ifdef ECONNREFUSED
+ case ECONNREFUSED:
+ return DBUS_ERROR_NO_SERVER;
+#endif
+#ifdef ETIMEDOUT
+ case ETIMEDOUT:
+ return DBUS_ERROR_TIMEOUT;
+#endif
+#ifdef ENETUNREACH
+ case ENETUNREACH:
+ return DBUS_ERROR_NO_NETWORK;
+#endif
+#ifdef EADDRINUSE
+ case EADDRINUSE:
+ return DBUS_ERROR_ADDRESS_IN_USE;
+#endif
+#ifdef EEXIST
+ case EEXIST:
+ return DBUS_ERROR_FILE_NOT_FOUND;
+#endif
+#ifdef ENOENT
+ case ENOENT:
+ return DBUS_ERROR_FILE_NOT_FOUND;
+#endif
+ }
+
+ return DBUS_ERROR_FAILED;
+}
+
+/**
+ * Exit the process, returning the given value.
+ *
+ * @param code the exit code
+ */
+void
+_dbus_exit (int code)
+{
+ _exit (code);
+}
+
+/**
+ * stat() wrapper.
+ *
+ * @param filename the filename to stat
+ * @param statbuf the stat info to fill in
+ * @param error return location for error
+ * @returns #FALSE if error was set
+ */
+dbus_bool_t
+_dbus_stat (const DBusString *filename,
+ DBusStat *statbuf,
+ DBusError *error)
+{
+ const char *filename_c;
+ struct stat sb;
+
+ _dbus_string_get_const_data (filename, &filename_c);
+
+ if (stat (filename_c, &sb) < 0)
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "%s", _dbus_strerror (errno));
+ return FALSE;
+ }
+
+ statbuf->mode = sb.st_mode;
+ statbuf->nlink = sb.st_nlink;
+ statbuf->uid = sb.st_uid;
+ statbuf->gid = sb.st_gid;
+ statbuf->size = sb.st_size;
+ statbuf->atime = sb.st_atime;
+ statbuf->mtime = sb.st_mtime;
+ statbuf->ctime = sb.st_ctime;
+
+ return TRUE;
+}
+
/** @} end of sysdeps */
diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h
index fb8362e2..f1ac47c8 100644
--- a/dbus/dbus-sysdeps.h
+++ b/dbus/dbus-sysdeps.h
@@ -138,8 +138,9 @@ void _dbus_sleep_milliseconds (int milliseconds);
void _dbus_get_current_time (long *tv_sec,
long *tv_usec);
-DBusResultCode _dbus_file_get_contents (DBusString *str,
- const DBusString *filename);
+dbus_bool_t _dbus_file_get_contents (DBusString *str,
+ const DBusString *filename,
+ DBusError *error);
DBusResultCode _dbus_string_save_to_file (const DBusString *str,
const DBusString *filename);
@@ -156,17 +157,18 @@ dbus_bool_t _dbus_concat_dir_and_file (DBusString *dir,
typedef struct DBusDirIter DBusDirIter;
DBusDirIter* _dbus_directory_open (const DBusString *filename,
- DBusResultCode *result);
+ DBusError *error);
dbus_bool_t _dbus_directory_get_next_file (DBusDirIter *iter,
DBusString *filename,
- DBusResultCode *result);
+ DBusError *error);
void _dbus_directory_close (DBusDirIter *iter);
dbus_bool_t _dbus_generate_random_bytes (DBusString *str,
int n_bytes);
-const char *_dbus_errno_to_string (int errnum);
+const char *_dbus_errno_to_string (int errnum);
+const char* _dbus_error_from_errno (int error_number);
typedef void (* DBusSpawnChildSetupFunc) (void *user_data);
@@ -180,6 +182,24 @@ void _dbus_disable_sigpipe (void);
void _dbus_fd_set_close_on_exec (int fd);
+void _dbus_exit (int code);
+
+typedef struct
+{
+ unsigned long mode;
+ unsigned long nlink;
+ unsigned long uid;
+ unsigned long gid;
+ unsigned long size;
+ unsigned long atime;
+ unsigned long mtime;
+ unsigned long ctime;
+} DBusStat;
+
+dbus_bool_t _dbus_stat (const DBusString *filename,
+ DBusStat *statbuf,
+ DBusError *error);
+
DBUS_END_DECLS;
#endif /* DBUS_SYSDEPS_H */
diff --git a/glib/test-dbus-glib.c b/glib/test-dbus-glib.c
index fe9cd6b9..b5c44024 100644
--- a/glib/test-dbus-glib.c
+++ b/glib/test-dbus-glib.c
@@ -7,13 +7,13 @@ main (int argc, char **argv)
{
DBusConnection *connection;
DBusResultCode result;
- DBusMessage *message, *reply;
-
+ DBusMessage *message, *reply;
GMainLoop *loop;
+ DBusError error;
if (argc < 2)
{
- fprintf (stderr, "Give the server address as an argument\n");
+ g_printerr ("Give the server address as an argument\n");
return 1;
}
@@ -22,8 +22,8 @@ main (int argc, char **argv)
connection = dbus_connection_open (argv[1], &result);
if (connection == NULL)
{
- fprintf (stderr, "Failed to open connection to %s: %s\n", argv[1],
- dbus_result_to_string (result));
+ g_printerr ("Failed to open connection to %s: %s\n", argv[1],
+ dbus_result_to_string (result));
return 1;
}
@@ -31,7 +31,15 @@ main (int argc, char **argv)
message = dbus_message_new ("org.freedesktop.DBus", "org.freedesktop.DBus.Hello");
- reply = dbus_connection_send_message_with_reply_and_block (connection, message, -1, &result);
+ dbus_error_init (&error);
+ reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error);
+ if (reply == NULL)
+ {
+ g_printerr ("Error on hello message: %s\n", error.message);
+ dbus_error_free (&error);
+ return 1;
+ }
+
g_print ("reply name: %s\n", dbus_message_get_name (reply));
g_main_loop_run (loop);
diff --git a/glib/test-thread-client.c b/glib/test-thread-client.c
index ca78dbb8..23ec3f33 100644
--- a/glib/test-thread-client.c
+++ b/glib/test-thread-client.c
@@ -37,12 +37,13 @@ thread_func (gpointer data)
}
g_free (str);
- if (!dbus_connection_send_message (connection,
- message,
- NULL, NULL))
+ if (!dbus_connection_send (connection,
+ message,
+ NULL))
{
- g_print ("thread %d: send message failerd\n", threadnr);
+ g_print ("thread %d: send message failed\n", threadnr);
}
+
dbus_message_unref (message);
counter ++;
diff --git a/test/bus-test.c b/test/bus-test.c
index 342e806b..e059e6cb 100644
--- a/test/bus-test.c
+++ b/test/bus-test.c
@@ -62,24 +62,34 @@ test_hello_client1_handler (DBusMessageHandler *handler,
if (!test_hello_succeeding)
goto out;
+
+#if 1
+ printf ("In stage %d got message %s\n",
+ client1_stage, dbus_message_get_name (message));
+#endif
if (dbus_message_name_is (message, DBUS_MESSAGE_HELLO))
{
TEST_HELLO_HANDLE_FAIL (client1_stage == 0);
- TEST_HELLO_HANDLE_FAIL ((dbus_message_get_args (message,
- DBUS_TYPE_STRING, &client1_name,
- 0) == DBUS_RESULT_SUCCESS));
+ TEST_HELLO_HANDLE_FAIL (dbus_message_get_args (message, NULL,
+ DBUS_TYPE_STRING, &client1_name,
+ 0));
client1_stage += 1;
}
else if (dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_CREATED))
{
- TEST_HELLO_HANDLE_FAIL (client1_stage == 1 || client1_stage == 3);
+ TEST_HELLO_HANDLE_FAIL (dbus_message_get_args (message, NULL,
+ DBUS_TYPE_STRING, &tmp,
+ 0));
- TEST_HELLO_HANDLE_FAIL ((dbus_message_get_args (message,
- DBUS_TYPE_STRING, &tmp,
- 0) == DBUS_RESULT_SUCCESS));
+#if 0
+ printf ("ServiceCreated is %s\n", tmp);
+#endif
+
+ TEST_HELLO_HANDLE_FAIL (client1_stage == 1 || client1_stage == 3);
+
if (client1_stage == 1)
TEST_HELLO_HANDLE_FAIL (strcmp (client1_name, tmp) == 0);
else
@@ -94,9 +104,9 @@ test_hello_client1_handler (DBusMessageHandler *handler,
{
TEST_HELLO_HANDLE_FAIL (client1_stage == 2);
- TEST_HELLO_HANDLE_FAIL ((dbus_message_get_args (message,
- DBUS_TYPE_STRING, &tmp,
- 0) == DBUS_RESULT_SUCCESS));
+ TEST_HELLO_HANDLE_FAIL (dbus_message_get_args (message, NULL,
+ DBUS_TYPE_STRING, &tmp,
+ 0));
TEST_HELLO_HANDLE_FAIL (strcmp (client1_name, tmp) == 0);
client1_stage += 1;
@@ -132,9 +142,9 @@ test_hello_client2_handler (DBusMessageHandler *handler,
{
TEST_HELLO_HANDLE_FAIL (client2_stage == 0);
- TEST_HELLO_HANDLE_FAIL ((dbus_message_get_args (message,
- DBUS_TYPE_STRING, &client2_name,
- 0) == DBUS_RESULT_SUCCESS));
+ TEST_HELLO_HANDLE_FAIL (dbus_message_get_args (message, NULL,
+ DBUS_TYPE_STRING, &client2_name,
+ 0));
client2_stage += 1;
}
@@ -142,9 +152,9 @@ test_hello_client2_handler (DBusMessageHandler *handler,
{
TEST_HELLO_HANDLE_FAIL (client2_stage == 1);
- TEST_HELLO_HANDLE_FAIL ((dbus_message_get_args (message,
- DBUS_TYPE_STRING, &tmp,
- 0) == DBUS_RESULT_SUCCESS));
+ TEST_HELLO_HANDLE_FAIL (dbus_message_get_args (message, NULL,
+ DBUS_TYPE_STRING, &tmp,
+ 0));
TEST_HELLO_HANDLE_FAIL (strcmp (client2_name, tmp) == 0);
client2_stage += 1;
@@ -153,9 +163,9 @@ test_hello_client2_handler (DBusMessageHandler *handler,
{
TEST_HELLO_HANDLE_FAIL (client2_stage == 2);
- TEST_HELLO_HANDLE_FAIL ((dbus_message_get_args (message,
- DBUS_TYPE_STRING, &tmp,
- 0) == DBUS_RESULT_SUCCESS));
+ TEST_HELLO_HANDLE_FAIL (dbus_message_get_args (message, NULL,
+ DBUS_TYPE_STRING, &tmp,
+ 0));
TEST_HELLO_HANDLE_FAIL (strcmp (client2_name, tmp) == 0);
client2_stage += 1;
@@ -177,9 +187,9 @@ static dbus_bool_t
test_hello_replies (void)
{
DBusConnection *connection;
- DBusResultCode result;
DBusMessage *message;
DBusMessageHandler *handler;
+ DBusResultCode result;
/* First start client 1 */
connection = dbus_connection_open ("debug:name=test-server", &result);
@@ -188,7 +198,8 @@ test_hello_replies (void)
DBUS_MESSAGE_HELLO);
handler = dbus_message_handler_new (test_hello_client1_handler, NULL, NULL);
dbus_connection_add_filter (connection, handler);
- dbus_connection_send_message (connection, message, NULL, NULL);
+ if (!dbus_connection_send (connection, message, NULL))
+ die ("no memory to send message");
dbus_message_unref (message);
/* Then start client 2 */
@@ -198,7 +209,8 @@ test_hello_replies (void)
DBUS_MESSAGE_HELLO);
handler = dbus_message_handler_new (test_hello_client2_handler, NULL, NULL);
dbus_connection_add_filter (connection, handler);
- dbus_connection_send_message (connection, message, NULL, NULL);
+ if (!dbus_connection_send (connection, message, NULL))
+ die ("no memory to send message");
dbus_message_unref (message);
bus_test_loop_run ();
diff --git a/test/data/valid-messages/dict-simple.message b/test/data/valid-messages/dict-simple.message
index 0b9d0186..0de1a782 100644
--- a/test/data/valid-messages/dict-simple.message
+++ b/test/data/valid-messages/dict-simple.message
@@ -1,6 +1,9 @@
# A simple dict
VALID_HEADER
+FIELD_NAME name
+TYPE STRING
+STRING 'org.freedesktop.Foo'
END_LENGTH Header
ALIGN 8
START_LENGTH Body
diff --git a/test/data/valid-messages/dict.message b/test/data/valid-messages/dict.message
index 0532e682..ce99a282 100644
--- a/test/data/valid-messages/dict.message
+++ b/test/data/valid-messages/dict.message
@@ -1,8 +1,11 @@
# Dict with different values
VALID_HEADER
-END_LENGTH Header
+FIELD_NAME name
+TYPE STRING
+STRING 'org.freedesktop.Foo'
ALIGN 8
+END_LENGTH Header
START_LENGTH Body
TYPE DICT
STRING_ARRAY { 'boolean', 'int32', 'uint32', 'double', 'string', 'boolean_array', 'int32_array', 'uint32_array', 'double_array', 'string_array' }
diff --git a/test/data/valid-messages/lots-of-arguments.message b/test/data/valid-messages/lots-of-arguments.message
index 6a7d5eba..cc9c5a75 100644
--- a/test/data/valid-messages/lots-of-arguments.message
+++ b/test/data/valid-messages/lots-of-arguments.message
@@ -1,6 +1,9 @@
# Message with lots of different argument types
VALID_HEADER
+FIELD_NAME name
+TYPE STRING
+STRING 'org.freedesktop.Foo'
END_LENGTH Header
ALIGN 8
START_LENGTH Body
diff --git a/test/data/valid-messages/no-padding.message b/test/data/valid-messages/no-padding.message
index c21c84d3..ab5b5a80 100644
--- a/test/data/valid-messages/no-padding.message
+++ b/test/data/valid-messages/no-padding.message
@@ -3,6 +3,10 @@
## VALID_HEADER includes a LENGTH Header and LENGTH Body
VALID_HEADER
+FIELD_NAME name
+TYPE STRING
+STRING 'org.freedesktop.Foo'
+
## this byte array is filled with zeros to the natural length
## of the header
FIELD_NAME unkn
diff --git a/test/data/valid-messages/simplest-manual.message b/test/data/valid-messages/simplest-manual.message
index 3f002ed1..8eed1e5f 100644
--- a/test/data/valid-messages/simplest-manual.message
+++ b/test/data/valid-messages/simplest-manual.message
@@ -10,6 +10,9 @@ LENGTH Header
LENGTH Body
## client serial
INT32 7
+FIELD_NAME name
+TYPE STRING
+STRING 'org.freedesktop.Foo'
ALIGN 8
END_LENGTH Header
START_LENGTH Body
diff --git a/test/data/valid-messages/simplest.message b/test/data/valid-messages/simplest.message
index a0283aa2..7bb1872d 100644
--- a/test/data/valid-messages/simplest.message
+++ b/test/data/valid-messages/simplest.message
@@ -2,6 +2,9 @@
## VALID_HEADER includes a LENGTH Header and LENGTH Body
VALID_HEADER
+FIELD_NAME name
+TYPE STRING
+STRING 'org.freedesktop.Foo'
ALIGN 8
END_LENGTH Header
START_LENGTH Body
diff --git a/test/echo-client.c b/test/echo-client.c
index 47d7314d..de32957f 100644
--- a/test/echo-client.c
+++ b/test/echo-client.c
@@ -28,10 +28,10 @@ main (int argc,
/* Send a message to get things going */
message = dbus_message_new ("org.freedesktop.DBus.Test", "org.freedesktop.DBus.Test");
- dbus_connection_send_message (connection,
- message,
- NULL,
- NULL);
+ if (!dbus_connection_send (connection,
+ message,
+ NULL))
+ fprintf (stderr, "No memory to send reply\n");
dbus_message_unref (message);
do_mainloop ();
diff --git a/test/unbase64.c b/test/unbase64.c
index cc123658..f3894bd8 100644
--- a/test/unbase64.c
+++ b/test/unbase64.c
@@ -14,6 +14,7 @@ main (int argc,
DBusString decoded;
DBusString filename;
const char *s;
+ DBusError error;
if (argc < 2)
{
@@ -29,8 +30,13 @@ main (int argc,
if (!_dbus_string_init (&decoded, _DBUS_INT_MAX))
return 1;
- if (_dbus_file_get_contents (&contents, &filename) != DBUS_RESULT_SUCCESS)
- return 1;
+ dbus_error_init (&error);
+ if (!_dbus_file_get_contents (&contents, &filename, &error))
+ {
+ fprintf (stderr, "Failed to load file: %s\n", error.message);
+ dbus_error_free (&error);
+ return 1;
+ }
if (!_dbus_string_base64_decode (&contents, 0,
&decoded, 0))
diff --git a/test/watch.c b/test/watch.c
index 1a31e64b..d8e91b78 100644
--- a/test/watch.c
+++ b/test/watch.c
@@ -168,10 +168,10 @@ check_messages (void)
fprintf (stderr, "Received message %d, sending reply\n", count);
reply = dbus_message_new ("org.freedesktop.DBus.Test", "org.freedesktop.DBus.Test");
- dbus_connection_send_message (connection,
- reply,
- NULL,
- NULL);
+ if (!dbus_connection_send (connection,
+ reply,
+ NULL))
+ fprintf (stderr, "No memory to send reply\n");
dbus_message_unref (reply);
dbus_message_unref (message);