void _dbus_loop_remove_watch (DBusLoop *loop, DBusWatch *watch, DBusWatchFunction function, void *data) { DBusList *link; link = _dbus_list_get_first_link (&loop->callbacks); while (link != NULL) { DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); Callback *this = link->data; if (this->type == CALLBACK_WATCH && WATCH_CALLBACK (this)->watch == watch && this->data == data && WATCH_CALLBACK (this)->function == function) { remove_callback (loop, link); return; } link = next; } _dbus_warn ("could not find watch %p function %p data %p to remove\n", watch, (void *)function, data); }
dbus_bool_t bus_service_list_queued_owners (BusService *service, DBusList **return_list, DBusError *error) { DBusList *link; _dbus_assert (*return_list == NULL); link = _dbus_list_get_first_link (&service->owners); _dbus_assert (link != NULL); while (link != NULL) { BusOwner *owner; const char *uname; owner = (BusOwner *) link->data; uname = bus_connection_get_name (owner->conn); if (!_dbus_list_append (return_list, (char *)uname)) goto oom; link = _dbus_list_get_next_link (&service->owners, link); } return TRUE; oom: _dbus_list_clear (return_list); BUS_SET_OOM (error); return FALSE; }
static int do_expiration_with_monotonic_time (BusExpireList *list, long tv_sec, long tv_usec) { DBusList *link; int next_interval, min_wait_time, items_to_expire; next_interval = -1; min_wait_time = 3600 * 1000; /* this is reset anyway if used */ items_to_expire = 0; link = _dbus_list_get_first_link (&list->items); while (link != NULL) { DBusList *next = _dbus_list_get_next_link (&list->items, link); double elapsed; BusExpireItem *item; item = link->data; elapsed = ELAPSED_MILLISECONDS_SINCE (item->added_tv_sec, item->added_tv_usec, tv_sec, tv_usec); if (((item->added_tv_sec == 0) && (item->added_tv_usec == 0)) || ((list->expire_after > 0) && (elapsed >= (double) list->expire_after))) { _dbus_verbose ("Expiring an item %p\n", item); /* If the expire function fails, we just end up expiring * this item next time we walk through the list. This would * be an indeterminate time normally, so we set up the * next_interval to be "shortly" (just enough to avoid * a busy loop) */ if (!(* list->expire_func) (list, link, list->data)) { next_interval = _dbus_get_oom_wait (); break; } } else if (list->expire_after > 0) { double to_wait; items_to_expire = 1; to_wait = (double) list->expire_after - elapsed; if (min_wait_time > to_wait) min_wait_time = to_wait; } link = next; } if (next_interval < 0 && items_to_expire) next_interval = min_wait_time; return next_interval; }
void _dbus_loop_remove_timeout (DBusLoop *loop, DBusTimeout *timeout, DBusTimeoutFunction function, void *data) { DBusList *link; link = _dbus_list_get_first_link (&loop->callbacks); while (link != NULL) { DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); Callback *this = link->data; if (this->type == CALLBACK_TIMEOUT && TIMEOUT_CALLBACK (this)->timeout == timeout && this->data == data && TIMEOUT_CALLBACK (this)->function == function) { remove_callback (loop, link); return; } link = next; } _dbus_warn ("could not find timeout %p function %p data %p to remove\n", timeout, (void *)function, data); }
static dbus_bool_t add_list_to_client (DBusList **list, BusClientPolicy *client) { DBusList *link; link = _dbus_list_get_first_link (list); while (link != NULL) { BusPolicyRule *rule = link->data; link = _dbus_list_get_next_link (list, link); switch (rule->type) { case BUS_POLICY_RULE_USER: case BUS_POLICY_RULE_GROUP: /* These aren't per-connection policies */ break; case BUS_POLICY_RULE_OWN: case BUS_POLICY_RULE_SEND: case BUS_POLICY_RULE_RECEIVE: /* These are per-connection */ if (!bus_client_policy_append_rule (client, rule)) return FALSE; break; } } return TRUE; }
static dbus_bool_t list_allows_user (dbus_bool_t def, DBusList **list, unsigned long uid, const unsigned long *group_ids, int n_group_ids) { DBusList *link; dbus_bool_t allowed; allowed = def; link = _dbus_list_get_first_link (list); while (link != NULL) { BusPolicyRule *rule = link->data; link = _dbus_list_get_next_link (list, link); if (rule->type == BUS_POLICY_RULE_USER) { _dbus_verbose ("List %p user rule uid="DBUS_UID_FORMAT"\n", list, rule->d.user.uid); if (rule->d.user.uid == DBUS_UID_UNSET) ; /* '*' wildcard */ else if (rule->d.user.uid != uid) continue; } else if (rule->type == BUS_POLICY_RULE_GROUP) { _dbus_verbose ("List %p group rule uid="DBUS_UID_FORMAT"\n", list, rule->d.user.uid); if (rule->d.group.gid == DBUS_GID_UNSET) ; /* '*' wildcard */ else { int i; i = 0; while (i < n_group_ids) { if (rule->d.group.gid == group_ids[i]) break; ++i; } if (i == n_group_ids) continue; } } else continue; allowed = rule->allow; } return allowed; }
static int do_expiration_with_current_time (BusExpireList *list, long tv_sec, long tv_usec) { DBusList *link; int next_interval; next_interval = -1; link = _dbus_list_get_first_link (&list->items); while (link != NULL) { DBusList *next = _dbus_list_get_next_link (&list->items, link); double elapsed; BusExpireItem *item; item = link->data; elapsed = ELAPSED_MILLISECONDS_SINCE (item->added_tv_sec, item->added_tv_usec, tv_sec, tv_usec); if (elapsed >= (double) list->expire_after) { _dbus_verbose ("Expiring an item %p\n", item); /* If the expire function fails, we just end up expiring * this item next time we walk through the list. This would * be an indeterminate time normally, so we set up the * next_interval to be "shortly" (just enough to avoid * a busy loop) */ if (!(* list->expire_func) (list, link, list->data)) { next_interval = _dbus_get_oom_wait (); break; } } else { /* We can end the loop, since the connections are in oldest-first order */ next_interval = ((double)list->expire_after) - elapsed; _dbus_verbose ("Item %p expires in %d milliseconds\n", item, next_interval); break; } link = next; } return next_interval; }
/** * Sets all watches to the given enabled state, invoking the * application's DBusWatchToggledFunction if appropriate. * * @param watch_list the watch list. * @param enabled #TRUE to enable */ void _dbus_watch_list_toggle_all_watches (DBusWatchList *watch_list, dbus_bool_t enabled) { DBusList *link; for (link = _dbus_list_get_first_link (&watch_list->watches); link != NULL; link = _dbus_list_get_next_link (&watch_list->watches, link)) { _dbus_watch_list_toggle_watch (watch_list, link->data, enabled); } }
/** * Removes the first link in the list and returns it. This is a * constant-time operation. * * @param list address of the list head. * @returns the first link in the list, or #NULL for an empty list. */ DBusList* _dbus_list_pop_first_link (DBusList **list) { DBusList *link; link = _dbus_list_get_first_link (list); if (link == NULL) return NULL; _dbus_list_unlink (list, link); return link; }
dbus_bool_t bus_service_get_allow_replacement (BusService *service) { BusOwner *owner; DBusList *link; _dbus_assert (service->owners != NULL); link = _dbus_list_get_first_link (&service->owners); owner = (BusOwner *) link->data; return owner->allow_replacement; }
static dbus_bool_t add_restore_ownership_to_transaction (BusTransaction *transaction, BusService *service, BusOwner *owner) { OwnershipRestoreData *d; DBusList *link; d = dbus_new (OwnershipRestoreData, 1); if (d == NULL) return FALSE; d->service = service; d->owner = owner; d->service_link = _dbus_list_alloc_link (service); d->owner_link = _dbus_list_alloc_link (owner); d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash); bus_service_ref (d->service); bus_owner_ref (d->owner); dbus_connection_ref (d->owner->conn); d->before_owner = NULL; link = _dbus_list_get_first_link (&service->owners); while (link != NULL) { if (link->data == owner) { link = _dbus_list_get_next_link (&service->owners, link); if (link) d->before_owner = link->data; break; } link = _dbus_list_get_next_link (&service->owners, link); } if (d->service_link == NULL || d->owner_link == NULL || d->hash_entry == NULL || !bus_transaction_add_cancel_hook (transaction, restore_ownership, d, free_ownership_restore_data)) { free_ownership_restore_data (d); return FALSE; } return TRUE; }
static dbus_bool_t lists_equal (DBusList **list1, DBusList **list2) { DBusList *link1; DBusList *link2; link1 = _dbus_list_get_first_link (list1); link2 = _dbus_list_get_first_link (list2); while (link1 && link2) { if (link1->data != link2->data) return FALSE; link1 = _dbus_list_get_next_link (list1, link1); link2 = _dbus_list_get_next_link (list2, link2); } if (link1 || link2) return FALSE; return TRUE; }
/** * Removes the first value in the list and returns it. This is a * constant-time operation. * * @param list address of the list head. * @returns the first data in the list, or #NULL for an empty list. */ void* _dbus_list_pop_first (DBusList **list) { DBusList *link; void *data; link = _dbus_list_get_first_link (list); if (link == NULL) return NULL; data = link->data; _dbus_list_remove_link (list, link); return data; }
static void restore_ownership (void *data) { OwnershipRestoreData *d = data; DBusList *link; _dbus_assert (d->service_link != NULL); _dbus_assert (d->owner_link != NULL); if (d->service->owners == NULL) { _dbus_assert (d->hash_entry != NULL); bus_service_relink (d->service, d->hash_entry); } else { _dbus_assert (d->hash_entry == NULL); } /* We don't need to send messages notifying of these * changes, since we're reverting something that was * cancelled (effectively never really happened) */ link = _dbus_list_get_first_link (&d->service->owners); while (link != NULL) { if (link->data == d->before_owner) break; link = _dbus_list_get_next_link (&d->service->owners, link); } _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link); /* Note that removing then restoring this changes the order in which * ServiceDeleted messages are sent on destruction of the * connection. This should be OK as the only guarantee there is * that the base service is destroyed last, and we never even * tentatively remove the base service. */ bus_connection_add_owned_service_link (d->owner->conn, d->service_link); d->hash_entry = NULL; d->service_link = NULL; d->owner_link = NULL; }
static dbus_bool_t all_odd_values (DBusList **list) { DBusList *link; link = _dbus_list_get_first_link (list); while (link != NULL) { int v = _DBUS_POINTER_TO_INT (link->data); if ((v % 2) == 0) return FALSE; link = _dbus_list_get_next_link (list, link); } return TRUE; }
void bus_test_clients_foreach (BusConnectionForeachFunction function, void *data) { DBusList *link; link = _dbus_list_get_first_link (&clients); while (link != NULL) { DBusConnection *connection = link->data; DBusList *next = _dbus_list_get_next_link (&clients, link); if (!(* function) (connection, data)) break; link = next; } }
dbus_bool_t bus_test_client_listed (DBusConnection *connection) { DBusList *link; link = _dbus_list_get_first_link (&clients); while (link != NULL) { DBusConnection *c = link->data; DBusList *next = _dbus_list_get_next_link (&clients, link); if (c == connection) return TRUE; link = next; } return FALSE; }
static DBusList * _bus_service_find_owner_link (BusService *service, DBusConnection *connection) { DBusList *link; link = _dbus_list_get_first_link (&service->owners); while (link != NULL) { BusOwner *bus_owner; bus_owner = (BusOwner *) link->data; if (bus_owner->conn == connection) break; link = _dbus_list_get_next_link (&service->owners, link); } return link; }
static dbus_bool_t is_descending_sequence (DBusList **list) { DBusList *link; int prev; prev = _DBUS_INT_MAX; link = _dbus_list_get_first_link (list); while (link != NULL) { int v = _DBUS_POINTER_TO_INT (link->data); if (v >= prev) return FALSE; prev = v; link = _dbus_list_get_next_link (list, link); } return TRUE; }
dbus_bool_t bus_service_swap_owner (BusService *service, DBusConnection *connection, BusTransaction *transaction, DBusError *error) { DBusList *swap_link; 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) _dbus_assert_not_reached ("Tried to swap a non primary owner"); if (!bus_driver_send_service_lost (connection, service->name, transaction, error)) return FALSE; if (service->owners == NULL) { _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners"); } else if (_dbus_list_length_is_one (&service->owners)) { _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue"); } 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; } /* unlink the primary and make it the second link */ swap_link = _dbus_list_get_first_link (&service->owners); _dbus_list_unlink (&service->owners, swap_link); _dbus_list_insert_after_link (&service->owners, _dbus_list_get_first_link (&service->owners), swap_link); return TRUE; }
void bus_set_watched_dirs (BusContext *context, DBusList **directories) { int new_fds[MAX_DIRS_TO_WATCH]; char *new_dirs[MAX_DIRS_TO_WATCH]; DBusList *link; int i, j, fd; struct kevent ev; #ifdef O_CLOEXEC dbus_bool_t cloexec_done = 0; #endif if (!_init_kqueue (context)) goto out; for (i = 0; i < MAX_DIRS_TO_WATCH; i++) { new_fds[i] = -1; new_dirs[i] = NULL; } i = 0; link = _dbus_list_get_first_link (directories); while (link != NULL) { new_dirs[i++] = (char *)link->data; link = _dbus_list_get_next_link (directories, link); } /* Look for directories in both the old and new sets, if * we find one, move its data into the new set. */ for (i = 0; new_dirs[i]; i++) { for (j = 0; j < num_fds; j++) { if (dirs[j] && strcmp (new_dirs[i], dirs[j]) == 0) { new_fds[i] = fds[j]; new_dirs[i] = dirs[j]; fds[j] = -1; dirs[j] = NULL; break; } } } /* Any directory we find in "fds" with a nonzero fd must * not be in the new set, so perform cleanup now. */ for (j = 0; j < num_fds; j++) { if (fds[j] != -1) { close (fds[j]); dbus_free (dirs[j]); fds[j] = -1; dirs[j] = NULL; } } for (i = 0; new_dirs[i]; i++) { if (new_fds[i] == -1) { /* FIXME - less lame error handling for failing to add a watch; * we may need to sleep. */ #ifdef O_CLOEXEC fd = open (new_dirs[i], O_RDONLY | O_CLOEXEC); cloexec_done = (fd >= 0); if (fd < 0 && errno == EINVAL) #endif { fd = open (new_dirs[i], O_RDONLY); } if (fd < 0) { if (errno != ENOENT) { _dbus_warn ("Cannot open directory '%s'; error '%s'\n", new_dirs[i], _dbus_strerror (errno)); goto out; } else { new_fds[i] = -1; new_dirs[i] = NULL; continue; } } #ifdef O_CLOEXEC if (!cloexec_done) #endif { _dbus_fd_set_close_on_exec (fd); } EV_SET (&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_RENAME, 0, 0); if (kevent (kq, &ev, 1, NULL, 0, NULL) == -1) { _dbus_warn ("Cannot setup a kevent for '%s'; error '%s'\n", new_dirs[i], _dbus_strerror (errno)); close (fd); goto out; } new_fds[i] = fd; new_dirs[i] = _dbus_strdup (new_dirs[i]); if (!new_dirs[i]) { /* FIXME have less lame handling for OOM, we just silently fail to * watch. (In reality though, the whole OOM handling in dbus is * stupid but we won't go into that in this comment =) ) */ close (fd); new_fds[i] = -1; } } } num_fds = i; for (i = 0; i < MAX_DIRS_TO_WATCH; i++) { fds[i] = new_fds[i]; dirs[i] = new_dirs[i]; } out: ; }
/** * Sets the watch functions. This function is the "backend" * for dbus_connection_set_watch_functions() and * dbus_server_set_watch_functions(). * * @param watch_list the watch list. * @param add_function the add watch function. * @param remove_function the remove watch function. * @param toggled_function function on toggling enabled flag, or #NULL * @param data the data for those functions. * @param free_data_function the function to free the data. * @returns #FALSE if not enough memory * */ dbus_bool_t _dbus_watch_list_set_functions (DBusWatchList *watch_list, DBusAddWatchFunction add_function, DBusRemoveWatchFunction remove_function, DBusWatchToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function) { /* Add watches with the new watch function, failing on OOM */ if (add_function != NULL) { DBusList *link; link = _dbus_list_get_first_link (&watch_list->watches); while (link != NULL) { DBusList *next = _dbus_list_get_next_link (&watch_list->watches, link); #ifdef DBUS_ENABLE_VERBOSE_MODE { const char *watch_type; int flags; flags = dbus_watch_get_flags (link->data); if ((flags & DBUS_WATCH_READABLE) && (flags & DBUS_WATCH_WRITABLE)) watch_type = "readwrite"; else if (flags & DBUS_WATCH_READABLE) watch_type = "read"; else if (flags & DBUS_WATCH_WRITABLE) watch_type = "write"; else watch_type = "not read or write"; _dbus_verbose ("Adding a %s watch on fd %d using newly-set add watch function\n", watch_type, dbus_watch_get_socket (link->data)); } #endif /* DBUS_ENABLE_VERBOSE_MODE */ if (!(* add_function) (link->data, data)) { /* remove it all again and return FALSE */ DBusList *link2; link2 = _dbus_list_get_first_link (&watch_list->watches); while (link2 != link) { DBusList *next = _dbus_list_get_next_link (&watch_list->watches, link2); _dbus_verbose ("Removing watch on fd %d using newly-set remove function because initial add failed\n", dbus_watch_get_socket (link2->data)); (* remove_function) (link2->data, data); link2 = next; } return FALSE; } link = next; } } /* Remove all current watches from previous watch handlers */ if (watch_list->remove_watch_function != NULL) { _dbus_verbose ("Removing all pre-existing watches\n"); _dbus_list_foreach (&watch_list->watches, (DBusForeachFunction) watch_list->remove_watch_function, watch_list->watch_data); } if (watch_list->watch_free_data_function != NULL) (* watch_list->watch_free_data_function) (watch_list->watch_data); watch_list->add_watch_function = add_function; watch_list->remove_watch_function = remove_function; watch_list->watch_toggled_function = toggled_function; watch_list->watch_data = data; watch_list->watch_free_data_function = free_data_function; return TRUE; }
/* this function is self-cancelling if you cancel the transaction */ dbus_bool_t bus_service_add_owner (BusService *service, DBusConnection *connection, dbus_uint32_t flags, BusTransaction *transaction, DBusError *error) { BusOwner *bus_owner; DBusList *bus_owner_link; _DBUS_ASSERT_ERROR_IS_CLEAR (error); /* Send service acquired message first, OOM will result * in cancelling the transaction */ if (service->owners == NULL) { if (!bus_driver_send_service_acquired (connection, service->name, transaction, error)) return FALSE; } bus_owner_link = _bus_service_find_owner_link (service, connection); if (bus_owner_link == NULL) { bus_owner = bus_owner_new (service, connection, flags); if (bus_owner == NULL) { BUS_SET_OOM (error); return FALSE; } bus_owner_set_flags (bus_owner, flags); if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL) { if (!_dbus_list_append (&service->owners, bus_owner)) { bus_owner_unref (bus_owner); BUS_SET_OOM (error); return FALSE; } } else { if (!_dbus_list_insert_after (&service->owners, _dbus_list_get_first_link (&service->owners), bus_owner)) { bus_owner_unref (bus_owner); BUS_SET_OOM (error); return FALSE; } } } else { /* Update the link since we are already in the queue * No need for operations that can produce OOM */ bus_owner = (BusOwner *) bus_owner_link->data; if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING) { DBusList *link; _dbus_list_unlink (&service->owners, bus_owner_link); link = _dbus_list_get_first_link (&service->owners); _dbus_assert (link != NULL); _dbus_list_insert_after_link (&service->owners, link, bus_owner_link); } bus_owner_set_flags (bus_owner, flags); return TRUE; } if (!add_cancel_ownership_to_transaction (transaction, service, bus_owner)) { bus_service_unlink_owner (service, bus_owner); BUS_SET_OOM (error); return FALSE; } return TRUE; }
static dbus_bool_t test_command_line (const char *arg1, ...) { int i, original_argc, shell_argc; char **shell_argv; char **original_argv; char *command_line, *tmp; DBusString str; DBusList *list = NULL, *node; va_list var_args; DBusError error; va_start (var_args, arg1); _dbus_list_append (&list, (char *)arg1); do { tmp = va_arg (var_args, char *); if (!tmp) break; _dbus_list_append (&list, tmp); } while (tmp); va_end (var_args); original_argc = _dbus_list_get_length (&list); original_argv = dbus_new (char *, original_argc); _dbus_string_init (&str); for (i = 0, node = _dbus_list_get_first_link (&list); i < original_argc && node; i++, node = _dbus_list_get_next_link (&list, node)) { original_argv[i] = node->data; if (i > 0) _dbus_string_append_byte (&str, ' '); _dbus_string_append (&str, original_argv[i]); } _dbus_list_clear (&list); command_line = _dbus_string_get_data (&str); printf ("\n\nTesting command line '%s'\n", command_line); dbus_error_init (&error); if (!_dbus_shell_parse_argv (command_line, &shell_argc, &shell_argv, &error)) { fprintf (stderr, "Error parsing command line: %s\n", error.message ? error.message : ""); return FALSE; } else { if (shell_argc != original_argc) { printf ("Number of arguments returned (%d) don't match original (%d)\n", shell_argc, original_argc); return FALSE; } printf ("Number of arguments: %d\n", shell_argc); for (i = 0; i < shell_argc; i++) { char *unquoted; unquoted = _dbus_shell_unquote (original_argv[i]); if (strcmp (unquoted ? unquoted : "", shell_argv[i] ? shell_argv[i] : "")) { printf ("Position %d, returned argument (%s) does not match original (%s)\n", i, shell_argv[i], unquoted); dbus_free (unquoted); return FALSE; } dbus_free (unquoted); if (shell_argv[i]) printf ("Argument %d = %s\n", i, shell_argv[i]); } dbus_free_string_array (shell_argv); } _dbus_string_free (&str); return TRUE; }
static BusDesktopFile * desktop_file_for_name (BusConfigParser *parser, const char *name, DBusError *error) { BusDesktopFile *desktop_file; DBusList **service_dirs; DBusList *link; DBusError tmp_error; DBusString full_path; DBusString filename; const char *dir; _DBUS_ASSERT_ERROR_IS_CLEAR (error); desktop_file = NULL; if (!_dbus_string_init (&filename)) { BUS_SET_OOM (error); goto out_all; } if (!_dbus_string_init (&full_path)) { BUS_SET_OOM (error); goto out_filename; } if (!_dbus_string_append (&filename, name) || !_dbus_string_append (&filename, ".service")) { BUS_SET_OOM (error); goto out; } service_dirs = bus_config_parser_get_service_dirs (parser); for (link = _dbus_list_get_first_link (service_dirs); link != NULL; link = _dbus_list_get_next_link (service_dirs, link)) { dir = link->data; _dbus_verbose ("Looking at '%s'\n", dir); dbus_error_init (&tmp_error); /* clear the path from last time */ _dbus_string_set_length (&full_path, 0); /* build the full path */ if (!_dbus_string_append (&full_path, dir) || !_dbus_concat_dir_and_file (&full_path, &filename)) { BUS_SET_OOM (error); goto out; } _dbus_verbose ("Trying to load file '%s'\n", _dbus_string_get_data (&full_path)); desktop_file = bus_desktop_file_load (&full_path, &tmp_error); if (desktop_file == NULL) { _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); _dbus_verbose ("Could not load %s: %s: %s\n", _dbus_string_get_const_data (&full_path), tmp_error.name, tmp_error.message); /* we may have failed if the file is not found; this is not fatal */ if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY)) { dbus_move_error (&tmp_error, error); /* we only bail out on OOM */ goto out; } dbus_error_free (&tmp_error); } /* did we find the desktop file we want? */ if (desktop_file != NULL) break; } /* Didn't find desktop file; set error */ if (desktop_file == NULL) { dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND, "The name %s was not provided by any .service files", name); } out: _dbus_string_free (&full_path); out_filename: _dbus_string_free (&filename); out_all: return desktop_file; }
/** * @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; }
/* This code only gets executed the first time the * config files are parsed. It is not executed * when config files are reloaded. */ static dbus_bool_t process_config_first_time_only (BusContext *context, BusConfigParser *parser, const DBusString *address, BusContextFlags flags, DBusError *error) { DBusString log_prefix; DBusList *link; DBusList **addresses; const char *user, *pidfile; char **auth_mechanisms; DBusList **auth_mechanisms_list; int len; dbus_bool_t retval; _DBUS_ASSERT_ERROR_IS_CLEAR (error); retval = FALSE; auth_mechanisms = NULL; pidfile = NULL; _dbus_init_system_log (TRUE); if (flags & BUS_CONTEXT_FLAG_SYSTEMD_ACTIVATION) context->systemd_activation = TRUE; else context->systemd_activation = FALSE; /* Check for an existing pid file. Of course this is a race; * we'd have to use fcntl() locks on the pid file to * avoid that. But we want to check for the pid file * before overwriting any existing sockets, etc. */ if (flags & BUS_CONTEXT_FLAG_WRITE_PID_FILE) pidfile = bus_config_parser_get_pidfile (parser); if (pidfile != NULL) { DBusString u; DBusStat stbuf; _dbus_string_init_const (&u, pidfile); if (_dbus_stat (&u, &stbuf, NULL)) { #ifdef DBUS_CYGWIN DBusString p; long /* int */ pid; _dbus_string_init (&p); _dbus_file_get_contents(&p, &u, NULL); _dbus_string_parse_int(&p, 0, &pid, NULL); _dbus_string_free(&p); if ((kill((int)pid, 0))) { dbus_set_error(NULL, DBUS_ERROR_FILE_EXISTS, "pid %ld not running, removing stale pid file\n", pid); _dbus_delete_file(&u, NULL); } else { #endif dbus_set_error (error, DBUS_ERROR_FAILED, "The pid file \"%s\" exists, if the message bus is not running, remove this file", pidfile); goto failed; #ifdef DBUS_CYGWIN } #endif } } /* keep around the pid filename so we can delete it later */ context->pidfile = _dbus_strdup (pidfile); /* note that type may be NULL */ context->type = _dbus_strdup (bus_config_parser_get_type (parser)); if (bus_config_parser_get_type (parser) != NULL && context->type == NULL) goto oom; user = bus_config_parser_get_user (parser); if (user != NULL) { context->user = _dbus_strdup (user); if (context->user == NULL) goto oom; } /* Set up the prefix for syslog messages */ if (!_dbus_string_init (&log_prefix)) goto oom; if (context->type && !strcmp (context->type, "system")) { if (!_dbus_string_append (&log_prefix, "[system] ")) goto oom; } else if (context->type && !strcmp (context->type, "session")) { DBusCredentials *credentials; credentials = _dbus_credentials_new_from_current_process (); if (!credentials) goto oom; if (!_dbus_string_append (&log_prefix, "[session ")) { _dbus_credentials_unref (credentials); goto oom; } if (!_dbus_credentials_to_string_append (credentials, &log_prefix)) { _dbus_credentials_unref (credentials); goto oom; } if (!_dbus_string_append (&log_prefix, "] ")) { _dbus_credentials_unref (credentials); goto oom; } _dbus_credentials_unref (credentials); } if (!_dbus_string_steal_data (&log_prefix, &context->log_prefix)) goto oom; _dbus_string_free (&log_prefix); /* Build an array of auth mechanisms */ auth_mechanisms_list = bus_config_parser_get_mechanisms (parser); len = _dbus_list_get_length (auth_mechanisms_list); if (len > 0) { int i; auth_mechanisms = dbus_new0 (char*, len + 1); if (auth_mechanisms == NULL) goto oom; i = 0; link = _dbus_list_get_first_link (auth_mechanisms_list); while (link != NULL) { auth_mechanisms[i] = _dbus_strdup (link->data); if (auth_mechanisms[i] == NULL) goto oom; link = _dbus_list_get_next_link (auth_mechanisms_list, link); i += 1; } }
static dbus_bool_t bus_driver_handle_list_queued_owners (DBusConnection *connection, BusTransaction *transaction, DBusMessage *message, DBusError *error) { const char *text; DBusList *base_names; DBusList *link; DBusString str; BusRegistry *registry; BusService *service; DBusMessage *reply; DBusMessageIter iter, array_iter; char *dbus_service_name = DBUS_SERVICE_DBUS; _DBUS_ASSERT_ERROR_IS_CLEAR (error); registry = bus_connection_get_registry (connection); base_names = NULL; text = NULL; reply = NULL; if (! dbus_message_get_args (message, error, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID)) goto failed; _dbus_string_init_const (&str, text); service = bus_registry_lookup (registry, &str); if (service == NULL && _dbus_string_equal_c_str (&str, DBUS_SERVICE_DBUS)) { /* ORG_FREEDESKTOP_DBUS owns itself */ if (! _dbus_list_append (&base_names, dbus_service_name)) goto oom; } else if (service == NULL) { dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name", text); goto failed; } else { if (!bus_service_list_queued_owners (service, &base_names, error)) goto failed; } _dbus_assert (base_names != NULL); reply = dbus_message_new_method_return (message); if (reply == NULL) goto oom; dbus_message_iter_init_append (reply, &iter); if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &array_iter)) goto oom; link = _dbus_list_get_first_link (&base_names); while (link != NULL) { char *uname; _dbus_assert (link->data != NULL); uname = (char *)link->data; if (!dbus_message_iter_append_basic (&array_iter, DBUS_TYPE_STRING, &uname)) goto oom; link = _dbus_list_get_next_link (&base_names, link); } if (! dbus_message_iter_close_container (&iter, &array_iter)) goto oom; if (! bus_transaction_send_from_driver (transaction, connection, reply)) goto oom; dbus_message_unref (reply); return TRUE; oom: BUS_SET_OOM (error); failed: _DBUS_ASSERT_ERROR_IS_SET (error); if (reply) dbus_message_unref (reply); if (base_names) _dbus_list_clear (&base_names); return FALSE; }
/** * Sets the timeout functions. This function is the "backend" * for dbus_connection_set_timeout_functions(). * * @param timeout_list the timeout list * @param add_function the add timeout function. * @param remove_function the remove timeout function. * @param toggled_function toggle notify function, or #NULL * @param data the data for those functions. * @param free_data_function the function to free the data. * @returns #FALSE if no memory * */ dbus_bool_t _dbus_timeout_list_set_functions (DBusTimeoutList *timeout_list, DBusAddTimeoutFunction add_function, DBusRemoveTimeoutFunction remove_function, DBusTimeoutToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function) { /* Add timeouts with the new function, failing on OOM */ if (add_function != NULL) { DBusList *link; link = _dbus_list_get_first_link (&timeout_list->timeouts); while (link != NULL) { DBusList *next = _dbus_list_get_next_link (&timeout_list->timeouts, link); if (!(* add_function) (link->data, data)) { /* remove it all again and return FALSE */ DBusList *link2; link2 = _dbus_list_get_first_link (&timeout_list->timeouts); while (link2 != link) { DBusList *next = _dbus_list_get_next_link (&timeout_list->timeouts, link2); (* remove_function) (link2->data, data); link2 = next; } return FALSE; } link = next; } } /* Remove all current timeouts from previous timeout handlers */ if (timeout_list->remove_timeout_function != NULL) { _dbus_list_foreach (&timeout_list->timeouts, (DBusForeachFunction) timeout_list->remove_timeout_function, timeout_list->timeout_data); } if (timeout_list->timeout_free_data_function != NULL) (* timeout_list->timeout_free_data_function) (timeout_list->timeout_data); timeout_list->add_timeout_function = add_function; timeout_list->remove_timeout_function = remove_function; timeout_list->timeout_toggled_function = toggled_function; timeout_list->timeout_data = data; timeout_list->timeout_free_data_function = free_data_function; return TRUE; }
/* 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; }