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
6 * Copyright (C) 2013 Samsung Electronics
8 * Licensed under the Academic Free License version 2.1
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include <dbus/dbus-hash.h>
28 #include <dbus/dbus-list.h>
29 #include <dbus/dbus-mempool.h>
30 #include <dbus/dbus-marshal-validate.h>
33 #include "connection.h"
35 #include "activation.h"
40 #ifdef ENABLE_KDBUS_TRANSPORT
41 #include <linux/types.h>
48 #include "dbus/kdbus.h"
49 #include "dbus/kdbus-common.h"
56 BusRegistry *registry;
68 unsigned int allow_replacement : 1;
69 unsigned int do_not_queue : 1;
70 #ifdef ENABLE_KDBUS_TRANSPORT
71 unsigned int is_kdbus_starter : 1;
81 DBusHashTable *service_hash;
82 DBusMemPool *service_pool;
83 DBusMemPool *owner_pool;
85 DBusHashTable *service_sid_table;
89 bus_registry_new (BusContext *context)
91 BusRegistry *registry;
93 registry = dbus_new0 (BusRegistry, 1);
97 registry->refcount = 1;
98 registry->context = context;
100 registry->service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
102 if (registry->service_hash == NULL)
105 registry->service_pool = _dbus_mem_pool_new (sizeof (BusService),
108 if (registry->service_pool == NULL)
111 registry->owner_pool = _dbus_mem_pool_new (sizeof (BusOwner),
114 if (registry->owner_pool == NULL)
117 registry->service_sid_table = NULL;
122 bus_registry_unref (registry);
127 bus_registry_ref (BusRegistry *registry)
129 _dbus_assert (registry->refcount > 0);
130 registry->refcount += 1;
136 bus_registry_unref (BusRegistry *registry)
138 _dbus_assert (registry->refcount > 0);
139 registry->refcount -= 1;
141 if (registry->refcount == 0)
143 if (registry->service_hash)
144 _dbus_hash_table_unref (registry->service_hash);
145 if (registry->service_pool)
146 _dbus_mem_pool_free (registry->service_pool);
147 if (registry->owner_pool)
148 _dbus_mem_pool_free (registry->owner_pool);
149 if (registry->service_sid_table)
150 _dbus_hash_table_unref (registry->service_sid_table);
152 dbus_free (registry);
157 bus_registry_lookup (BusRegistry *registry,
158 const DBusString *service_name)
162 service = _dbus_hash_table_lookup_string (registry->service_hash,
163 _dbus_string_get_const_data (service_name));
169 _bus_service_find_owner_link (BusService *service,
170 DBusConnection *connection)
174 link = _dbus_list_get_first_link (&service->owners);
180 bus_owner = (BusOwner *) link->data;
181 if (bus_owner->conn == connection)
184 link = _dbus_list_get_next_link (&service->owners, link);
190 #ifdef ENABLE_KDBUS_TRANSPORT
191 static DBusConnection *
192 _bus_service_find_owner_connection (BusService *service,
193 const char* unique_name)
197 link = _dbus_list_get_first_link (&service->owners);
203 bus_owner = (BusOwner *) link->data;
204 if(!strcmp(bus_connection_get_name(bus_owner->conn), unique_name))
205 return bus_owner->conn;
207 link = _dbus_list_get_next_link (&service->owners, link);
215 bus_owner_set_flags (BusOwner *owner,
218 owner->allow_replacement =
219 (flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT) != FALSE;
221 owner->do_not_queue =
222 (flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) != FALSE;
224 #ifdef ENABLE_KDBUS_TRANSPORT
225 owner->is_kdbus_starter =
226 (flags & KDBUS_NAME_STARTER) != FALSE;
231 bus_owner_new (BusService *service,
232 DBusConnection *conn,
237 result = _dbus_mem_pool_alloc (service->registry->owner_pool);
240 result->refcount = 1;
241 /* don't ref the connection because we don't want
242 to block the connection from going away.
243 transactions take care of reffing the connection
244 but we need to use refcounting on the owner
245 so that the owner does not get freed before
246 we can deref the connection in the transaction
249 result->service = service;
251 if (!bus_connection_add_owned_service (conn, service))
253 _dbus_mem_pool_dealloc (service->registry->owner_pool, result);
257 bus_owner_set_flags (result, flags);
263 bus_owner_ref (BusOwner *owner)
265 _dbus_assert (owner->refcount > 0);
266 owner->refcount += 1;
272 bus_owner_unref (BusOwner *owner)
274 _dbus_assert (owner->refcount > 0);
275 owner->refcount -= 1;
277 if (owner->refcount == 0)
279 bus_connection_remove_owned_service (owner->conn, owner->service);
280 _dbus_mem_pool_dealloc (owner->service->registry->owner_pool, owner);
285 bus_registry_ensure (BusRegistry *registry,
286 const DBusString *service_name,
287 DBusConnection *owner_connection_if_created,
289 BusTransaction *transaction,
294 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
296 _dbus_assert (owner_connection_if_created != NULL);
297 _dbus_assert (transaction != NULL);
299 service = _dbus_hash_table_lookup_string (registry->service_hash,
300 _dbus_string_get_const_data (service_name));
304 service = _dbus_mem_pool_alloc (registry->service_pool);
311 service->registry = registry;
312 service->refcount = 1;
314 _dbus_verbose ("copying string %p '%s' to service->name\n",
315 service_name, _dbus_string_get_const_data (service_name));
316 if (!_dbus_string_copy_data (service_name, &service->name))
318 _dbus_mem_pool_dealloc (registry->service_pool, service);
322 _dbus_verbose ("copied string %p '%s' to '%s'\n",
323 service_name, _dbus_string_get_const_data (service_name),
326 if (!bus_driver_send_service_owner_changed (service->name,
328 bus_connection_get_name (owner_connection_if_created),
331 bus_service_unref (service);
335 if (!bus_activation_service_created (bus_context_get_activation (registry->context),
336 service->name, transaction, error))
338 bus_service_unref (service);
342 if (!bus_service_add_owner (service, owner_connection_if_created, flags,
345 bus_service_unref (service);
349 if (!_dbus_hash_table_insert_string (registry->service_hash,
353 /* The add_owner gets reverted on transaction cancel */
362 bus_registry_foreach (BusRegistry *registry,
363 BusServiceForeachFunction function,
368 _dbus_hash_iter_init (registry->service_hash, &iter);
369 while (_dbus_hash_iter_next (&iter))
371 BusService *service = _dbus_hash_iter_get_value (&iter);
373 (* function) (service, data);
378 bus_registry_list_services (BusRegistry *registry,
386 len = _dbus_hash_table_get_n_entries (registry->service_hash);
387 retval = dbus_new (char *, len + 1);
392 _dbus_hash_iter_init (registry->service_hash, &iter);
394 while (_dbus_hash_iter_next (&iter))
396 BusService *service = _dbus_hash_iter_get_value (&iter);
398 retval[i] = _dbus_strdup (service->name);
399 if (retval[i] == NULL)
414 for (j = 0; j < i; j++)
415 dbus_free (retval[j]);
422 bus_registry_acquire_service (BusRegistry *registry,
423 DBusConnection *connection,
424 const DBusString *service_name,
426 dbus_uint32_t *result,
427 BusTransaction *transaction,
431 DBusConnection *old_owner_conn;
432 BusClientPolicy *policy;
434 BusActivation *activation;
436 BusOwner *primary_owner;
440 if (!_dbus_validate_bus_name (service_name, 0,
441 _dbus_string_get_length (service_name)))
443 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
444 "Requested bus name \"%s\" is not valid",
445 _dbus_string_get_const_data (service_name));
447 _dbus_verbose ("Attempt to acquire invalid service name\n");
452 if (_dbus_string_get_byte (service_name, 0) == ':')
454 /* Not allowed; only base services can start with ':' */
455 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
456 "Cannot acquire a service starting with ':' such as \"%s\"",
457 _dbus_string_get_const_data (service_name));
459 _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
460 _dbus_string_get_const_data (service_name));
465 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
467 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
468 "Connection \"%s\" is not allowed to own the service \"%s\"because "
469 "it is reserved for D-Bus' use only",
470 bus_connection_is_active (connection) ?
471 bus_connection_get_name (connection) :
477 policy = bus_connection_get_policy (connection);
478 _dbus_assert (policy != NULL);
480 /* Note that if sid is #NULL then the bus's own context gets used
481 * in bus_connection_selinux_allows_acquire_service()
483 sid = bus_selinux_id_table_lookup (registry->service_sid_table,
486 if (!bus_selinux_allows_acquire_service (connection, sid,
487 _dbus_string_get_const_data (service_name), error))
490 if (dbus_error_is_set (error) &&
491 dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
496 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
497 "Connection \"%s\" is not allowed to own the service \"%s\" due "
499 bus_connection_is_active (connection) ?
500 bus_connection_get_name (connection) :
502 _dbus_string_get_const_data (service_name));
506 if (!bus_client_policy_check_can_own (policy, service_name))
508 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
509 "Connection \"%s\" is not allowed to own the service \"%s\" due "
510 "to security policies in the configuration file",
511 bus_connection_is_active (connection) ?
512 bus_connection_get_name (connection) :
514 _dbus_string_get_const_data (service_name));
518 if (bus_connection_get_n_services_owned (connection) >=
519 bus_context_get_max_services_per_connection (registry->context))
521 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
522 "Connection \"%s\" is not allowed to own more services "
523 "(increase limits in configuration file if required)",
524 bus_connection_is_active (connection) ?
525 bus_connection_get_name (connection) :
530 service = bus_registry_lookup (registry, service_name);
534 primary_owner = bus_service_get_primary_owner (service);
535 if (primary_owner != NULL)
536 old_owner_conn = primary_owner->conn;
538 old_owner_conn = NULL;
541 old_owner_conn = NULL;
545 service = bus_registry_ensure (registry,
546 service_name, connection, flags,
552 primary_owner = bus_service_get_primary_owner (service);
553 if (primary_owner == NULL)
556 if (old_owner_conn == NULL)
558 _dbus_assert (primary_owner->conn == connection);
560 *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
562 else if (old_owner_conn == connection)
564 bus_owner_set_flags (primary_owner, flags);
565 *result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
567 else if (((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
568 !(bus_service_get_allow_replacement (service))) ||
569 ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
570 !(flags & DBUS_NAME_FLAG_REPLACE_EXISTING)))
573 BusOwner *temp_owner;
574 /* Since we can't be queued if we are already in the queue
577 link = _bus_service_find_owner_link (service, connection);
580 _dbus_list_unlink (&service->owners, link);
581 temp_owner = (BusOwner *)link->data;
582 bus_owner_unref (temp_owner);
583 _dbus_list_free_link (link);
586 *result = DBUS_REQUEST_NAME_REPLY_EXISTS;
588 else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
589 (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
590 !(bus_service_get_allow_replacement (service))))
592 /* Queue the connection */
593 if (!bus_service_add_owner (service, connection,
598 *result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
602 /* Replace the current owner */
604 /* We enqueue the new owner and remove the first one because
605 * that will cause NameAcquired and NameLost messages to
609 if (!bus_service_add_owner (service, connection,
614 if (primary_owner->do_not_queue)
616 if (!bus_service_remove_owner (service, old_owner_conn,
622 if (!bus_service_swap_owner (service, old_owner_conn,
628 _dbus_assert (connection == bus_service_get_primary_owner (service)->conn);
629 *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
632 activation = bus_context_get_activation (registry->context);
633 retval = bus_activation_send_pending_auto_activation_messages (activation,
642 #ifdef ENABLE_KDBUS_TRANSPORT
644 bus_registry_acquire_kdbus_service (BusRegistry *registry,
645 DBusConnection *connection,
646 DBusMessage *message,
647 dbus_uint32_t *result,
648 BusTransaction *transaction,
653 BusActivation *activation;
654 DBusString service_name_real;
655 const DBusString *service_name = &service_name_real;
659 const char* conn_unique_name;
660 DBusConnection* phantom;
661 unsigned long int uid;
663 if (!dbus_message_get_args (message, error,
664 DBUS_TYPE_STRING, &name,
665 DBUS_TYPE_UINT32, &flags,
671 _dbus_string_init_const (&service_name_real, name);
673 if (!_dbus_validate_bus_name (service_name, 0,
674 _dbus_string_get_length (service_name)))
676 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
677 "Requested bus name \"%s\" is not valid", name);
679 _dbus_verbose ("Attempt to acquire invalid service name\n");
684 if (_dbus_string_get_byte (service_name, 0) == ':')
686 /* Not allowed; only base services can start with ':' */
687 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
688 "Cannot acquire a service starting with ':' such as \"%s\"", name);
690 _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"", name);
695 conn_unique_name = dbus_message_get_sender(message);
697 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
699 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
700 "Connection \"%s\" is not allowed to own the service \"%s\"because "
701 "it is reserved for D-Bus' use only",
702 conn_unique_name, DBUS_SERVICE_DBUS);
706 sender_id = sender_name_to_id(conn_unique_name, error);
707 if(dbus_error_is_set(error))
710 phantom = bus_connections_find_conn_by_name(bus_connection_get_connections(connection), conn_unique_name);
713 phantom = create_phantom_connection(connection, conn_unique_name, error);
718 if (!bus_client_policy_check_can_own (bus_connection_get_policy (phantom), service_name))
720 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
721 "Connection \"%s\" is not allowed to own the service \"%s\" due "
722 "to security policies in the configuration file", conn_unique_name, name);
726 if (!kdbus_get_unix_user(phantom, conn_unique_name, &uid, NULL))
729 if (!register_kdbus_policy(name, dbus_connection_get_transport(phantom), uid))
731 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
732 "Kdbus error when setting policy for connection \"%s\" and service name \"%s\"",
733 conn_unique_name, name);
737 *result = kdbus_request_name(connection, service_name, flags, sender_id);
738 if(*result == -EPERM)
740 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
741 "Kdbus not allowed %s to own the service \"%s\"",
742 conn_unique_name, _dbus_string_get_const_data (service_name));
747 dbus_set_error (error, DBUS_ERROR_FAILED , "Name \"%s\" could not be acquired", name);
751 if((*result == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) || (*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER))
753 service = bus_registry_lookup (registry, service_name);
756 service = bus_registry_ensure (registry, service_name, phantom, flags,
763 if (!bus_service_add_owner (service, phantom, flags, transaction, error))
767 activation = bus_context_get_activation (registry->context);
768 retval = bus_activation_send_pending_auto_activation_messages (activation,
779 kdbus_release_name(phantom, service_name, sender_id);
781 bus_connection_disconnected(phantom);
788 bus_registry_release_service (BusRegistry *registry,
789 DBusConnection *connection,
790 const DBusString *service_name,
791 dbus_uint32_t *result,
792 BusTransaction *transaction,
800 if (!_dbus_validate_bus_name (service_name, 0,
801 _dbus_string_get_length (service_name)))
803 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
804 "Given bus name \"%s\" is not valid",
805 _dbus_string_get_const_data (service_name));
807 _dbus_verbose ("Attempt to release invalid service name\n");
812 if (_dbus_string_get_byte (service_name, 0) == ':')
814 /* Not allowed; the base service name cannot be created or released */
815 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
816 "Cannot release a service starting with ':' such as \"%s\"",
817 _dbus_string_get_const_data (service_name));
819 _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
820 _dbus_string_get_const_data (service_name));
825 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
827 /* Not allowed; the base service name cannot be created or released */
828 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
829 "Cannot release the %s service because it is owned by the bus",
832 _dbus_verbose ("Attempt to release service name \"%s\"",
838 service = bus_registry_lookup (registry, service_name);
842 *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
844 else if (!bus_service_has_owner (service, connection))
846 *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
850 if (!bus_service_remove_owner (service, connection,
854 _dbus_assert (!bus_service_has_owner (service, connection));
855 *result = DBUS_RELEASE_NAME_REPLY_RELEASED;
864 #ifdef ENABLE_KDBUS_TRANSPORT
866 bus_registry_release_service_kdbus (const char* sender_name,
867 DBusConnection *connection,
868 const DBusString *service_name,
869 dbus_uint32_t *result,
870 BusTransaction *transaction,
873 dbus_bool_t retval = FALSE;
876 if (!_dbus_validate_bus_name (service_name, 0,
877 _dbus_string_get_length (service_name)))
879 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
880 "Given bus name \"%s\" is not valid",
881 _dbus_string_get_const_data (service_name));
883 _dbus_verbose ("Attempt to release invalid service name\n");
888 if (_dbus_string_get_byte (service_name, 0) == ':')
890 /* Not allowed; the base service name cannot be created or released */
891 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
892 "Cannot release a service starting with ':' such as \"%s\"",
893 _dbus_string_get_const_data (service_name));
895 _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
896 _dbus_string_get_const_data (service_name));
901 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
903 /* Not allowed; the base service name cannot be created or released */
904 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
905 "Cannot release the %s service because it is owned by the bus",
908 _dbus_verbose ("Attempt to release service name \"%s\"",
914 sender_id = sender_name_to_id(sender_name, error);
915 if(dbus_error_is_set(error))
918 *result = kdbus_release_name(connection, service_name, sender_id);
920 if(*result == DBUS_RELEASE_NAME_REPLY_RELEASED)
922 BusRegistry* registry;
925 registry = bus_connection_get_registry (connection);
926 service = bus_registry_lookup (registry, service_name);
929 DBusConnection* phantom;
931 phantom = _bus_service_find_owner_connection(service, sender_name);
934 bus_service_remove_owner (service, phantom, transaction, NULL);
935 /* todo we could remove phantom if he doesn't own any name
936 * to do this we should write function in connection.c to check if
937 * _dbus_list_get_last (&d->services_owned) returns not NULL
938 * or we can leave phantom - he will be removed when he disconnects from the bus
942 _dbus_verbose ("Didn't find phantom connection for released name!\n");
954 bus_registry_set_service_context_table (BusRegistry *registry,
955 DBusHashTable *table)
957 DBusHashTable *new_table;
960 new_table = bus_selinux_id_table_new ();
964 _dbus_hash_iter_init (table, &iter);
965 while (_dbus_hash_iter_next (&iter))
967 const char *service = _dbus_hash_iter_get_string_key (&iter);
968 const char *context = _dbus_hash_iter_get_value (&iter);
970 if (!bus_selinux_id_table_insert (new_table,
976 if (registry->service_sid_table)
977 _dbus_hash_table_unref (registry->service_sid_table);
978 registry->service_sid_table = new_table;
983 bus_service_unlink_owner (BusService *service,
986 _dbus_list_remove_last (&service->owners, owner);
987 bus_owner_unref (owner);
991 bus_service_unlink (BusService *service)
993 _dbus_assert (service->owners == NULL);
995 /* the service may not be in the hash, if
996 * the failure causing transaction cancel
997 * was in the right place, but that's OK
999 _dbus_hash_table_remove_string (service->registry->service_hash,
1002 bus_service_unref (service);
1006 bus_service_relink (BusService *service,
1007 DBusPreallocatedHash *preallocated)
1009 _dbus_assert (service->owners == NULL);
1010 _dbus_assert (preallocated != NULL);
1012 _dbus_hash_table_insert_string_preallocated (service->registry->service_hash,
1017 bus_service_ref (service);
1021 * Data used to represent an ownership cancellation in
1022 * a bus transaction.
1026 BusOwner *owner; /**< the owner */
1027 BusService *service; /**< service to cancel ownership of */
1028 } OwnershipCancelData;
1031 cancel_ownership (void *data)
1033 OwnershipCancelData *d = data;
1035 /* We don't need to send messages notifying of these
1036 * changes, since we're reverting something that was
1037 * cancelled (effectively never really happened)
1039 bus_service_unlink_owner (d->service, d->owner);
1041 if (d->service->owners == NULL)
1042 bus_service_unlink (d->service);
1046 free_ownership_cancel_data (void *data)
1048 OwnershipCancelData *d = data;
1050 dbus_connection_unref (d->owner->conn);
1051 bus_owner_unref (d->owner);
1052 bus_service_unref (d->service);
1058 add_cancel_ownership_to_transaction (BusTransaction *transaction,
1059 BusService *service,
1062 OwnershipCancelData *d;
1064 d = dbus_new (OwnershipCancelData, 1);
1068 d->service = service;
1071 if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
1072 free_ownership_cancel_data))
1078 bus_service_ref (d->service);
1079 bus_owner_ref (owner);
1080 dbus_connection_ref (d->owner->conn);
1085 /* this function is self-cancelling if you cancel the transaction */
1087 bus_service_add_owner (BusService *service,
1088 DBusConnection *connection,
1089 dbus_uint32_t flags,
1090 BusTransaction *transaction,
1093 BusOwner *bus_owner;
1094 DBusList *bus_owner_link;
1096 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1098 /* Send service acquired message first, OOM will result
1099 * in cancelling the transaction
1101 if (service->owners == NULL)
1103 if (!bus_driver_send_service_acquired (connection, service->name, transaction, error))
1107 bus_owner_link = _bus_service_find_owner_link (service, connection);
1109 if (bus_owner_link == NULL)
1111 bus_owner = bus_owner_new (service, connection, flags);
1112 if (bus_owner == NULL)
1114 BUS_SET_OOM (error);
1118 bus_owner_set_flags (bus_owner, flags);
1119 if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL)
1121 if (!_dbus_list_append (&service->owners,
1124 bus_owner_unref (bus_owner);
1125 BUS_SET_OOM (error);
1131 if (!_dbus_list_insert_after (&service->owners,
1132 _dbus_list_get_first_link (&service->owners),
1135 bus_owner_unref (bus_owner);
1136 BUS_SET_OOM (error);
1143 /* Update the link since we are already in the queue
1144 * No need for operations that can produce OOM
1147 bus_owner = (BusOwner *) bus_owner_link->data;
1148 if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
1151 _dbus_list_unlink (&service->owners, bus_owner_link);
1152 link = _dbus_list_get_first_link (&service->owners);
1153 _dbus_assert (link != NULL);
1155 _dbus_list_insert_after_link (&service->owners, link, bus_owner_link);
1158 bus_owner_set_flags (bus_owner, flags);
1162 if (!add_cancel_ownership_to_transaction (transaction,
1166 bus_service_unlink_owner (service, bus_owner);
1167 BUS_SET_OOM (error);
1177 BusService *service;
1178 BusOwner *before_owner; /* restore to position before this connection in owners list */
1179 DBusList *owner_link;
1180 DBusList *service_link;
1181 DBusPreallocatedHash *hash_entry;
1182 } OwnershipRestoreData;
1185 restore_ownership (void *data)
1187 OwnershipRestoreData *d = data;
1190 _dbus_assert (d->service_link != NULL);
1191 _dbus_assert (d->owner_link != NULL);
1193 if (d->service->owners == NULL)
1195 _dbus_assert (d->hash_entry != NULL);
1196 bus_service_relink (d->service, d->hash_entry);
1200 _dbus_assert (d->hash_entry == NULL);
1203 /* We don't need to send messages notifying of these
1204 * changes, since we're reverting something that was
1205 * cancelled (effectively never really happened)
1207 link = _dbus_list_get_first_link (&d->service->owners);
1208 while (link != NULL)
1210 if (link->data == d->before_owner)
1213 link = _dbus_list_get_next_link (&d->service->owners, link);
1216 _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link);
1218 /* Note that removing then restoring this changes the order in which
1219 * ServiceDeleted messages are sent on destruction of the
1220 * connection. This should be OK as the only guarantee there is
1221 * that the base service is destroyed last, and we never even
1222 * tentatively remove the base service.
1224 bus_connection_add_owned_service_link (d->owner->conn, d->service_link);
1226 d->hash_entry = NULL;
1227 d->service_link = NULL;
1228 d->owner_link = NULL;
1232 free_ownership_restore_data (void *data)
1234 OwnershipRestoreData *d = data;
1236 if (d->service_link)
1237 _dbus_list_free_link (d->service_link);
1239 _dbus_list_free_link (d->owner_link);
1241 _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
1244 dbus_connection_unref (d->owner->conn);
1245 bus_owner_unref (d->owner);
1246 bus_service_unref (d->service);
1252 add_restore_ownership_to_transaction (BusTransaction *transaction,
1253 BusService *service,
1256 OwnershipRestoreData *d;
1259 d = dbus_new (OwnershipRestoreData, 1);
1263 d->service = service;
1265 d->service_link = _dbus_list_alloc_link (service);
1266 d->owner_link = _dbus_list_alloc_link (owner);
1267 d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
1269 bus_service_ref (d->service);
1270 bus_owner_ref (d->owner);
1271 dbus_connection_ref (d->owner->conn);
1273 d->before_owner = NULL;
1274 link = _dbus_list_get_first_link (&service->owners);
1275 while (link != NULL)
1277 if (link->data == owner)
1279 link = _dbus_list_get_next_link (&service->owners, link);
1282 d->before_owner = link->data;
1287 link = _dbus_list_get_next_link (&service->owners, link);
1290 if (d->service_link == NULL ||
1291 d->owner_link == NULL ||
1292 d->hash_entry == NULL ||
1293 !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
1294 free_ownership_restore_data))
1296 free_ownership_restore_data (d);
1304 bus_service_swap_owner (BusService *service,
1305 DBusConnection *connection,
1306 BusTransaction *transaction,
1309 DBusList *swap_link;
1310 BusOwner *primary_owner;
1312 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1314 /* We send out notifications before we do any work we
1315 * might have to undo if the notification-sending failed
1318 /* Send service lost message */
1319 primary_owner = bus_service_get_primary_owner (service);
1320 if (primary_owner == NULL || primary_owner->conn != connection)
1321 _dbus_assert_not_reached ("Tried to swap a non primary owner");
1324 if (!bus_driver_send_service_lost (connection, service->name,
1325 transaction, error))
1328 if (service->owners == NULL)
1330 _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners");
1332 else if (_dbus_list_length_is_one (&service->owners))
1334 _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue");
1339 BusOwner *new_owner;
1340 DBusConnection *new_owner_conn;
1341 link = _dbus_list_get_first_link (&service->owners);
1342 _dbus_assert (link != NULL);
1343 link = _dbus_list_get_next_link (&service->owners, link);
1344 _dbus_assert (link != NULL);
1346 new_owner = (BusOwner *)link->data;
1347 new_owner_conn = new_owner->conn;
1349 if (!bus_driver_send_service_owner_changed (service->name,
1350 bus_connection_get_name (connection),
1351 bus_connection_get_name (new_owner_conn),
1352 transaction, error))
1355 /* This will be our new owner */
1356 if (!bus_driver_send_service_acquired (new_owner_conn,
1363 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1365 BUS_SET_OOM (error);
1369 /* unlink the primary and make it the second link */
1370 swap_link = _dbus_list_get_first_link (&service->owners);
1371 _dbus_list_unlink (&service->owners, swap_link);
1373 _dbus_list_insert_after_link (&service->owners,
1374 _dbus_list_get_first_link (&service->owners),
1380 /* this function is self-cancelling if you cancel the transaction */
1382 bus_service_remove_owner (BusService *service,
1383 DBusConnection *connection,
1384 BusTransaction *transaction,
1387 BusOwner *primary_owner;
1389 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1391 /* We send out notifications before we do any work we
1392 * might have to undo if the notification-sending failed
1395 /* Send service lost message */
1396 primary_owner = bus_service_get_primary_owner (service);
1397 if (primary_owner != NULL && primary_owner->conn == connection)
1399 if (!bus_driver_send_service_lost (connection, service->name,
1400 transaction, error))
1405 /* if we are not the primary owner then just remove us from the queue */
1407 BusOwner *temp_owner;
1409 link = _bus_service_find_owner_link (service, connection);
1410 _dbus_list_unlink (&service->owners, link);
1411 temp_owner = (BusOwner *)link->data;
1412 bus_owner_unref (temp_owner);
1413 _dbus_list_free_link (link);
1418 if (service->owners == NULL)
1420 _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
1422 else if (_dbus_list_length_is_one (&service->owners))
1424 if (!bus_driver_send_service_owner_changed (service->name,
1425 bus_connection_get_name (connection),
1427 transaction, error))
1433 BusOwner *new_owner;
1434 DBusConnection *new_owner_conn;
1435 link = _dbus_list_get_first_link (&service->owners);
1436 _dbus_assert (link != NULL);
1437 link = _dbus_list_get_next_link (&service->owners, link);
1438 _dbus_assert (link != NULL);
1440 new_owner = (BusOwner *)link->data;
1441 new_owner_conn = new_owner->conn;
1443 if (!bus_driver_send_service_owner_changed (service->name,
1444 bus_connection_get_name (connection),
1445 bus_connection_get_name (new_owner_conn),
1446 transaction, error))
1449 /* This will be our new owner */
1450 if (!bus_driver_send_service_acquired (new_owner_conn,
1457 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1459 BUS_SET_OOM (error);
1463 bus_service_unlink_owner (service, primary_owner);
1465 if (service->owners == NULL)
1466 bus_service_unlink (service);
1472 bus_service_ref (BusService *service)
1474 _dbus_assert (service->refcount > 0);
1476 service->refcount += 1;
1482 bus_service_unref (BusService *service)
1484 _dbus_assert (service->refcount > 0);
1486 service->refcount -= 1;
1488 if (service->refcount == 0)
1490 _dbus_assert (service->owners == NULL);
1492 dbus_free (service->name);
1493 _dbus_mem_pool_dealloc (service->registry->service_pool, service);
1498 bus_service_get_primary_owners_connection (BusService *service)
1501 #ifdef ENABLE_KDBUS_TRANSPORT
1502 char unique_name[(unsigned int)(snprintf((char*)NULL, 0, "%llu", ULLONG_MAX) + sizeof(":1."))];
1505 owner = bus_service_get_primary_owner (service);
1507 #ifdef ENABLE_KDBUS_TRANSPORT
1510 if(bus_context_is_kdbus(service->registry->context))
1512 if(kdbus_get_name_owner(owner->conn, bus_service_get_name(service), unique_name) < 0)
1514 return _bus_service_find_owner_connection(service, unique_name); //bus_connections_find_conn_by_name would be safer? but slower
1527 bus_service_get_primary_owner (BusService *service)
1529 return _dbus_list_get_first (&service->owners);
1533 bus_service_get_name (BusService *service)
1535 return service->name;
1539 bus_service_get_allow_replacement (BusService *service)
1544 _dbus_assert (service->owners != NULL);
1546 link = _dbus_list_get_first_link (&service->owners);
1547 owner = (BusOwner *) link->data;
1549 return owner->allow_replacement;
1552 #ifdef ENABLE_KDBUS_TRANSPORT
1554 bus_service_get_is_kdbus_starter (BusService *service)
1559 _dbus_assert (service->owners != NULL);
1561 link = _dbus_list_get_first_link (&service->owners);
1562 owner = (BusOwner *) link->data;
1564 return owner->is_kdbus_starter;
1569 bus_service_has_owner (BusService *service,
1570 DBusConnection *connection)
1574 link = _bus_service_find_owner_link (service, connection);
1583 bus_service_list_queued_owners (BusService *service,
1584 DBusList **return_list,
1589 _dbus_assert (*return_list == NULL);
1591 link = _dbus_list_get_first_link (&service->owners);
1592 _dbus_assert (link != NULL);
1594 while (link != NULL)
1599 owner = (BusOwner *) link->data;
1600 uname = bus_connection_get_name (owner->conn);
1602 #ifdef ENABLE_KDBUS_TRANSPORT
1603 if(!owner->is_kdbus_starter)
1605 if (!_dbus_list_append (return_list, (char *)uname))
1608 link = _dbus_list_get_next_link (&service->owners, link);
1614 _dbus_list_clear (return_list);
1615 BUS_SET_OOM (error);