static void free_ownership_restore_data (void *data) { OwnershipRestoreData *d = data; if (d->service_link) _dbus_list_free_link (d->service_link); if (d->owner_link) _dbus_list_free_link (d->owner_link); if (d->hash_entry) _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash, d->hash_entry); dbus_connection_unref (d->owner->conn); bus_owner_unref (d->owner); bus_service_unref (d->service); dbus_free (d); }
static void service_dirs_append_link_unique_or_free (DBusList **service_dirs, DBusList *dir_link) { if (!service_dirs_find_dir (service_dirs, dir_link->data)) { _dbus_list_append_link (service_dirs, dir_link); } else { dbus_free (dir_link->data); _dbus_list_free_link (dir_link); } }
static dbus_bool_t print_service_dirs() { DBusList *dirs; DBusList *link; dirs = NULL; if (!_dbus_get_standard_session_servicedirs (&dirs)) _dbus_assert_not_reached ("couldn't get standard dirs"); while ((link = _dbus_list_pop_first_link (&dirs))) { printf ("default service dir: %s\n", (char *)link->data); dbus_free (link->data); _dbus_list_free_link (link); } dbus_free (dirs); return TRUE; }
static void _dbus_pending_call_last_unref (DBusPendingCall *pending) { DBusConnection *connection; /* If we get here, we should be already detached * from the connection, or never attached. */ _dbus_assert (!pending->timeout_added); connection = pending->connection; /* this assumes we aren't holding connection lock... */ _dbus_data_slot_list_free (&pending->slot_list); if (pending->timeout != NULL) _dbus_timeout_unref (pending->timeout); if (pending->timeout_link) { dbus_message_unref ((DBusMessage *)pending->timeout_link->data); _dbus_list_free_link (pending->timeout_link); pending->timeout_link = NULL; } if (pending->reply) { dbus_message_unref (pending->reply); pending->reply = NULL; } dbus_free (pending); dbus_pending_call_free_data_slot (¬ify_user_data_slot); /* connection lock should not be held. */ /* Free the connection last to avoid a weird state while * calling out to application code where the pending exists * but not the connection. */ dbus_connection_unref (connection); }
/** * @ingroup DBusListInternals * Unit test for DBusList * @returns #TRUE on success. */ dbus_bool_t _dbus_list_test (void) { DBusList *list1; DBusList *list2; DBusList *link1; DBusList *link2; DBusList *copy1; DBusList *copy2; int i; list1 = NULL; list2 = NULL; /* Test append and prepend */ i = 0; while (i < 10) { if (!_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i))) _dbus_assert_not_reached ("could not allocate for append"); if (!_dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i))) _dbus_assert_not_reached ("count not allocate for prepend"); ++i; verify_list (&list1); verify_list (&list2); _dbus_assert (_dbus_list_get_length (&list1) == i); _dbus_assert (_dbus_list_get_length (&list2) == i); } _dbus_assert (is_ascending_sequence (&list1)); _dbus_assert (is_descending_sequence (&list2)); /* Test list clear */ _dbus_list_clear (&list1); _dbus_list_clear (&list2); verify_list (&list1); verify_list (&list2); /* Test get_first, get_last, pop_first, pop_last */ i = 0; while (i < 10) { _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)); _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)); ++i; } --i; while (i >= 0) { void *got_data1; void *got_data2; void *data1; void *data2; got_data1 = _dbus_list_get_last (&list1); got_data2 = _dbus_list_get_first (&list2); data1 = _dbus_list_pop_last (&list1); data2 = _dbus_list_pop_first (&list2); _dbus_assert (got_data1 == data1); _dbus_assert (got_data2 == data2); _dbus_assert (_DBUS_POINTER_TO_INT (data1) == i); _dbus_assert (_DBUS_POINTER_TO_INT (data2) == i); verify_list (&list1); verify_list (&list2); _dbus_assert (is_ascending_sequence (&list1)); _dbus_assert (is_descending_sequence (&list2)); --i; } _dbus_assert (list1 == NULL); _dbus_assert (list2 == NULL); /* Test get_first_link, get_last_link, pop_first_link, pop_last_link */ i = 0; while (i < 10) { _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)); _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)); ++i; } --i; while (i >= 0) { DBusList *got_link1; DBusList *got_link2; DBusList *link1; DBusList *link2; void *data1; void *data2; got_link1 = _dbus_list_get_last_link (&list1); got_link2 = _dbus_list_get_first_link (&list2); link1 = _dbus_list_pop_last_link (&list1); link2 = _dbus_list_pop_first_link (&list2); _dbus_assert (got_link1 == link1); _dbus_assert (got_link2 == link2); data1 = link1->data; data2 = link2->data; _dbus_list_free_link (link1); _dbus_list_free_link (link2); _dbus_assert (_DBUS_POINTER_TO_INT (data1) == i); _dbus_assert (_DBUS_POINTER_TO_INT (data2) == i); verify_list (&list1); verify_list (&list2); _dbus_assert (is_ascending_sequence (&list1)); _dbus_assert (is_descending_sequence (&list2)); --i; } _dbus_assert (list1 == NULL); _dbus_assert (list2 == NULL); /* Test iteration */ i = 0; while (i < 10) { _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)); _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)); ++i; verify_list (&list1); verify_list (&list2); _dbus_assert (_dbus_list_get_length (&list1) == i); _dbus_assert (_dbus_list_get_length (&list2) == i); } _dbus_assert (is_ascending_sequence (&list1)); _dbus_assert (is_descending_sequence (&list2)); --i; link2 = _dbus_list_get_first_link (&list2); while (link2 != NULL) { verify_list (&link2); /* pretend this link is the head */ _dbus_assert (_DBUS_POINTER_TO_INT (link2->data) == i); link2 = _dbus_list_get_next_link (&list2, link2); --i; } i = 0; link1 = _dbus_list_get_first_link (&list1); while (link1 != NULL) { verify_list (&link1); /* pretend this link is the head */ _dbus_assert (_DBUS_POINTER_TO_INT (link1->data) == i); link1 = _dbus_list_get_next_link (&list1, link1); ++i; } --i; link1 = _dbus_list_get_last_link (&list1); while (link1 != NULL) { verify_list (&link1); /* pretend this link is the head */ _dbus_assert (_DBUS_POINTER_TO_INT (link1->data) == i); link1 = _dbus_list_get_prev_link (&list1, link1); --i; } _dbus_list_clear (&list1); _dbus_list_clear (&list2); /* Test remove */ i = 0; while (i < 10) { _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)); _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)); ++i; } --i; while (i >= 0) { if ((i % 2) == 0) { if (!_dbus_list_remove (&list1, _DBUS_INT_TO_POINTER (i))) _dbus_assert_not_reached ("element should have been in list"); if (!_dbus_list_remove (&list2, _DBUS_INT_TO_POINTER (i))) _dbus_assert_not_reached ("element should have been in list"); verify_list (&list1); verify_list (&list2); } --i; } _dbus_assert (all_odd_values (&list1)); _dbus_assert (all_odd_values (&list2)); _dbus_list_clear (&list1); _dbus_list_clear (&list2); /* test removing the other half of the elements */ i = 0; while (i < 10) { _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)); _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)); ++i; } --i; while (i >= 0) { if ((i % 2) != 0) { if (!_dbus_list_remove (&list1, _DBUS_INT_TO_POINTER (i))) _dbus_assert_not_reached ("element should have been in list"); if (!_dbus_list_remove (&list2, _DBUS_INT_TO_POINTER (i))) _dbus_assert_not_reached ("element should have been in list"); verify_list (&list1); verify_list (&list2); } --i; } _dbus_assert (all_even_values (&list1)); _dbus_assert (all_even_values (&list2)); /* clear list using remove_link */ while (list1 != NULL) { _dbus_list_remove_link (&list1, list1); verify_list (&list1); } while (list2 != NULL) { _dbus_list_remove_link (&list2, list2); verify_list (&list2); } /* Test remove link more generally */ i = 0; while (i < 10) { _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)); _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)); ++i; } --i; link2 = _dbus_list_get_first_link (&list2); while (link2 != NULL) { DBusList *next = _dbus_list_get_next_link (&list2, link2); _dbus_assert (_DBUS_POINTER_TO_INT (link2->data) == i); if ((i % 2) == 0) _dbus_list_remove_link (&list2, link2); verify_list (&list2); link2 = next; --i; } _dbus_assert (all_odd_values (&list2)); _dbus_list_clear (&list2); i = 0; link1 = _dbus_list_get_first_link (&list1); while (link1 != NULL) { DBusList *next = _dbus_list_get_next_link (&list1, link1); _dbus_assert (_DBUS_POINTER_TO_INT (link1->data) == i); if ((i % 2) != 0) _dbus_list_remove_link (&list1, link1); verify_list (&list1); link1 = next; ++i; } _dbus_assert (all_even_values (&list1)); _dbus_list_clear (&list1); /* Test copying a list */ i = 0; while (i < 10) { _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)); _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)); ++i; } /* bad pointers, because they are allowed in the copy dest */ copy1 = _DBUS_INT_TO_POINTER (0x342234); copy2 = _DBUS_INT_TO_POINTER (23); _dbus_list_copy (&list1, ©1); verify_list (&list1); verify_list (©1); _dbus_assert (lists_equal (&list1, ©1)); _dbus_list_copy (&list2, ©2); verify_list (&list2); verify_list (©2); _dbus_assert (lists_equal (&list2, ©2)); /* Now test copying empty lists */ _dbus_list_clear (&list1); _dbus_list_clear (&list2); _dbus_list_clear (©1); _dbus_list_clear (©2); /* bad pointers, because they are allowed in the copy dest */ copy1 = _DBUS_INT_TO_POINTER (0x342234); copy2 = _DBUS_INT_TO_POINTER (23); _dbus_list_copy (&list1, ©1); verify_list (&list1); verify_list (©1); _dbus_assert (lists_equal (&list1, ©1)); _dbus_list_copy (&list2, ©2); verify_list (&list2); verify_list (©2); _dbus_assert (lists_equal (&list2, ©2)); _dbus_list_clear (&list1); _dbus_list_clear (&list2); /* insert_before on empty list */ _dbus_list_insert_before (&list1, NULL, _DBUS_INT_TO_POINTER (0)); verify_list (&list1); /* inserting before first element */ _dbus_list_insert_before (&list1, list1, _DBUS_INT_TO_POINTER (2)); verify_list (&list1); _dbus_assert (is_descending_sequence (&list1)); /* inserting in the middle */ _dbus_list_insert_before (&list1, list1->next, _DBUS_INT_TO_POINTER (1)); verify_list (&list1); _dbus_assert (is_descending_sequence (&list1)); /* using insert_before to append */ _dbus_list_insert_before (&list1, NULL, _DBUS_INT_TO_POINTER (-1)); verify_list (&list1); _dbus_assert (is_descending_sequence (&list1)); _dbus_list_clear (&list1); /* insert_after on empty list */ _dbus_list_insert_after (&list1, NULL, _DBUS_INT_TO_POINTER (0)); verify_list (&list1); /* inserting after first element */ _dbus_list_insert_after (&list1, list1, _DBUS_INT_TO_POINTER (1)); verify_list (&list1); _dbus_assert (is_ascending_sequence (&list1)); /* inserting at the end */ _dbus_list_insert_after (&list1, list1->next, _DBUS_INT_TO_POINTER (2)); verify_list (&list1); _dbus_assert (is_ascending_sequence (&list1)); /* using insert_after to prepend */ _dbus_list_insert_after (&list1, NULL, _DBUS_INT_TO_POINTER (-1)); verify_list (&list1); _dbus_assert (is_ascending_sequence (&list1)); _dbus_list_clear (&list1); /* using remove_last */ _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (2)); _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (1)); _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (3)); _dbus_list_remove_last (&list1, _DBUS_INT_TO_POINTER (2)); verify_list (&list1); _dbus_assert (is_ascending_sequence (&list1)); _dbus_list_clear (&list1); return TRUE; }
dbus_bool_t bus_registry_acquire_service (BusRegistry *registry, DBusConnection *connection, const DBusString *service_name, dbus_uint32_t flags, dbus_uint32_t *result, BusTransaction *transaction, DBusError *error) { dbus_bool_t retval; DBusConnection *old_owner_conn; BusClientPolicy *policy; BusService *service; BusActivation *activation; BusSELinuxID *sid; BusOwner *primary_owner; retval = FALSE; if (!_dbus_validate_bus_name (service_name, 0, _dbus_string_get_length (service_name))) { dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Requested bus name \"%s\" is not valid", _dbus_string_get_const_data (service_name)); _dbus_verbose ("Attempt to acquire invalid service name\n"); goto out; } if (_dbus_string_get_byte (service_name, 0) == ':') { /* Not allowed; only base services can start with ':' */ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Cannot acquire a service starting with ':' such as \"%s\"", _dbus_string_get_const_data (service_name)); _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"", _dbus_string_get_const_data (service_name)); goto out; } if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS)) { dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Connection \"%s\" is not allowed to own the service \"%s\"because " "it is reserved for D-Bus' use only", bus_connection_is_active (connection) ? bus_connection_get_name (connection) : "(inactive)", DBUS_SERVICE_DBUS); goto out; } policy = bus_connection_get_policy (connection); _dbus_assert (policy != NULL); /* Note that if sid is #NULL then the bus's own context gets used * in bus_connection_selinux_allows_acquire_service() */ sid = bus_selinux_id_table_lookup (registry->service_sid_table, service_name); if (!bus_selinux_allows_acquire_service (connection, sid, _dbus_string_get_const_data (service_name), error)) { if (dbus_error_is_set (error) && dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY)) { goto out; } dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, "Connection \"%s\" is not allowed to own the service \"%s\" due " "to SELinux policy", bus_connection_is_active (connection) ? bus_connection_get_name (connection) : "(inactive)", _dbus_string_get_const_data (service_name)); goto out; } if (!bus_client_policy_check_can_own (policy, service_name)) { dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, "Connection \"%s\" is not allowed to own the service \"%s\" due " "to security policies in the configuration file", bus_connection_is_active (connection) ? bus_connection_get_name (connection) : "(inactive)", _dbus_string_get_const_data (service_name)); goto out; } if (bus_connection_get_n_services_owned (connection) >= bus_context_get_max_services_per_connection (registry->context)) { dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, "Connection \"%s\" is not allowed to own more services " "(increase limits in configuration file if required)", bus_connection_is_active (connection) ? bus_connection_get_name (connection) : "(inactive)"); goto out; } service = bus_registry_lookup (registry, service_name); if (service != NULL) { primary_owner = bus_service_get_primary_owner (service); if (primary_owner != NULL) old_owner_conn = primary_owner->conn; else old_owner_conn = NULL; } else old_owner_conn = NULL; if (service == NULL) { service = bus_registry_ensure (registry, service_name, connection, flags, transaction, error); if (service == NULL) goto out; } primary_owner = bus_service_get_primary_owner (service); if (primary_owner == NULL) goto out; if (old_owner_conn == NULL) { _dbus_assert (primary_owner->conn == connection); *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER; } else if (old_owner_conn == connection) { bus_owner_set_flags (primary_owner, flags); *result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER; } else if (((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) && !(bus_service_get_allow_replacement (service))) || ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) && !(flags & DBUS_NAME_FLAG_REPLACE_EXISTING))) { DBusList *link; BusOwner *temp_owner; /* Since we can't be queued if we are already in the queue remove us */ link = _bus_service_find_owner_link (service, connection); if (link != NULL) { _dbus_list_unlink (&service->owners, link); temp_owner = (BusOwner *)link->data; bus_owner_unref (temp_owner); _dbus_list_free_link (link); } *result = DBUS_REQUEST_NAME_REPLY_EXISTS; } else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) && (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || !(bus_service_get_allow_replacement (service)))) { /* Queue the connection */ if (!bus_service_add_owner (service, connection, flags, transaction, error)) goto out; *result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE; } else { /* Replace the current owner */ /* We enqueue the new owner and remove the first one because * that will cause NameAcquired and NameLost messages to * be sent. */ if (!bus_service_add_owner (service, connection, flags, transaction, error)) goto out; if (primary_owner->do_not_queue) { if (!bus_service_remove_owner (service, old_owner_conn, transaction, error)) goto out; } else { if (!bus_service_swap_owner (service, old_owner_conn, transaction, error)) goto out; } _dbus_assert (connection == bus_service_get_primary_owner (service)->conn); *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER; } activation = bus_context_get_activation (registry->context); retval = bus_activation_send_pending_auto_activation_messages (activation, service, transaction); if (!retval) BUS_SET_OOM (error); out: return retval; }
/* this function is self-cancelling if you cancel the transaction */ dbus_bool_t bus_service_remove_owner (BusService *service, DBusConnection *connection, BusTransaction *transaction, DBusError *error) { BusOwner *primary_owner; _DBUS_ASSERT_ERROR_IS_CLEAR (error); /* We send out notifications before we do any work we * might have to undo if the notification-sending failed */ /* Send service lost message */ primary_owner = bus_service_get_primary_owner (service); if (primary_owner != NULL && primary_owner->conn == connection) { if (!bus_driver_send_service_lost (connection, service->name, transaction, error)) return FALSE; } else { /* if we are not the primary owner then just remove us from the queue */ DBusList *link; BusOwner *temp_owner; link = _bus_service_find_owner_link (service, connection); _dbus_list_unlink (&service->owners, link); temp_owner = (BusOwner *)link->data; bus_owner_unref (temp_owner); _dbus_list_free_link (link); return TRUE; } if (service->owners == NULL) { _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners"); } else if (_dbus_list_length_is_one (&service->owners)) { if (!bus_driver_send_service_owner_changed (service->name, bus_connection_get_name (connection), NULL, transaction, error)) return FALSE; } else { DBusList *link; BusOwner *new_owner; DBusConnection *new_owner_conn; link = _dbus_list_get_first_link (&service->owners); _dbus_assert (link != NULL); link = _dbus_list_get_next_link (&service->owners, link); _dbus_assert (link != NULL); new_owner = (BusOwner *)link->data; new_owner_conn = new_owner->conn; if (!bus_driver_send_service_owner_changed (service->name, bus_connection_get_name (connection), bus_connection_get_name (new_owner_conn), transaction, error)) return FALSE; /* This will be our new owner */ if (!bus_driver_send_service_acquired (new_owner_conn, service->name, transaction, error)) return FALSE; } if (!add_restore_ownership_to_transaction (transaction, service, primary_owner)) { BUS_SET_OOM (error); return FALSE; } bus_service_unlink_owner (service, primary_owner); if (service->owners == NULL) bus_service_unlink (service); return TRUE; }