From bf14ac7dda8f33e7ae37b18ec412ad5a9ea02eca Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Fri, 14 Oct 2016 11:06:39 -0400 Subject: [PATCH] Support runtime relocation in Unix with the DBUS_ROOT environment variable. This patch also cleans up some unused defines and moves a few functions now shared by the Unix and Windows backends into a common location. --- bus/config-parser.c | 82 +++++++++++++++++++++++++++ cmake/CMakeLists.txt | 6 -- cmake/config.h.cmake | 2 - dbus/Makefile.am | 5 -- dbus/dbus-sysdeps-util-unix.c | 129 +++++++++++++++++++++++++++++------------- dbus/dbus-sysdeps-util-win.c | 56 +----------------- dbus/dbus-sysdeps-util.c | 53 +++++++++++++++++ 7 files changed, 227 insertions(+), 106 deletions(-) diff --git a/bus/config-parser.c b/bus/config-parser.c index 5af1024..b6b61e4 100644 --- a/bus/config-parser.c +++ b/bus/config-parser.c @@ -3627,6 +3627,80 @@ test_default_system_servicedirs (void) _dbus_string_free (&progs); return TRUE; } + +static dbus_bool_t +test_relocated_system_servicedirs (void) +{ + DBusList *dirs; + DBusList *link; + + dirs = NULL; + + printf ("Testing relocated system service directories\n"); + + if (!dbus_setenv ("DBUS_ROOT", "/testroot")) + _dbus_assert_not_reached ("couldn't setenv DBUS_ROOT"); + + if (!_dbus_get_standard_system_servicedirs (&dirs)) + _dbus_assert_not_reached ("couldn't get stardard system dirs"); + + if (!dbus_setenv ("DBUS_ROOT", NULL)) + _dbus_assert_not_reached ("couldn't unsetenv DBUS_ROOT"); + + /* Find the DATADIR standard dir that got relocated */ + while ((link = _dbus_list_pop_first_link (&dirs))) + { + DBusString path; + + printf (" default service dir: %s\n", (char *)link->data); + _dbus_string_init_const (&path, (char *)link->data); + if (_dbus_string_equal_c_str (&path, "/testroot" DBUS_DATADIR "/dbus-1/system-services")) + return TRUE; + + dbus_free (link->data); + _dbus_list_free_link (link); + } + + printf ("could not find relocated path\n"); + return FALSE; +} + +static dbus_bool_t +test_relocated_session_servicedirs (void) +{ + DBusList *dirs; + DBusList *link; + + dirs = NULL; + + printf ("Testing relocated session service directories\n"); + + if (!dbus_setenv ("DBUS_ROOT", "/testroot")) + _dbus_assert_not_reached ("couldn't setenv DBUS_ROOT"); + + if (!_dbus_get_standard_session_servicedirs (&dirs)) + _dbus_assert_not_reached ("couldn't get stardard session dirs"); + + if (!dbus_setenv ("DBUS_ROOT", NULL)) + _dbus_assert_not_reached ("couldn't unsetenv DBUS_ROOT"); + + /* Find the DATADIR standard dir that got relocated */ + while ((link = _dbus_list_pop_first_link (&dirs))) + { + DBusString path; + + printf (" default service dir: %s\n", (char *)link->data); + _dbus_string_init_const (&path, (char *)link->data); + if (_dbus_string_equal_c_str (&path, "/testroot" DBUS_DATADIR "/dbus-1/services")) + return TRUE; + + dbus_free (link->data); + _dbus_list_free_link (link); + } + + printf ("could not find relocated path\n"); + return FALSE; +} #endif dbus_bool_t @@ -3649,6 +3723,14 @@ bus_config_parser_test (const DBusString *test_data_dir) return FALSE; #endif +#ifndef DBUS_WIN + if (!test_relocated_system_servicedirs()) + return FALSE; + + if (!test_relocated_session_servicedirs()) + return FALSE; +#endif + if (!process_test_valid_subdir (test_data_dir, "valid-config-files", VALID)) return FALSE; diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 5bb4240..eb7ec0b 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -464,8 +464,6 @@ if (WIN32) set (DBUS_SESSION_BUS_LISTEN_ADDRESS "autolaunch:" CACHE STRING "session bus default listening address") set (DBUS_SESSION_BUS_CONNECT_ADDRESS "autolaunch:" CACHE STRING "session bus fallback address for clients") - set (DBUS_SYSTEM_CONFIG_FILE "share/dbus-1/system.conf") - set (DBUS_SESSION_CONFIG_FILE "share/dbus-1/session.conf") # bus-test expects a non empty string set (DBUS_USER "Administrator") set (DBUS_TEST_USER "guest") @@ -473,10 +471,6 @@ if (WIN32) else (WIN32) set (DBUS_SESSION_BUS_LISTEN_ADDRESS "unix:tmpdir=${DBUS_SESSION_SOCKET_DIR}" CACHE STRING "session bus default listening address") set (DBUS_SESSION_BUS_CONNECT_ADDRESS "autolaunch:" CACHE STRING "session bus fallback address for clients") - set (sysconfdir "") - set (configdir ${sysconfdir}/dbus-1 ) - set (DBUS_SYSTEM_CONFIG_FILE ${configdir}/system.conf) - set (DBUS_SESSION_CONFIG_FILE ${configdir}/session.conf) set (DBUS_USER "messagebus") set (DBUS_TEST_USER "nobody") # For best security, assume that all non-Windows platforms can do diff --git a/cmake/config.h.cmake b/cmake/config.h.cmake index c498362..af46ea2 100644 --- a/cmake/config.h.cmake +++ b/cmake/config.h.cmake @@ -18,8 +18,6 @@ #cmakedefine DBUS_DATADIR "@DBUS_DATADIR@" #cmakedefine DBUS_BINDIR "@DBUS_BINDIR@" #cmakedefine DBUS_PREFIX "@DBUS_PREFIX@" -#cmakedefine DBUS_SYSTEM_CONFIG_FILE "@DBUS_SYSTEM_CONFIG_FILE@" -#cmakedefine DBUS_SESSION_CONFIG_FILE "@DBUS_SESSION_CONFIG_FILE@" #cmakedefine DBUS_DAEMON_NAME "@DBUS_DAEMON_NAME@" #cmakedefine DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "@DBUS_SYSTEM_BUS_DEFAULT_ADDRESS@" #cmakedefine DBUS_SESSION_BUS_CONNECT_ADDRESS "@DBUS_SESSION_BUS_CONNECT_ADDRESS@" diff --git a/dbus/Makefile.am b/dbus/Makefile.am index e4aa2ee..5a85803 100644 --- a/dbus/Makefile.am +++ b/dbus/Makefile.am @@ -1,6 +1,3 @@ - -dbusdatadir=$(datadir)/dbus-1 - AM_CPPFLAGS = \ $(CODE_COVERAGE_CPPFLAGS) \ -I$(top_builddir) \ @@ -10,8 +7,6 @@ AM_CPPFLAGS = \ $(VALGRIND_CFLAGS) \ -DDBUS_COMPILATION \ -DDBUS_MACHINE_UUID_FILE=\""$(localstatedir)/lib/dbus/machine-id"\" \ - -DDBUS_SYSTEM_CONFIG_FILE=\""$(dbusdatadir)/system.conf"\" \ - -DDBUS_SESSION_CONFIG_FILE=\""$(dbusdatadir)/session.conf"\" \ $(NULL) AM_CFLAGS = \ diff --git a/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c index d9e8c4f..fada816 100644 --- a/dbus/dbus-sysdeps-util-unix.c +++ b/dbus/dbus-sysdeps-util-unix.c @@ -1177,7 +1177,8 @@ fail: /** * Replace the DBUS_PREFIX in the given path, in-place, by the * current D-Bus installation directory. On Unix this function - * does nothing, successfully. + * will prefix the value of $DBUS_ROOT if defined; otherwise, + * it will do nothing. * * @param path path to edit * @return #FALSE on OOM @@ -1185,7 +1186,46 @@ fail: dbus_bool_t _dbus_replace_install_prefix (DBusString *path) { + char *path_data; + const char *env_root; + DBusString root; + + env_root = _dbus_getenv ("DBUS_ROOT"); + + if (env_root == NULL) + { + /* cannot determine install root, leave path unchanged */ + return TRUE; + } + + _dbus_string_init_const (&root, env_root); + + if (!_dbus_string_replace_len (&root, 0, _dbus_string_get_length (&root), + path, 0, 0)) + return FALSE; + + return TRUE; +} + +static dbus_bool_t +_dbus_string_init_datadir (DBusString *path) +{ + if (!_dbus_string_init (path)) + goto oom; + + /* DBUS_DATADIR is assumed to be absolute; the build systems should + * ensure that. */ + if (!_dbus_string_append (path, DBUS_DATADIR) || + !_dbus_replace_install_prefix (path)) + { + _dbus_string_free (path); + goto oom; + } + return TRUE; + +oom: + return FALSE; } #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" @@ -1202,7 +1242,7 @@ _dbus_replace_install_prefix (DBusString *path) * * and * - * DBUS_DATADIR + * relocated DBUS_DATADIR * * @param dirs the directory list we are returning * @returns #FALSE on OOM @@ -1265,8 +1305,21 @@ _dbus_get_standard_session_servicedirs (DBusList **dirs) * however the config parser should take * care of duplicates */ - if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR)) - goto oom; + { + DBusString datadir; + + if (!_dbus_string_init_datadir (&datadir)) + goto oom; + + if (!_dbus_string_append (&servicedir_path, + _dbus_string_get_const_data (&datadir))) + { + _dbus_string_free (&datadir); + goto oom; + } + + _dbus_string_free (&datadir); + } if (!_dbus_split_paths_and_append (&servicedir_path, DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, @@ -1292,7 +1345,7 @@ _dbus_get_standard_session_servicedirs (DBusList **dirs) * * and * - * DBUS_DATADIR + * relocated DBUS_DATADIR * * On Windows there is no system bus and this function can return nothing. * @@ -1312,46 +1365,44 @@ _dbus_get_standard_system_servicedirs (DBusList **dirs) * facilitate early boot system bus activation where /usr might not * be available. */ - static const char standard_search_path[] = + static const char early_standard_search_path[] = "/usr/local/share:" - "/usr/share:" - DBUS_DATADIR ":" - "/lib"; + "/usr/share:"; + static const char late_standard_search_path[] = + ":/lib"; DBusString servicedir_path; + DBusString datadir; - _dbus_string_init_const (&servicedir_path, standard_search_path); + if (!_dbus_string_init (&servicedir_path)) + return FALSE; - return _dbus_split_paths_and_append (&servicedir_path, - DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, - dirs); -} + if (!_dbus_string_init_datadir (&datadir)) + { + _dbus_string_free (&servicedir_path); + return FALSE; + } -/** - * Get the absolute path of the system.conf file - * (there is no system bus on Windows so this can just - * return FALSE and print a warning or something) - * - * @param str the string to append to, which must be empty on entry - * @returns #FALSE if no memory - */ -dbus_bool_t -_dbus_get_system_config_file (DBusString *str) -{ - _dbus_assert (_dbus_string_get_length (str) == 0); + if (!_dbus_string_append (&servicedir_path, early_standard_search_path)) + goto oom; - return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE); -} + if (!_dbus_string_append (&servicedir_path, + _dbus_string_get_const_data (&datadir))) + goto oom; -/** - * Get the absolute path of the session.conf file. - * - * @param str the string to append to, which must be empty on entry - * @returns #FALSE if no memory - */ -dbus_bool_t -_dbus_get_session_config_file (DBusString *str) -{ - _dbus_assert (_dbus_string_get_length (str) == 0); + if (!_dbus_string_append (&servicedir_path, late_standard_search_path)) + goto oom; - return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE); + if (!_dbus_split_paths_and_append (&servicedir_path, + DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, + dirs)) + goto oom; + + _dbus_string_free (&datadir); + _dbus_string_free (&servicedir_path); + return TRUE; + +oom: + _dbus_string_free (&datadir); + _dbus_string_free (&servicedir_path); + return FALSE; } diff --git a/dbus/dbus-sysdeps-util-win.c b/dbus/dbus-sysdeps-util-win.c index eb860f4..23668ce 100644 --- a/dbus/dbus-sysdeps-util-win.c +++ b/dbus/dbus-sysdeps-util-win.c @@ -1416,7 +1416,8 @@ _dbus_command_for_pid (unsigned long pid, /** * Replace the DBUS_PREFIX in the given path, in-place, by the * current D-Bus installation directory. On Unix this function - * does nothing, successfully. + * will prefix the value of $DBUS_ROOT if defined; otherwise, + * it will do nothing. * * @param path path to edit * @return #FALSE on OOM @@ -1596,56 +1597,3 @@ _dbus_get_standard_system_servicedirs (DBusList **dirs) *dirs = NULL; return TRUE; } - -static dbus_bool_t -_dbus_get_config_file_name (DBusString *str, - const char *basename) -{ - DBusString tmp; - - if (!_dbus_string_append (str, DBUS_DATADIR) || - !_dbus_replace_install_prefix (str)) - return FALSE; - - _dbus_string_init_const (&tmp, "dbus-1"); - - if (!_dbus_concat_dir_and_file (str, &tmp)) - return FALSE; - - _dbus_string_init_const (&tmp, basename); - - if (!_dbus_concat_dir_and_file (str, &tmp)) - return FALSE; - - return TRUE; -} - -/** - * Get the absolute path of the system.conf file - * (there is no system bus on Windows so this can just - * return FALSE and print a warning or something) - * - * @param str the string to append to, which must be empty on entry - * @returns #FALSE if no memory - */ -dbus_bool_t -_dbus_get_system_config_file (DBusString *str) -{ - _dbus_assert (_dbus_string_get_length (str) == 0); - - return _dbus_get_config_file_name(str, "system.conf"); -} - -/** - * Get the absolute path of the session.conf file. - * - * @param str the string to append to, which must be empty on entry - * @returns #FALSE if no memory - */ -dbus_bool_t -_dbus_get_session_config_file (DBusString *str) -{ - _dbus_assert (_dbus_string_get_length (str) == 0); - - return _dbus_get_config_file_name(str, "session.conf"); -} diff --git a/dbus/dbus-sysdeps-util.c b/dbus/dbus-sysdeps-util.c index f35c966..f4a13ec 100644 --- a/dbus/dbus-sysdeps-util.c +++ b/dbus/dbus-sysdeps-util.c @@ -80,6 +80,59 @@ _dbus_get_environment (void) return environment; } +static dbus_bool_t +_dbus_get_config_file_name (DBusString *str, + const char *basename) +{ + DBusString tmp; + + if (!_dbus_string_append (str, DBUS_DATADIR) || + !_dbus_replace_install_prefix (str)) + return FALSE; + + _dbus_string_init_const (&tmp, "dbus-1"); + + if (!_dbus_concat_dir_and_file (str, &tmp)) + return FALSE; + + _dbus_string_init_const (&tmp, basename); + + if (!_dbus_concat_dir_and_file (str, &tmp)) + return FALSE; + + return TRUE; +} + +/** + * Get the absolute path of the system.conf file + * (there is no system bus on Windows so this can just + * return FALSE and print a warning or something) + * + * @param str the string to append to, which must be empty on entry + * @returns #FALSE if no memory + */ +dbus_bool_t +_dbus_get_system_config_file (DBusString *str) +{ + _dbus_assert (_dbus_string_get_length (str) == 0); + + return _dbus_get_config_file_name(str, "system.conf"); +} + +/** + * Get the absolute path of the session.conf file. + * + * @param str the string to append to, which must be empty on entry + * @returns #FALSE if no memory + */ +dbus_bool_t +_dbus_get_session_config_file (DBusString *str) +{ + _dbus_assert (_dbus_string_get_length (str) == 0); + + return _dbus_get_config_file_name(str, "session.conf"); +} + #ifdef DBUS_ENABLE_EMBEDDED_TESTS static void check_dirname (const char *filename, -- 2.7.4