mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-05-08 14:58:04 +02:00
Merge branch 'win32-uds' into 'master'
Add Unix socket support on Windows See merge request dbus/dbus!249
This commit is contained in:
commit
b3163746a9
36 changed files with 1047 additions and 617 deletions
|
|
@ -5181,9 +5181,9 @@ bus_unix_fds_passing_test (const char *test_data_dir_cstr)
|
|||
DBUS_TYPE_INVALID))
|
||||
_dbus_test_fatal ("Failed to attach fds.");
|
||||
|
||||
if (!_dbus_close_socket (one[0], &error))
|
||||
if (!_dbus_close_socket (&one[0], &error))
|
||||
_dbus_test_fatal ("Failed to close pipe #1 ");
|
||||
if (!_dbus_close_socket (two[0], &error))
|
||||
if (!_dbus_close_socket (&two[0], &error))
|
||||
_dbus_test_fatal ("Failed to close pipe #2 ");
|
||||
|
||||
if (!(dbus_connection_can_send_type(foo, DBUS_TYPE_UNIX_FD)))
|
||||
|
|
@ -5250,9 +5250,9 @@ bus_unix_fds_passing_test (const char *test_data_dir_cstr)
|
|||
if (read(two[1].fd, &r, 1) != 1 || r != 'Z')
|
||||
_dbus_test_fatal ("Failed to read value from pipe.");
|
||||
|
||||
if (!_dbus_close_socket (one[1], &error))
|
||||
if (!_dbus_close_socket (&one[1], &error))
|
||||
_dbus_test_fatal ("Failed to close pipe #1 ");
|
||||
if (!_dbus_close_socket (two[1], &error))
|
||||
if (!_dbus_close_socket (&two[1], &error))
|
||||
_dbus_test_fatal ("Failed to close pipe #2 ");
|
||||
|
||||
_dbus_verbose ("Disconnecting foo\n");
|
||||
|
|
|
|||
|
|
@ -387,11 +387,8 @@ close_reload_pipe (DBusWatch **watch)
|
|||
_dbus_watch_unref (*watch);
|
||||
*watch = NULL;
|
||||
|
||||
_dbus_close_socket (reload_pipe[RELOAD_READ_END], NULL);
|
||||
_dbus_socket_invalidate (&reload_pipe[RELOAD_READ_END]);
|
||||
|
||||
_dbus_close_socket (reload_pipe[RELOAD_WRITE_END], NULL);
|
||||
_dbus_socket_invalidate (&reload_pipe[RELOAD_WRITE_END]);
|
||||
_dbus_close_socket (&reload_pipe[RELOAD_READ_END], NULL);
|
||||
_dbus_close_socket (&reload_pipe[RELOAD_WRITE_END], NULL);
|
||||
}
|
||||
#endif /* DBUS_UNIX */
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ include(CheckTypeSize)
|
|||
include(CheckCSourceCompiles)
|
||||
include(CheckCSourceRuns)
|
||||
|
||||
check_include_files("winsock2.h;afunix.h" HAVE_AFUNIX_H)
|
||||
check_include_file(alloca.h HAVE_ALLOCA_H)
|
||||
check_include_file(byteswap.h HAVE_BYTESWAP_H)
|
||||
check_include_file(crt/externs.h HAVE_CRT_EXTERNS_H)
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@
|
|||
#cmakedefine GLIB_VERSION_MAX_ALLOWED @GLIB_VERSION_MAX_ALLOWED@
|
||||
|
||||
// headers
|
||||
#cmakedefine HAVE_AFUNIX_H 1
|
||||
#cmakedefine HAVE_ALLOCA_H 1
|
||||
#cmakedefine HAVE_BYTESWAP_H 1
|
||||
#cmakedefine HAVE_CRT_EXTERNS_H 1
|
||||
|
|
|
|||
|
|
@ -430,6 +430,7 @@ sys/syscall.h
|
|||
sys/syslimits.h
|
||||
sys/time.h
|
||||
unistd.h
|
||||
winsock2.h
|
||||
ws2tcpip.h
|
||||
])
|
||||
|
||||
|
|
@ -1052,6 +1053,13 @@ if test x$dbus_win = xyes ; then
|
|||
fi
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADERS([afunix.h], [], [],
|
||||
[AC_INCLUDES_DEFAULT[
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
# include <winsock2.h>
|
||||
#endif
|
||||
]])
|
||||
|
||||
AC_SUBST([NETWORK_libs])
|
||||
|
||||
AC_ARG_WITH([valgrind],
|
||||
|
|
|
|||
|
|
@ -89,7 +89,6 @@ set(DBUS_LIB_HEADERS
|
|||
dbus-resources.h
|
||||
dbus-server-debug-pipe.h
|
||||
dbus-server-protected.h
|
||||
dbus-server-unix.h
|
||||
dbus-sha.h
|
||||
dbus-timeout.h
|
||||
dbus-threads.h
|
||||
|
|
@ -209,7 +208,6 @@ else(WIN32)
|
|||
dbus-userdb.c
|
||||
)
|
||||
set(DBUS_SHARED_HEADERS ${DBUS_SHARED_HEADERS}
|
||||
dbus-server-unix.h
|
||||
dbus-transport-unix.h
|
||||
dbus-sysdeps-unix.h
|
||||
dbus-userdb.h
|
||||
|
|
|
|||
|
|
@ -102,8 +102,7 @@ endif
|
|||
DBUS_LIB_arch_sources = \
|
||||
dbus-uuidgen.c \
|
||||
dbus-uuidgen.h \
|
||||
dbus-server-unix.c \
|
||||
dbus-server-unix.h
|
||||
dbus-server-unix.c
|
||||
|
||||
DBUS_SHARED_arch_sources = \
|
||||
$(launchd_source) \
|
||||
|
|
|
|||
|
|
@ -334,18 +334,7 @@ _dbus_verbose_init (void)
|
|||
}
|
||||
}
|
||||
|
||||
/** @def DBUS_IS_DIR_SEPARATOR(c)
|
||||
* macro for checking if character c is a patch separator
|
||||
*
|
||||
* @todo move to a header file so that others can use this too
|
||||
*/
|
||||
#ifdef DBUS_WIN
|
||||
#define DBUS_IS_DIR_SEPARATOR(c) (c == '\\' || c == '/')
|
||||
#else
|
||||
#define DBUS_IS_DIR_SEPARATOR(c) (c == '/')
|
||||
#endif
|
||||
|
||||
/**
|
||||
/**
|
||||
remove source root from file path
|
||||
the source root is determined by
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -488,6 +488,19 @@ dbus_bool_t _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str,
|
|||
# define _DBUS_END_IGNORE_LEAKS do { } while (0)
|
||||
#endif
|
||||
|
||||
/** @def DBUS_IS_DIR_SEPARATOR(c)
|
||||
* macro for checking if character c is a path separator
|
||||
*/
|
||||
#ifdef DBUS_WIN
|
||||
#define DBUS_IS_DIR_SEPARATOR(c) (c == '\\' || c == '/')
|
||||
#define DBUS_DIR_SEPARATOR '\\'
|
||||
#define DBUS_DIR_SEPARATOR_S "\\"
|
||||
#else
|
||||
#define DBUS_IS_DIR_SEPARATOR(c) (c == '/')
|
||||
#define DBUS_DIR_SEPARATOR '/'
|
||||
#define DBUS_DIR_SEPARATOR_S "/"
|
||||
#endif
|
||||
|
||||
DBUS_END_DECLS
|
||||
|
||||
#endif /* DBUS_INTERNALS_H */
|
||||
|
|
|
|||
|
|
@ -194,8 +194,7 @@ _dbus_accept_with_noncefile (DBusSocket listen_fd, const DBusNonceFile *noncefil
|
|||
|
||||
if (do_check_nonce(fd, &nonce, NULL) != TRUE) {
|
||||
_dbus_verbose ("nonce check failed. Closing socket.\n");
|
||||
_dbus_close_socket(fd, NULL);
|
||||
_dbus_socket_invalidate (&fd);
|
||||
_dbus_close_socket (&fd, NULL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -260,8 +260,8 @@ _dbus_transport_debug_pipe_new (const char *server_name,
|
|||
NULL, &address);
|
||||
if (client_transport == NULL)
|
||||
{
|
||||
_dbus_close_socket (client_fd, NULL);
|
||||
_dbus_close_socket (server_fd, NULL);
|
||||
_dbus_close_socket (&client_fd, NULL);
|
||||
_dbus_close_socket (&server_fd, NULL);
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
_dbus_string_free (&address);
|
||||
return NULL;
|
||||
|
|
@ -276,7 +276,7 @@ _dbus_transport_debug_pipe_new (const char *server_name,
|
|||
if (server_transport == NULL)
|
||||
{
|
||||
_dbus_transport_unref (client_transport);
|
||||
_dbus_close_socket (server_fd, NULL);
|
||||
_dbus_close_socket (&server_fd, NULL);
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,6 +126,10 @@ typedef enum
|
|||
DBUS_SERVER_LISTEN_ADDRESS_ALREADY_USED /**< address is already used */
|
||||
} DBusServerListenResult;
|
||||
|
||||
DBusServerListenResult _dbus_server_listen_unix_socket (DBusAddressEntry *entry,
|
||||
DBusServer **server_p,
|
||||
DBusError *error);
|
||||
|
||||
DBusServerListenResult _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
|
||||
DBusServer **server_p,
|
||||
DBusError *error);
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ handle_new_client_fd_and_unlock (DBusServer *server,
|
|||
transport = _dbus_transport_new_for_socket (client_fd, &server->guid_hex, NULL);
|
||||
if (transport == NULL)
|
||||
{
|
||||
_dbus_close_socket (client_fd, NULL);
|
||||
_dbus_close_socket (&client_fd, NULL);
|
||||
SERVER_UNLOCK (server);
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -242,10 +242,7 @@ socket_disconnect (DBusServer *server)
|
|||
}
|
||||
|
||||
if (_dbus_socket_is_valid (socket_server->fds[i]))
|
||||
{
|
||||
_dbus_close_socket (socket_server->fds[i], NULL);
|
||||
_dbus_socket_invalidate (&socket_server->fds[i]);
|
||||
}
|
||||
_dbus_close_socket (&socket_server->fds[i], NULL);
|
||||
}
|
||||
|
||||
if (socket_server->socket_name != NULL)
|
||||
|
|
@ -513,7 +510,7 @@ failed:
|
|||
if (listen_fds != NULL)
|
||||
{
|
||||
for (i = 0; i < nlisten_fds; i++)
|
||||
_dbus_close_socket (listen_fds[i], NULL);
|
||||
_dbus_close_socket (&listen_fds[i], NULL);
|
||||
dbus_free (listen_fds);
|
||||
}
|
||||
|
||||
|
|
@ -596,5 +593,298 @@ _dbus_server_socket_own_filename (DBusServer *server,
|
|||
socket_server->socket_name = filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new server listening on the given Unix domain socket.
|
||||
*
|
||||
* @param path the path for the domain socket.
|
||||
* @param abstract #TRUE to use abstract socket namespace
|
||||
* @param error location to store reason for failure.
|
||||
* @returns the new server, or #NULL on failure.
|
||||
*/
|
||||
DBusServer*
|
||||
_dbus_server_new_for_domain_socket (const char *path,
|
||||
dbus_bool_t abstract,
|
||||
DBusError *error)
|
||||
{
|
||||
DBusServer *server;
|
||||
DBusSocket listen_fd;
|
||||
DBusString address;
|
||||
char *path_copy;
|
||||
DBusString path_str;
|
||||
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||
|
||||
if (!_dbus_string_init (&address))
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_dbus_string_init_const (&path_str, path);
|
||||
if ((abstract &&
|
||||
!_dbus_string_append (&address, "unix:abstract=")) ||
|
||||
(!abstract &&
|
||||
!_dbus_string_append (&address, "unix:path=")) ||
|
||||
!_dbus_address_append_escaped (&address, &path_str))
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
goto failed_0;
|
||||
}
|
||||
|
||||
if (abstract)
|
||||
{
|
||||
path_copy = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
path_copy = _dbus_strdup (path);
|
||||
if (path_copy == NULL)
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
goto failed_0;
|
||||
}
|
||||
}
|
||||
|
||||
listen_fd = _dbus_listen_unix_socket (path, abstract, error);
|
||||
|
||||
if (!_dbus_socket_is_valid (listen_fd))
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET (error);
|
||||
goto failed_1;
|
||||
}
|
||||
|
||||
server = _dbus_server_new_for_socket (&listen_fd, 1, &address, 0, error);
|
||||
if (server == NULL)
|
||||
{
|
||||
goto failed_2;
|
||||
}
|
||||
|
||||
if (path_copy != NULL)
|
||||
_dbus_server_socket_own_filename(server, path_copy);
|
||||
|
||||
_dbus_string_free (&address);
|
||||
|
||||
return server;
|
||||
|
||||
failed_2:
|
||||
_dbus_close_socket (&listen_fd, NULL);
|
||||
failed_1:
|
||||
dbus_free (path_copy);
|
||||
failed_0:
|
||||
_dbus_string_free (&address);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Unix domain socket server listening under the given directory.
|
||||
* This function is used for "unix:dir/tmpdir" kind of addresses.
|
||||
*
|
||||
* @param dir the path to a directory.
|
||||
* @param abstract #TRUE to use abstract socket namespace
|
||||
* @param error location to store reason for failure.
|
||||
* @returns the new server, or #NULL on failure.
|
||||
*/
|
||||
DBusServer *
|
||||
_dbus_server_new_for_dir (const char *dir,
|
||||
dbus_bool_t use_abstract,
|
||||
DBusError *error)
|
||||
{
|
||||
DBusServer *server;
|
||||
DBusString full_path;
|
||||
DBusString filename;
|
||||
|
||||
if (!_dbus_string_init (&full_path))
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_dbus_string_init (&filename))
|
||||
{
|
||||
_dbus_string_free (&full_path);
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_dbus_string_append (&filename, "dbus-"))
|
||||
{
|
||||
_dbus_string_free (&full_path);
|
||||
_dbus_string_free (&filename);
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_dbus_generate_random_ascii (&filename, 10, error))
|
||||
{
|
||||
_dbus_string_free (&full_path);
|
||||
_dbus_string_free (&filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_dbus_string_append (&full_path, dir) ||
|
||||
!_dbus_concat_dir_and_file (&full_path, &filename))
|
||||
{
|
||||
_dbus_string_free (&full_path);
|
||||
_dbus_string_free (&filename);
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
server =
|
||||
_dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path),
|
||||
use_abstract,
|
||||
error);
|
||||
|
||||
_dbus_string_free (&full_path);
|
||||
_dbus_string_free (&filename);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to interpret the address entry for UNIX socket
|
||||
* addresses.
|
||||
*
|
||||
* Sets error if the result is not OK.
|
||||
*
|
||||
* @param entry an address entry
|
||||
* @param server_p location to store a new DBusServer, or #NULL on failure.
|
||||
* @param error location to store rationale for failure on bad address
|
||||
* @returns the outcome
|
||||
*
|
||||
*/
|
||||
DBusServerListenResult
|
||||
_dbus_server_listen_unix_socket (DBusAddressEntry *entry,
|
||||
DBusServer **server_p,
|
||||
DBusError *error)
|
||||
{
|
||||
const char *method;
|
||||
|
||||
*server_p = NULL;
|
||||
|
||||
method = dbus_address_entry_get_method (entry);
|
||||
|
||||
if (strcmp (method, "unix") == 0)
|
||||
{
|
||||
const char *path = dbus_address_entry_get_value (entry, "path");
|
||||
const char *dir = dbus_address_entry_get_value (entry, "dir");
|
||||
const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir");
|
||||
const char *abstract = dbus_address_entry_get_value (entry, "abstract");
|
||||
const char *runtime = dbus_address_entry_get_value (entry, "runtime");
|
||||
int mutually_exclusive_modes = 0;
|
||||
|
||||
mutually_exclusive_modes = (path != NULL) + (tmpdir != NULL) +
|
||||
(abstract != NULL) + (runtime != NULL) + (dir != NULL);
|
||||
|
||||
if (mutually_exclusive_modes < 1)
|
||||
{
|
||||
_dbus_set_bad_address(error, "unix",
|
||||
"path or tmpdir or abstract or runtime or dir",
|
||||
NULL);
|
||||
return DBUS_SERVER_LISTEN_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
if (mutually_exclusive_modes > 1)
|
||||
{
|
||||
_dbus_set_bad_address(error, NULL, NULL,
|
||||
"cannot specify two of \"path\", \"tmpdir\", \"abstract\", \"runtime\" and \"dir\" at the same time");
|
||||
return DBUS_SERVER_LISTEN_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
if (runtime != NULL)
|
||||
{
|
||||
DBusString full_path;
|
||||
DBusString filename;
|
||||
const char *runtimedir;
|
||||
|
||||
if (strcmp (runtime, "yes") != 0)
|
||||
{
|
||||
_dbus_set_bad_address(error, NULL, NULL,
|
||||
"if given, the only value allowed for \"runtime\" is \"yes\"");
|
||||
return DBUS_SERVER_LISTEN_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
runtimedir = _dbus_getenv ("XDG_RUNTIME_DIR");
|
||||
|
||||
if (runtimedir == NULL)
|
||||
{
|
||||
dbus_set_error (error,
|
||||
DBUS_ERROR_NOT_SUPPORTED, "\"XDG_RUNTIME_DIR\" is not set");
|
||||
return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
|
||||
}
|
||||
|
||||
_dbus_string_init_const (&filename, "bus");
|
||||
|
||||
if (!_dbus_string_init (&full_path))
|
||||
{
|
||||
_DBUS_SET_OOM (error);
|
||||
return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
|
||||
}
|
||||
|
||||
if (!_dbus_string_append (&full_path, runtimedir) ||
|
||||
!_dbus_concat_dir_and_file (&full_path, &filename))
|
||||
{
|
||||
_dbus_string_free (&full_path);
|
||||
_DBUS_SET_OOM (error);
|
||||
return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
|
||||
}
|
||||
|
||||
/* We can safely use filesystem sockets in the runtime directory,
|
||||
* and they are preferred because they can be bind-mounted between
|
||||
* Linux containers. */
|
||||
*server_p = _dbus_server_new_for_domain_socket (
|
||||
_dbus_string_get_const_data (&full_path),
|
||||
FALSE, error);
|
||||
|
||||
_dbus_string_free (&full_path);
|
||||
}
|
||||
else if (tmpdir != NULL || dir != NULL)
|
||||
{
|
||||
dbus_bool_t use_abstract = FALSE;
|
||||
|
||||
if (tmpdir != NULL)
|
||||
{
|
||||
dir = tmpdir;
|
||||
|
||||
#ifdef __linux__
|
||||
/* Use abstract sockets for tmpdir if supported, so that it
|
||||
* never needs to be cleaned up. Use dir instead if you want a
|
||||
* path-based socket. */
|
||||
use_abstract = TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
*server_p = _dbus_server_new_for_dir (dir, use_abstract, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (path)
|
||||
*server_p = _dbus_server_new_for_domain_socket (path, FALSE, error);
|
||||
else
|
||||
*server_p = _dbus_server_new_for_domain_socket (abstract, TRUE, error);
|
||||
}
|
||||
|
||||
if (*server_p != NULL)
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR(error);
|
||||
return DBUS_SERVER_LISTEN_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET(error);
|
||||
return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If we don't handle the method, we return NULL with the
|
||||
* error unset
|
||||
*/
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR(error);
|
||||
return DBUS_SERVER_LISTEN_NOT_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @} */
|
||||
|
|
|
|||
|
|
@ -43,6 +43,9 @@ DBusServer* _dbus_server_new_for_tcp_socket (const char *host,
|
|||
const char *family,
|
||||
DBusError *error,
|
||||
dbus_bool_t use_nonce);
|
||||
DBusServer* _dbus_server_new_for_dir (const char *dir,
|
||||
dbus_bool_t use_abstract,
|
||||
DBusError *error);
|
||||
DBusServerListenResult _dbus_server_listen_socket (DBusAddressEntry *entry,
|
||||
DBusServer **server_p,
|
||||
DBusError *error);
|
||||
|
|
@ -51,6 +54,9 @@ DBusServerListenResult _dbus_server_listen_socket (DBusAddressEntry *entry,
|
|||
void _dbus_server_socket_own_filename (DBusServer *server,
|
||||
char *filename);
|
||||
|
||||
DBusServer* _dbus_server_new_for_domain_socket (const char *path,
|
||||
dbus_bool_t abstract,
|
||||
DBusError *error);
|
||||
DBUS_END_DECLS
|
||||
|
||||
#endif /* DBUS_SERVER_SOCKET_H */
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
#include <config.h>
|
||||
#include "dbus-internals.h"
|
||||
#include "dbus-server-unix.h"
|
||||
#include "dbus-server-socket.h"
|
||||
#include "dbus-server-launchd.h"
|
||||
#include "dbus-transport-unix.h"
|
||||
|
|
@ -60,164 +59,7 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
|
|||
*server_p = NULL;
|
||||
|
||||
method = dbus_address_entry_get_method (entry);
|
||||
|
||||
if (strcmp (method, "unix") == 0)
|
||||
{
|
||||
const char *path = dbus_address_entry_get_value (entry, "path");
|
||||
const char *dir = dbus_address_entry_get_value (entry, "dir");
|
||||
const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir");
|
||||
const char *abstract = dbus_address_entry_get_value (entry, "abstract");
|
||||
const char *runtime = dbus_address_entry_get_value (entry, "runtime");
|
||||
int mutually_exclusive_modes = 0;
|
||||
|
||||
mutually_exclusive_modes = (path != NULL) + (tmpdir != NULL) +
|
||||
(abstract != NULL) + (runtime != NULL) + (dir != NULL);
|
||||
|
||||
if (mutually_exclusive_modes < 1)
|
||||
{
|
||||
_dbus_set_bad_address(error, "unix",
|
||||
"path or tmpdir or abstract or runtime or dir",
|
||||
NULL);
|
||||
return DBUS_SERVER_LISTEN_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
if (mutually_exclusive_modes > 1)
|
||||
{
|
||||
_dbus_set_bad_address(error, NULL, NULL,
|
||||
"cannot specify two of \"path\", \"tmpdir\", \"abstract\", \"runtime\" and \"dir\" at the same time");
|
||||
return DBUS_SERVER_LISTEN_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
if (runtime != NULL)
|
||||
{
|
||||
DBusString full_path;
|
||||
DBusString filename;
|
||||
const char *runtimedir;
|
||||
|
||||
if (strcmp (runtime, "yes") != 0)
|
||||
{
|
||||
_dbus_set_bad_address(error, NULL, NULL,
|
||||
"if given, the only value allowed for \"runtime\" is \"yes\"");
|
||||
return DBUS_SERVER_LISTEN_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
runtimedir = _dbus_getenv ("XDG_RUNTIME_DIR");
|
||||
|
||||
if (runtimedir == NULL)
|
||||
{
|
||||
dbus_set_error (error,
|
||||
DBUS_ERROR_NOT_SUPPORTED, "\"XDG_RUNTIME_DIR\" is not set");
|
||||
return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
|
||||
}
|
||||
|
||||
_dbus_string_init_const (&filename, "bus");
|
||||
|
||||
if (!_dbus_string_init (&full_path))
|
||||
{
|
||||
_DBUS_SET_OOM (error);
|
||||
return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
|
||||
}
|
||||
|
||||
if (!_dbus_string_append (&full_path, runtimedir) ||
|
||||
!_dbus_concat_dir_and_file (&full_path, &filename))
|
||||
{
|
||||
_dbus_string_free (&full_path);
|
||||
_DBUS_SET_OOM (error);
|
||||
return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
|
||||
}
|
||||
|
||||
/* We can safely use filesystem sockets in the runtime directory,
|
||||
* and they are preferred because they can be bind-mounted between
|
||||
* Linux containers. */
|
||||
*server_p = _dbus_server_new_for_domain_socket (
|
||||
_dbus_string_get_const_data (&full_path),
|
||||
FALSE, error);
|
||||
|
||||
_dbus_string_free (&full_path);
|
||||
}
|
||||
else if (tmpdir != NULL || dir != NULL)
|
||||
{
|
||||
DBusString full_path;
|
||||
DBusString filename;
|
||||
dbus_bool_t use_abstract = FALSE;
|
||||
|
||||
if (tmpdir != NULL)
|
||||
{
|
||||
dir = tmpdir;
|
||||
|
||||
#ifdef __linux__
|
||||
/* Use abstract sockets for tmpdir if supported, so that it
|
||||
* never needs to be cleaned up. Use dir instead if you want a
|
||||
* path-based socket. */
|
||||
use_abstract = TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!_dbus_string_init (&full_path))
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
|
||||
}
|
||||
|
||||
if (!_dbus_string_init (&filename))
|
||||
{
|
||||
_dbus_string_free (&full_path);
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
|
||||
}
|
||||
|
||||
if (!_dbus_string_append (&filename, "dbus-"))
|
||||
{
|
||||
_dbus_string_free (&full_path);
|
||||
_dbus_string_free (&filename);
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
|
||||
}
|
||||
|
||||
if (!_dbus_generate_random_ascii (&filename, 10, error))
|
||||
{
|
||||
_dbus_string_free (&full_path);
|
||||
_dbus_string_free (&filename);
|
||||
return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
|
||||
}
|
||||
|
||||
if (!_dbus_string_append (&full_path, dir) ||
|
||||
!_dbus_concat_dir_and_file (&full_path, &filename))
|
||||
{
|
||||
_dbus_string_free (&full_path);
|
||||
_dbus_string_free (&filename);
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
|
||||
}
|
||||
|
||||
*server_p =
|
||||
_dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path),
|
||||
use_abstract,
|
||||
error);
|
||||
|
||||
_dbus_string_free (&full_path);
|
||||
_dbus_string_free (&filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (path)
|
||||
*server_p = _dbus_server_new_for_domain_socket (path, FALSE, error);
|
||||
else
|
||||
*server_p = _dbus_server_new_for_domain_socket (abstract, TRUE, error);
|
||||
}
|
||||
|
||||
if (*server_p != NULL)
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR(error);
|
||||
return DBUS_SERVER_LISTEN_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET(error);
|
||||
return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
|
||||
}
|
||||
}
|
||||
else if (strcmp (method, "systemd") == 0)
|
||||
if (strcmp (method, "systemd") == 0)
|
||||
{
|
||||
int i, n;
|
||||
DBusSocket *fds;
|
||||
|
|
@ -258,7 +100,7 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
|
|||
systemd_err:
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
_dbus_close_socket (fds[i], NULL);
|
||||
_dbus_close_socket (&fds[i], NULL);
|
||||
}
|
||||
dbus_free (fds);
|
||||
_dbus_string_free (&address);
|
||||
|
|
@ -298,87 +140,4 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new server listening on the given Unix domain socket.
|
||||
*
|
||||
* @param path the path for the domain socket.
|
||||
* @param abstract #TRUE to use abstract socket namespace
|
||||
* @param error location to store reason for failure.
|
||||
* @returns the new server, or #NULL on failure.
|
||||
*/
|
||||
DBusServer*
|
||||
_dbus_server_new_for_domain_socket (const char *path,
|
||||
dbus_bool_t abstract,
|
||||
DBusError *error)
|
||||
{
|
||||
DBusServer *server;
|
||||
DBusSocket listen_fd;
|
||||
DBusString address;
|
||||
char *path_copy;
|
||||
DBusString path_str;
|
||||
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||
|
||||
if (!_dbus_string_init (&address))
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_dbus_string_init_const (&path_str, path);
|
||||
if ((abstract &&
|
||||
!_dbus_string_append (&address, "unix:abstract=")) ||
|
||||
(!abstract &&
|
||||
!_dbus_string_append (&address, "unix:path=")) ||
|
||||
!_dbus_address_append_escaped (&address, &path_str))
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
goto failed_0;
|
||||
}
|
||||
|
||||
if (abstract)
|
||||
{
|
||||
path_copy = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
path_copy = _dbus_strdup (path);
|
||||
if (path_copy == NULL)
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
goto failed_0;
|
||||
}
|
||||
}
|
||||
|
||||
listen_fd.fd = _dbus_listen_unix_socket (path, abstract, error);
|
||||
|
||||
if (listen_fd.fd < 0)
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET (error);
|
||||
goto failed_1;
|
||||
}
|
||||
|
||||
server = _dbus_server_new_for_socket (&listen_fd, 1, &address, 0, error);
|
||||
if (server == NULL)
|
||||
{
|
||||
goto failed_2;
|
||||
}
|
||||
|
||||
if (path_copy != NULL)
|
||||
_dbus_server_socket_own_filename(server, path_copy);
|
||||
|
||||
_dbus_string_free (&address);
|
||||
|
||||
return server;
|
||||
|
||||
failed_2:
|
||||
_dbus_close_socket (listen_fd, NULL);
|
||||
failed_1:
|
||||
dbus_free (path_copy);
|
||||
failed_0:
|
||||
_dbus_string_free (&address);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/* dbus-server-unix.h Server implementation for Unix network protocols.
|
||||
*
|
||||
* Copyright (C) 2002 Red Hat Inc.
|
||||
*
|
||||
* Licensed under the Academic Free License version 2.1
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
#ifndef DBUS_SERVER_UNIX_H
|
||||
#define DBUS_SERVER_UNIX_H
|
||||
|
||||
#include <dbus/dbus-internals.h>
|
||||
#include <dbus/dbus-server-protected.h>
|
||||
|
||||
DBUS_BEGIN_DECLS
|
||||
|
||||
DBusServer* _dbus_server_new_for_domain_socket (const char *path,
|
||||
dbus_bool_t abstract,
|
||||
DBusError *error);
|
||||
|
||||
DBUS_END_DECLS
|
||||
|
||||
#endif /* DBUS_SERVER_UNIX_H */
|
||||
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
#include <config.h>
|
||||
#include "dbus-server.h"
|
||||
#include "dbus-server-unix.h"
|
||||
#include "dbus-server-socket.h"
|
||||
#include "dbus-string.h"
|
||||
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
|
||||
|
|
@ -527,6 +526,7 @@ static const struct {
|
|||
DBusError *error);
|
||||
} listen_funcs[] = {
|
||||
{ _dbus_server_listen_socket }
|
||||
, { _dbus_server_listen_unix_socket }
|
||||
, { _dbus_server_listen_platform_specific }
|
||||
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
|
||||
, { _dbus_server_listen_debug_pipe }
|
||||
|
|
|
|||
|
|
@ -560,7 +560,7 @@ close_socket_to_babysitter (DBusBabysitter *sitter)
|
|||
|
||||
if (sitter->socket_to_babysitter.fd >= 0)
|
||||
{
|
||||
_dbus_close_socket (sitter->socket_to_babysitter, NULL);
|
||||
_dbus_close_socket (&sitter->socket_to_babysitter, NULL);
|
||||
sitter->socket_to_babysitter.fd = -1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ close_socket_to_babysitter (DBusBabysitter *sitter)
|
|||
|
||||
if (sitter->socket_to_babysitter.sock != INVALID_SOCKET)
|
||||
{
|
||||
_dbus_close_socket (sitter->socket_to_babysitter, NULL);
|
||||
_dbus_close_socket (&sitter->socket_to_babysitter, NULL);
|
||||
sitter->socket_to_babysitter.sock = INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
|
@ -188,7 +188,7 @@ _dbus_babysitter_unref (DBusBabysitter *sitter)
|
|||
|
||||
if (sitter->socket_to_main.sock != INVALID_SOCKET)
|
||||
{
|
||||
_dbus_close_socket (sitter->socket_to_main, NULL);
|
||||
_dbus_close_socket (&sitter->socket_to_main, NULL);
|
||||
sitter->socket_to_main.sock = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -293,22 +293,34 @@ static dbus_bool_t
|
|||
_dbus_open_unix_socket (int *fd,
|
||||
DBusError *error)
|
||||
{
|
||||
return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
|
||||
return _dbus_open_socket(fd, AF_UNIX, SOCK_STREAM, 0, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes a socket. Should not be used on non-socket
|
||||
* file descriptors or handles.
|
||||
* Closes a socket and invalidates it. Should not be used on non-socket file
|
||||
* descriptors or handles.
|
||||
*
|
||||
* If an error is detected, this function returns #FALSE and sets the error, but
|
||||
* the socket is still closed and invalidated. Callers can use the error in a
|
||||
* diagnostic message, but should not retry closing the socket.
|
||||
*
|
||||
* @param fd the socket
|
||||
* @param error return location for an error
|
||||
* @returns #FALSE if error is set
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_close_socket (DBusSocket fd,
|
||||
_dbus_close_socket (DBusSocket *fd,
|
||||
DBusError *error)
|
||||
{
|
||||
return _dbus_close (fd.fd, error);
|
||||
dbus_bool_t rv;
|
||||
|
||||
_dbus_assert (fd != NULL);
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||
|
||||
rv = _dbus_close (fd->fd, error);
|
||||
_dbus_socket_invalidate (fd);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -923,21 +935,6 @@ _dbus_write_two (int fd,
|
|||
#endif /* !HAVE_WRITEV */
|
||||
}
|
||||
|
||||
#define _DBUS_MAX_SUN_PATH_LENGTH 99
|
||||
|
||||
/**
|
||||
* @def _DBUS_MAX_SUN_PATH_LENGTH
|
||||
*
|
||||
* Maximum length of the path to a UNIX domain socket,
|
||||
* sockaddr_un::sun_path member. POSIX requires that all systems
|
||||
* support at least 100 bytes here, including the nul termination.
|
||||
* We use 99 for the max value to allow for the nul.
|
||||
*
|
||||
* We could probably also do sizeof (addr.sun_path)
|
||||
* but this way we are the same on all platforms
|
||||
* which is probably a good idea.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a socket and connects it to the UNIX domain socket at the
|
||||
* given path. The connection fd is returned, and is set up as
|
||||
|
|
@ -952,14 +949,14 @@ _dbus_write_two (int fd,
|
|||
* @param path the path to UNIX domain socket
|
||||
* @param abstract #TRUE to use abstract namespace
|
||||
* @param error return location for error code
|
||||
* @returns connection file descriptor or -1 on error
|
||||
* @returns a valid socket on success or an invalid socket on error
|
||||
*/
|
||||
int
|
||||
DBusSocket
|
||||
_dbus_connect_unix_socket (const char *path,
|
||||
dbus_bool_t abstract,
|
||||
DBusError *error)
|
||||
{
|
||||
int fd;
|
||||
DBusSocket fd = DBUS_SOCKET_INIT;
|
||||
size_t path_len;
|
||||
struct sockaddr_un addr;
|
||||
_DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
|
||||
|
|
@ -970,10 +967,10 @@ _dbus_connect_unix_socket (const char *path,
|
|||
path, abstract);
|
||||
|
||||
|
||||
if (!_dbus_open_unix_socket (&fd, error))
|
||||
if (!_dbus_open_unix_socket (&fd.fd, error))
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET(error);
|
||||
return -1;
|
||||
return fd;
|
||||
}
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR(error);
|
||||
|
||||
|
|
@ -991,8 +988,8 @@ _dbus_connect_unix_socket (const char *path,
|
|||
{
|
||||
dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
|
||||
"Abstract socket name too long\n");
|
||||
_dbus_close (fd, NULL);
|
||||
return -1;
|
||||
_dbus_close_socket (&fd, NULL);
|
||||
return fd;
|
||||
}
|
||||
|
||||
strncpy (&addr.sun_path[1], path, sizeof (addr.sun_path) - 2);
|
||||
|
|
@ -1000,8 +997,8 @@ _dbus_connect_unix_socket (const char *path,
|
|||
#else /* !__linux__ */
|
||||
dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
|
||||
"Operating system does not support abstract socket namespace\n");
|
||||
_dbus_close (fd, NULL);
|
||||
return -1;
|
||||
_dbus_close_socket (&fd, NULL);
|
||||
return fd;
|
||||
#endif /* !__linux__ */
|
||||
}
|
||||
else
|
||||
|
|
@ -1010,30 +1007,30 @@ _dbus_connect_unix_socket (const char *path,
|
|||
{
|
||||
dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
|
||||
"Socket name too long\n");
|
||||
_dbus_close (fd, NULL);
|
||||
return -1;
|
||||
_dbus_close_socket (&fd, NULL);
|
||||
return fd;
|
||||
}
|
||||
|
||||
strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
|
||||
}
|
||||
|
||||
if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
|
||||
if (connect (fd.fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
|
||||
{
|
||||
dbus_set_error (error,
|
||||
_dbus_error_from_errno (errno),
|
||||
"Failed to connect to socket %s: %s",
|
||||
path, _dbus_strerror (errno));
|
||||
|
||||
_dbus_close (fd, NULL);
|
||||
return -1;
|
||||
_dbus_close_socket (&fd, NULL);
|
||||
return fd;
|
||||
}
|
||||
|
||||
if (!_dbus_set_fd_nonblocking (fd, error))
|
||||
if (!_dbus_set_fd_nonblocking (fd.fd, error))
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET (error);
|
||||
|
||||
_dbus_close (fd, NULL);
|
||||
return -1;
|
||||
_dbus_close_socket (&fd, NULL);
|
||||
return fd;
|
||||
}
|
||||
|
||||
return fd;
|
||||
|
|
@ -1049,13 +1046,14 @@ _dbus_connect_unix_socket (const char *path,
|
|||
* @param argv the argument list for the process to execute.
|
||||
* argv[0] typically is identical to the path of the executable
|
||||
* @param error return location for error code
|
||||
* @returns connection file descriptor or -1 on error
|
||||
* @returns a valid socket on success or an invalid socket on error
|
||||
*/
|
||||
int
|
||||
DBusSocket
|
||||
_dbus_connect_exec (const char *path,
|
||||
char *const argv[],
|
||||
DBusError *error)
|
||||
{
|
||||
DBusSocket s = DBUS_SOCKET_INIT;
|
||||
int fds[2];
|
||||
pid_t pid;
|
||||
int retval;
|
||||
|
|
@ -1081,7 +1079,8 @@ _dbus_connect_exec (const char *path,
|
|||
_dbus_error_from_errno (errno),
|
||||
"Failed to create socket pair: %s",
|
||||
_dbus_strerror (errno));
|
||||
return -1;
|
||||
_dbus_assert (!_dbus_socket_is_valid (s));
|
||||
return s;
|
||||
}
|
||||
|
||||
if (!cloexec_done)
|
||||
|
|
@ -1104,7 +1103,8 @@ _dbus_connect_exec (const char *path,
|
|||
path, _dbus_strerror (errno));
|
||||
close (fds[0]);
|
||||
close (fds[1]);
|
||||
return -1;
|
||||
_dbus_assert (!_dbus_socket_is_valid (s));
|
||||
return s;
|
||||
}
|
||||
|
||||
if (pid == 0)
|
||||
|
|
@ -1139,10 +1139,12 @@ _dbus_connect_exec (const char *path,
|
|||
_DBUS_ASSERT_ERROR_IS_SET (error);
|
||||
|
||||
close (fds[0]);
|
||||
return -1;
|
||||
_dbus_assert (!_dbus_socket_is_valid (s));
|
||||
return s;
|
||||
}
|
||||
|
||||
return fds[0];
|
||||
s.fd = fds[0];
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1160,13 +1162,14 @@ _dbus_connect_exec (const char *path,
|
|||
* @param path the socket name
|
||||
* @param abstract #TRUE to use abstract namespace
|
||||
* @param error return location for errors
|
||||
* @returns the listening file descriptor or -1 on error
|
||||
* @returns a valid socket on success or an invalid socket on error
|
||||
*/
|
||||
int
|
||||
DBusSocket
|
||||
_dbus_listen_unix_socket (const char *path,
|
||||
dbus_bool_t abstract,
|
||||
DBusError *error)
|
||||
{
|
||||
DBusSocket s = DBUS_SOCKET_INIT;
|
||||
int listen_fd;
|
||||
struct sockaddr_un addr;
|
||||
size_t path_len;
|
||||
|
|
@ -1180,7 +1183,7 @@ _dbus_listen_unix_socket (const char *path,
|
|||
if (!_dbus_open_unix_socket (&listen_fd, error))
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET(error);
|
||||
return -1;
|
||||
return s;
|
||||
}
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR(error);
|
||||
|
||||
|
|
@ -1202,7 +1205,7 @@ _dbus_listen_unix_socket (const char *path,
|
|||
dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
|
||||
"Abstract socket name too long\n");
|
||||
_dbus_close (listen_fd, NULL);
|
||||
return -1;
|
||||
return s;
|
||||
}
|
||||
|
||||
strncpy (&addr.sun_path[1], path, sizeof (addr.sun_path) - 2);
|
||||
|
|
@ -1211,7 +1214,7 @@ _dbus_listen_unix_socket (const char *path,
|
|||
dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
|
||||
"Operating system does not support abstract socket namespace\n");
|
||||
_dbus_close (listen_fd, NULL);
|
||||
return -1;
|
||||
return s;
|
||||
#endif /* !__linux__ */
|
||||
}
|
||||
else
|
||||
|
|
@ -1239,8 +1242,8 @@ _dbus_listen_unix_socket (const char *path,
|
|||
dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
|
||||
"Socket name too long\n");
|
||||
_dbus_close (listen_fd, NULL);
|
||||
return -1;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
|
||||
}
|
||||
|
|
@ -1251,7 +1254,7 @@ _dbus_listen_unix_socket (const char *path,
|
|||
"Failed to bind socket \"%s\": %s",
|
||||
path, _dbus_strerror (errno));
|
||||
_dbus_close (listen_fd, NULL);
|
||||
return -1;
|
||||
return s;
|
||||
}
|
||||
|
||||
if (listen (listen_fd, SOMAXCONN /* backlog */) < 0)
|
||||
|
|
@ -1260,14 +1263,14 @@ _dbus_listen_unix_socket (const char *path,
|
|||
"Failed to listen on socket \"%s\": %s",
|
||||
path, _dbus_strerror (errno));
|
||||
_dbus_close (listen_fd, NULL);
|
||||
return -1;
|
||||
return s;
|
||||
}
|
||||
|
||||
if (!_dbus_set_fd_nonblocking (listen_fd, error))
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET (error);
|
||||
_dbus_close (listen_fd, NULL);
|
||||
return -1;
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Try opening up the permissions, but if we can't, just go ahead
|
||||
|
|
@ -1276,7 +1279,8 @@ _dbus_listen_unix_socket (const char *path,
|
|||
if (!abstract && chmod (path, 0777) < 0)
|
||||
_dbus_warn ("Could not set mode 0777 on socket %s", path);
|
||||
|
||||
return listen_fd;
|
||||
s.fd = listen_fd;
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1491,7 +1495,6 @@ _dbus_connect_tcp_socket_with_nonce (const char *host,
|
|||
_dbus_error_from_gai (res, errno),
|
||||
"Failed to lookup host/port: \"%s:%s\": %s (%d)",
|
||||
host, port, gai_strerror(res), res);
|
||||
_dbus_socket_invalidate (&fd);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -1509,8 +1512,7 @@ _dbus_connect_tcp_socket_with_nonce (const char *host,
|
|||
if (connect (fd.fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
|
||||
{
|
||||
saved_errno = errno;
|
||||
_dbus_close (fd.fd, NULL);
|
||||
_dbus_socket_invalidate (&fd);
|
||||
_dbus_close_socket (&fd, NULL);
|
||||
|
||||
connect_error = dbus_new0 (DBusError, 1);
|
||||
|
||||
|
|
@ -1557,16 +1559,14 @@ _dbus_connect_tcp_socket_with_nonce (const char *host,
|
|||
|
||||
if (!ret)
|
||||
{
|
||||
_dbus_close (fd.fd, NULL);
|
||||
_dbus_socket_invalidate (&fd);
|
||||
_dbus_close_socket (&fd, NULL);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_dbus_set_fd_nonblocking (fd.fd, error))
|
||||
{
|
||||
_dbus_close (fd.fd, NULL);
|
||||
_dbus_socket_invalidate (&fd);
|
||||
_dbus_close_socket (&fd, NULL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,17 +66,6 @@ _dbus_write_two (int fd,
|
|||
int start2,
|
||||
int len2);
|
||||
|
||||
int _dbus_connect_unix_socket (const char *path,
|
||||
dbus_bool_t abstract,
|
||||
DBusError *error);
|
||||
int _dbus_listen_unix_socket (const char *path,
|
||||
dbus_bool_t abstract,
|
||||
DBusError *error);
|
||||
|
||||
int _dbus_connect_exec (const char *path,
|
||||
char *const argv[],
|
||||
DBusError *error);
|
||||
|
||||
int _dbus_listen_systemd_sockets (DBusSocket **fd,
|
||||
DBusError *error);
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,9 @@
|
|||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
#include <iphlpapi.h>
|
||||
#ifdef HAVE_AFUNIX_H
|
||||
#include <afunix.h>
|
||||
#endif
|
||||
|
||||
/* Declarations missing in mingw's and windows sdk 7.0 headers */
|
||||
extern BOOL WINAPI ConvertStringSidToSidA (LPCSTR StringSid, PSID *Sid);
|
||||
|
|
@ -483,20 +486,21 @@ _dbus_write_socket (DBusSocket fd,
|
|||
|
||||
|
||||
/**
|
||||
* Closes a file descriptor.
|
||||
* Closes a socket and invalidates it.
|
||||
*
|
||||
* @param fd the file descriptor
|
||||
* @param error error object
|
||||
* @returns #FALSE if error set
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_close_socket (DBusSocket fd,
|
||||
DBusError *error)
|
||||
_dbus_close_socket (DBusSocket *fd,
|
||||
DBusError *error)
|
||||
{
|
||||
_dbus_assert (fd != NULL);
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||
|
||||
again:
|
||||
if (closesocket (fd.sock) == SOCKET_ERROR)
|
||||
if (closesocket (fd->sock) == SOCKET_ERROR)
|
||||
{
|
||||
DBUS_SOCKET_SET_ERRNO ();
|
||||
|
||||
|
|
@ -505,11 +509,13 @@ _dbus_close_socket (DBusSocket fd,
|
|||
|
||||
dbus_set_error (error, _dbus_error_from_errno (errno),
|
||||
"Could not close socket: socket=%Iu, , %s",
|
||||
fd.sock, _dbus_strerror_from_errno ());
|
||||
fd->sock, _dbus_strerror_from_errno ());
|
||||
_dbus_socket_invalidate (fd);
|
||||
return FALSE;
|
||||
}
|
||||
_dbus_verbose ("socket=%Iu, \n", fd.sock);
|
||||
_dbus_verbose ("socket=%Iu, \n", fd->sock);
|
||||
|
||||
_dbus_socket_invalidate (fd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -1642,7 +1648,7 @@ _dbus_connect_tcp_socket_with_nonce (const char *host,
|
|||
_dbus_error_from_errno (saved_errno),
|
||||
"Failed to open socket: %s",
|
||||
_dbus_strerror (saved_errno));
|
||||
_dbus_socket_invalidate (&fd);
|
||||
_dbus_assert (!_dbus_socket_is_valid (fd));
|
||||
goto out;
|
||||
}
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR(error);
|
||||
|
|
@ -1650,8 +1656,7 @@ _dbus_connect_tcp_socket_with_nonce (const char *host,
|
|||
if (connect (fd.sock, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR)
|
||||
{
|
||||
saved_errno = _dbus_get_low_level_socket_errno ();
|
||||
closesocket(fd.sock);
|
||||
_dbus_socket_invalidate (&fd);
|
||||
_dbus_close_socket (&fd, NULL);
|
||||
|
||||
connect_error = dbus_new0 (DBusError, 1);
|
||||
|
||||
|
|
@ -1698,8 +1703,7 @@ _dbus_connect_tcp_socket_with_nonce (const char *host,
|
|||
|
||||
if (!ret)
|
||||
{
|
||||
closesocket (fd.sock);
|
||||
_dbus_socket_invalidate (&fd);
|
||||
_dbus_close_socket (&fd, NULL);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
|
@ -1709,8 +1713,7 @@ _dbus_connect_tcp_socket_with_nonce (const char *host,
|
|||
|
||||
if (!_dbus_set_socket_nonblocking (fd, error))
|
||||
{
|
||||
closesocket (fd.sock);
|
||||
_dbus_socket_invalidate (&fd);
|
||||
_dbus_close_socket (&fd, NULL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -1828,6 +1831,7 @@ _dbus_listen_tcp_socket (const char *host,
|
|||
_dbus_error_from_errno (saved_errno),
|
||||
"Failed to open socket: %s",
|
||||
_dbus_strerror (saved_errno));
|
||||
_dbus_assert (!_dbus_socket_is_valid (fd));
|
||||
goto failed;
|
||||
}
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR(error);
|
||||
|
|
@ -1848,7 +1852,7 @@ _dbus_listen_tcp_socket (const char *host,
|
|||
host ? host : "*", port, _dbus_strerror (saved_errno));
|
||||
}
|
||||
|
||||
if (bind (fd.sock, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR)
|
||||
if (bind (fd.sock, (struct sockaddr *) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR)
|
||||
{
|
||||
saved_errno = _dbus_get_low_level_socket_errno ();
|
||||
closesocket (fd.sock);
|
||||
|
|
@ -2112,6 +2116,56 @@ again:
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_AFUNIX_H
|
||||
/*
|
||||
* Returns false with no error set if the socket is non-AF_UNIX
|
||||
* (contrary to our usual convention).
|
||||
*
|
||||
* Returns false with an error set on failure to identify it.
|
||||
*/
|
||||
static dbus_bool_t
|
||||
_dbus_socket_is_af_unix (DBusSocket s,
|
||||
DBusError *error)
|
||||
{
|
||||
struct sockaddr_un saddr;
|
||||
int len;
|
||||
|
||||
len = sizeof (saddr);
|
||||
if (getsockname (s.sock, (struct sockaddr *)&saddr, &len) == SOCKET_ERROR)
|
||||
{
|
||||
DBUS_SOCKET_SET_ERRNO ();
|
||||
dbus_set_error (error, _dbus_error_from_errno (errno),
|
||||
"Failed to getsockname: %s",
|
||||
_dbus_strerror_from_errno ());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return saddr.sun_family == AF_UNIX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief return peer process id from Unix domain socket handle
|
||||
* @param handle AF_UNIX socket descriptor
|
||||
* @return process id or 0 in case the process id could not be fetched
|
||||
*/
|
||||
static dbus_pid_t
|
||||
_dbus_get_peer_pid_from_uds_handle (int handle)
|
||||
{
|
||||
DWORD pid, drc;
|
||||
|
||||
if (WSAIoctl (handle, SIO_AF_UNIX_GETPEERPID,
|
||||
NULL, 0U,
|
||||
&pid, sizeof (pid), &drc,
|
||||
NULL, NULL) == SOCKET_ERROR)
|
||||
{
|
||||
_dbus_verbose ("failed to get peer's pid\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pid;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Reads a single byte which must be nul (an error occurs otherwise),
|
||||
* and reads unix credentials if available. Fills in pid/uid/gid with
|
||||
|
|
@ -2137,6 +2191,9 @@ _dbus_read_credentials_socket (DBusSocket handle,
|
|||
{
|
||||
int bytes_read = 0;
|
||||
DBusString buf;
|
||||
#ifdef HAVE_AFUNIX_H
|
||||
dbus_bool_t uds = FALSE;
|
||||
#endif
|
||||
|
||||
char *sid = NULL;
|
||||
dbus_pid_t pid;
|
||||
|
|
@ -2153,7 +2210,16 @@ _dbus_read_credentials_socket (DBusSocket handle,
|
|||
_dbus_string_free (&buf);
|
||||
}
|
||||
|
||||
pid = _dbus_get_peer_pid_from_tcp_handle (handle.sock);
|
||||
#ifdef HAVE_AFUNIX_H
|
||||
uds = _dbus_socket_is_af_unix (handle, error);
|
||||
if (dbus_error_is_set (error))
|
||||
return FALSE;
|
||||
|
||||
if (uds)
|
||||
pid = _dbus_get_peer_pid_from_uds_handle (handle.sock);
|
||||
else
|
||||
#endif
|
||||
pid = _dbus_get_peer_pid_from_tcp_handle (handle.sock);
|
||||
if (pid == 0)
|
||||
return TRUE;
|
||||
|
||||
|
|
@ -2524,8 +2590,7 @@ _dbus_generate_random_bytes (DBusString *str,
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the temporary files directory by inspecting the environment variables
|
||||
* TMPDIR, TMP, and TEMP in that order. If none of those are set "/tmp" is returned
|
||||
* Gets the temporary files directory, using GetTempPath()
|
||||
*
|
||||
* @returns location of temp directory, or #NULL if no memory for locking
|
||||
*/
|
||||
|
|
@ -4408,5 +4473,228 @@ _dbus_win_event_free (HANDLE handle, DBusError *error)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_AFUNIX_H
|
||||
static dbus_bool_t
|
||||
_dbus_open_socket (SOCKET *socket_p,
|
||||
int domain,
|
||||
int type,
|
||||
int protocol,
|
||||
DBusError *error)
|
||||
{
|
||||
if (!_dbus_win_startup_winsock ())
|
||||
{
|
||||
_DBUS_SET_OOM (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*socket_p = socket (domain, type, protocol);
|
||||
if (*socket_p == INVALID_SOCKET)
|
||||
{
|
||||
DBUS_SOCKET_SET_ERRNO ();
|
||||
dbus_set_error (error, _dbus_error_from_errno (errno),
|
||||
"Failed to open socket: %s",
|
||||
_dbus_strerror_from_errno ());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_dbus_win_handle_set_close_on_exec ((HANDLE) *socket_p);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a UNIX domain socket (as in the socket() call).
|
||||
* Does not bind the socket.
|
||||
*
|
||||
* This will set CLOEXEC for the socket returned
|
||||
*
|
||||
* @param return location for socket descriptor
|
||||
* @param error return location for an error
|
||||
* @returns #FALSE if error is set
|
||||
*/
|
||||
static dbus_bool_t
|
||||
_dbus_open_unix_socket (SOCKET *socket,
|
||||
DBusError *error)
|
||||
{
|
||||
return _dbus_open_socket (socket, AF_UNIX, SOCK_STREAM, 0, error);
|
||||
}
|
||||
#endif /* HAVE_AFUNIX_H */
|
||||
|
||||
/**
|
||||
* Creates a socket and connects it to the UNIX domain socket at the
|
||||
* given path. The socket is returned, and is set up as
|
||||
* nonblocking.
|
||||
*
|
||||
* Abstract socket usage always fails.
|
||||
*
|
||||
* This will set FD_CLOEXEC for the socket returned.
|
||||
*
|
||||
* @param path the path to UNIX domain socket
|
||||
* @param abstract #TRUE to use abstract namespace
|
||||
* @param error return location for error code
|
||||
* @returns a valid socket on success or an invalid socket on error
|
||||
*/
|
||||
DBusSocket
|
||||
_dbus_connect_unix_socket (const char *path,
|
||||
dbus_bool_t abstract,
|
||||
DBusError *error)
|
||||
{
|
||||
DBusSocket s = DBUS_SOCKET_INIT;
|
||||
|
||||
#ifdef HAVE_AFUNIX_H
|
||||
struct sockaddr_un addr;
|
||||
size_t path_len;
|
||||
|
||||
_DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||
|
||||
_dbus_verbose ("connecting to unix socket %s abstract=%d\n",
|
||||
path, abstract);
|
||||
|
||||
if (abstract)
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
|
||||
"Failed to connect: UNIX abstract socket is not supported on this system");
|
||||
return s;
|
||||
}
|
||||
|
||||
path_len = strlen (path);
|
||||
if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
|
||||
"Failed to connect: socket name too long");
|
||||
return s;
|
||||
}
|
||||
|
||||
if (!_dbus_open_unix_socket (&s.sock, error))
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET (error);
|
||||
return s;
|
||||
}
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||
|
||||
_DBUS_ZERO (addr);
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
|
||||
|
||||
if (connect (s.sock, (struct sockaddr *) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
|
||||
{
|
||||
DBUS_SOCKET_SET_ERRNO ();
|
||||
dbus_set_error (error,
|
||||
_dbus_error_from_errno (errno),
|
||||
"Failed to connect to socket %s: %s",
|
||||
path, _dbus_strerror (errno));
|
||||
|
||||
_dbus_close_socket (&s, NULL);
|
||||
return s;
|
||||
}
|
||||
|
||||
if (!_dbus_set_socket_nonblocking (s, error))
|
||||
_dbus_close_socket (&s, NULL);
|
||||
|
||||
#else
|
||||
dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
|
||||
"Failed to connect: UNIX socket is not supported with this build");
|
||||
#endif
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a socket and binds it to the given path,
|
||||
* then listens on the socket. The socket is
|
||||
* set to be nonblocking.
|
||||
*
|
||||
* Abstract socket usage always fails.
|
||||
*
|
||||
* This will set CLOEXEC for the socket returned
|
||||
*
|
||||
* @param path the socket name
|
||||
* @param abstract #TRUE to use abstract namespace
|
||||
* @param error return location for errors
|
||||
* @returns a valid socket on success or an invalid socket on error
|
||||
*/
|
||||
DBusSocket
|
||||
_dbus_listen_unix_socket (const char *path,
|
||||
dbus_bool_t abstract,
|
||||
DBusError *error)
|
||||
{
|
||||
DBusSocket s = DBUS_SOCKET_INIT;
|
||||
|
||||
#ifdef HAVE_AFUNIX_H
|
||||
struct sockaddr_un addr;
|
||||
size_t path_len;
|
||||
_DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
|
||||
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||
|
||||
_dbus_verbose ("listening on unix socket %s abstract=%d\n",
|
||||
path, abstract);
|
||||
|
||||
if (abstract)
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
|
||||
"Failed to listen: UNIX abstract socket is not supported on this system");
|
||||
return s;
|
||||
}
|
||||
|
||||
if (!_dbus_open_unix_socket (&s.sock, error))
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET (error);
|
||||
return s;
|
||||
}
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||
|
||||
_DBUS_ZERO (addr);
|
||||
addr.sun_family = AF_UNIX;
|
||||
path_len = strlen (path);
|
||||
|
||||
/* see related comment in dbus-sysdeps-unix.c */
|
||||
/* there is no S_ISSOCK on windows yet, so just unlink the path */
|
||||
unlink (path);
|
||||
|
||||
if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
|
||||
"Failed to listen: socket name too long");
|
||||
_dbus_close_socket (&s, NULL);
|
||||
return s;
|
||||
}
|
||||
|
||||
strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
|
||||
|
||||
if (bind (s.sock, (struct sockaddr *) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
|
||||
{
|
||||
DBUS_SOCKET_SET_ERRNO ();
|
||||
dbus_set_error (error, _dbus_error_from_errno (errno),
|
||||
"Failed to bind socket \"%s\": %s",
|
||||
path, _dbus_strerror (errno));
|
||||
_dbus_close_socket (&s, NULL);
|
||||
return s;
|
||||
}
|
||||
|
||||
if (listen (s.sock, SOMAXCONN /* backlog */) < 0)
|
||||
{
|
||||
DBUS_SOCKET_SET_ERRNO ();
|
||||
dbus_set_error (error, _dbus_error_from_errno (errno),
|
||||
"Failed to listen on socket \"%s\": %s",
|
||||
path, _dbus_strerror (errno));
|
||||
_dbus_close_socket (&s, NULL);
|
||||
return s;
|
||||
}
|
||||
|
||||
if (!_dbus_set_socket_nonblocking (s, error))
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET (error);
|
||||
_dbus_close_socket (&s, NULL);
|
||||
return s;
|
||||
}
|
||||
#else
|
||||
dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
|
||||
"Failed to listen: UNIX socket is not supported with this build");
|
||||
#endif
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/** @} end of sysdeps-win */
|
||||
/* tests in dbus-sysdeps-util.c */
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ dbus_bool_t _dbus_set_socket_nonblocking (DBusSocket fd,
|
|||
DBusError *error);
|
||||
|
||||
DBUS_PRIVATE_EXPORT
|
||||
dbus_bool_t _dbus_close_socket (DBusSocket fd,
|
||||
dbus_bool_t _dbus_close_socket (DBusSocket *fd,
|
||||
DBusError *error);
|
||||
DBUS_PRIVATE_EXPORT
|
||||
int _dbus_read_socket (DBusSocket fd,
|
||||
|
|
@ -561,6 +561,18 @@ typedef struct
|
|||
dbus_bool_t _dbus_stat (const DBusString *filename,
|
||||
DBusStat *statbuf,
|
||||
DBusError *error);
|
||||
|
||||
DBusSocket _dbus_connect_unix_socket (const char *path,
|
||||
dbus_bool_t abstract,
|
||||
DBusError *error);
|
||||
DBusSocket _dbus_listen_unix_socket (const char *path,
|
||||
dbus_bool_t abstract,
|
||||
DBusError *error);
|
||||
|
||||
DBusSocket _dbus_connect_exec (const char *path,
|
||||
char *const argv[],
|
||||
DBusError *error);
|
||||
|
||||
DBUS_PRIVATE_EXPORT
|
||||
dbus_bool_t _dbus_socketpair (DBusSocket *fd1,
|
||||
DBusSocket *fd2,
|
||||
|
|
@ -718,6 +730,20 @@ void _dbus_combine_tcp_errors (DBusList **sources,
|
|||
const char *port,
|
||||
DBusError *dest);
|
||||
|
||||
/**
|
||||
* @def _DBUS_MAX_SUN_PATH_LENGTH
|
||||
*
|
||||
* Maximum length of the path to a UNIX domain socket,
|
||||
* sockaddr_un::sun_path member. POSIX requires that all systems
|
||||
* support at least 100 bytes here, including the nul termination.
|
||||
* We use 99 for the max value to allow for the nul.
|
||||
*
|
||||
* We could probably also do sizeof (addr.sun_path)
|
||||
* but this way we are the same on all platforms
|
||||
* which is probably a good idea.
|
||||
*/
|
||||
#define _DBUS_MAX_SUN_PATH_LENGTH 99
|
||||
|
||||
/** @} */
|
||||
|
||||
DBUS_END_DECLS
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@
|
|||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dbus-internals.h"
|
||||
#include "dbus-connection-internal.h"
|
||||
#include "dbus-nonce.h"
|
||||
|
|
@ -1042,8 +1045,7 @@ socket_disconnect (DBusTransport *transport)
|
|||
|
||||
free_watches (transport);
|
||||
|
||||
_dbus_close_socket (socket_transport->fd, NULL);
|
||||
_dbus_socket_invalidate (&socket_transport->fd);
|
||||
_dbus_close_socket (&socket_transport->fd, NULL);
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
|
|
@ -1430,8 +1432,7 @@ _dbus_transport_new_for_tcp_socket (const char *host,
|
|||
if (transport == NULL)
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
_dbus_close_socket (fd, NULL);
|
||||
_dbus_socket_invalidate (&fd);
|
||||
_dbus_close_socket (&fd, NULL);
|
||||
}
|
||||
|
||||
return transport;
|
||||
|
|
@ -1502,4 +1503,141 @@ _dbus_transport_open_socket(DBusAddressEntry *entry,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new transport for the given Unix domain socket
|
||||
* path. This creates a client-side of a transport.
|
||||
*
|
||||
* @todo once we add a way to escape paths in a dbus
|
||||
* address, this function needs to do escaping.
|
||||
*
|
||||
* @param path the path to the domain socket.
|
||||
* @param abstract #TRUE to use abstract socket namespace
|
||||
* @param error address where an error can be returned.
|
||||
* @returns a new transport, or #NULL on failure.
|
||||
*/
|
||||
DBusTransport*
|
||||
_dbus_transport_new_for_domain_socket (const char *path,
|
||||
dbus_bool_t abstract,
|
||||
DBusError *error)
|
||||
{
|
||||
DBusSocket fd = DBUS_SOCKET_INIT;
|
||||
DBusTransport *transport;
|
||||
DBusString address;
|
||||
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||
|
||||
if (!_dbus_string_init (&address))
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((abstract &&
|
||||
!_dbus_string_append (&address, "unix:abstract=")) ||
|
||||
(!abstract &&
|
||||
!_dbus_string_append (&address, "unix:path=")) ||
|
||||
!_dbus_string_append (&address, path))
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
goto failed_0;
|
||||
}
|
||||
|
||||
fd = _dbus_connect_unix_socket (path, abstract, error);
|
||||
if (!_dbus_socket_is_valid (fd))
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET (error);
|
||||
goto failed_0;
|
||||
}
|
||||
|
||||
_dbus_verbose ("Successfully connected to unix socket %s\n",
|
||||
path);
|
||||
|
||||
transport = _dbus_transport_new_for_socket (fd, NULL, &address);
|
||||
if (transport == NULL)
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
goto failed_1;
|
||||
}
|
||||
|
||||
_dbus_string_free (&address);
|
||||
|
||||
return transport;
|
||||
|
||||
failed_1:
|
||||
_dbus_close_socket (&fd, NULL);
|
||||
failed_0:
|
||||
_dbus_string_free (&address);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a UNIX socket transport.
|
||||
*
|
||||
* @param entry the address entry to try opening as a unix transport.
|
||||
* @param transport_p return location for the opened transport
|
||||
* @param error error to be set
|
||||
* @returns result of the attempt
|
||||
*/
|
||||
DBusTransportOpenResult
|
||||
_dbus_transport_open_unix_socket (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;
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
|
|||
|
|
@ -39,7 +39,13 @@ DBusTransportOpenResult _dbus_transport_open_socket (DBusAddressEntry *e
|
|||
DBusTransport **transport_p,
|
||||
DBusError *error);
|
||||
|
||||
DBusTransport* _dbus_transport_new_for_domain_socket (const char *path,
|
||||
dbus_bool_t abstract,
|
||||
DBusError *error);
|
||||
|
||||
DBusTransportOpenResult _dbus_transport_open_unix_socket (DBusAddressEntry *entry,
|
||||
DBusTransport **transport_p,
|
||||
DBusError *error);
|
||||
|
||||
DBUS_END_DECLS
|
||||
|
||||
|
|
|
|||
|
|
@ -42,73 +42,6 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new transport for the given Unix domain socket
|
||||
* path. This creates a client-side of a transport.
|
||||
*
|
||||
* @todo once we add a way to escape paths in a dbus
|
||||
* address, this function needs to do escaping.
|
||||
*
|
||||
* @param path the path to the domain socket.
|
||||
* @param abstract #TRUE to use abstract socket namespace
|
||||
* @param error address where an error can be returned.
|
||||
* @returns a new transport, or #NULL on failure.
|
||||
*/
|
||||
DBusTransport*
|
||||
_dbus_transport_new_for_domain_socket (const char *path,
|
||||
dbus_bool_t abstract,
|
||||
DBusError *error)
|
||||
{
|
||||
DBusSocket fd = DBUS_SOCKET_INIT;
|
||||
DBusTransport *transport;
|
||||
DBusString address;
|
||||
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||
|
||||
if (!_dbus_string_init (&address))
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((abstract &&
|
||||
!_dbus_string_append (&address, "unix:abstract=")) ||
|
||||
(!abstract &&
|
||||
!_dbus_string_append (&address, "unix:path=")) ||
|
||||
!_dbus_string_append (&address, path))
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
goto failed_0;
|
||||
}
|
||||
|
||||
fd.fd = _dbus_connect_unix_socket (path, abstract, error);
|
||||
if (fd.fd < 0)
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET (error);
|
||||
goto failed_0;
|
||||
}
|
||||
|
||||
_dbus_verbose ("Successfully connected to unix socket %s\n",
|
||||
path);
|
||||
|
||||
transport = _dbus_transport_new_for_socket (fd, NULL, &address);
|
||||
if (transport == NULL)
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
goto failed_1;
|
||||
}
|
||||
|
||||
_dbus_string_free (&address);
|
||||
|
||||
return transport;
|
||||
|
||||
failed_1:
|
||||
_dbus_close_socket (fd, NULL);
|
||||
failed_0:
|
||||
_dbus_string_free (&address);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new transport for the given binary and arguments. This
|
||||
* creates a client-side of a transport. The process will be forked
|
||||
|
|
@ -180,8 +113,8 @@ _dbus_transport_new_for_exec (const char *path,
|
|||
}
|
||||
}
|
||||
|
||||
fd.fd = _dbus_connect_exec (path, argv, error);
|
||||
if (fd.fd < 0)
|
||||
fd = _dbus_connect_exec (path, argv, error);
|
||||
if (!_dbus_socket_is_valid (fd))
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET (error);
|
||||
goto failed;
|
||||
|
|
@ -202,77 +135,25 @@ _dbus_transport_new_for_exec (const char *path,
|
|||
return transport;
|
||||
|
||||
failed:
|
||||
if (fd.fd >= 0)
|
||||
_dbus_close_socket (fd, NULL);
|
||||
if (_dbus_socket_is_valid (fd))
|
||||
_dbus_close_socket (&fd, NULL);
|
||||
|
||||
_dbus_string_free (&address);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
_dbus_transport_open_unixexec (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 if (strcmp (method, "unixexec") == 0)
|
||||
if (strcmp (method, "unixexec") == 0)
|
||||
{
|
||||
const char *path;
|
||||
unsigned i;
|
||||
|
|
@ -346,8 +227,33 @@ _dbus_transport_open_platform_specific (DBusAddressEntry *entry,
|
|||
return DBUS_TRANSPORT_OPEN_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||
return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
#ifdef DBUS_ENABLE_LAUNCHD
|
||||
else if (strcmp (method, "launchd") == 0)
|
||||
const char *method;
|
||||
|
||||
method = dbus_address_entry_get_method (entry);
|
||||
_dbus_assert (method != NULL);
|
||||
|
||||
if (strcmp (method, "launchd") == 0)
|
||||
{
|
||||
DBusError tmp_error = DBUS_ERROR_INIT;
|
||||
const char *launchd_env_var = dbus_address_entry_get_value (entry, "env");
|
||||
|
|
@ -398,8 +304,8 @@ _dbus_transport_open_platform_specific (DBusAddressEntry *entry,
|
|||
return DBUS_TRANSPORT_OPEN_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
#endif /* DBUS_ENABLE_LAUNCHD */
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||
return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
|
||||
|
|
|
|||
|
|
@ -23,15 +23,13 @@
|
|||
#ifndef DBUS_TRANSPORT_UNIX_H
|
||||
#define DBUS_TRANSPORT_UNIX_H
|
||||
|
||||
#include <dbus/dbus-transport.h>
|
||||
#include <dbus/dbus-transport-protected.h>
|
||||
|
||||
DBUS_BEGIN_DECLS
|
||||
|
||||
DBusTransport* _dbus_transport_new_for_domain_socket (const char *path,
|
||||
dbus_bool_t abstract,
|
||||
DBusError *error);
|
||||
|
||||
|
||||
DBusTransportOpenResult _dbus_transport_open_unixexec (DBusAddressEntry *entry,
|
||||
DBusTransport **transport_p,
|
||||
DBusError *error);
|
||||
DBUS_END_DECLS
|
||||
|
||||
#endif /* DBUS_TRANSPORT_UNIX_H */
|
||||
|
|
|
|||
|
|
@ -348,6 +348,10 @@ static const struct {
|
|||
DBusError *error);
|
||||
} open_funcs[] = {
|
||||
{ _dbus_transport_open_socket },
|
||||
{ _dbus_transport_open_unix_socket },
|
||||
#ifndef _WIN32
|
||||
{ _dbus_transport_open_unixexec },
|
||||
#endif
|
||||
{ _dbus_transport_open_platform_specific },
|
||||
{ _dbus_transport_open_autolaunch }
|
||||
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
|
||||
|
|
|
|||
|
|
@ -3655,18 +3655,14 @@
|
|||
</para>
|
||||
|
||||
<para>
|
||||
When a socket is opened by the D-Bus library it truncates the path
|
||||
name right before the first trailing Nul byte. This is true for both
|
||||
normal paths and abstract paths. Note that this is a departure from
|
||||
previous versions of D-Bus that would create sockets with a fixed
|
||||
length path name. Names which were shorter than the fixed length
|
||||
would be padded by Nul bytes.
|
||||
When a Unix socket is opened by the D-Bus library, the socket address
|
||||
length does not include the whole <literal>struct sockaddr_un</literal>,
|
||||
but only the length of the pathname or abstract string (beside other
|
||||
fields).
|
||||
</para>
|
||||
<para>
|
||||
Unix domain sockets are not available on Windows.
|
||||
On all other platforms, they are the recommended transport for
|
||||
D-Bus, either used alone or in conjunction with
|
||||
<link linkend="transports-systemd">systemd</link> or
|
||||
They are the recommended transport for D-Bus, either used alone or in
|
||||
conjunction with <link linkend="transports-systemd">systemd</link> or
|
||||
<link linkend="transports-launchd">launchd</link> addresses.
|
||||
</para>
|
||||
<para>
|
||||
|
|
@ -3967,14 +3963,6 @@
|
|||
information on situations where these transports have been used,
|
||||
and alternatives to these transports.
|
||||
</para>
|
||||
<para>
|
||||
Implementations of D-Bus on Windows operating systems normally
|
||||
use a nonce-tcp transport via the local loopback interface.
|
||||
This is because the
|
||||
<link linkend="transports-unix-domain-sockets">unix</link>
|
||||
transport, which would otherwise be recommended, is not
|
||||
available on these operating systems.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
On start, the server generates a random 16 byte nonce and writes it
|
||||
|
|
|
|||
|
|
@ -607,6 +607,7 @@ foreach function : check_functions
|
|||
endforeach
|
||||
|
||||
check_headers = [
|
||||
'afunix.h',
|
||||
'alloca.h',
|
||||
'byteswap.h',
|
||||
'crt_externs.h',
|
||||
|
|
|
|||
|
|
@ -86,9 +86,10 @@ setup (Fixture *f,
|
|||
dbus_error_init (&f->e);
|
||||
g_queue_init (&f->client_messages);
|
||||
|
||||
if ((g_str_has_prefix (addr, "tcp:") ||
|
||||
g_str_has_prefix (addr, "nonce-tcp:")) &&
|
||||
!test_check_tcp_works ())
|
||||
if ((g_str_has_prefix (addr, "unix:") && !test_check_af_unix_works ()) ||
|
||||
((g_str_has_prefix (addr, "tcp:") ||
|
||||
g_str_has_prefix (addr, "nonce-tcp:")) &&
|
||||
!test_check_tcp_works ()))
|
||||
{
|
||||
f->skip = TRUE;
|
||||
return;
|
||||
|
|
@ -406,26 +407,31 @@ main (int argc,
|
|||
char **argv)
|
||||
{
|
||||
int ret;
|
||||
#ifdef DBUS_UNIX
|
||||
char *tmp = _dbus_strdup ("/tmp");
|
||||
#else
|
||||
char *tmp = dbus_address_escape_value (g_get_tmp_dir ());
|
||||
#endif
|
||||
gchar *unix_tmpdir = g_strdup_printf ("unix:tmpdir=%s", tmp);
|
||||
|
||||
test_init (&argc, &argv);
|
||||
|
||||
g_test_add ("/corrupt/tcp", Fixture, "tcp:host=127.0.0.1", setup,
|
||||
test_corrupt, teardown);
|
||||
|
||||
#ifdef DBUS_UNIX
|
||||
g_test_add ("/corrupt/unix", Fixture, "unix:tmpdir=/tmp", setup,
|
||||
g_test_add ("/corrupt/unix", Fixture, unix_tmpdir, setup,
|
||||
test_corrupt, teardown);
|
||||
#endif
|
||||
|
||||
g_test_add ("/corrupt/byte-order/tcp", Fixture, "tcp:host=127.0.0.1", setup,
|
||||
test_byte_order, teardown);
|
||||
|
||||
#ifdef DBUS_UNIX
|
||||
g_test_add ("/corrupt/byte-order/unix", Fixture, "unix:tmpdir=/tmp", setup,
|
||||
g_test_add ("/corrupt/byte-order/unix", Fixture, unix_tmpdir, setup,
|
||||
test_byte_order, teardown);
|
||||
#endif
|
||||
|
||||
ret = g_test_run ();
|
||||
dbus_shutdown ();
|
||||
|
||||
g_free (unix_tmpdir);
|
||||
dbus_free (tmp);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,6 +94,10 @@ test_oom_wrapper (gconstpointer data)
|
|||
{
|
||||
const OOMTestCase *test = data;
|
||||
|
||||
if (g_str_has_prefix (test->data, "unix:") &&
|
||||
!test_check_af_unix_works ())
|
||||
return;
|
||||
|
||||
if ((g_str_has_prefix (test->data, "tcp:") ||
|
||||
g_str_has_prefix (test->data, "nonce-tcp:")) &&
|
||||
!test_check_tcp_works ())
|
||||
|
|
@ -131,6 +135,12 @@ main (int argc,
|
|||
char **argv)
|
||||
{
|
||||
int ret;
|
||||
#ifdef DBUS_UNIX
|
||||
char *tmp = _dbus_strdup ("/tmp");
|
||||
#else
|
||||
char *tmp = dbus_address_escape_value (g_get_tmp_dir ());
|
||||
#endif
|
||||
gchar *unix_tmpdir = g_strdup_printf ("unix:tmpdir=%s", tmp);
|
||||
|
||||
test_init (&argc, &argv);
|
||||
|
||||
|
|
@ -139,13 +149,13 @@ main (int argc,
|
|||
add_oom_test ("/server/new-nonce-tcp", test_new_server, "nonce-tcp:host=127.0.0.1,bind=127.0.0.1");
|
||||
add_oom_test ("/server/new-tcp-star", test_new_server, "tcp:host=127.0.0.1,bind=*");
|
||||
add_oom_test ("/server/new-tcp-v4", test_new_server, "tcp:host=127.0.0.1,bind=127.0.0.1,family=ipv4");
|
||||
#ifdef DBUS_UNIX
|
||||
add_oom_test ("/server/unix", test_new_server, "unix:tmpdir=/tmp");
|
||||
#endif
|
||||
add_oom_test ("/server/unix", test_new_server, unix_tmpdir);
|
||||
|
||||
ret = g_test_run ();
|
||||
|
||||
g_queue_free_full (test_cases_to_free, g_free);
|
||||
dbus_shutdown ();
|
||||
g_free (unix_tmpdir);
|
||||
dbus_free (tmp);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,9 +99,10 @@ setup (Fixture *f,
|
|||
dbus_error_init (&f->e);
|
||||
g_queue_init (&f->server_messages);
|
||||
|
||||
if ((g_str_has_prefix (addr, "tcp:") ||
|
||||
g_str_has_prefix (addr, "nonce-tcp:")) &&
|
||||
!test_check_tcp_works ())
|
||||
if ((g_str_has_prefix (addr, "unix:") && !test_check_af_unix_works ()) ||
|
||||
((g_str_has_prefix (addr, "tcp:") ||
|
||||
g_str_has_prefix (addr, "nonce-tcp:")) &&
|
||||
!test_check_tcp_works ()))
|
||||
{
|
||||
f->skip = TRUE;
|
||||
return;
|
||||
|
|
@ -116,7 +117,6 @@ setup (Fixture *f,
|
|||
test_server_setup (f->ctx, f->server);
|
||||
}
|
||||
|
||||
#ifdef DBUS_UNIX
|
||||
static void
|
||||
setup_runtime (Fixture *f,
|
||||
gconstpointer addr)
|
||||
|
|
@ -131,6 +131,7 @@ setup_runtime (Fixture *f,
|
|||
/* we're relying on being single-threaded for this to be safe */
|
||||
f->saved_runtime_dir = g_strdup (g_getenv ("XDG_RUNTIME_DIR"));
|
||||
g_setenv ("XDG_RUNTIME_DIR", f->tmp_runtime_dir, TRUE);
|
||||
g_test_message ("XDG_RUNTIME_DIR %s", f->tmp_runtime_dir);
|
||||
|
||||
setup (f, addr);
|
||||
|
||||
|
|
@ -140,9 +141,12 @@ setup_runtime (Fixture *f,
|
|||
listening_at = dbus_server_get_address (f->server);
|
||||
g_test_message ("listening at %s", listening_at);
|
||||
g_assert (g_str_has_prefix (listening_at, "unix:path="));
|
||||
#ifndef DBUS_WIN
|
||||
/* FIXME: on gitlab CI win32, it doesn't use runtime dir, why..? */
|
||||
g_assert (strstr (listening_at, "dbus%3ddaemon%3dtest.") != NULL);
|
||||
g_assert (strstr (listening_at, "/bus,") != NULL ||
|
||||
g_str_has_suffix (listening_at, "/bus"));
|
||||
g_assert (strstr (listening_at, DBUS_DIR_SEPARATOR_S "bus,") != NULL ||
|
||||
g_str_has_suffix (listening_at, DBUS_DIR_SEPARATOR_S "bus"));
|
||||
#endif
|
||||
|
||||
dbus_free (listening_at);
|
||||
}
|
||||
|
|
@ -166,11 +170,12 @@ setup_no_runtime (Fixture *f,
|
|||
g_test_message ("listening at %s", listening_at);
|
||||
/* we have fallen back to something in /tmp, either abstract or not */
|
||||
g_assert (g_str_has_prefix (listening_at, "unix:"));
|
||||
g_assert (strstr (listening_at, "=/tmp/") != NULL);
|
||||
#ifdef DBUS_UNIX
|
||||
g_assert (strstr (listening_at, "=/tmp" DBUS_DIR_SEPARATOR_S) != NULL);
|
||||
#endif
|
||||
|
||||
dbus_free (listening_at);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
test_connect (Fixture *f,
|
||||
|
|
@ -221,8 +226,7 @@ test_connect (Fixture *f,
|
|||
g_assert_cmpstr (dbus_address_entry_get_value (entries[0], "noncefile"),
|
||||
!=, NULL);
|
||||
}
|
||||
#ifdef DBUS_UNIX
|
||||
else if (g_strcmp0 (listening_address, "unix:tmpdir=/tmp") == 0)
|
||||
else if (g_str_has_prefix (listening_address, "unix:tmpdir="))
|
||||
{
|
||||
g_assert_cmpstr (dbus_address_entry_get_method (entries[0]), ==, "unix");
|
||||
|
||||
|
|
@ -231,7 +235,7 @@ test_connect (Fixture *f,
|
|||
const char *abstract = dbus_address_entry_get_value (entries[0],
|
||||
"abstract");
|
||||
|
||||
g_assert_true (g_str_has_prefix (abstract, "/tmp/dbus-"));
|
||||
g_assert_true (g_str_has_prefix (abstract, "/tmp" DBUS_DIR_SEPARATOR_S "dbus-"));
|
||||
g_assert_cmpstr (dbus_address_entry_get_value (entries[0], "path"),
|
||||
==, NULL);
|
||||
}
|
||||
|
|
@ -241,26 +245,29 @@ test_connect (Fixture *f,
|
|||
"path");
|
||||
|
||||
g_assert_nonnull (path);
|
||||
g_assert_true (g_str_has_prefix (path, "/tmp/dbus-"));
|
||||
#ifdef DBUS_UNIX
|
||||
g_assert_true (g_str_has_prefix (path, "/tmp" DBUS_DIR_SEPARATOR_S "dbus-"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (listening_address, "unix:dir=/tmp") == 0)
|
||||
else if (g_str_has_prefix (listening_address, "unix:dir="))
|
||||
{
|
||||
const char *path = dbus_address_entry_get_value (entries[0],
|
||||
"path");
|
||||
|
||||
g_assert_cmpstr (dbus_address_entry_get_method (entries[0]), ==, "unix");
|
||||
g_assert_nonnull (path);
|
||||
g_assert_true (g_str_has_prefix (path, "/tmp/dbus-"));
|
||||
#ifdef DBUS_UNIX
|
||||
g_assert_true (g_str_has_prefix (path, "/tmp" DBUS_DIR_SEPARATOR_S "dbus-"));
|
||||
#endif
|
||||
}
|
||||
else if (g_strcmp0 (listening_address,
|
||||
"unix:runtime=yes;unix:tmpdir=/tmp") == 0)
|
||||
else if (g_str_has_prefix (listening_address,
|
||||
"unix:runtime=yes;unix:tmpdir="))
|
||||
{
|
||||
g_assert_cmpstr (dbus_address_entry_get_method (entries[0]), ==, "unix");
|
||||
/* No particular statement about the path here: for that see
|
||||
* setup_runtime() and setup_no_runtime() */
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
|
|
@ -441,7 +448,6 @@ teardown (Fixture *f,
|
|||
test_main_context_unref (f->ctx);
|
||||
}
|
||||
|
||||
#ifdef DBUS_UNIX
|
||||
static void
|
||||
teardown_no_runtime (Fixture *f,
|
||||
gconstpointer addr)
|
||||
|
|
@ -479,13 +485,20 @@ teardown_runtime (Fixture *f,
|
|||
g_free (f->saved_runtime_dir);
|
||||
g_free (f->tmp_runtime_dir);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char **argv)
|
||||
{
|
||||
int ret;
|
||||
#ifdef DBUS_UNIX
|
||||
char *tmp = _dbus_strdup ("/tmp");
|
||||
#else
|
||||
char *tmp = dbus_address_escape_value (g_get_tmp_dir ());
|
||||
#endif
|
||||
gchar *unix_tmpdir = g_strdup_printf ("unix:tmpdir=%s", tmp);
|
||||
gchar *unix_dir = g_strdup_printf ("unix:dir=%s", tmp);
|
||||
gchar *unix_runtime_or_fallback = g_strdup_printf ("unix:runtime=yes;%s", unix_tmpdir);
|
||||
|
||||
test_init (&argc, &argv);
|
||||
|
||||
|
|
@ -502,28 +515,31 @@ main (int argc,
|
|||
g_test_add ("/message/bad-guid/tcp", Fixture, "tcp:host=127.0.0.1", setup,
|
||||
test_bad_guid, teardown);
|
||||
|
||||
#ifdef DBUS_UNIX
|
||||
g_test_add ("/connect/unix/tmpdir", Fixture, "unix:tmpdir=/tmp", setup,
|
||||
g_test_add ("/connect/unix/tmpdir", Fixture, unix_tmpdir, setup,
|
||||
test_connect, teardown);
|
||||
g_test_add ("/message/unix/tmpdir", Fixture, "unix:tmpdir=/tmp", setup,
|
||||
g_test_add ("/message/unix/tmpdir", Fixture, unix_tmpdir, setup,
|
||||
test_message, teardown);
|
||||
g_test_add ("/connect/unix/dir", Fixture, "unix:dir=/tmp", setup,
|
||||
g_test_add ("/connect/unix/dir", Fixture, unix_dir, setup,
|
||||
test_connect, teardown);
|
||||
g_test_add ("/message/unix/dir", Fixture, "unix:dir=/tmp", setup,
|
||||
g_test_add ("/message/unix/dir", Fixture, unix_dir, setup,
|
||||
test_message, teardown);
|
||||
|
||||
g_test_add ("/connect/unix/runtime", Fixture,
|
||||
"unix:runtime=yes;unix:tmpdir=/tmp", setup_runtime, test_connect,
|
||||
unix_runtime_or_fallback, setup_runtime, test_connect,
|
||||
teardown_runtime);
|
||||
g_test_add ("/connect/unix/no-runtime", Fixture,
|
||||
"unix:runtime=yes;unix:tmpdir=/tmp", setup_no_runtime, test_connect,
|
||||
unix_runtime_or_fallback, setup_no_runtime, test_connect,
|
||||
teardown_no_runtime);
|
||||
|
||||
g_test_add ("/message/bad-guid/unix", Fixture, "unix:tmpdir=/tmp", setup,
|
||||
g_test_add ("/message/bad-guid/unix", Fixture, unix_tmpdir, setup,
|
||||
test_bad_guid, teardown);
|
||||
#endif
|
||||
|
||||
ret = g_test_run ();
|
||||
dbus_shutdown ();
|
||||
|
||||
g_free (unix_tmpdir);
|
||||
g_free (unix_dir);
|
||||
g_free (unix_runtime_or_fallback);
|
||||
dbus_free (tmp);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
23
test/relay.c
23
test/relay.c
|
|
@ -129,9 +129,10 @@ setup (Fixture *f,
|
|||
dbus_error_init (&f->e);
|
||||
g_queue_init (&f->messages);
|
||||
|
||||
if ((g_str_has_prefix (address, "tcp:") ||
|
||||
g_str_has_prefix (address, "nonce-tcp:")) &&
|
||||
!test_check_tcp_works ())
|
||||
if ((g_str_has_prefix (address, "unix:") && !test_check_af_unix_works ()) ||
|
||||
((g_str_has_prefix (address, "tcp:") ||
|
||||
g_str_has_prefix (address, "nonce-tcp:")) &&
|
||||
!test_check_tcp_works ()))
|
||||
{
|
||||
f->skip = TRUE;
|
||||
return;
|
||||
|
|
@ -338,6 +339,12 @@ main (int argc,
|
|||
char **argv)
|
||||
{
|
||||
int ret;
|
||||
#ifdef DBUS_UNIX
|
||||
char *tmp = _dbus_strdup ("/tmp");
|
||||
#else
|
||||
char *tmp = dbus_address_escape_value (g_get_tmp_dir ());
|
||||
#endif
|
||||
gchar *unix_tmpdir = g_strdup_printf ("unix:tmpdir=%s", tmp);
|
||||
|
||||
test_init (&argc, &argv);
|
||||
|
||||
|
|
@ -348,16 +355,16 @@ main (int argc,
|
|||
g_test_add ("/limit/tcp", Fixture, "tcp:host=127.0.0.1", setup,
|
||||
test_limit, teardown);
|
||||
|
||||
#ifdef DBUS_UNIX
|
||||
g_test_add ("/connect/unix", Fixture, "unix:tmpdir=/tmp", setup,
|
||||
g_test_add ("/connect/unix", Fixture, unix_tmpdir, setup,
|
||||
test_connect, teardown);
|
||||
g_test_add ("/relay/unix", Fixture, "unix:tmpdir=/tmp", setup,
|
||||
g_test_add ("/relay/unix", Fixture, unix_tmpdir, setup,
|
||||
test_relay, teardown);
|
||||
g_test_add ("/limit/unix", Fixture, "unix:tmpdir=/tmp", setup,
|
||||
g_test_add ("/limit/unix", Fixture, unix_tmpdir, setup,
|
||||
test_limit, teardown);
|
||||
#endif
|
||||
|
||||
ret = g_test_run ();
|
||||
dbus_shutdown ();
|
||||
g_free (unix_tmpdir);
|
||||
dbus_free (tmp);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -899,6 +899,25 @@ test_check_tcp_works (void)
|
|||
#endif
|
||||
}
|
||||
|
||||
gboolean
|
||||
test_check_af_unix_works (void)
|
||||
{
|
||||
#if defined(G_OS_WIN32) && !defined(HAVE_AFUNIX_H)
|
||||
/* AFUNIX support is compiled out, skip system check */
|
||||
return FALSE;
|
||||
#else
|
||||
#ifdef G_OS_WIN32
|
||||
SOCKET fd = socket (AF_UNIX, SOCK_STREAM, 0);
|
||||
closesocket (fd);
|
||||
return fd != INVALID_SOCKET;
|
||||
#else
|
||||
int fd = socket (AF_UNIX, SOCK_STREAM, 0);
|
||||
close (fd);
|
||||
return fd >= 0;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the result of an async operation. @user_data is a pointer to a
|
||||
* variable that can store @result, initialized to %NULL.
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ backported_g_steal_pointer (gpointer pointer_to_pointer)
|
|||
#endif
|
||||
|
||||
gboolean test_check_tcp_works (void);
|
||||
gboolean test_check_af_unix_works (void);
|
||||
|
||||
void test_store_result_cb (GObject *source_object,
|
||||
GAsyncResult *result,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue