static dbus_bool_t handle_reload_watch (DBusWatch *watch, unsigned int flags, void *data) { DBusError error; DBusString str; char *action_str; char action = '\0'; while (!_dbus_string_init (&str)) _dbus_wait_for_memory (); if ((reload_pipe[RELOAD_READ_END].fd > 0) && _dbus_read_socket (reload_pipe[RELOAD_READ_END], &str, 1) != 1) { _dbus_warn ("Couldn't read from reload pipe.\n"); close_reload_pipe (&watch); return TRUE; } action_str = _dbus_string_get_data (&str); if (action_str != NULL) { action = action_str[0]; } _dbus_string_free (&str); /* this can only fail if we don't understand the config file * or OOM. Either way we should just stick with the currently * loaded config. */ dbus_error_init (&error); switch (action) { case ACTION_RELOAD: if (! bus_context_reload_config (context, &error)) { _DBUS_ASSERT_ERROR_IS_SET (&error); _dbus_assert (dbus_error_has_name (&error, DBUS_ERROR_FAILED) || dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)); _dbus_warn ("Unable to reload configuration: %s\n", error.message); dbus_error_free (&error); } break; case ACTION_QUIT: { DBusLoop *loop; /* * On OSs without abstract sockets, we want to quit * gracefully rather than being killed by SIGTERM, * so that DBusServer gets a chance to clean up the * sockets from the filesystem. fd.o #38656 */ loop = bus_context_get_loop (context); if (loop != NULL) { _dbus_loop_quit (loop); } } break; default: break; } return TRUE; }
/** * @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; }
/** * Wrapper for setenv(). If the value is #NULL, unsets * the environment variable. * * There is an unfixable memleak in that it is unsafe to * free memory malloced for use with setenv. This is because * we can not rely on internal implementation details of * the underlying libc library. * * @param varname name of environment variable * @param value value of environment variable * @returns #TRUE on success. */ dbus_bool_t _dbus_setenv (const char *varname, const char *value) { _dbus_assert (varname != NULL); if (value == NULL) { #ifdef HAVE_UNSETENV unsetenv (varname); return TRUE; #else char *putenv_value; size_t len; len = strlen (varname); /* Use system malloc to avoid memleaks that dbus_malloc * will get upset about. */ putenv_value = malloc (len + 2); if (putenv_value == NULL) return FALSE; strcpy (putenv_value, varname); #if defined(DBUS_WIN) strcat (putenv_value, "="); #endif return (putenv (putenv_value) == 0); #endif } else { #ifdef HAVE_SETENV return (setenv (varname, value, TRUE) == 0); #else char *putenv_value; size_t len; size_t varname_len; size_t value_len; varname_len = strlen (varname); value_len = strlen (value); len = varname_len + value_len + 1 /* '=' */ ; /* Use system malloc to avoid memleaks that dbus_malloc * will get upset about. */ putenv_value = malloc (len + 1); if (putenv_value == NULL) return FALSE; strcpy (putenv_value, varname); strcpy (putenv_value + varname_len, "="); strcpy (putenv_value + varname_len + 1, value); return (putenv (putenv_value) == 0); #endif } }
static dbus_bool_t init_uninitialized_locks (void) { DBusList *link; _dbus_assert (thread_init_generation != _dbus_current_generation); link = uninitialized_mutex_list; while (link != NULL) { DBusMutex **mp; mp = (DBusMutex **)link->data; _dbus_assert (*mp == _DBUS_DUMMY_MUTEX); *mp = _dbus_mutex_new (); if (*mp == NULL) goto fail_mutex; link = _dbus_list_get_next_link (&uninitialized_mutex_list, link); } link = uninitialized_condvar_list; while (link != NULL) { DBusCondVar **cp; cp = (DBusCondVar **)link->data; _dbus_assert (*cp == _DBUS_DUMMY_CONDVAR); *cp = _dbus_condvar_new (); if (*cp == NULL) goto fail_condvar; link = _dbus_list_get_next_link (&uninitialized_condvar_list, link); } _dbus_list_clear (&uninitialized_mutex_list); _dbus_list_clear (&uninitialized_condvar_list); if (!_dbus_register_shutdown_func (shutdown_uninitialized_locks, NULL)) goto fail_condvar; return TRUE; fail_condvar: link = uninitialized_condvar_list; while (link != NULL) { DBusCondVar **cp; cp = (DBusCondVar **)link->data; if (*cp != _DBUS_DUMMY_CONDVAR) _dbus_condvar_free (*cp); else break; *cp = _DBUS_DUMMY_CONDVAR; link = _dbus_list_get_next_link (&uninitialized_condvar_list, link); } fail_mutex: link = uninitialized_mutex_list; while (link != NULL) { DBusMutex **mp; mp = (DBusMutex **)link->data; if (*mp != _DBUS_DUMMY_MUTEX) _dbus_mutex_free (*mp); else break; *mp = _DBUS_DUMMY_MUTEX; link = _dbus_list_get_next_link (&uninitialized_mutex_list, link); } return FALSE; }
static dbus_bool_t socket_handle_watch (DBusWatch *watch, unsigned int flags, void *data) { DBusServer *server = data; DBusServerSocket *socket_server = data; #ifndef DBUS_DISABLE_ASSERT int i; dbus_bool_t found = FALSE; #endif SERVER_LOCK (server); #ifndef DBUS_DISABLE_ASSERT for (i = 0 ; i < socket_server->n_fds ; i++) { if (socket_server->watch[i] == watch) found = TRUE; } _dbus_assert (found); #endif _dbus_verbose ("Handling client connection, flags 0x%x\n", flags); if (flags & DBUS_WATCH_READABLE) { int client_fd; int listen_fd; listen_fd = dbus_watch_get_socket (watch); if (socket_server->noncefile) client_fd = _dbus_accept_with_noncefile (listen_fd, socket_server->noncefile); else client_fd = _dbus_accept (listen_fd); if (client_fd < 0) { /* EINTR handled for us */ if (_dbus_get_is_errno_eagain_or_ewouldblock ()) _dbus_verbose ("No client available to accept after all\n"); else _dbus_verbose ("Failed to accept a client connection: %s\n", _dbus_strerror_from_errno ()); SERVER_UNLOCK (server); } else { if (!handle_new_client_fd_and_unlock (server, client_fd)) _dbus_verbose ("Rejected client connection due to lack of memory\n"); } } if (flags & DBUS_WATCH_ERROR) _dbus_verbose ("Error on server listening socket\n"); if (flags & DBUS_WATCH_HANGUP) _dbus_verbose ("Hangup on server listening socket\n"); return TRUE; }
/** * Spawns a new process. The child_setup * function is passed the given user_data and is run in the child * just before calling exec(). * * Also creates a "babysitter" which tracks the status of the * child process, advising the parent if the child exits. * If the spawn fails, no babysitter is created. * If sitter_p is #NULL, no babysitter is kept. * * @param sitter_p return location for babysitter or #NULL * @param log_name the name under which to log messages about this process being spawned * @param argv the executable and arguments * @param env the environment, or #NULL to copy the parent's * @param child_setup function to call in child pre-exec() * @param user_data user data for setup function * @param error error object to be filled in if function fails * @returns #TRUE on success, #FALSE if error is filled in */ dbus_bool_t _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, const char *log_name, char **argv, char **env, DBusSpawnChildSetupFunc child_setup, void *user_data, DBusError *error) { DBusBabysitter *sitter; int child_err_report_pipe[2] = { -1, -1 }; DBusSocket babysitter_pipe[2] = { DBUS_SOCKET_INIT, DBUS_SOCKET_INIT }; pid_t pid; #ifdef HAVE_SYSTEMD int fd_out = -1; int fd_err = -1; #endif _DBUS_ASSERT_ERROR_IS_CLEAR (error); _dbus_assert (argv[0] != NULL); if (sitter_p != NULL) *sitter_p = NULL; sitter = NULL; sitter = _dbus_babysitter_new (); if (sitter == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return FALSE; } sitter->log_name = _dbus_strdup (log_name); if (sitter->log_name == NULL && log_name != NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto cleanup_and_fail; } if (sitter->log_name == NULL) sitter->log_name = _dbus_strdup (argv[0]); if (sitter->log_name == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto cleanup_and_fail; } if (!make_pipe (child_err_report_pipe, error)) goto cleanup_and_fail; if (!_dbus_socketpair (&babysitter_pipe[0], &babysitter_pipe[1], TRUE, error)) goto cleanup_and_fail; /* Setting up the babysitter is only useful in the parent, * but we don't want to run out of memory and fail * after we've already forked, since then we'd leak * child processes everywhere. */ sitter->error_watch = _dbus_watch_new (child_err_report_pipe[READ_END], DBUS_WATCH_READABLE, TRUE, handle_watch, sitter, NULL); if (sitter->error_watch == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto cleanup_and_fail; } if (!_dbus_watch_list_add_watch (sitter->watches, sitter->error_watch)) { /* we need to free it early so the destructor won't try to remove it * without it having been added, which DBusLoop doesn't allow */ _dbus_watch_invalidate (sitter->error_watch); _dbus_watch_unref (sitter->error_watch); sitter->error_watch = NULL; dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto cleanup_and_fail; } sitter->sitter_watch = _dbus_watch_new (babysitter_pipe[0].fd, DBUS_WATCH_READABLE, TRUE, handle_watch, sitter, NULL); if (sitter->sitter_watch == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto cleanup_and_fail; } if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch)) { /* we need to free it early so the destructor won't try to remove it * without it having been added, which DBusLoop doesn't allow */ _dbus_watch_invalidate (sitter->sitter_watch); _dbus_watch_unref (sitter->sitter_watch); sitter->sitter_watch = NULL; dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto cleanup_and_fail; } _DBUS_ASSERT_ERROR_IS_CLEAR (error); #ifdef HAVE_SYSTEMD /* This may fail, but it's not critical. * In particular, if we were compiled with journald support but are now * running on a non-systemd system, this is going to fail, so we * have to cope gracefully. */ fd_out = sd_journal_stream_fd (sitter->log_name, LOG_INFO, FALSE); fd_err = sd_journal_stream_fd (sitter->log_name, LOG_WARNING, FALSE); #endif pid = fork (); if (pid < 0) { dbus_set_error (error, DBUS_ERROR_SPAWN_FORK_FAILED, "Failed to fork (%s)", _dbus_strerror (errno)); goto cleanup_and_fail; } else if (pid == 0) { /* Immediate child, this is the babysitter process. */ int grandchild_pid; /* Be sure we crash if the parent exits * and we write to the err_report_pipe */ signal (SIGPIPE, SIG_DFL); /* Close the parent's end of the pipes. */ close_and_invalidate (&child_err_report_pipe[READ_END]); close_and_invalidate (&babysitter_pipe[0].fd); /* Create the child that will exec () */ grandchild_pid = fork (); if (grandchild_pid < 0) { write_err_and_exit (babysitter_pipe[1].fd, CHILD_FORK_FAILED); _dbus_assert_not_reached ("Got to code after write_err_and_exit()"); } else if (grandchild_pid == 0) { /* Go back to ignoring SIGPIPE, since it's evil */ signal (SIGPIPE, SIG_IGN); close_and_invalidate (&babysitter_pipe[1].fd); #ifdef HAVE_SYSTEMD /* log to systemd journal if possible */ if (fd_out >= 0) dup2 (fd_out, STDOUT_FILENO); if (fd_err >= 0) dup2 (fd_err, STDERR_FILENO); close_and_invalidate (&fd_out); close_and_invalidate (&fd_err); #endif do_exec (child_err_report_pipe[WRITE_END], argv, env, child_setup, user_data); _dbus_assert_not_reached ("Got to code after exec() - should have exited on error"); } else { close_and_invalidate (&child_err_report_pipe[WRITE_END]); #ifdef HAVE_SYSTEMD close_and_invalidate (&fd_out); close_and_invalidate (&fd_err); #endif babysit (grandchild_pid, babysitter_pipe[1].fd); _dbus_assert_not_reached ("Got to code after babysit()"); } } else { /* Close the uncared-about ends of the pipes */ close_and_invalidate (&child_err_report_pipe[WRITE_END]); close_and_invalidate (&babysitter_pipe[1].fd); #ifdef HAVE_SYSTEMD close_and_invalidate (&fd_out); close_and_invalidate (&fd_err); #endif sitter->socket_to_babysitter = babysitter_pipe[0]; babysitter_pipe[0].fd = -1; sitter->error_pipe_from_child = child_err_report_pipe[READ_END]; child_err_report_pipe[READ_END] = -1; sitter->sitter_pid = pid; if (sitter_p != NULL) *sitter_p = sitter; else _dbus_babysitter_unref (sitter); dbus_free_string_array (env); _DBUS_ASSERT_ERROR_IS_CLEAR (error); return TRUE; } cleanup_and_fail: _DBUS_ASSERT_ERROR_IS_SET (error); close_and_invalidate (&child_err_report_pipe[READ_END]); close_and_invalidate (&child_err_report_pipe[WRITE_END]); close_and_invalidate (&babysitter_pipe[0].fd); close_and_invalidate (&babysitter_pipe[1].fd); #ifdef HAVE_SYSTEMD close_and_invalidate (&fd_out); close_and_invalidate (&fd_err); #endif if (sitter != NULL) _dbus_babysitter_unref (sitter); return FALSE; }
static dbus_bool_t fill_group_info (DBusGroupInfo *info, dbus_gid_t gid, const DBusString *groupname, DBusError *error) { const char *group_c_str; _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET); _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET); if (groupname) group_c_str = _dbus_string_get_const_data (groupname); else group_c_str = NULL; /* For now assuming that the getgrnam() and getgrgid() flavors * always correspond to the pwnam flavors, if not we have * to add more configure checks. */ #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R) { struct group *g; int result; size_t buflen; char *buf; struct group g_str; dbus_bool_t b; /* retrieve maximum needed size for buf */ buflen = sysconf (_SC_GETGR_R_SIZE_MAX); /* sysconf actually returns a long, but everything else expects size_t, * so just recast here. * https://bugs.freedesktop.org/show_bug.cgi?id=17061 */ if ((long) buflen <= 0) buflen = 1024; result = -1; while (1) { buf = dbus_malloc (buflen); if (buf == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return FALSE; } g = NULL; #ifdef HAVE_POSIX_GETPWNAM_R if (group_c_str) result = getgrnam_r (group_c_str, &g_str, buf, buflen, &g); else result = getgrgid_r (gid, &g_str, buf, buflen, &g); #else g = getgrnam_r (group_c_str, &g_str, buf, buflen); result = 0; #endif /* !HAVE_POSIX_GETPWNAM_R */ /* Try a bigger buffer if ERANGE was returned: https://bugs.freedesktop.org/show_bug.cgi?id=16727 */ if (result == ERANGE && buflen < 512 * 1024) { dbus_free (buf); buflen *= 2; } else { break; } } if (result == 0 && g == &g_str) { b = fill_user_info_from_group (g, info, error); dbus_free (buf); return b; } else { dbus_set_error (error, _dbus_error_from_errno (errno), "Group %s unknown or failed to look it up\n", group_c_str ? group_c_str : "???"); dbus_free (buf); return FALSE; } } #else /* ! HAVE_GETPWNAM_R */ { /* I guess we're screwed on thread safety here */ struct group *g; g = getgrnam (group_c_str); if (g != NULL) { return fill_user_info_from_group (g, info, error); } else { dbus_set_error (error, _dbus_error_from_errno (errno), "Group %s unknown or failed to look it up\n", group_c_str ? group_c_str : "???"); return FALSE; } } #endif /* ! HAVE_GETPWNAM_R */ }
static void byteswap_body_helper (DBusTypeReader *reader, dbus_bool_t walk_reader_to_end, int old_byte_order, int new_byte_order, unsigned char *p, unsigned char **new_p) { int current_type; while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID) { switch (current_type) { case DBUS_TYPE_BYTE: ++p; break; case DBUS_TYPE_INT16: case DBUS_TYPE_UINT16: { p = _DBUS_ALIGN_ADDRESS (p, 2); *((dbus_uint16_t*)p) = DBUS_UINT16_SWAP_LE_BE (*((dbus_uint16_t*)p)); p += 2; } break; case DBUS_TYPE_BOOLEAN: case DBUS_TYPE_INT32: case DBUS_TYPE_UINT32: { p = _DBUS_ALIGN_ADDRESS (p, 4); *((dbus_uint32_t*)p) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)p)); p += 4; } break; case DBUS_TYPE_INT64: case DBUS_TYPE_UINT64: case DBUS_TYPE_DOUBLE: { p = _DBUS_ALIGN_ADDRESS (p, 8); #ifdef DBUS_HAVE_INT64 *((dbus_uint64_t*)p) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)p)); #else _dbus_swap_array (p, 1, 8); #endif p += 8; } break; case DBUS_TYPE_ARRAY: case DBUS_TYPE_STRING: case DBUS_TYPE_OBJECT_PATH: { dbus_uint32_t array_len; p = _DBUS_ALIGN_ADDRESS (p, 4); array_len = _dbus_unpack_uint32 (old_byte_order, p); *((dbus_uint32_t*)p) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)p)); p += 4; if (current_type == DBUS_TYPE_ARRAY) { int elem_type; int alignment; elem_type = _dbus_type_reader_get_element_type (reader); alignment = _dbus_type_get_alignment (elem_type); _dbus_assert ((array_len / alignment) < DBUS_MAXIMUM_ARRAY_LENGTH); p = _DBUS_ALIGN_ADDRESS (p, alignment); if (dbus_type_is_fixed (elem_type)) { if (alignment > 1) _dbus_swap_array (p, array_len / alignment, alignment); p += array_len; } else { DBusTypeReader sub; const unsigned char *array_end; array_end = p + array_len; _dbus_type_reader_recurse (reader, &sub); while (p < array_end) { byteswap_body_helper (&sub, FALSE, old_byte_order, new_byte_order, p, &p); } } } else { _dbus_assert (current_type == DBUS_TYPE_STRING || current_type == DBUS_TYPE_OBJECT_PATH); p += (array_len + 1); /* + 1 for nul */ } } break; case DBUS_TYPE_SIGNATURE: { dbus_uint32_t sig_len; sig_len = *p; p += (sig_len + 2); /* +2 for len and nul */ } break; case DBUS_TYPE_VARIANT: { /* 1 byte sig len, sig typecodes, align to * contained-type-boundary, values. */ dbus_uint32_t sig_len; DBusString sig; DBusTypeReader sub; int contained_alignment; sig_len = *p; ++p; _dbus_string_init_const_len (&sig, p, sig_len); p += (sig_len + 1); /* 1 for nul */ contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (&sig, 0)); p = _DBUS_ALIGN_ADDRESS (p, contained_alignment); _dbus_type_reader_init_types_only (&sub, &sig, 0); byteswap_body_helper (&sub, FALSE, old_byte_order, new_byte_order, p, &p); } break; case DBUS_TYPE_STRUCT: case DBUS_TYPE_DICT_ENTRY: { DBusTypeReader sub; p = _DBUS_ALIGN_ADDRESS (p, 8); _dbus_type_reader_recurse (reader, &sub); byteswap_body_helper (&sub, TRUE, old_byte_order, new_byte_order, p, &p); } break; default: _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature"); break; } if (walk_reader_to_end) _dbus_type_reader_next (reader); else break; } if (new_p) *new_p = p; }
static void time_for_size (int size) { int i; int j; clock_t start; clock_t end; #define FREE_ARRAY_SIZE 512 #define N_ITERATIONS FREE_ARRAY_SIZE * 512 void *to_free[FREE_ARRAY_SIZE]; DBusMemPool *pool; _dbus_verbose ("Timings for size %d\n", size); _dbus_verbose (" malloc\n"); start = clock (); i = 0; j = 0; while (i < N_ITERATIONS) { to_free[j] = dbus_malloc (size); _dbus_assert (to_free[j] != NULL); /* in a real app of course this is wrong */ ++j; if (j == FREE_ARRAY_SIZE) { j = 0; while (j < FREE_ARRAY_SIZE) { dbus_free (to_free[j]); ++j; } j = 0; } ++i; } end = clock (); _dbus_verbose (" created/destroyed %d elements in %g seconds\n", N_ITERATIONS, (end - start) / (double) CLOCKS_PER_SEC); _dbus_verbose (" mempools\n"); start = clock (); pool = _dbus_mem_pool_new (size, FALSE); i = 0; j = 0; while (i < N_ITERATIONS) { to_free[j] = _dbus_mem_pool_alloc (pool); _dbus_assert (to_free[j] != NULL); /* in a real app of course this is wrong */ ++j; if (j == FREE_ARRAY_SIZE) { j = 0; while (j < FREE_ARRAY_SIZE) { _dbus_mem_pool_dealloc (pool, to_free[j]); ++j; } j = 0; } ++i; } _dbus_mem_pool_free (pool); end = clock (); _dbus_verbose (" created/destroyed %d elements in %g seconds\n", N_ITERATIONS, (end - start) / (double) CLOCKS_PER_SEC); _dbus_verbose (" zeroed malloc\n"); start = clock (); i = 0; j = 0; while (i < N_ITERATIONS) { to_free[j] = dbus_malloc0 (size); _dbus_assert (to_free[j] != NULL); /* in a real app of course this is wrong */ ++j; if (j == FREE_ARRAY_SIZE) { j = 0; while (j < FREE_ARRAY_SIZE) { dbus_free (to_free[j]); ++j; } j = 0; } ++i; } end = clock (); _dbus_verbose (" created/destroyed %d elements in %g seconds\n", N_ITERATIONS, (end - start) / (double) CLOCKS_PER_SEC); _dbus_verbose (" zeroed mempools\n"); start = clock (); pool = _dbus_mem_pool_new (size, TRUE); i = 0; j = 0; while (i < N_ITERATIONS) { to_free[j] = _dbus_mem_pool_alloc (pool); _dbus_assert (to_free[j] != NULL); /* in a real app of course this is wrong */ ++j; if (j == FREE_ARRAY_SIZE) { j = 0; while (j < FREE_ARRAY_SIZE) { _dbus_mem_pool_dealloc (pool, to_free[j]); ++j; } j = 0; } ++i; } _dbus_mem_pool_free (pool); end = clock (); _dbus_verbose (" created/destroyed %d elements in %g seconds\n", N_ITERATIONS, (end - start) / (double) CLOCKS_PER_SEC); }
dbus_bool_t _dbus_message_test (const char *test_data_dir) { DBusMessage *message; DBusMessageLoader *loader; int i; const char *data; DBusMessage *copy; const char *name1; const char *name2; const dbus_uint32_t our_uint32_array[] = { 0x12345678, 0x23456781, 0x34567812, 0x45678123 }; const dbus_int32_t our_int32_array[] = { 0x12345678, -0x23456781, 0x34567812, -0x45678123 }; const dbus_uint32_t *v_ARRAY_UINT32 = our_uint32_array; const dbus_int32_t *v_ARRAY_INT32 = our_int32_array; #ifdef DBUS_HAVE_INT64 const dbus_uint64_t our_uint64_array[] = { 0x12345678, 0x23456781, 0x34567812, 0x45678123 }; const dbus_int64_t our_int64_array[] = { 0x12345678, -0x23456781, 0x34567812, -0x45678123 }; const dbus_uint64_t *v_ARRAY_UINT64 = our_uint64_array; const dbus_int64_t *v_ARRAY_INT64 = our_int64_array; #endif const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" }; const char **v_ARRAY_STRING = our_string_array; const double our_double_array[] = { 0.1234, 9876.54321, -300.0 }; const double *v_ARRAY_DOUBLE = our_double_array; const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 }; const unsigned char *v_ARRAY_BYTE = our_byte_array; const dbus_bool_t our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE }; const dbus_bool_t *v_ARRAY_BOOLEAN = our_boolean_array; char sig[64]; const char *s; const char *v_STRING; double v_DOUBLE; dbus_int16_t v_INT16; dbus_uint16_t v_UINT16; dbus_int32_t v_INT32; dbus_uint32_t v_UINT32; #ifdef DBUS_HAVE_INT64 dbus_int64_t v_INT64; dbus_uint64_t v_UINT64; #endif unsigned char v_BYTE; unsigned char v2_BYTE; dbus_bool_t v_BOOLEAN; message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService", "/org/freedesktop/TestPath", "Foo.TestInterface", "TestMethod"); _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService")); _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface", "TestMethod")); _dbus_assert (strcmp (dbus_message_get_path (message), "/org/freedesktop/TestPath") == 0); _dbus_message_set_serial (message, 1234); /* string length including nul byte not a multiple of 4 */ if (!dbus_message_set_sender (message, "org.foo.bar1")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (dbus_message_has_sender (message, "org.foo.bar1")); dbus_message_set_reply_serial (message, 5678); _dbus_verbose_bytes_of_string (&message->header.data, 0, _dbus_string_get_length (&message->header.data)); _dbus_verbose_bytes_of_string (&message->body, 0, _dbus_string_get_length (&message->body)); if (!dbus_message_set_sender (message, NULL)) _dbus_assert_not_reached ("out of memory"); _dbus_verbose_bytes_of_string (&message->header.data, 0, _dbus_string_get_length (&message->header.data)); _dbus_verbose_bytes_of_string (&message->body, 0, _dbus_string_get_length (&message->body)); _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1")); _dbus_assert (dbus_message_get_serial (message) == 1234); _dbus_assert (dbus_message_get_reply_serial (message) == 5678); _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService")); _dbus_assert (dbus_message_get_no_reply (message) == FALSE); dbus_message_set_no_reply (message, TRUE); _dbus_assert (dbus_message_get_no_reply (message) == TRUE); dbus_message_set_no_reply (message, FALSE); _dbus_assert (dbus_message_get_no_reply (message) == FALSE); /* Set/get some header fields */ if (!dbus_message_set_path (message, "/foo")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (strcmp (dbus_message_get_path (message), "/foo") == 0); if (!dbus_message_set_interface (message, "org.Foo")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (strcmp (dbus_message_get_interface (message), "org.Foo") == 0); if (!dbus_message_set_member (message, "Bar")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (strcmp (dbus_message_get_member (message), "Bar") == 0); /* Set/get them with longer values */ if (!dbus_message_set_path (message, "/foo/bar")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (strcmp (dbus_message_get_path (message), "/foo/bar") == 0); if (!dbus_message_set_interface (message, "org.Foo.Bar")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (strcmp (dbus_message_get_interface (message), "org.Foo.Bar") == 0); if (!dbus_message_set_member (message, "BarFoo")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (strcmp (dbus_message_get_member (message), "BarFoo") == 0); /* Realloc shorter again */ if (!dbus_message_set_path (message, "/foo")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (strcmp (dbus_message_get_path (message), "/foo") == 0); if (!dbus_message_set_interface (message, "org.Foo")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (strcmp (dbus_message_get_interface (message), "org.Foo") == 0); if (!dbus_message_set_member (message, "Bar")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (strcmp (dbus_message_get_member (message), "Bar") == 0); dbus_message_unref (message); /* Test the vararg functions */ message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService", "/org/freedesktop/TestPath", "Foo.TestInterface", "TestMethod"); _dbus_message_set_serial (message, 1); dbus_message_set_reply_serial (message, 5678); v_INT16 = -0x123; v_UINT16 = 0x123; v_INT32 = -0x12345678; v_UINT32 = 0x12300042; #ifdef DBUS_HAVE_INT64 v_INT64 = DBUS_INT64_CONSTANT (-0x123456789abcd); v_UINT64 = DBUS_UINT64_CONSTANT (0x123456789abcd); #endif v_STRING = "Test string"; v_DOUBLE = 3.14159; v_BOOLEAN = TRUE; v_BYTE = 42; v2_BYTE = 24; dbus_message_append_args (message, DBUS_TYPE_INT16, &v_INT16, DBUS_TYPE_UINT16, &v_UINT16, DBUS_TYPE_INT32, &v_INT32, DBUS_TYPE_UINT32, &v_UINT32, #ifdef DBUS_HAVE_INT64 DBUS_TYPE_INT64, &v_INT64, DBUS_TYPE_UINT64, &v_UINT64, #endif DBUS_TYPE_STRING, &v_STRING, DBUS_TYPE_DOUBLE, &v_DOUBLE, DBUS_TYPE_BOOLEAN, &v_BOOLEAN, DBUS_TYPE_BYTE, &v_BYTE, DBUS_TYPE_BYTE, &v2_BYTE, DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &v_ARRAY_UINT32, _DBUS_N_ELEMENTS (our_uint32_array), DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY_INT32, _DBUS_N_ELEMENTS (our_int32_array), #ifdef DBUS_HAVE_INT64 DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, &v_ARRAY_UINT64, _DBUS_N_ELEMENTS (our_uint64_array), DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, &v_ARRAY_INT64, _DBUS_N_ELEMENTS (our_int64_array), #endif DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &v_ARRAY_DOUBLE, _DBUS_N_ELEMENTS (our_double_array), DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &v_ARRAY_BYTE, _DBUS_N_ELEMENTS (our_byte_array), DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, &v_ARRAY_BOOLEAN, _DBUS_N_ELEMENTS (our_boolean_array), DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &v_ARRAY_STRING, _DBUS_N_ELEMENTS (our_string_array), DBUS_TYPE_INVALID); i = 0; sig[i++] = DBUS_TYPE_INT16; sig[i++] = DBUS_TYPE_UINT16; sig[i++] = DBUS_TYPE_INT32; sig[i++] = DBUS_TYPE_UINT32; #ifdef DBUS_HAVE_INT64 sig[i++] = DBUS_TYPE_INT64; sig[i++] = DBUS_TYPE_UINT64; #endif sig[i++] = DBUS_TYPE_STRING; sig[i++] = DBUS_TYPE_DOUBLE; sig[i++] = DBUS_TYPE_BOOLEAN; sig[i++] = DBUS_TYPE_BYTE; sig[i++] = DBUS_TYPE_BYTE; sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_UINT32; sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_INT32; #ifdef DBUS_HAVE_INT64 sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_UINT64; sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_INT64; #endif sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_DOUBLE; sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_BYTE; sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_BOOLEAN; sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_STRING; sig[i++] = DBUS_TYPE_INVALID; _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig)); _dbus_verbose ("HEADER\n"); _dbus_verbose_bytes_of_string (&message->header.data, 0, _dbus_string_get_length (&message->header.data)); _dbus_verbose ("BODY\n"); _dbus_verbose_bytes_of_string (&message->body, 0, _dbus_string_get_length (&message->body)); _dbus_verbose ("Signature expected \"%s\" actual \"%s\"\n", sig, dbus_message_get_signature (message)); s = dbus_message_get_signature (message); _dbus_assert (dbus_message_has_signature (message, sig)); _dbus_assert (strcmp (s, sig) == 0); verify_test_message (message); copy = dbus_message_copy (message); _dbus_assert (dbus_message_get_reply_serial (message) == dbus_message_get_reply_serial (copy)); _dbus_assert (message->header.padding == copy->header.padding); _dbus_assert (_dbus_string_get_length (&message->header.data) == _dbus_string_get_length (©->header.data)); _dbus_assert (_dbus_string_get_length (&message->body) == _dbus_string_get_length (©->body)); verify_test_message (copy); name1 = dbus_message_get_interface (message); name2 = dbus_message_get_interface (copy); _dbus_assert (strcmp (name1, name2) == 0); name1 = dbus_message_get_member (message); name2 = dbus_message_get_member (copy); _dbus_assert (strcmp (name1, name2) == 0); dbus_message_unref (copy); /* Message loader test */ _dbus_message_lock (message); loader = _dbus_message_loader_new (); /* check ref/unref */ _dbus_message_loader_ref (loader); _dbus_message_loader_unref (loader); /* Write the header data one byte at a time */ data = _dbus_string_get_const_data (&message->header.data); for (i = 0; i < _dbus_string_get_length (&message->header.data); i++) { DBusString *buffer; _dbus_message_loader_get_buffer (loader, &buffer); _dbus_string_append_byte (buffer, data[i]); _dbus_message_loader_return_buffer (loader, buffer, 1); } /* Write the body data one byte at a time */ data = _dbus_string_get_const_data (&message->body); for (i = 0; i < _dbus_string_get_length (&message->body); i++) { DBusString *buffer; _dbus_message_loader_get_buffer (loader, &buffer); _dbus_string_append_byte (buffer, data[i]); _dbus_message_loader_return_buffer (loader, buffer, 1); } dbus_message_unref (message); /* Now pop back the message */ if (!_dbus_message_loader_queue_messages (loader)) _dbus_assert_not_reached ("no memory to queue messages"); if (_dbus_message_loader_get_is_corrupted (loader)) _dbus_assert_not_reached ("message loader corrupted"); message = _dbus_message_loader_pop_message (loader); if (!message) _dbus_assert_not_reached ("received a NULL message"); if (dbus_message_get_reply_serial (message) != 5678) _dbus_assert_not_reached ("reply serial fields differ"); verify_test_message (message); dbus_message_unref (message); _dbus_message_loader_unref (loader); check_memleaks (); /* Load all the sample messages from the message factory */ { DBusMessageDataIter diter; DBusMessageData mdata; int count; reset_validities_seen (); count = 0; _dbus_message_data_iter_init (&diter); while (_dbus_message_data_iter_get_and_next (&diter, &mdata)) { if (!dbus_internal_do_not_use_try_message_data (&mdata.data, mdata.expected_validity)) { _dbus_warn ("expected validity %d and did not get it\n", mdata.expected_validity); _dbus_assert_not_reached ("message data failed"); } _dbus_message_data_free (&mdata); count += 1; } printf ("%d sample messages tested\n", count); print_validities_seen (FALSE); print_validities_seen (TRUE); } check_memleaks (); /* Now load every message in test_data_dir if we have one */ if (test_data_dir == NULL) return TRUE; return dbus_internal_do_not_use_foreach_message_file (test_data_dir, (DBusForeachMessageFileFunc) dbus_internal_do_not_use_try_message_file, NULL); }
/** * Allocates an object from the memory pool. * The object must be freed with _dbus_mem_pool_dealloc(). * * @param pool the memory pool * @returns the allocated object or #NULL if no memory. */ void* _dbus_mem_pool_alloc (DBusMemPool *pool) { #ifdef DBUS_BUILD_TESTS if (_dbus_disable_mem_pools ()) { DBusMemBlock *block; int alloc_size; /* This is obviously really silly, but it's * debug-mode-only code that is compiled out * when tests are disabled (_dbus_disable_mem_pools() * is a constant expression FALSE so this block * should vanish) */ alloc_size = sizeof (DBusMemBlock) - ELEMENT_PADDING + pool->element_size; if (pool->zero_elements) block = dbus_malloc0 (alloc_size); else block = dbus_malloc (alloc_size); if (block != NULL) { block->next = pool->blocks; pool->blocks = block; pool->allocated_elements += 1; return (void*) &block->elements[0]; } else return NULL; } else #endif { if (_dbus_decrement_fail_alloc_counter ()) { _dbus_verbose (" FAILING mempool alloc\n"); return NULL; } else if (pool->free_elements) { DBusFreedElement *element = pool->free_elements; pool->free_elements = pool->free_elements->next; if (pool->zero_elements) memset (element, '\0', pool->element_size); pool->allocated_elements += 1; return element; } else { void *element; if (pool->blocks == NULL || pool->blocks->used_so_far == pool->block_size) { /* Need a new block */ DBusMemBlock *block; int alloc_size; #ifdef DBUS_BUILD_TESTS int saved_counter; #endif if (pool->block_size <= _DBUS_INT_MAX / 4) /* avoid overflow */ { /* use a larger block size for our next block */ pool->block_size *= 2; _dbus_assert ((pool->block_size % pool->element_size) == 0); } alloc_size = sizeof (DBusMemBlock) - ELEMENT_PADDING + pool->block_size; #ifdef DBUS_BUILD_TESTS /* We save/restore the counter, so that memory pools won't * cause a given function to have different number of * allocations on different invocations. i.e. when testing * we want consistent alloc patterns. So we skip our * malloc here for purposes of failed alloc simulation. */ saved_counter = _dbus_get_fail_alloc_counter (); _dbus_set_fail_alloc_counter (_DBUS_INT_MAX); #endif if (pool->zero_elements) block = dbus_malloc0 (alloc_size); else block = dbus_malloc (alloc_size); #ifdef DBUS_BUILD_TESTS _dbus_set_fail_alloc_counter (saved_counter); _dbus_assert (saved_counter == _dbus_get_fail_alloc_counter ()); #endif if (block == NULL) return NULL; block->used_so_far = 0; block->next = pool->blocks; pool->blocks = block; } element = &pool->blocks->elements[pool->blocks->used_so_far]; pool->blocks->used_so_far += pool->element_size; pool->allocated_elements += 1; return element; } } }
EXPORT_C #endif dbus_bool_t dbus_threads_init (const DBusThreadFunctions *functions) { dbus_bool_t mutex_set; dbus_bool_t recursive_mutex_set; _dbus_assert (functions != NULL); /* these base functions are required. Future additions to * DBusThreadFunctions may be optional. */ _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK); _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK); _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK); _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK); _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK); _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK); _dbus_assert (functions->condvar_new != NULL); _dbus_assert (functions->condvar_free != NULL); _dbus_assert (functions->condvar_wait != NULL); _dbus_assert (functions->condvar_wait_timeout != NULL); _dbus_assert (functions->condvar_wake_one != NULL); _dbus_assert (functions->condvar_wake_all != NULL); /* Either the mutex function set or recursive mutex set needs * to be available but not both */ mutex_set = (functions->mask & DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK) && (functions->mask & DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK) && (functions->mask & DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK) && (functions->mask & DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK) && functions->mutex_new && functions->mutex_free && functions->mutex_lock && functions->mutex_unlock; recursive_mutex_set = (functions->mask & DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_NEW_MASK) && (functions->mask & DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_FREE_MASK) && (functions->mask & DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_LOCK_MASK) && (functions->mask & DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_UNLOCK_MASK) && functions->recursive_mutex_new && functions->recursive_mutex_free && functions->recursive_mutex_lock && functions->recursive_mutex_unlock; if (!(mutex_set || recursive_mutex_set)) _dbus_assert_not_reached ("Either the nonrecusrive or recursive mutex " "functions sets should be passed into " "dbus_threads_init. Neither sets were passed."); if (mutex_set && recursive_mutex_set) _dbus_assert_not_reached ("Either the nonrecusrive or recursive mutex " "functions sets should be passed into " "dbus_threads_init. Both sets were passed. " "You most likely just want to set the recursive " "mutex functions to avoid deadlocks in D-Bus."); /* Check that all bits in the mask actually are valid mask bits. * ensures people won't write code that breaks when we add * new bits. */ _dbus_assert ((functions->mask & ~DBUS_THREAD_FUNCTIONS_ALL_MASK) == 0); if (thread_init_generation != _dbus_current_generation) thread_functions.mask = 0; /* allow re-init in new generation */ /* Silently allow multiple init * First init wins and D-Bus will always use its threading system */ if (thread_functions.mask != 0) return TRUE; thread_functions.mutex_new = functions->mutex_new; thread_functions.mutex_free = functions->mutex_free; thread_functions.mutex_lock = functions->mutex_lock; thread_functions.mutex_unlock = functions->mutex_unlock; thread_functions.condvar_new = functions->condvar_new; thread_functions.condvar_free = functions->condvar_free; thread_functions.condvar_wait = functions->condvar_wait; thread_functions.condvar_wait_timeout = functions->condvar_wait_timeout; thread_functions.condvar_wake_one = functions->condvar_wake_one; thread_functions.condvar_wake_all = functions->condvar_wake_all; if (functions->mask & DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_NEW_MASK) thread_functions.recursive_mutex_new = functions->recursive_mutex_new; if (functions->mask & DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_FREE_MASK) thread_functions.recursive_mutex_free = functions->recursive_mutex_free; if (functions->mask & DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_LOCK_MASK) thread_functions.recursive_mutex_lock = functions->recursive_mutex_lock; if (functions->mask & DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_UNLOCK_MASK) thread_functions.recursive_mutex_unlock = functions->recursive_mutex_unlock; thread_functions.mask = functions->mask; if (!init_locks ()) return FALSE; thread_init_generation = _dbus_current_generation; return TRUE; }
static dbus_bool_t init_locks (void) { int i; DBusMutex ***dynamic_global_locks; #ifndef EMULATOR DBusMutex **global_locks[] = { #define LOCK_ADDR(name) (& _dbus_lock_##name) LOCK_ADDR (win_fds), LOCK_ADDR (sid_atom_cache), LOCK_ADDR (list), LOCK_ADDR (connection_slots), LOCK_ADDR (pending_call_slots), LOCK_ADDR (server_slots), LOCK_ADDR (message_slots), LOCK_ADDR (atomic), LOCK_ADDR (bus), LOCK_ADDR (bus_datas), LOCK_ADDR (shutdown_funcs), LOCK_ADDR (system_users), LOCK_ADDR (message_cache), LOCK_ADDR (shared_connections), LOCK_ADDR (machine_uuid) #undef LOCK_ADDR }; #else DBusMutex **global_locks[15]; #define LOCK_ADDR(name) ((DBusMutex **)& _dbus_lock_##name) global_locks[0]=LOCK_ADDR (win_fds); global_locks[1]=LOCK_ADDR (sid_atom_cache); global_locks[2]=LOCK_ADDR (list); global_locks[3]=LOCK_ADDR (connection_slots); global_locks[4]=LOCK_ADDR (pending_call_slots); global_locks[5]=LOCK_ADDR (server_slots); global_locks[6]=LOCK_ADDR (message_slots); global_locks[7]=LOCK_ADDR (atomic); global_locks[8]=LOCK_ADDR (bus); global_locks[9]=LOCK_ADDR (bus_datas); global_locks[10]=LOCK_ADDR (shutdown_funcs); global_locks[11]=LOCK_ADDR (system_users); global_locks[12]=LOCK_ADDR (message_cache); global_locks[13]=LOCK_ADDR (shared_connections); global_locks[14]=LOCK_ADDR (machine_uuid); #undef LOCK_ADDR #endif _dbus_assert (_DBUS_N_ELEMENTS (global_locks) == _DBUS_N_GLOBAL_LOCKS); i = 0; dynamic_global_locks = dbus_new (DBusMutex**, _DBUS_N_GLOBAL_LOCKS); if (dynamic_global_locks == NULL) goto failed; while (i < _DBUS_N_ELEMENTS (global_locks)) { *global_locks[i] = _dbus_mutex_new (); if (*global_locks[i] == NULL) goto failed; dynamic_global_locks[i] = global_locks[i]; ++i; } if (!_dbus_register_shutdown_func (shutdown_global_locks, dynamic_global_locks)) goto failed; if (!init_uninitialized_locks ()) goto failed; return TRUE; failed: dbus_free (dynamic_global_locks); for (i = i - 1; i >= 0; i--) { _dbus_mutex_free (*global_locks[i]); *global_locks[i] = NULL; } return FALSE; }
/** * Looks up a uid or username in the user database. Only one of name * or UID can be provided. There are wrapper functions for this that * are better to use, this one does no locking or anything on the * database and otherwise sort of sucks. * * @param db the database * @param uid the user ID or #DBUS_UID_UNSET * @param username username or #NULL * @param error error to fill in * @returns the entry in the database */ DBusUserInfo* _dbus_user_database_lookup (DBusUserDatabase *db, dbus_uid_t uid, const DBusString *username, DBusError *error) { DBusUserInfo *info; _DBUS_ASSERT_ERROR_IS_CLEAR (error); _dbus_assert (uid != DBUS_UID_UNSET || username != NULL); /* See if the username is really a number */ if (uid == DBUS_UID_UNSET) { unsigned long n; if (_dbus_is_a_number (username, &n)) uid = n; } #ifdef DBUS_ENABLE_USERDB_CACHE if (uid != DBUS_UID_UNSET) info = _dbus_hash_table_lookup_ulong (db->users, uid); else info = _dbus_hash_table_lookup_string (db->users_by_name, _dbus_string_get_const_data (username)); if (info) { _dbus_verbose ("Using cache for UID "DBUS_UID_FORMAT" information\n", info->uid); return info; } else #else if (1) #endif { if (uid != DBUS_UID_UNSET) _dbus_verbose ("No cache for UID "DBUS_UID_FORMAT"\n", uid); else _dbus_verbose ("No cache for user \"%s\"\n", _dbus_string_get_const_data (username)); info = dbus_new0 (DBusUserInfo, 1); if (info == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } if (uid != DBUS_UID_UNSET) { if (!_dbus_user_info_fill_uid (info, uid, error)) { _DBUS_ASSERT_ERROR_IS_SET (error); _dbus_user_info_free_allocated (info); return NULL; } } else { if (!_dbus_user_info_fill (info, username, error)) { _DBUS_ASSERT_ERROR_IS_SET (error); _dbus_user_info_free_allocated (info); return NULL; } } /* be sure we don't use these after here */ uid = DBUS_UID_UNSET; username = NULL; /* insert into hash */ if (!_dbus_hash_table_insert_ulong (db->users, info->uid, info)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); _dbus_user_info_free_allocated (info); return NULL; } if (!_dbus_hash_table_insert_string (db->users_by_name, info->username, info)) { _dbus_hash_table_remove_ulong (db->users, info->uid); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } return info; } }
/** * Returns true if the given connection can acquire a service, * using the tasks security context * * @param connection connection that wants to own the service * @param bustype name of the bus * @param service_name the name of the service to acquire * @param error the reason for failure when FALSE is returned * @returns TRUE if acquire is permitted */ dbus_bool_t bus_apparmor_allows_acquire_service (DBusConnection *connection, const char *bustype, const char *service_name, DBusError *error) { #ifdef HAVE_APPARMOR BusAppArmorConfinement *con = NULL; DBusString qstr, auxdata; dbus_bool_t free_auxdata = FALSE; /* the AppArmor API uses pointers to int for pointers to boolean, and * int is not strictly guaranteed to be the same as dbus_bool_t */ int allow = FALSE, audit = TRUE; unsigned long pid; int res, serrno = 0; if (!apparmor_enabled) return TRUE; _dbus_assert (connection != NULL); con = bus_connection_dup_apparmor_confinement (connection); if (is_unconfined (con->label, con->mode)) { allow = TRUE; audit = FALSE; goto out; } if (!_dbus_string_init (&qstr)) goto oom; if (!build_service_query (&qstr, con->label, bustype, service_name)) { _dbus_string_free (&qstr); goto oom; } res = aa_query_label (AA_DBUS_BIND, _dbus_string_get_data (&qstr), _dbus_string_get_length (&qstr), &allow, &audit); _dbus_string_free (&qstr); if (res == -1) { serrno = errno; set_error_from_query_errno (error, serrno); goto audit; } /* Don't fail operations on profiles in complain mode */ if (modestr_is_complain (con->mode)) allow = TRUE; if (!allow) dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, "Connection \"%s\" is not allowed to own the service " "\"%s\" due to AppArmor policy", bus_connection_is_active (connection) ? bus_connection_get_name (connection) : "(inactive)", service_name); if (!audit) goto out; audit: if (!_dbus_string_init (&auxdata)) goto oom; free_auxdata = TRUE; if (!_dbus_append_pair_str (&auxdata, "bus", bustype ? bustype : "unknown")) goto oom; if (!_dbus_append_pair_str (&auxdata, "name", service_name)) goto oom; if (serrno && !_dbus_append_pair_str (&auxdata, "info", strerror (serrno))) goto oom; if (!_dbus_append_mask (&auxdata, AA_DBUS_BIND)) goto oom; if (connection && dbus_connection_get_unix_process_id (connection, &pid) && !_dbus_append_pair_uint (&auxdata, "pid", pid)) goto oom; if (con->label && !_dbus_append_pair_str (&auxdata, "label", con->label)) goto oom; log_message (allow, "bind", &auxdata); out: if (con != NULL) bus_apparmor_confinement_unref (con); if (free_auxdata) _dbus_string_free (&auxdata); return allow; oom: if (error != NULL && !dbus_error_is_set (error)) BUS_SET_OOM (error); allow = FALSE; goto out; #else return TRUE; #endif /* HAVE_APPARMOR */ }
static dbus_bool_t init_system_db (void) { _dbus_assert (database_locked); if (system_db == NULL) { DBusError error = DBUS_ERROR_INIT; const DBusUserInfo *info; system_db = _dbus_user_database_new (); if (system_db == NULL) return FALSE; if (!_dbus_user_database_get_uid (system_db, _dbus_getuid (), &info, &error)) { _dbus_user_database_unref (system_db); system_db = NULL; if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) { dbus_error_free (&error); return FALSE; } else { /* This really should not happen. */ _dbus_warn ("Could not get password database information for UID of current process: %s\n", error.message); dbus_error_free (&error); return FALSE; } } if (!_dbus_string_init (&process_username)) { _dbus_user_database_unref (system_db); system_db = NULL; return FALSE; } if (!_dbus_string_init (&process_homedir)) { _dbus_string_free (&process_username); _dbus_user_database_unref (system_db); system_db = NULL; return FALSE; } if (!_dbus_string_append (&process_username, info->username) || !_dbus_string_append (&process_homedir, info->homedir) || !_dbus_register_shutdown_func (shutdown_system_db, NULL)) { _dbus_string_free (&process_username); _dbus_string_free (&process_homedir); _dbus_user_database_unref (system_db); system_db = NULL; return FALSE; } } return TRUE; }
/** * Check if Apparmor security controls allow the message to be sent to a * particular connection based on the security context of the sender and * that of the receiver. The destination connection need not be the * addressed recipient, it could be an "eavesdropper" * * @param sender the sender of the message. * @param proposed_recipient the connection the message is to be sent to. * @param requested_reply TRUE if the message is a reply requested by * proposed_recipient * @param bustype name of the bus * @param msgtype message type (DBUS_MESSAGE_TYPE_METHOD_CALL, etc.) * @param path object path the message should be sent to * @param interface the type of the object instance * @param member the member of the object * @param error_name the name of the error if the message type is error * @param destination name that the message should be sent to * @param source name that the message should be sent from * @param error the reason for failure when FALSE is returned * @returns TRUE if the message is permitted */ dbus_bool_t bus_apparmor_allows_send (DBusConnection *sender, DBusConnection *proposed_recipient, dbus_bool_t requested_reply, const char *bustype, int msgtype, const char *path, const char *interface, const char *member, const char *error_name, const char *destination, const char *source, BusActivationEntry *activation_entry, DBusError *error) { #ifdef HAVE_APPARMOR BusAppArmorConfinement *src_con = NULL, *dst_con = NULL; DBusString qstr, auxdata; int src_allow = FALSE, dst_allow = FALSE; int src_audit = TRUE, dst_audit = TRUE; dbus_bool_t free_auxdata = FALSE; unsigned long pid; int len, res, src_errno = 0, dst_errno = 0; uint32_t src_perm = AA_DBUS_SEND, dst_perm = AA_DBUS_RECEIVE; const char *msgtypestr = dbus_message_type_to_string(msgtype); const char *dst_label = NULL; const char *dst_mode = NULL; if (!apparmor_enabled) return TRUE; _dbus_assert (sender != NULL); src_con = bus_connection_dup_apparmor_confinement (sender); if (proposed_recipient) { dst_con = bus_connection_dup_apparmor_confinement (proposed_recipient); } else if (activation_entry != NULL) { dst_label = bus_activation_entry_get_assumed_apparmor_label (activation_entry); } else { dst_con = bus_con; bus_apparmor_confinement_ref (dst_con); } if (dst_con != NULL) { dst_label = dst_con->label; dst_mode = dst_con->mode; } /* map reply messages to initial send and receive permission. That is * permission to receive a message from X grants permission to reply to X. * And permission to send a message to Y grants permission to receive a reply * from Y. Note that this only applies to requested replies. Unrequested * replies still require a policy query. */ if (requested_reply) { /* ignore requested reply messages and let dbus reply mapping handle them * as the send was already allowed */ src_allow = TRUE; dst_allow = TRUE; goto out; } if (is_unconfined (src_con->label, src_con->mode)) { src_allow = TRUE; src_audit = FALSE; } else { if (!_dbus_string_init (&qstr)) goto oom; if (!build_message_query (&qstr, src_con->label, bustype, destination, dst_label, path, interface, member)) { _dbus_string_free (&qstr); goto oom; } res = aa_query_label (src_perm, _dbus_string_get_data (&qstr), _dbus_string_get_length (&qstr), &src_allow, &src_audit); _dbus_string_free (&qstr); if (res == -1) { src_errno = errno; set_error_from_query_errno (error, src_errno); goto audit; } } /* When deciding whether we can activate a service, we only check that * we are allowed to send a message to it, not that it is allowed to * receive that message from us. */ if (activation_entry != NULL || is_unconfined (dst_label, dst_mode)) { dst_allow = TRUE; dst_audit = FALSE; } else { if (!_dbus_string_init (&qstr)) goto oom; if (!build_message_query (&qstr, dst_label, bustype, source, src_con->label, path, interface, member)) { _dbus_string_free (&qstr); goto oom; } res = aa_query_label (dst_perm, _dbus_string_get_data (&qstr), _dbus_string_get_length (&qstr), &dst_allow, &dst_audit); _dbus_string_free (&qstr); if (res == -1) { dst_errno = errno; set_error_from_query_errno (error, dst_errno); goto audit; } } /* Don't fail operations on profiles in complain mode */ if (modestr_is_complain (src_con->mode)) src_allow = TRUE; if (modestr_is_complain (dst_mode)) dst_allow = TRUE; if (!src_allow || !dst_allow) set_error_from_denied_message (error, sender, proposed_recipient, requested_reply, msgtypestr, path, interface, member, error_name, destination); /* Don't audit the message if one of the following conditions is true: * 1) The AppArmor query indicates that auditing should not happen. * 2) The message is a reply type. Reply message are not audited because * the AppArmor policy language does not have the notion of a reply * message. Unrequested replies will be silently discarded if the sender * does not have permission to send to the receiver or if the receiver * does not have permission to receive from the sender. */ if ((!src_audit && !dst_audit) || (msgtype == DBUS_MESSAGE_TYPE_METHOD_RETURN || msgtype == DBUS_MESSAGE_TYPE_ERROR)) goto out; audit: if (!_dbus_string_init (&auxdata)) goto oom; free_auxdata = TRUE; if (!_dbus_append_pair_str (&auxdata, "bus", bustype ? bustype : "unknown")) goto oom; if (path && !_dbus_append_pair_str (&auxdata, "path", path)) goto oom; if (interface && !_dbus_append_pair_str (&auxdata, "interface", interface)) goto oom; if (member && !_dbus_append_pair_str (&auxdata, "member", member)) goto oom; if (error_name && !_dbus_append_pair_str (&auxdata, "error_name", error_name)) goto oom; len = _dbus_string_get_length (&auxdata); if (src_audit) { if (!_dbus_append_mask (&auxdata, src_perm)) goto oom; if (destination && !_dbus_append_pair_str (&auxdata, "name", destination)) goto oom; if (sender && dbus_connection_get_unix_process_id (sender, &pid) && !_dbus_append_pair_uint (&auxdata, "pid", pid)) goto oom; if (src_con->label && !_dbus_append_pair_str (&auxdata, "label", src_con->label)) goto oom; if (proposed_recipient && dbus_connection_get_unix_process_id (proposed_recipient, &pid) && !_dbus_append_pair_uint (&auxdata, "peer_pid", pid)) goto oom; if (dst_label && !_dbus_append_pair_str (&auxdata, "peer_label", dst_label)) goto oom; if (src_errno && !_dbus_append_pair_str (&auxdata, "info", strerror (src_errno))) goto oom; if (dst_errno && !_dbus_append_pair_str (&auxdata, "peer_info", strerror (dst_errno))) goto oom; log_message (src_allow, msgtypestr, &auxdata); } if (dst_audit) { _dbus_string_set_length (&auxdata, len); if (source && !_dbus_append_pair_str (&auxdata, "name", source)) goto oom; if (!_dbus_append_mask (&auxdata, dst_perm)) goto oom; if (proposed_recipient && dbus_connection_get_unix_process_id (proposed_recipient, &pid) && !_dbus_append_pair_uint (&auxdata, "pid", pid)) goto oom; if (dst_label && !_dbus_append_pair_str (&auxdata, "label", dst_label)) goto oom; if (sender && dbus_connection_get_unix_process_id (sender, &pid) && !_dbus_append_pair_uint (&auxdata, "peer_pid", pid)) goto oom; if (src_con->label && !_dbus_append_pair_str (&auxdata, "peer_label", src_con->label)) goto oom; if (dst_errno && !_dbus_append_pair_str (&auxdata, "info", strerror (dst_errno))) goto oom; if (src_errno && !_dbus_append_pair_str (&auxdata, "peer_info", strerror (src_errno))) goto oom; log_message (dst_allow, msgtypestr, &auxdata); } out: if (src_con != NULL) bus_apparmor_confinement_unref (src_con); if (dst_con != NULL) bus_apparmor_confinement_unref (dst_con); if (free_auxdata) _dbus_string_free (&auxdata); return src_allow && dst_allow; oom: if (error != NULL && !dbus_error_is_set (error)) BUS_SET_OOM (error); src_allow = FALSE; dst_allow = FALSE; goto out; #else return TRUE; #endif /* HAVE_APPARMOR */ }
static inline DBusSocketSetPoll * socket_set_poll_cast (DBusSocketSet *set) { _dbus_assert (set->cls == &_dbus_socket_set_poll_class); return (DBusSocketSetPoll *) set; }
/** * Opens platform specific transport types. * * @param entry the address entry to try opening * @param transport_p return location for the opened transport * @param error error to be set * @returns result of the attempt */ DBusTransportOpenResult _dbus_transport_open_platform_specific (DBusAddressEntry *entry, DBusTransport **transport_p, DBusError *error) { const char *method; method = dbus_address_entry_get_method (entry); _dbus_assert (method != NULL); if (strcmp (method, "unix") == 0) { const char *path = dbus_address_entry_get_value (entry, "path"); const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir"); const char *abstract = dbus_address_entry_get_value (entry, "abstract"); if (tmpdir != NULL) { _dbus_set_bad_address (error, NULL, NULL, "cannot use the \"tmpdir\" option for an address to connect to, only in an address to listen on"); return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; } if (path == NULL && abstract == NULL) { _dbus_set_bad_address (error, "unix", "path or abstract", NULL); return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; } if (path != NULL && abstract != NULL) { _dbus_set_bad_address (error, NULL, NULL, "can't specify both \"path\" and \"abstract\" options in an address"); return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; } if (path) *transport_p = _dbus_transport_new_for_domain_socket (path, FALSE, error); else *transport_p = _dbus_transport_new_for_domain_socket (abstract, TRUE, error); if (*transport_p == NULL) { _DBUS_ASSERT_ERROR_IS_SET (error); return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; } else { _DBUS_ASSERT_ERROR_IS_CLEAR (error); return DBUS_TRANSPORT_OPEN_OK; } } else { _DBUS_ASSERT_ERROR_IS_CLEAR (error); return DBUS_TRANSPORT_OPEN_NOT_HANDLED; } }
dbus_bool_t bus_expire_list_test (const DBusString *test_data_dir) { DBusLoop *loop; BusExpireList *list; long tv_sec, tv_usec; long tv_sec_not_expired, tv_usec_not_expired; long tv_sec_expired, tv_usec_expired; long tv_sec_past, tv_usec_past; TestExpireItem *item; int next_interval; dbus_bool_t result = FALSE; loop = _dbus_loop_new (); _dbus_assert (loop != NULL); #define EXPIRE_AFTER 100 list = bus_expire_list_new (loop, EXPIRE_AFTER, test_expire_func, NULL); _dbus_assert (list != NULL); _dbus_get_monotonic_time (&tv_sec, &tv_usec); tv_sec_not_expired = tv_sec; tv_usec_not_expired = tv_usec; time_add_milliseconds (&tv_sec_not_expired, &tv_usec_not_expired, EXPIRE_AFTER - 1); tv_sec_expired = tv_sec; tv_usec_expired = tv_usec; time_add_milliseconds (&tv_sec_expired, &tv_usec_expired, EXPIRE_AFTER); tv_sec_past = tv_sec - 1; tv_usec_past = tv_usec; item = dbus_new0 (TestExpireItem, 1); if (item == NULL) goto oom; item->item.added_tv_sec = tv_sec; item->item.added_tv_usec = tv_usec; if (!bus_expire_list_add (list, &item->item)) _dbus_test_fatal ("out of memory"); next_interval = do_expiration_with_monotonic_time (list, tv_sec_not_expired, tv_usec_not_expired); _dbus_assert (item->expire_count == 0); _dbus_verbose ("next_interval = %d\n", next_interval); _dbus_assert (next_interval == 1); next_interval = do_expiration_with_monotonic_time (list, tv_sec_expired, tv_usec_expired); _dbus_assert (item->expire_count == 1); _dbus_verbose ("next_interval = %d\n", next_interval); _dbus_assert (next_interval == -1); next_interval = do_expiration_with_monotonic_time (list, tv_sec_past, tv_usec_past); _dbus_assert (item->expire_count == 1); _dbus_verbose ("next_interval = %d\n", next_interval); _dbus_assert (next_interval == 1000 + EXPIRE_AFTER); bus_expire_list_remove (list, &item->item); dbus_free (item); bus_expire_list_free (list); _dbus_loop_unref (loop); result = TRUE; oom: return result; }
/** * @ingroup DBusStringInternals * Unit test for DBusString. * * @todo Need to write tests for _dbus_string_copy() and * _dbus_string_move() moving to/from each of start/middle/end of a * string. Also need tests for _dbus_string_move_len () * * @returns #TRUE on success. */ dbus_bool_t _dbus_string_test (void) { DBusString str; DBusString other; int i, a, end; long v; int lens[] = { 0, 1, 2, 3, 4, 5, 10, 16, 17, 18, 25, 31, 32, 33, 34, 35, 63, 64, 65, 66, 67, 68, 69, 70, 71, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136 }; char *s; /* Test shortening and setting length */ i = 0; while (i < _DBUS_N_ELEMENTS (lens)) { int j; if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("failed to init string"); if (!_dbus_string_set_length (&str, lens[i])) _dbus_assert_not_reached ("failed to set string length"); j = lens[i]; while (j > 0) { _dbus_assert (_dbus_string_get_length (&str) == j); if (j > 0) { _dbus_string_shorten (&str, 1); _dbus_assert (_dbus_string_get_length (&str) == (j - 1)); } --j; } _dbus_string_free (&str); ++i; } /* Test equality */ if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("oom"); if (!_dbus_string_append (&str, "Hello World")) _dbus_assert_not_reached ("oom"); _dbus_string_init_const (&other, "H"); _dbus_assert (_dbus_string_equal_substring (&str, 0, 1, &other, 0)); _dbus_assert (_dbus_string_equal_substring (&str, 1, 0, &other, 1)); _dbus_string_init_const (&other, "Hello"); _dbus_assert (_dbus_string_equal_substring (&str, 0, 5, &other, 0)); _dbus_assert (_dbus_string_equal_substring (&str, 1, 4, &other, 1)); _dbus_assert (_dbus_string_equal_substring (&str, 2, 3, &other, 2)); _dbus_assert (_dbus_string_equal_substring (&str, 3, 2, &other, 3)); _dbus_assert (_dbus_string_equal_substring (&str, 4, 1, &other, 4)); _dbus_assert (_dbus_string_equal_substring (&str, 5, 0, &other, 5)); _dbus_assert (_dbus_string_equal_substring (&other, 0, 5, &str, 0)); _dbus_assert (_dbus_string_equal_substring (&other, 1, 4, &str, 1)); _dbus_assert (_dbus_string_equal_substring (&other, 2, 3, &str, 2)); _dbus_assert (_dbus_string_equal_substring (&other, 3, 2, &str, 3)); _dbus_assert (_dbus_string_equal_substring (&other, 4, 1, &str, 4)); _dbus_assert (_dbus_string_equal_substring (&other, 5, 0, &str, 5)); _dbus_string_init_const (&other, "World"); _dbus_assert (_dbus_string_equal_substring (&str, 6, 5, &other, 0)); _dbus_assert (_dbus_string_equal_substring (&str, 7, 4, &other, 1)); _dbus_assert (_dbus_string_equal_substring (&str, 8, 3, &other, 2)); _dbus_assert (_dbus_string_equal_substring (&str, 9, 2, &other, 3)); _dbus_assert (_dbus_string_equal_substring (&str, 10, 1, &other, 4)); _dbus_assert (_dbus_string_equal_substring (&str, 11, 0, &other, 5)); _dbus_assert (_dbus_string_equal_substring (&other, 0, 5, &str, 6)); _dbus_assert (_dbus_string_equal_substring (&other, 1, 4, &str, 7)); _dbus_assert (_dbus_string_equal_substring (&other, 2, 3, &str, 8)); _dbus_assert (_dbus_string_equal_substring (&other, 3, 2, &str, 9)); _dbus_assert (_dbus_string_equal_substring (&other, 4, 1, &str, 10)); _dbus_assert (_dbus_string_equal_substring (&other, 5, 0, &str, 11)); _dbus_string_free (&str); /* Test appending data */ if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("failed to init string"); i = 0; while (i < 10) { if (!_dbus_string_append (&str, "a")) _dbus_assert_not_reached ("failed to append string to string"); _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1); if (!_dbus_string_append_byte (&str, 'b')) _dbus_assert_not_reached ("failed to append byte to string"); _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2); ++i; } _dbus_string_free (&str); /* Check steal_data */ if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("failed to init string"); if (!_dbus_string_append (&str, "Hello World")) _dbus_assert_not_reached ("could not append to string"); i = _dbus_string_get_length (&str); if (!_dbus_string_steal_data (&str, &s)) _dbus_assert_not_reached ("failed to steal data"); _dbus_assert (_dbus_string_get_length (&str) == 0); _dbus_assert (((int)strlen (s)) == i); dbus_free (s); /* Check move */ if (!_dbus_string_append (&str, "Hello World")) _dbus_assert_not_reached ("could not append to string"); i = _dbus_string_get_length (&str); if (!_dbus_string_init (&other)) _dbus_assert_not_reached ("could not init string"); if (!_dbus_string_move (&str, 0, &other, 0)) _dbus_assert_not_reached ("could not move"); _dbus_assert (_dbus_string_get_length (&str) == 0); _dbus_assert (_dbus_string_get_length (&other) == i); if (!_dbus_string_append (&str, "Hello World")) _dbus_assert_not_reached ("could not append to string"); if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other))) _dbus_assert_not_reached ("could not move"); _dbus_assert (_dbus_string_get_length (&str) == 0); _dbus_assert (_dbus_string_get_length (&other) == i * 2); if (!_dbus_string_append (&str, "Hello World")) _dbus_assert_not_reached ("could not append to string"); if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2)) _dbus_assert_not_reached ("could not move"); _dbus_assert (_dbus_string_get_length (&str) == 0); _dbus_assert (_dbus_string_get_length (&other) == i * 3); _dbus_string_free (&other); /* Check copy */ if (!_dbus_string_append (&str, "Hello World")) _dbus_assert_not_reached ("could not append to string"); i = _dbus_string_get_length (&str); if (!_dbus_string_init (&other)) _dbus_assert_not_reached ("could not init string"); if (!_dbus_string_copy (&str, 0, &other, 0)) _dbus_assert_not_reached ("could not copy"); _dbus_assert (_dbus_string_get_length (&str) == i); _dbus_assert (_dbus_string_get_length (&other) == i); if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other))) _dbus_assert_not_reached ("could not copy"); _dbus_assert (_dbus_string_get_length (&str) == i); _dbus_assert (_dbus_string_get_length (&other) == i * 2); _dbus_assert (_dbus_string_equal_c_str (&other, "Hello WorldHello World")); if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2)) _dbus_assert_not_reached ("could not copy"); _dbus_assert (_dbus_string_get_length (&str) == i); _dbus_assert (_dbus_string_get_length (&other) == i * 3); _dbus_assert (_dbus_string_equal_c_str (&other, "Hello WorldHello WorldHello World")); _dbus_string_free (&str); _dbus_string_free (&other); /* Check replace */ if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("failed to init string"); if (!_dbus_string_append (&str, "Hello World")) _dbus_assert_not_reached ("could not append to string"); i = _dbus_string_get_length (&str); if (!_dbus_string_init (&other)) _dbus_assert_not_reached ("could not init string"); if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str), &other, 0, _dbus_string_get_length (&other))) _dbus_assert_not_reached ("could not replace"); _dbus_assert (_dbus_string_get_length (&str) == i); _dbus_assert (_dbus_string_get_length (&other) == i); _dbus_assert (_dbus_string_equal_c_str (&other, "Hello World")); if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str), &other, 5, 1)) _dbus_assert_not_reached ("could not replace center space"); _dbus_assert (_dbus_string_get_length (&str) == i); _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1); _dbus_assert (_dbus_string_equal_c_str (&other, "HelloHello WorldWorld")); if (!_dbus_string_replace_len (&str, 1, 1, &other, _dbus_string_get_length (&other) - 1, 1)) _dbus_assert_not_reached ("could not replace end character"); _dbus_assert (_dbus_string_get_length (&str) == i); _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1); _dbus_assert (_dbus_string_equal_c_str (&other, "HelloHello WorldWorle")); _dbus_string_free (&str); _dbus_string_free (&other); /* Different tests are provided because different behaviours are * implemented in _dbus_string_replace_len() in function of replacing and * replaced lengths */ if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("failed to init string"); if (!_dbus_string_append (&str, "Hello World")) _dbus_assert_not_reached ("could not append to string"); i = _dbus_string_get_length (&str); if (!_dbus_string_init (&other)) _dbus_assert_not_reached ("could not init string"); if (!_dbus_string_append (&other, "Foo String")) _dbus_assert_not_reached ("could not append to string"); a = _dbus_string_get_length (&other); if (!_dbus_string_replace_len (&str, 0, 6, &other, 4, 0)) _dbus_assert_not_reached ("could not replace 0 length"); _dbus_assert (_dbus_string_get_length (&str) == i); _dbus_assert (_dbus_string_get_length (&other) == a + 6); _dbus_assert (_dbus_string_equal_c_str (&other, "Foo Hello String")); if (!_dbus_string_replace_len (&str, 5, 6, &other, _dbus_string_get_length (&other), 0)) _dbus_assert_not_reached ("could not replace at the end"); _dbus_assert (_dbus_string_get_length (&str) == i); _dbus_assert (_dbus_string_get_length (&other) == a + 6 + 6); _dbus_assert (_dbus_string_equal_c_str (&other, "Foo Hello String World")); if (!_dbus_string_replace_len (&str, 0, 5, &other, _dbus_string_get_length (&other) - 5, 5)) _dbus_assert_not_reached ("could not replace same length"); _dbus_assert (_dbus_string_get_length (&str) == i); _dbus_assert (_dbus_string_get_length (&other) == a + 6 + 6); _dbus_assert (_dbus_string_equal_c_str (&other, "Foo Hello String Hello")); if (!_dbus_string_replace_len (&str, 6, 5, &other, 4, 12)) _dbus_assert_not_reached ("could not replace with shorter string"); _dbus_assert (_dbus_string_get_length (&str) == i); _dbus_assert (_dbus_string_get_length (&other) == a + 5); _dbus_assert (_dbus_string_equal_c_str (&other, "Foo World Hello")); if (!_dbus_string_replace_len (&str, 0, 1, &other, 0, 3)) _dbus_assert_not_reached ("could not replace at the beginning"); _dbus_assert (_dbus_string_get_length (&str) == i); _dbus_assert (_dbus_string_get_length (&other) == a + 3); _dbus_assert (_dbus_string_equal_c_str (&other, "H World Hello")); if (!_dbus_string_replace_len (&str, 6, 5, &other, _dbus_string_get_length (&other) - 5, 5)) _dbus_assert_not_reached ("could not replace same length"); _dbus_assert (_dbus_string_get_length (&str) == i); _dbus_assert (_dbus_string_get_length (&other) == a + 3); _dbus_assert (_dbus_string_equal_c_str (&other, "H World World")); _dbus_string_free (&str); _dbus_string_free (&other); /* Check insert/set/get byte */ if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("failed to init string"); if (!_dbus_string_append (&str, "Hello")) _dbus_assert_not_reached ("failed to append Hello"); _dbus_assert (_dbus_string_get_byte (&str, 0) == 'H'); _dbus_assert (_dbus_string_get_byte (&str, 1) == 'e'); _dbus_assert (_dbus_string_get_byte (&str, 2) == 'l'); _dbus_assert (_dbus_string_get_byte (&str, 3) == 'l'); _dbus_assert (_dbus_string_get_byte (&str, 4) == 'o'); _dbus_string_set_byte (&str, 1, 'q'); _dbus_assert (_dbus_string_get_byte (&str, 1) == 'q'); if (!_dbus_string_insert_bytes (&str, 0, 1, 255)) _dbus_assert_not_reached ("can't insert byte"); if (!_dbus_string_insert_bytes (&str, 2, 4, 'Z')) _dbus_assert_not_reached ("can't insert byte"); if (!_dbus_string_insert_bytes (&str, _dbus_string_get_length (&str), 1, 'W')) _dbus_assert_not_reached ("can't insert byte"); _dbus_assert (_dbus_string_get_byte (&str, 0) == 255); _dbus_assert (_dbus_string_get_byte (&str, 1) == 'H'); _dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z'); _dbus_assert (_dbus_string_get_byte (&str, 3) == 'Z'); _dbus_assert (_dbus_string_get_byte (&str, 4) == 'Z'); _dbus_assert (_dbus_string_get_byte (&str, 5) == 'Z'); _dbus_assert (_dbus_string_get_byte (&str, 6) == 'q'); _dbus_assert (_dbus_string_get_byte (&str, 7) == 'l'); _dbus_assert (_dbus_string_get_byte (&str, 8) == 'l'); _dbus_assert (_dbus_string_get_byte (&str, 9) == 'o'); _dbus_assert (_dbus_string_get_byte (&str, 10) == 'W'); _dbus_string_free (&str); /* Check append/parse int/double */ if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("failed to init string"); if (!_dbus_string_append_int (&str, 27)) _dbus_assert_not_reached ("failed to append int"); i = _dbus_string_get_length (&str); if (!_dbus_string_parse_int (&str, 0, &v, &end)) _dbus_assert_not_reached ("failed to parse int"); _dbus_assert (v == 27); _dbus_assert (end == i); _dbus_string_free (&str); /* Test find */ if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("failed to init string"); if (!_dbus_string_append (&str, "Hello")) _dbus_assert_not_reached ("couldn't append to string"); if (!_dbus_string_find (&str, 0, "He", &i)) _dbus_assert_not_reached ("didn't find 'He'"); _dbus_assert (i == 0); if (!_dbus_string_find (&str, 0, "Hello", &i)) _dbus_assert_not_reached ("didn't find 'Hello'"); _dbus_assert (i == 0); if (!_dbus_string_find (&str, 0, "ello", &i)) _dbus_assert_not_reached ("didn't find 'ello'"); _dbus_assert (i == 1); if (!_dbus_string_find (&str, 0, "lo", &i)) _dbus_assert_not_reached ("didn't find 'lo'"); _dbus_assert (i == 3); if (!_dbus_string_find (&str, 2, "lo", &i)) _dbus_assert_not_reached ("didn't find 'lo'"); _dbus_assert (i == 3); if (_dbus_string_find (&str, 4, "lo", &i)) _dbus_assert_not_reached ("did find 'lo'"); if (!_dbus_string_find (&str, 0, "l", &i)) _dbus_assert_not_reached ("didn't find 'l'"); _dbus_assert (i == 2); if (!_dbus_string_find (&str, 0, "H", &i)) _dbus_assert_not_reached ("didn't find 'H'"); _dbus_assert (i == 0); if (!_dbus_string_find (&str, 0, "", &i)) _dbus_assert_not_reached ("didn't find ''"); _dbus_assert (i == 0); if (_dbus_string_find (&str, 0, "Hello!", NULL)) _dbus_assert_not_reached ("Did find 'Hello!'"); if (_dbus_string_find (&str, 0, "Oh, Hello", NULL)) _dbus_assert_not_reached ("Did find 'Oh, Hello'"); if (_dbus_string_find (&str, 0, "ill", NULL)) _dbus_assert_not_reached ("Did find 'ill'"); if (_dbus_string_find (&str, 0, "q", NULL)) _dbus_assert_not_reached ("Did find 'q'"); if (!_dbus_string_find_to (&str, 0, 2, "He", NULL)) _dbus_assert_not_reached ("Didn't find 'He'"); if (_dbus_string_find_to (&str, 0, 2, "Hello", NULL)) _dbus_assert_not_reached ("Did find 'Hello'"); if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'H', &i)) _dbus_assert_not_reached ("Did not find 'H'"); _dbus_assert (i == 0); if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'o', &i)) _dbus_assert_not_reached ("Did not find 'o'"); _dbus_assert (i == _dbus_string_get_length (&str) - 1); if (_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str) - 1, 'o', &i)) _dbus_assert_not_reached ("Did find 'o'"); _dbus_assert (i == -1); if (_dbus_string_find_byte_backward (&str, 1, 'e', &i)) _dbus_assert_not_reached ("Did find 'e'"); _dbus_assert (i == -1); if (!_dbus_string_find_byte_backward (&str, 2, 'e', &i)) _dbus_assert_not_reached ("Didn't find 'e'"); _dbus_assert (i == 1); _dbus_string_free (&str); /* Hex encoding */ _dbus_string_init_const (&str, "cafebabe, this is a bogus hex string"); if (!_dbus_string_init (&other)) _dbus_assert_not_reached ("could not init string"); if (!_dbus_string_hex_decode (&str, 0, &end, &other, 0)) _dbus_assert_not_reached ("deccoded bogus hex string with no error"); _dbus_assert (end == 8); _dbus_string_free (&other); test_roundtrips (test_hex_roundtrip); _dbus_string_free (&str); { int found, found_len; _dbus_string_init_const (&str, "012\r\n567\n90"); if (!_dbus_string_find_eol (&str, 0, &found, &found_len) || found != 3 || found_len != 2) _dbus_assert_not_reached ("Did not find '\\r\\n'"); if (found != 3 || found_len != 2) _dbus_assert_not_reached ("invalid return values"); if (!_dbus_string_find_eol (&str, 5, &found, &found_len)) _dbus_assert_not_reached ("Did not find '\\n'"); if (found != 8 || found_len != 1) _dbus_assert_not_reached ("invalid return values"); if (_dbus_string_find_eol (&str, 9, &found, &found_len)) _dbus_assert_not_reached ("Found not expected '\\n'"); else if (found != 11 || found_len != 0) _dbus_assert_not_reached ("invalid return values '\\n'"); found = -1; found_len = -1; _dbus_string_init_const (&str, ""); if (_dbus_string_find_eol (&str, 0, &found, &found_len)) _dbus_assert_not_reached ("found an eol in an empty string"); _dbus_assert (found == 0); _dbus_assert (found_len == 0); found = -1; found_len = -1; _dbus_string_init_const (&str, "foobar"); if (_dbus_string_find_eol (&str, 0, &found, &found_len)) _dbus_assert_not_reached ("found eol in string that lacks one"); _dbus_assert (found == 6); _dbus_assert (found_len == 0); found = -1; found_len = -1; _dbus_string_init_const (&str, "foobar\n"); if (!_dbus_string_find_eol (&str, 0, &found, &found_len)) _dbus_assert_not_reached ("did not find eol in string that has one at end"); _dbus_assert (found == 6); _dbus_assert (found_len == 1); } { DBusString line; #define FIRST_LINE "this is a line" #define SECOND_LINE "this is a second line" /* third line is empty */ #define THIRD_LINE "" #define FOURTH_LINE "this is a fourth line" if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_append (&str, FIRST_LINE "\n" SECOND_LINE "\r\n" THIRD_LINE "\n" FOURTH_LINE)) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_init (&line)) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_pop_line (&str, &line)) _dbus_assert_not_reached ("failed to pop first line"); _dbus_assert (_dbus_string_equal_c_str (&line, FIRST_LINE)); if (!_dbus_string_pop_line (&str, &line)) _dbus_assert_not_reached ("failed to pop second line"); _dbus_assert (_dbus_string_equal_c_str (&line, SECOND_LINE)); if (!_dbus_string_pop_line (&str, &line)) _dbus_assert_not_reached ("failed to pop third line"); _dbus_assert (_dbus_string_equal_c_str (&line, THIRD_LINE)); if (!_dbus_string_pop_line (&str, &line)) _dbus_assert_not_reached ("failed to pop fourth line"); _dbus_assert (_dbus_string_equal_c_str (&line, FOURTH_LINE)); _dbus_string_free (&str); _dbus_string_free (&line); } { if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("no memory"); for (i = 0; i < 10000; i++) if (!_dbus_string_append (&str, "abcdefghijklmnopqrstuvwxyz")) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_set_length (&str, 10)) _dbus_assert_not_reached ("failed to set length"); /* actually compact */ if (!_dbus_string_compact (&str, 2048)) _dbus_assert_not_reached ("failed to compact after set_length"); /* peek inside to make sure it worked */ if (((DBusRealString *)&str)->allocated > 30) _dbus_assert_not_reached ("compacting string didn't do anything"); if (!_dbus_string_equal_c_str (&str, "abcdefghij")) _dbus_assert_not_reached ("unexpected content after compact"); /* compact nothing */ if (!_dbus_string_compact (&str, 2048)) _dbus_assert_not_reached ("failed to compact 2nd time"); if (!_dbus_string_equal_c_str (&str, "abcdefghij")) _dbus_assert_not_reached ("unexpected content after 2nd compact"); /* and make sure it still works...*/ if (!_dbus_string_append (&str, "123456")) _dbus_assert_not_reached ("failed to append after compact"); if (!_dbus_string_equal_c_str (&str, "abcdefghij123456")) _dbus_assert_not_reached ("unexpected content after append"); /* after growing automatically, this should do nothing */ if (!_dbus_string_compact (&str, 20000)) _dbus_assert_not_reached ("failed to compact after grow"); /* but this one will do something */ if (!_dbus_string_compact (&str, 0)) _dbus_assert_not_reached ("failed to compact after grow"); if (!_dbus_string_equal_c_str (&str, "abcdefghij123456")) _dbus_assert_not_reached ("unexpected content"); if (!_dbus_string_append (&str, "!@#$%")) _dbus_assert_not_reached ("failed to append after compact"); if (!_dbus_string_equal_c_str (&str, "abcdefghij123456!@#$%")) _dbus_assert_not_reached ("unexpected content"); _dbus_string_free (&str); } { const char two_strings[] = "one\ttwo"; if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_init (&other)) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_append (&str, two_strings)) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_split_on_byte (&str, '\t', &other)) _dbus_assert_not_reached ("no memory or delimiter not found"); if (strcmp (_dbus_string_get_data (&str), "one") != 0) _dbus_assert_not_reached ("left side after split on tab is wrong"); if (strcmp (_dbus_string_get_data (&other), "two") != 0) _dbus_assert_not_reached ("right side after split on tab is wrong"); _dbus_string_free (&str); _dbus_string_free (&other); } { const char upper_string[] = "TOUPPERSTRING"; const char lower_string[] = "toupperstring"; const char lower2_string[] = "toupperSTRING"; if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_append (&str, upper_string)) _dbus_assert_not_reached ("no memory"); _dbus_string_tolower_ascii (&str, 0, _dbus_string_get_length(&str)); if (!_dbus_string_equal_c_str (&str, lower_string)) _dbus_assert_not_reached ("_dbus_string_tolower_ascii failed"); _dbus_string_free (&str); if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_append (&str, upper_string)) _dbus_assert_not_reached ("no memory"); _dbus_string_tolower_ascii (&str, 0, 7); if (!_dbus_string_equal_c_str (&str, lower2_string)) _dbus_assert_not_reached ("_dbus_string_tolower_ascii failed in partial conversion"); _dbus_string_free (&str); } { const char lower_string[] = "toupperstring"; const char upper_string[] = "TOUPPERSTRING"; const char upper2_string[] = "TOUPPERstring"; if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_append (&str, lower_string)) _dbus_assert_not_reached ("no memory"); _dbus_string_toupper_ascii (&str, 0, _dbus_string_get_length(&str)); if (!_dbus_string_equal_c_str (&str, upper_string)) _dbus_assert_not_reached ("_dbus_string_toupper_ascii failed"); _dbus_string_free (&str); if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_append (&str, lower_string)) _dbus_assert_not_reached ("no memory"); _dbus_string_toupper_ascii (&str, 0, 7); if (!_dbus_string_equal_c_str (&str, upper2_string)) _dbus_assert_not_reached ("_dbus_string_toupper_ascii failed in partial conversion"); _dbus_string_free (&str); } return TRUE; }
/** * Decrement the reference count on the babysitter object. * When the reference count of the babysitter object reaches * zero, the babysitter is killed and the child that was being * babysat gets emancipated. * * @param sitter the babysitter */ void _dbus_babysitter_unref (DBusBabysitter *sitter) { _dbus_assert (sitter != NULL); _dbus_assert (sitter->refcount > 0); sitter->refcount -= 1; if (sitter->refcount == 0) { /* If we haven't forked other babysitters * since this babysitter and socket were * created then this close will cause the * babysitter to wake up from poll with * a hangup and then the babysitter will * quit itself. */ close_socket_to_babysitter (sitter); close_error_pipe_from_child (sitter); if (sitter->sitter_pid > 0) { int status; int ret; /* It's possible the babysitter died on its own above * from the close, or was killed randomly * by some other process, so first try to reap it */ ret = waitpid (sitter->sitter_pid, &status, WNOHANG); /* If we couldn't reap the child then kill it, and * try again */ if (ret == 0) kill (sitter->sitter_pid, SIGKILL); if (ret == 0) { do { ret = waitpid (sitter->sitter_pid, &status, 0); } while (_DBUS_UNLIKELY (ret < 0 && errno == EINTR)); } if (ret < 0) { if (errno == ECHILD) _dbus_warn ("Babysitter process not available to be reaped; should not happen\n"); else _dbus_warn ("Unexpected error %d in waitpid() for babysitter: %s\n", errno, _dbus_strerror (errno)); } else { _dbus_verbose ("Reaped %ld, waiting for babysitter %ld\n", (long) ret, (long) sitter->sitter_pid); if (WIFEXITED (sitter->status)) _dbus_verbose ("Babysitter exited with status %d\n", WEXITSTATUS (sitter->status)); else if (WIFSIGNALED (sitter->status)) _dbus_verbose ("Babysitter received signal %d\n", WTERMSIG (sitter->status)); else _dbus_verbose ("Babysitter exited abnormally\n"); } sitter->sitter_pid = -1; } if (sitter->watches) _dbus_watch_list_free (sitter->watches); dbus_free (sitter->log_name); dbus_free (sitter); } }
void _dbus_trace_ref (const char *obj_name, void *obj, int old_refcount, int new_refcount, const char *why, const char *env_var, int *enabled) { _dbus_assert (obj_name != NULL); _dbus_assert (obj != NULL); _dbus_assert (old_refcount >= -1); _dbus_assert (new_refcount >= -1); if (old_refcount == -1) { _dbus_assert (new_refcount == -1); } else { _dbus_assert (new_refcount >= 0); _dbus_assert (old_refcount >= 0); _dbus_assert (old_refcount > 0 || new_refcount > 0); } _dbus_assert (why != NULL); _dbus_assert (env_var != NULL); _dbus_assert (enabled != NULL); if (*enabled < 0) { const char *s = _dbus_getenv (env_var); *enabled = FALSE; if (s && *s) { if (*s == '0') *enabled = FALSE; else if (*s == '1') *enabled = TRUE; else _dbus_warn ("%s should be 0 or 1 if set, not '%s'", env_var, s); } } if (*enabled) { if (old_refcount == -1) { VALGRIND_PRINTF_BACKTRACE ("%s %p ref stolen (%s)", obj_name, obj, why); _dbus_verbose ("%s %p ref stolen (%s)\n", obj_name, obj, why); } else { VALGRIND_PRINTF_BACKTRACE ("%s %p %d -> %d refs (%s)", obj_name, obj, old_refcount, new_refcount, why); _dbus_verbose ("%s %p %d -> %d refs (%s)\n", obj_name, obj, old_refcount, new_refcount, why); } } }
/* Calls strtod in a locale-independent fashion, by looking at * the locale data and patching the decimal comma to a point. * * Relicensed from glib. */ static double ascii_strtod (const char *nptr, char **endptr) { /* FIXME: The Win32 C library's strtod() doesn't handle hex. * Presumably many Unixes don't either. */ char *fail_pos; double val; struct lconv *locale_data; const char *decimal_point; int decimal_point_len; const char *p, *decimal_point_pos; const char *end = NULL; /* Silence gcc */ fail_pos = NULL; locale_data = localeconv (); decimal_point = locale_data->decimal_point; decimal_point_len = strlen (decimal_point); _dbus_assert (decimal_point_len != 0); decimal_point_pos = NULL; if (decimal_point[0] != '.' || decimal_point[1] != 0) { p = nptr; /* Skip leading space */ while (ascii_isspace (*p)) p++; /* Skip leading optional sign */ if (*p == '+' || *p == '-') p++; if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { p += 2; /* HEX - find the (optional) decimal point */ while (ascii_isxdigit (*p)) p++; if (*p == '.') { decimal_point_pos = p++; while (ascii_isxdigit (*p)) p++; if (*p == 'p' || *p == 'P') p++; if (*p == '+' || *p == '-') p++; while (ascii_isdigit (*p)) p++; end = p; } } else { while (ascii_isdigit (*p)) p++; if (*p == '.') { decimal_point_pos = p++; while (ascii_isdigit (*p)) p++; if (*p == 'e' || *p == 'E') p++; if (*p == '+' || *p == '-') p++; while (ascii_isdigit (*p)) p++; end = p; } } /* For the other cases, we need not convert the decimal point */ } /* Set errno to zero, so that we can distinguish zero results and underflows */ errno = 0; if (decimal_point_pos) { char *copy, *c; /* We need to convert the '.' to the locale specific decimal point */ copy = dbus_malloc (end - nptr + 1 + decimal_point_len); c = copy; memcpy (c, nptr, decimal_point_pos - nptr); c += decimal_point_pos - nptr; memcpy (c, decimal_point, decimal_point_len); c += decimal_point_len; memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1)); c += end - (decimal_point_pos + 1); *c = 0; val = strtod (copy, &fail_pos); if (fail_pos) { if (fail_pos > decimal_point_pos) fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1); else fail_pos = (char *)nptr + (fail_pos - copy); } dbus_free (copy); } else val = strtod (nptr, &fail_pos); if (endptr) *endptr = fail_pos; return val; }
BusClientPolicy* bus_policy_create_client_policy (BusPolicy *policy, DBusConnection *connection, DBusError *error) { BusClientPolicy *client; dbus_uid_t uid; dbus_bool_t at_console; _dbus_assert (dbus_connection_get_is_authenticated (connection)); _DBUS_ASSERT_ERROR_IS_CLEAR (error); client = bus_client_policy_new (); if (client == NULL) goto nomem; if (!add_list_to_client (&policy->default_rules, client)) goto nomem; /* we avoid the overhead of looking up user's groups * if we don't have any group rules anyway */ if (_dbus_hash_table_get_n_entries (policy->rules_by_gid) > 0) { unsigned long *groups; int n_groups; int i; if (!bus_connection_get_groups (connection, &groups, &n_groups, error)) goto failed; i = 0; while (i < n_groups) { DBusList **list; list = _dbus_hash_table_lookup_ulong (policy->rules_by_gid, groups[i]); if (list != NULL) { if (!add_list_to_client (list, client)) { dbus_free (groups); goto nomem; } } ++i; } dbus_free (groups); } if (!dbus_connection_get_unix_user (connection, &uid)) { dbus_set_error (error, DBUS_ERROR_FAILED, "No user ID known for connection, cannot determine security policy\n"); goto failed; } if (_dbus_hash_table_get_n_entries (policy->rules_by_uid) > 0) { DBusList **list; list = _dbus_hash_table_lookup_ulong (policy->rules_by_uid, uid); if (list != NULL) { if (!add_list_to_client (list, client)) goto nomem; } } /* Add console rules */ at_console = _dbus_is_console_user (uid, error); if (at_console) { if (!add_list_to_client (&policy->at_console_true_rules, client)) goto nomem; } else if (dbus_error_is_set (error) == TRUE) { goto failed; } else if (!add_list_to_client (&policy->at_console_false_rules, client)) { goto nomem; } if (!add_list_to_client (&policy->mandatory_rules, client)) goto nomem; bus_client_policy_optimize (client); return client; nomem: BUS_SET_OOM (error); failed: _DBUS_ASSERT_ERROR_IS_SET (error); if (client) bus_client_policy_unref (client); return NULL; }