From: Mike Yuan Date: Sat, 7 Sep 2024 17:12:58 +0000 (+0200) Subject: path-lookup: refactor lookup_paths_init() search paths handling X-Git-Tag: v257-rc1~317^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5ce4902249e4f10d65022f097d8b7ac0348f3f4f;p=thirdparty%2Fsystemd.git path-lookup: refactor lookup_paths_init() search paths handling * Rename user_dirs() -> user_unit_search_dirs() and port to user_search_dirs() * Use STRV_IFNOTNULL to guard paths that could be NULL, assert otherwise --- diff --git a/src/libsystemd/sd-path/path-lookup.c b/src/libsystemd/sd-path/path-lookup.c index 6200acd8f52..d56144f3cc7 100644 --- a/src/libsystemd/sd-path/path-lookup.c +++ b/src/libsystemd/sd-path/path-lookup.c @@ -118,74 +118,6 @@ int xdg_user_dirs(char ***ret_config_dirs, char ***ret_data_dirs) { return 0; } -static char** user_dirs( - const char *persistent_config, - const char *runtime_config, - const char *global_persistent_config, - const char *global_runtime_config, - const char *generator, - const char *generator_early, - const char *generator_late, - const char *transient, - const char *persistent_control, - const char *runtime_control) { - - _cleanup_strv_free_ char **config_dirs = NULL, **data_dirs = NULL; - _cleanup_free_ char *data_home = NULL; - _cleanup_strv_free_ char **res = NULL; - int r; - - r = xdg_user_dirs(&config_dirs, &data_dirs); - if (r < 0) - return NULL; - - r = xdg_user_data_dir("/systemd/user", &data_home); - if (r < 0 && r != -ENXIO) - return NULL; - - /* Now merge everything we found. */ - if (strv_extend_many( - &res, - persistent_control, - runtime_control, - transient, - generator_early, - persistent_config) < 0) - return NULL; - - if (strv_extend_strv_concat(&res, (const char* const*) config_dirs, "/systemd/user") < 0) - return NULL; - - /* global config has lower priority than the user config of the same type */ - if (strv_extend(&res, global_persistent_config) < 0) - return NULL; - - if (strv_extend_strv(&res, (char**) user_config_unit_paths, false) < 0) - return NULL; - - if (strv_extend_many( - &res, - runtime_config, - global_runtime_config, - generator, - data_home) < 0) - return NULL; - - if (strv_extend_strv_concat(&res, (const char* const*) data_dirs, "/systemd/user") < 0) - return NULL; - - if (strv_extend_strv(&res, (char**) user_data_unit_paths, false) < 0) - return NULL; - - if (strv_extend(&res, generator_late) < 0) - return NULL; - - if (path_strv_make_absolute_cwd(res) < 0) - return NULL; - - return TAKE_PTR(res); -} - bool path_is_user_data_dir(const char *path) { assert(path); @@ -417,6 +349,70 @@ static int get_paths_from_environ(const char *var, char ***ret) { return append; } +static char** user_unit_search_dirs( + const char *persistent_config, + const char *runtime_config, + const char *global_persistent_config, + const char *global_runtime_config, + const char *generator, + const char *generator_early, + const char *generator_late, + const char *transient, + const char *persistent_control, + const char *runtime_control) { + + _cleanup_strv_free_ char **paths = NULL, **config_dirs = NULL, **data_dirs = NULL; + + /* The returned strv might contain duplicates, and we expect caller to filter them. */ + + assert(persistent_config); + assert(global_persistent_config); + assert(global_runtime_config); + assert(persistent_control); + + if (user_search_dirs("/systemd/user", &config_dirs, &data_dirs) < 0) + return NULL; + + paths = strv_new(persistent_control, + STRV_IFNOTNULL(runtime_control), + STRV_IFNOTNULL(transient), + STRV_IFNOTNULL(generator_early), + persistent_config); + if (!paths) + return NULL; + + if (strv_extend_strv_consume(&paths, TAKE_PTR(config_dirs), /* filter_duplicates = */ false) < 0) + return NULL; + + /* global config has lower priority than the user config of the same type */ + if (strv_extend(&paths, global_persistent_config) < 0) + return NULL; + + if (strv_extend_strv(&paths, (char* const*) user_config_unit_paths, /* filter_duplicates = */ false) < 0) + return NULL; + + /* strv_extend_many() can deal with NULL-s in arguments */ + if (strv_extend_many(&paths, + runtime_config, + global_runtime_config, + generator) < 0) + return NULL; + + if (strv_extend_strv_consume(&paths, TAKE_PTR(data_dirs), /* filter_duplicates = */ false) < 0) + return NULL; + + if (strv_extend_strv(&paths, (char* const*) user_data_unit_paths, false) < 0) + return NULL; + + if (strv_extend(&paths, generator_late) < 0) + return NULL; + + if (path_strv_make_absolute_cwd(paths) < 0) + return NULL; + + return TAKE_PTR(paths); +} + int lookup_paths_init( LookupPaths *lp, RuntimeScope scope, @@ -455,7 +451,7 @@ int lookup_paths_init( return -ENOMEM; } - if (flags & LOOKUP_PATHS_TEMPORARY_GENERATED) { + if (FLAGS_SET(flags, LOOKUP_PATHS_TEMPORARY_GENERATED)) { r = mkdtemp_malloc("/tmp/systemd-temporary-XXXXXX", &tempdir); if (r < 0) return log_debug_errno(r, "Failed to create temporary directory: %m"); @@ -480,7 +476,7 @@ int lookup_paths_init( if (r < 0 && r != -EOPNOTSUPP) return r; - if ((flags & LOOKUP_PATHS_EXCLUDE_GENERATED) == 0) { + if (!FLAGS_SET(flags, LOOKUP_PATHS_EXCLUDE_GENERATED)) { /* Note: if XDG_RUNTIME_DIR is not set, this will fail completely with ENXIO */ r = acquire_generator_dirs(scope, tempdir, &generator, &generator_early, &generator_late); @@ -503,67 +499,65 @@ int lookup_paths_init( _cleanup_strv_free_ char **add = NULL; - /* For the user units we include share/ in the search - * path in order to comply with the XDG basedir spec. - * For the system stuff we avoid such nonsense. OTOH - * we include /lib in the search path for the system - * stuff but avoid it for user stuff. */ + /* For the user units we include share/ in the search paths in order to comply with + * the XDG basedir spec. For the system stuff we avoid such nonsense. OTOH we include (/usr/)lib/ + * in the search paths for the system stuff but avoid it for user stuff. */ + + assert(persistent_config); switch (scope) { case RUNTIME_SCOPE_SYSTEM: - add = strv_new( - /* If you modify this you also want to modify - * systemdsystemunitpath= in systemd.pc.in! */ - STRV_IFNOTNULL(persistent_control), - STRV_IFNOTNULL(runtime_control), - STRV_IFNOTNULL(transient), - STRV_IFNOTNULL(generator_early), - persistent_config, - SYSTEM_CONFIG_UNIT_DIR, - "/etc/systemd/system", - STRV_IFNOTNULL(persistent_attached), - runtime_config, - "/run/systemd/system", - STRV_IFNOTNULL(runtime_attached), - STRV_IFNOTNULL(generator), - "/usr/local/lib/systemd/system", - SYSTEM_DATA_UNIT_DIR, - "/usr/lib/systemd/system", - /* To be used ONLY for images which might be legacy split-usr */ - STRV_IFNOTNULL(flags & LOOKUP_PATHS_SPLIT_USR ? "/lib/systemd/system" : NULL), - STRV_IFNOTNULL(generator_late)); + /* If you modify this you also want to modify systemdsystemunitpath= in systemd.pc.in! */ + add = strv_new(ASSERT_PTR(persistent_control), + ASSERT_PTR(runtime_control), + ASSERT_PTR(transient), + STRV_IFNOTNULL(generator_early), + persistent_config, + SYSTEM_CONFIG_UNIT_DIR, + "/etc/systemd/system", + ASSERT_PTR(persistent_attached), + ASSERT_PTR(runtime_config), + "/run/systemd/system", + ASSERT_PTR(runtime_attached), + STRV_IFNOTNULL(generator), + "/usr/local/lib/systemd/system", + SYSTEM_DATA_UNIT_DIR, + "/usr/lib/systemd/system", + /* To be used ONLY for images which might be legacy split-usr */ + FLAGS_SET(flags, LOOKUP_PATHS_SPLIT_USR) ? "/lib/systemd/system" : STRV_IGNORE, + STRV_IFNOTNULL(generator_late)); break; case RUNTIME_SCOPE_GLOBAL: - add = strv_new( - /* If you modify this you also want to modify - * systemduserunitpath= in systemd.pc.in, and - * the arrays in user_dirs() above! */ - STRV_IFNOTNULL(persistent_control), - STRV_IFNOTNULL(runtime_control), - STRV_IFNOTNULL(transient), - STRV_IFNOTNULL(generator_early), - persistent_config, - USER_CONFIG_UNIT_DIR, - "/etc/systemd/user", - runtime_config, - "/run/systemd/user", - STRV_IFNOTNULL(generator), - "/usr/local/share/systemd/user", - "/usr/share/systemd/user", - "/usr/local/lib/systemd/user", - USER_DATA_UNIT_DIR, - "/usr/lib/systemd/user", - STRV_IFNOTNULL(generator_late)); + /* If you modify this you also want to modify systemduserunitpath= in systemd.pc.in, + * and RUNTIME_SCOPE_USER search paths below! */ + + assert(!persistent_control); + assert(!runtime_control); + assert(!transient); + assert(!generator_early); + assert(!generator); + assert(!generator_late); + + add = strv_new(persistent_config, + USER_CONFIG_UNIT_DIR, + "/etc/systemd/user", + ASSERT_PTR(runtime_config), + "/run/systemd/user", + "/usr/local/share/systemd/user", + "/usr/share/systemd/user", + "/usr/local/lib/systemd/user", + USER_DATA_UNIT_DIR, + "/usr/lib/systemd/user"); break; case RUNTIME_SCOPE_USER: - add = user_dirs(persistent_config, runtime_config, - global_persistent_config, global_runtime_config, - generator, generator_early, generator_late, - transient, - persistent_control, runtime_control); + add = user_unit_search_dirs(persistent_config, runtime_config, + global_persistent_config, global_runtime_config, + generator, generator_early, generator_late, + transient, + persistent_control, runtime_control); break; default: @@ -573,14 +567,10 @@ int lookup_paths_init( if (!add) return -ENOMEM; - if (paths) { - r = strv_extend_strv(&paths, add, true); - if (r < 0) - return r; - } else - /* Small optimization: if paths is NULL (and it usually is), we can simply assign 'add' to it, - * and don't have to copy anything */ - paths = TAKE_PTR(add); + /* strv_uniq() below would filter all duplicates against the final strv */ + r = strv_extend_strv_consume(&paths, TAKE_PTR(add), /* filter_duplicates = */ false); + if (r < 0) + return r; } r = patch_root_prefix(&persistent_config, root);