1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* services.c Service management
4 * Copyright (C) 2003 Red Hat, Inc.
5 * Copyright (C) 2003 CodeFactory AB
7 * Licensed under the Academic Free License version 2.1
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include <dbus/dbus-hash.h>
27 #include <dbus/dbus-list.h>
28 #include <dbus/dbus-mempool.h>
29 #include <dbus/dbus-marshal-validate.h>
33 #include "connection.h"
35 #include "activation.h"
45 BusRegistry *registry;
57 unsigned int allow_replacement : 1;
58 unsigned int do_not_queue : 1;
67 DBusHashTable *service_hash;
68 DBusMemPool *service_pool;
69 DBusMemPool *owner_pool;
71 DBusHashTable *service_sid_table;
75 bus_registry_new (BusContext *context)
77 BusRegistry *registry;
79 _dbus_assert (context);
80 registry = dbus_new0 (BusRegistry, 1);
84 registry->refcount = 1;
85 registry->context = context;
87 registry->service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
89 if (registry->service_hash == NULL)
92 registry->service_pool = _dbus_mem_pool_new (sizeof (BusService),
95 if (registry->service_pool == NULL)
98 registry->owner_pool = _dbus_mem_pool_new (sizeof (BusOwner),
101 if (registry->owner_pool == NULL)
104 registry->service_sid_table = NULL;
109 bus_registry_unref (registry);
114 bus_registry_ref (BusRegistry *registry)
116 _dbus_assert (registry->refcount > 0);
117 registry->refcount += 1;
123 bus_registry_unref (BusRegistry *registry)
125 _dbus_assert (registry->refcount > 0);
126 registry->refcount -= 1;
128 if (registry->refcount == 0)
130 if (registry->service_hash)
131 _dbus_hash_table_unref (registry->service_hash);
132 if (registry->service_pool)
133 _dbus_mem_pool_free (registry->service_pool);
134 if (registry->owner_pool)
135 _dbus_mem_pool_free (registry->owner_pool);
136 if (registry->service_sid_table)
137 _dbus_hash_table_unref (registry->service_sid_table);
139 dbus_free (registry);
144 bus_registry_lookup (BusRegistry *registry,
145 const DBusString *service_name)
149 service = _dbus_hash_table_lookup_string (registry->service_hash,
150 _dbus_string_get_const_data (service_name));
156 _bus_service_find_owner_link (BusService *service,
157 DBusConnection *connection)
161 link = _dbus_list_get_first_link (&service->owners);
167 bus_owner = (BusOwner *) link->data;
168 if (bus_owner->conn == connection)
171 link = _dbus_list_get_next_link (&service->owners, link);
178 bus_owner_set_flags (BusOwner *owner,
181 owner->allow_replacement =
182 (flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT) != FALSE;
184 owner->do_not_queue =
185 (flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) != FALSE;
189 bus_owner_new (BusService *service,
190 DBusConnection *conn,
195 result = _dbus_mem_pool_alloc (service->registry->owner_pool);
198 result->refcount = 1;
199 /* don't ref the connection because we don't want
200 to block the connection from going away.
201 transactions take care of reffing the connection
202 but we need to use refcounting on the owner
203 so that the owner does not get freed before
204 we can deref the connection in the transaction
207 result->service = service;
209 if (!bus_connection_add_owned_service (conn, service))
211 _dbus_mem_pool_dealloc (service->registry->owner_pool, result);
215 bus_owner_set_flags (result, flags);
221 bus_owner_ref (BusOwner *owner)
223 _dbus_assert (owner->refcount > 0);
224 owner->refcount += 1;
230 bus_owner_unref (BusOwner *owner)
232 _dbus_assert (owner->refcount > 0);
233 owner->refcount -= 1;
235 if (owner->refcount == 0)
237 bus_connection_remove_owned_service (owner->conn, owner->service);
238 _dbus_mem_pool_dealloc (owner->service->registry->owner_pool, owner);
243 bus_registry_ensure (BusRegistry *registry,
244 const DBusString *service_name,
245 DBusConnection *owner_connection_if_created,
247 BusTransaction *transaction,
252 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
254 _dbus_assert (owner_connection_if_created != NULL);
255 _dbus_assert (transaction != NULL);
257 service = _dbus_hash_table_lookup_string (registry->service_hash,
258 _dbus_string_get_const_data (service_name));
262 service = _dbus_mem_pool_alloc (registry->service_pool);
269 service->registry = registry;
270 service->refcount = 1;
272 _dbus_verbose ("copying string %p '%s' to service->name\n",
273 service_name, _dbus_string_get_const_data (service_name));
274 if (!_dbus_string_copy_data (service_name, &service->name))
276 _dbus_mem_pool_dealloc (registry->service_pool, service);
280 _dbus_verbose ("copied string %p '%s' to '%s'\n",
281 service_name, _dbus_string_get_const_data (service_name),
284 if (!bus_driver_send_service_owner_changed (service->name,
286 bus_connection_get_name (owner_connection_if_created),
289 bus_service_unref (service);
293 if (!bus_activation_service_created (bus_context_get_activation (registry->context),
294 service->name, transaction, error))
296 bus_service_unref (service);
300 if (!bus_service_add_owner (service, owner_connection_if_created, flags,
303 bus_service_unref (service);
307 if (!_dbus_hash_table_insert_string (registry->service_hash,
311 /* The add_owner gets reverted on transaction cancel */
320 bus_registry_foreach (BusRegistry *registry,
321 BusServiceForeachFunction function,
326 _dbus_hash_iter_init (registry->service_hash, &iter);
327 while (_dbus_hash_iter_next (&iter))
329 BusService *service = _dbus_hash_iter_get_value (&iter);
331 (* function) (service, data);
336 bus_registry_list_services (BusRegistry *registry,
344 len = _dbus_hash_table_get_n_entries (registry->service_hash);
345 retval = dbus_new (char *, len + 1);
350 _dbus_hash_iter_init (registry->service_hash, &iter);
352 while (_dbus_hash_iter_next (&iter))
354 BusService *service = _dbus_hash_iter_get_value (&iter);
356 retval[i] = _dbus_strdup (service->name);
357 if (retval[i] == NULL)
372 for (j = 0; j < i; j++)
373 dbus_free (retval[j]);
380 bus_registry_acquire_service (BusRegistry *registry,
381 DBusConnection *connection,
382 DBusMessage *message,
383 const DBusString *service_name,
385 dbus_uint32_t *result,
386 BusTransaction *transaction,
390 DBusConnection *old_owner_conn;
391 BusClientPolicy *policy;
393 BusActivation *activation;
395 BusOwner *primary_owner;
398 retval = BUS_RESULT_FALSE;
400 if (!_dbus_validate_bus_name (service_name, 0,
401 _dbus_string_get_length (service_name)))
403 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
404 "Requested bus name \"%s\" is not valid",
405 _dbus_string_get_const_data (service_name));
407 _dbus_verbose ("Attempt to acquire invalid service name\n");
412 if (_dbus_string_get_byte (service_name, 0) == ':')
414 /* Not allowed; only base services can start with ':' */
415 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
416 "Cannot acquire a service starting with ':' such as \"%s\"",
417 _dbus_string_get_const_data (service_name));
419 _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
420 _dbus_string_get_const_data (service_name));
425 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
427 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
428 "Connection \"%s\" (%s) is not allowed to own the service \"%s\"because "
429 "it is reserved for D-Bus' use only",
430 bus_connection_is_active (connection) ?
431 bus_connection_get_name (connection) :
433 bus_connection_get_loginfo (connection),
438 policy = bus_connection_get_policy (connection);
439 _dbus_assert (policy != NULL);
441 /* Note that if sid is #NULL then the bus's own context gets used
442 * in bus_connection_selinux_allows_acquire_service()
444 sid = bus_selinux_id_table_lookup (registry->service_sid_table,
447 if (!bus_selinux_allows_acquire_service (connection, sid,
448 _dbus_string_get_const_data (service_name), error))
451 if (dbus_error_is_set (error) &&
452 dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
457 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
458 "Connection \"%s\" (%s) is not allowed to own the service \"%s\" due "
460 bus_connection_is_active (connection) ?
461 bus_connection_get_name (connection) :
463 bus_connection_get_loginfo (connection),
464 _dbus_string_get_const_data (service_name));
468 if (!bus_apparmor_allows_acquire_service (connection,
469 bus_context_get_type (registry->context),
470 _dbus_string_get_const_data (service_name), error))
473 switch (bus_client_policy_check_can_own (policy, service_name, connection, message))
475 case BUS_RESULT_TRUE:
477 case BUS_RESULT_FALSE:
478 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
479 "Connection \"%s\" (%s) is not allowed to own the service \"%s\" due "
480 "to security policies in the configuration file",
481 bus_connection_is_active (connection) ?
482 bus_connection_get_name (connection) :
484 bus_connection_get_loginfo (connection),
485 _dbus_string_get_const_data (service_name));
487 /* If we hit OOM while setting the error, this will syslog "out of memory"
488 * which is itself an indication that something is seriously wrong */
489 bus_context_log_literal (registry->context, DBUS_SYSTEM_LOG_SECURITY,
492 case BUS_RESULT_LATER:
493 retval = BUS_RESULT_LATER;
497 limit = bus_context_get_max_services_per_connection (registry->context);
499 if (bus_connection_get_n_services_owned (connection) >= limit)
503 dbus_error_init (&tmp_error);
504 dbus_set_error (&tmp_error, DBUS_ERROR_LIMITS_EXCEEDED,
505 "Connection \"%s\" (%s) is not allowed to own more services "
506 "(increase limits in configuration file if required)"
507 "max_names_per_connection=%d)",
508 bus_connection_is_active (connection) ?
509 bus_connection_get_name (connection) :
511 bus_connection_get_loginfo (connection),
513 bus_context_log (registry->context, DBUS_SYSTEM_LOG_WARNING,
514 "%s", tmp_error.message);
515 dbus_move_error (&tmp_error, error);
519 service = bus_registry_lookup (registry, service_name);
523 primary_owner = bus_service_get_primary_owner (service);
524 if (primary_owner != NULL)
525 old_owner_conn = primary_owner->conn;
527 old_owner_conn = NULL;
530 old_owner_conn = NULL;
534 service = bus_registry_ensure (registry,
535 service_name, connection, flags,
541 primary_owner = bus_service_get_primary_owner (service);
542 if (primary_owner == NULL)
545 if (old_owner_conn == NULL)
547 _dbus_assert (primary_owner->conn == connection);
549 *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
551 else if (old_owner_conn == connection)
553 bus_owner_set_flags (primary_owner, flags);
554 *result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
556 else if (((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
557 !(bus_service_get_allow_replacement (service))) ||
558 ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
559 !(flags & DBUS_NAME_FLAG_REPLACE_EXISTING)))
562 BusOwner *temp_owner;
563 /* Since we can't be queued if we are already in the queue
566 link = _bus_service_find_owner_link (service, connection);
569 _dbus_list_unlink (&service->owners, link);
570 temp_owner = (BusOwner *)link->data;
571 bus_owner_unref (temp_owner);
572 _dbus_list_free_link (link);
575 *result = DBUS_REQUEST_NAME_REPLY_EXISTS;
577 else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
578 (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
579 !(bus_service_get_allow_replacement (service))))
581 /* Queue the connection */
582 if (!bus_service_add_owner (service, connection,
587 *result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
591 /* Replace the current owner */
593 /* We enqueue the new owner and remove the first one because
594 * that will cause NameAcquired and NameLost messages to
598 if (!bus_service_add_owner (service, connection,
603 if (primary_owner->do_not_queue)
605 if (!bus_service_remove_owner (service, old_owner_conn,
611 if (!bus_service_swap_owner (service, old_owner_conn,
617 _dbus_assert (connection == bus_service_get_primary_owner (service)->conn);
618 *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
621 activation = bus_context_get_activation (registry->context);
622 if (bus_activation_send_pending_auto_activation_messages (activation,
625 retval = BUS_RESULT_TRUE;
634 bus_registry_release_service (BusRegistry *registry,
635 DBusConnection *connection,
636 const DBusString *service_name,
637 dbus_uint32_t *result,
638 BusTransaction *transaction,
646 if (!_dbus_validate_bus_name (service_name, 0,
647 _dbus_string_get_length (service_name)))
649 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
650 "Given bus name \"%s\" is not valid",
651 _dbus_string_get_const_data (service_name));
653 _dbus_verbose ("Attempt to release invalid service name\n");
658 if (_dbus_string_get_byte (service_name, 0) == ':')
660 /* Not allowed; the base service name cannot be created or released */
661 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
662 "Cannot release a service starting with ':' such as \"%s\"",
663 _dbus_string_get_const_data (service_name));
665 _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
666 _dbus_string_get_const_data (service_name));
671 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
673 /* Not allowed; the base service name cannot be created or released */
674 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
675 "Cannot release the %s service because it is owned by the bus",
678 _dbus_verbose ("Attempt to release service name \"%s\"",
684 service = bus_registry_lookup (registry, service_name);
688 *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
690 else if (!bus_service_has_owner (service, connection))
692 *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
696 if (!bus_service_remove_owner (service, connection,
700 _dbus_assert (!bus_service_has_owner (service, connection));
701 *result = DBUS_RELEASE_NAME_REPLY_RELEASED;
711 bus_registry_set_service_context_table (BusRegistry *registry,
712 DBusHashTable *table)
714 DBusHashTable *new_table;
717 new_table = bus_selinux_id_table_new ();
721 _dbus_hash_iter_init (table, &iter);
722 while (_dbus_hash_iter_next (&iter))
724 const char *service = _dbus_hash_iter_get_string_key (&iter);
725 const char *context = _dbus_hash_iter_get_value (&iter);
727 if (!bus_selinux_id_table_insert (new_table,
733 if (registry->service_sid_table)
734 _dbus_hash_table_unref (registry->service_sid_table);
735 registry->service_sid_table = new_table;
740 bus_service_unlink_owner (BusService *service,
743 _dbus_list_remove_last (&service->owners, owner);
744 bus_owner_unref (owner);
748 bus_service_unlink (BusService *service)
750 _dbus_assert (service->owners == NULL);
752 /* the service may not be in the hash, if
753 * the failure causing transaction cancel
754 * was in the right place, but that's OK
756 _dbus_hash_table_remove_string (service->registry->service_hash,
759 bus_service_unref (service);
763 bus_service_relink (BusService *service,
764 DBusPreallocatedHash *preallocated)
766 _dbus_assert (service->owners == NULL);
767 _dbus_assert (preallocated != NULL);
769 _dbus_hash_table_insert_string_preallocated (service->registry->service_hash,
774 bus_service_ref (service);
778 * Data used to represent an ownership cancellation in
783 BusOwner *owner; /**< the owner */
784 BusService *service; /**< service to cancel ownership of */
785 } OwnershipCancelData;
788 cancel_ownership (void *data)
790 OwnershipCancelData *d = data;
792 /* We don't need to send messages notifying of these
793 * changes, since we're reverting something that was
794 * cancelled (effectively never really happened)
796 bus_service_unlink_owner (d->service, d->owner);
798 if (d->service->owners == NULL)
799 bus_service_unlink (d->service);
803 free_ownership_cancel_data (void *data)
805 OwnershipCancelData *d = data;
807 dbus_connection_unref (d->owner->conn);
808 bus_owner_unref (d->owner);
809 bus_service_unref (d->service);
815 add_cancel_ownership_to_transaction (BusTransaction *transaction,
819 OwnershipCancelData *d;
821 d = dbus_new (OwnershipCancelData, 1);
825 d->service = service;
828 if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
829 free_ownership_cancel_data))
835 bus_service_ref (d->service);
836 bus_owner_ref (owner);
837 dbus_connection_ref (d->owner->conn);
842 /* this function is self-cancelling if you cancel the transaction */
844 bus_service_add_owner (BusService *service,
845 DBusConnection *connection,
847 BusTransaction *transaction,
851 DBusList *bus_owner_link;
853 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
855 /* Send service acquired message first, OOM will result
856 * in cancelling the transaction
858 if (service->owners == NULL)
860 if (!bus_driver_send_service_acquired (connection, service->name, transaction, error))
864 bus_owner_link = _bus_service_find_owner_link (service, connection);
866 if (bus_owner_link == NULL)
868 bus_owner = bus_owner_new (service, connection, flags);
869 if (bus_owner == NULL)
875 bus_owner_set_flags (bus_owner, flags);
876 if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL)
878 if (!_dbus_list_append (&service->owners,
881 bus_owner_unref (bus_owner);
888 if (!_dbus_list_insert_after (&service->owners,
889 _dbus_list_get_first_link (&service->owners),
892 bus_owner_unref (bus_owner);
900 /* Update the link since we are already in the queue
901 * No need for operations that can produce OOM
904 bus_owner = (BusOwner *) bus_owner_link->data;
905 if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
908 _dbus_list_unlink (&service->owners, bus_owner_link);
909 link = _dbus_list_get_first_link (&service->owners);
910 _dbus_assert (link != NULL);
912 _dbus_list_insert_after_link (&service->owners, link, bus_owner_link);
915 bus_owner_set_flags (bus_owner, flags);
919 if (!add_cancel_ownership_to_transaction (transaction,
923 bus_service_unlink_owner (service, bus_owner);
935 BusOwner *before_owner; /* restore to position before this connection in owners list */
936 DBusList *owner_link;
937 DBusList *service_link;
938 DBusPreallocatedHash *hash_entry;
939 } OwnershipRestoreData;
942 restore_ownership (void *data)
944 OwnershipRestoreData *d = data;
947 _dbus_assert (d->service_link != NULL);
948 _dbus_assert (d->owner_link != NULL);
950 if (d->service->owners == NULL)
952 _dbus_assert (d->hash_entry != NULL);
953 bus_service_relink (d->service, d->hash_entry);
957 _dbus_assert (d->hash_entry == NULL);
960 /* We don't need to send messages notifying of these
961 * changes, since we're reverting something that was
962 * cancelled (effectively never really happened)
964 link = _dbus_list_get_first_link (&d->service->owners);
967 if (link->data == d->before_owner)
970 link = _dbus_list_get_next_link (&d->service->owners, link);
973 _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link);
975 /* Note that removing then restoring this changes the order in which
976 * ServiceDeleted messages are sent on destruction of the
977 * connection. This should be OK as the only guarantee there is
978 * that the base service is destroyed last, and we never even
979 * tentatively remove the base service.
981 bus_connection_add_owned_service_link (d->owner->conn, d->service_link);
983 d->hash_entry = NULL;
984 d->service_link = NULL;
985 d->owner_link = NULL;
989 free_ownership_restore_data (void *data)
991 OwnershipRestoreData *d = data;
994 _dbus_list_free_link (d->service_link);
996 _dbus_list_free_link (d->owner_link);
998 _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
1001 dbus_connection_unref (d->owner->conn);
1002 bus_owner_unref (d->owner);
1003 bus_service_unref (d->service);
1009 add_restore_ownership_to_transaction (BusTransaction *transaction,
1010 BusService *service,
1013 OwnershipRestoreData *d;
1016 d = dbus_new (OwnershipRestoreData, 1);
1020 d->service = service;
1022 d->service_link = _dbus_list_alloc_link (service);
1023 d->owner_link = _dbus_list_alloc_link (owner);
1024 d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
1026 bus_service_ref (d->service);
1027 bus_owner_ref (d->owner);
1028 dbus_connection_ref (d->owner->conn);
1030 d->before_owner = NULL;
1031 link = _dbus_list_get_first_link (&service->owners);
1032 while (link != NULL)
1034 if (link->data == owner)
1036 link = _dbus_list_get_next_link (&service->owners, link);
1039 d->before_owner = link->data;
1044 link = _dbus_list_get_next_link (&service->owners, link);
1047 if (d->service_link == NULL ||
1048 d->owner_link == NULL ||
1049 d->hash_entry == NULL ||
1050 !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
1051 free_ownership_restore_data))
1053 free_ownership_restore_data (d);
1061 bus_service_swap_owner (BusService *service,
1062 DBusConnection *connection,
1063 BusTransaction *transaction,
1066 DBusList *swap_link;
1067 BusOwner *primary_owner;
1069 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1071 /* We send out notifications before we do any work we
1072 * might have to undo if the notification-sending failed
1075 /* Send service lost message */
1076 primary_owner = bus_service_get_primary_owner (service);
1077 if (primary_owner == NULL || primary_owner->conn != connection)
1078 _dbus_assert_not_reached ("Tried to swap a non primary owner");
1081 if (!bus_driver_send_service_lost (connection, service->name,
1082 transaction, error))
1085 if (service->owners == NULL)
1087 _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners");
1089 else if (_dbus_list_length_is_one (&service->owners))
1091 _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue");
1096 BusOwner *new_owner;
1097 DBusConnection *new_owner_conn;
1098 link = _dbus_list_get_first_link (&service->owners);
1099 _dbus_assert (link != NULL);
1100 link = _dbus_list_get_next_link (&service->owners, link);
1101 _dbus_assert (link != NULL);
1103 new_owner = (BusOwner *)link->data;
1104 new_owner_conn = new_owner->conn;
1106 if (!bus_driver_send_service_owner_changed (service->name,
1107 bus_connection_get_name (connection),
1108 bus_connection_get_name (new_owner_conn),
1109 transaction, error))
1112 /* This will be our new owner */
1113 if (!bus_driver_send_service_acquired (new_owner_conn,
1120 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1122 BUS_SET_OOM (error);
1126 /* unlink the primary and make it the second link */
1127 swap_link = _dbus_list_get_first_link (&service->owners);
1128 _dbus_list_unlink (&service->owners, swap_link);
1130 _dbus_list_insert_after_link (&service->owners,
1131 _dbus_list_get_first_link (&service->owners),
1137 /* this function is self-cancelling if you cancel the transaction */
1139 bus_service_remove_owner (BusService *service,
1140 DBusConnection *connection,
1141 BusTransaction *transaction,
1144 BusOwner *primary_owner;
1146 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1148 /* We send out notifications before we do any work we
1149 * might have to undo if the notification-sending failed
1152 /* Send service lost message */
1153 primary_owner = bus_service_get_primary_owner (service);
1154 if (primary_owner != NULL && primary_owner->conn == connection)
1156 if (!bus_driver_send_service_lost (connection, service->name,
1157 transaction, error))
1162 /* if we are not the primary owner then just remove us from the queue */
1164 BusOwner *temp_owner;
1166 link = _bus_service_find_owner_link (service, connection);
1167 _dbus_list_unlink (&service->owners, link);
1168 temp_owner = (BusOwner *)link->data;
1169 bus_owner_unref (temp_owner);
1170 _dbus_list_free_link (link);
1175 if (service->owners == NULL)
1177 _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
1179 else if (_dbus_list_length_is_one (&service->owners))
1181 if (!bus_driver_send_service_owner_changed (service->name,
1182 bus_connection_get_name (connection),
1184 transaction, error))
1190 BusOwner *new_owner;
1191 DBusConnection *new_owner_conn;
1192 link = _dbus_list_get_first_link (&service->owners);
1193 _dbus_assert (link != NULL);
1194 link = _dbus_list_get_next_link (&service->owners, link);
1195 _dbus_assert (link != NULL);
1197 new_owner = (BusOwner *)link->data;
1198 new_owner_conn = new_owner->conn;
1200 if (!bus_driver_send_service_owner_changed (service->name,
1201 bus_connection_get_name (connection),
1202 bus_connection_get_name (new_owner_conn),
1203 transaction, error))
1206 /* This will be our new owner */
1207 if (!bus_driver_send_service_acquired (new_owner_conn,
1214 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1216 BUS_SET_OOM (error);
1220 bus_service_unlink_owner (service, primary_owner);
1222 if (service->owners == NULL)
1223 bus_service_unlink (service);
1229 bus_service_ref (BusService *service)
1231 _dbus_assert (service->refcount > 0);
1233 service->refcount += 1;
1239 bus_service_unref (BusService *service)
1241 _dbus_assert (service->refcount > 0);
1243 service->refcount -= 1;
1245 if (service->refcount == 0)
1247 _dbus_assert (service->owners == NULL);
1249 dbus_free (service->name);
1250 _dbus_mem_pool_dealloc (service->registry->service_pool, service);
1255 bus_service_get_primary_owners_connection (BusService *service)
1259 owner = bus_service_get_primary_owner (service);
1268 bus_service_get_primary_owner (BusService *service)
1270 return _dbus_list_get_first (&service->owners);
1274 bus_service_get_name (BusService *service)
1276 return service->name;
1280 bus_service_get_allow_replacement (BusService *service)
1285 _dbus_assert (service->owners != NULL);
1287 link = _dbus_list_get_first_link (&service->owners);
1288 owner = (BusOwner *) link->data;
1290 return owner->allow_replacement;
1294 bus_service_has_owner (BusService *service,
1295 DBusConnection *connection)
1299 link = _bus_service_find_owner_link (service, connection);
1308 bus_service_list_queued_owners (BusService *service,
1309 DBusList **return_list,
1314 _dbus_assert (*return_list == NULL);
1316 link = _dbus_list_get_first_link (&service->owners);
1317 _dbus_assert (link != NULL);
1319 while (link != NULL)
1324 owner = (BusOwner *) link->data;
1325 uname = bus_connection_get_name (owner->conn);
1327 if (!_dbus_list_append (return_list, (char *)uname))
1330 link = _dbus_list_get_next_link (&service->owners, link);
1336 _dbus_list_clear (return_list);
1337 BUS_SET_OOM (error);