]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
path-lookup: unify acquire_{config,control,attached}_dir()
authorMike Yuan <me@yhndnzj.com>
Sun, 25 Aug 2024 18:07:12 +0000 (20:07 +0200)
committerMike Yuan <me@yhndnzj.com>
Sun, 6 Oct 2024 17:32:54 +0000 (19:32 +0200)
Note that -ENXIO reported by xdg_user_config_dir() is now properly
propagated rather than ignored, as unlike XDG_RUNTIME_DIR, XDG_CONFIG_HOME
has a default value hence ENXIO is not really expected.

src/libsystemd/sd-path/path-lookup.c

index 6f6a7cb4b0f8168940c2ed987a63b51bca033e0b..d37da14ec6140bc5ecbe331b0097734699c53343 100644 (file)
@@ -250,137 +250,91 @@ static int acquire_transient_dir(RuntimeScope scope, const char *tempdir, char *
         return 0;
 }
 
-static int acquire_config_dirs(RuntimeScope scope, char **persistent, char **runtime) {
-        _cleanup_free_ char *a = NULL, *b = NULL;
-        int r;
-
-        assert(persistent);
-        assert(runtime);
-
-        switch (scope) {
-
-        case RUNTIME_SCOPE_SYSTEM:
-                a = strdup(SYSTEM_CONFIG_UNIT_DIR);
-                b = strdup("/run/systemd/system");
-                break;
-
-        case RUNTIME_SCOPE_GLOBAL:
-                a = strdup(USER_CONFIG_UNIT_DIR);
-                b = strdup("/run/systemd/user");
-                break;
-
-        case RUNTIME_SCOPE_USER:
-                r = xdg_user_config_dir("/systemd/user", &a);
-                if (r < 0 && r != -ENXIO)
-                        return r;
-
-                r = xdg_user_runtime_dir("/systemd/user", runtime);
-                if (r < 0) {
-                        if (r != -ENXIO)
-                                return r;
-
-                        /* If XDG_RUNTIME_DIR is not set, don't consider that fatal, simply initialize the runtime
-                         * directory to NULL */
-                        *runtime = NULL;
-                }
-
-                *persistent = TAKE_PTR(a);
-
-                return 0;
-
-        default:
-                assert_not_reached();
-        }
-
-        if (!a || !b)
-                return -ENOMEM;
-
-        *persistent = TAKE_PTR(a);
-        *runtime = TAKE_PTR(b);
+typedef enum LookupDirType {
+        LOOKUP_DIR_CONFIG,
+        LOOKUP_DIR_CONTROL,
+        LOOKUP_DIR_ATTACHED,
+        _LOOKUP_DIR_MAX,
+        _LOOKUP_DIR_INVALID = -EINVAL,
+} LookupDirType;
+
+static int acquire_lookup_dirs(
+                LookupDirType type,
+                RuntimeScope scope,
+                char **ret_persistent,
+                char **ret_runtime) {
 
-        return 0;
-}
+        /* RUNTIME_SCOPE_USER dirs are relative to XDG_CONFIG_DIR and XDG_RUNTIME_DIR, respectively */
+        static const struct {
+                const char *persistent;
+                const char *runtime;
+        } dirs[_LOOKUP_DIR_MAX][_RUNTIME_SCOPE_MAX] = {
+                [LOOKUP_DIR_CONFIG] = {
+                        [RUNTIME_SCOPE_SYSTEM] = { SYSTEM_CONFIG_UNIT_DIR, "/run/systemd/system" },
+                        [RUNTIME_SCOPE_GLOBAL] = { USER_CONFIG_UNIT_DIR,   "/run/systemd/user"   },
+                        [RUNTIME_SCOPE_USER]   = { "systemd/user",         "systemd/user"        },
+                },
+                [LOOKUP_DIR_CONTROL] = {
+                        [RUNTIME_SCOPE_SYSTEM] = { "/etc/systemd/system.control", "/run/systemd/system.control" },
+                        [RUNTIME_SCOPE_USER]   = { "systemd/user.control",        "systemd/user.control"        },
+                },
+                [LOOKUP_DIR_ATTACHED] = {
+                        [RUNTIME_SCOPE_SYSTEM] = { "/etc/systemd/system.attached", "/run/systemd/system.attached" },
+                        /* Portable services are not available to regular users for now. */
+                },
+        };
 
-static int acquire_control_dirs(RuntimeScope scope, char **persistent, char **runtime) {
-        _cleanup_free_ char *a = NULL;
+        _cleanup_free_ char *a = NULL, *b = NULL;
         int r;
 
-        assert(persistent);
-        assert(runtime);
+        assert(type >= 0 && type < _LOOKUP_DIR_MAX);
+        assert(IN_SET(scope, RUNTIME_SCOPE_SYSTEM, RUNTIME_SCOPE_USER, RUNTIME_SCOPE_GLOBAL));
+        assert(ret_persistent);
+        assert(ret_runtime);
 
-        switch (scope) {
+        const char *persistent = dirs[type][scope].persistent;
+        const char *runtime = dirs[type][scope].runtime;
+        assert(!persistent == !runtime);
 
-        case RUNTIME_SCOPE_SYSTEM:  {
-                _cleanup_free_ char *b = NULL;
+        if (!persistent)
+                return -EOPNOTSUPP;
 
-                a = strdup("/etc/systemd/system.control");
-                if (!a)
-                        return -ENOMEM;
+        switch (scope) {
 
-                b = strdup("/run/systemd/system.control");
-                if (!b)
+        case RUNTIME_SCOPE_SYSTEM:
+        case RUNTIME_SCOPE_GLOBAL:
+                a = strdup(persistent);
+                b = strdup(runtime);
+                if (!a || !b)
                         return -ENOMEM;
 
-                *runtime = TAKE_PTR(b);
+                *ret_persistent = TAKE_PTR(a);
+                *ret_runtime = TAKE_PTR(b);
 
-                break;
-        }
+                return 0;
 
         case RUNTIME_SCOPE_USER:
-                r = xdg_user_config_dir("/systemd/user.control", &a);
-                if (r < 0 && r != -ENXIO)
+                r = xdg_user_config_dir(persistent, &a);
+                if (r < 0)
                         return r;
 
-                r = xdg_user_runtime_dir("/systemd/user.control", runtime);
+                r = xdg_user_runtime_dir(runtime, ret_runtime);
                 if (r < 0) {
                         if (r != -ENXIO)
                                 return r;
 
-                        /* If XDG_RUNTIME_DIR is not set, don't consider this fatal, simply initialize the directory to
-                         * NULL */
-                        *runtime = NULL;
+                        /* If XDG_RUNTIME_DIR is not set, don't consider that fatal, simply initialize
+                         * the runtime directory to NULL. */
+                        *ret_runtime = NULL;
                 }
 
-                break;
+                *ret_persistent = TAKE_PTR(a);
 
-        case RUNTIME_SCOPE_GLOBAL:
-                return -EOPNOTSUPP;
+                return 0;
 
         default:
                 assert_not_reached();
         }
-
-        *persistent = TAKE_PTR(a);
-
-        return 0;
-}
-
-static int acquire_attached_dirs(
-                RuntimeScope scope,
-                char **ret_persistent,
-                char **ret_runtime) {
-
-        _cleanup_free_ char *a = NULL, *b = NULL;
-
-        assert(ret_persistent);
-        assert(ret_runtime);
-
-        /* Portable services are not available to regular users for now. */
-        if (scope != RUNTIME_SCOPE_SYSTEM)
-                return -EOPNOTSUPP;
-
-        a = strdup("/etc/systemd/system.attached");
-        if (!a)
-                return -ENOMEM;
-
-        b = strdup("/run/systemd/system.attached");
-        if (!b)
-                return -ENOMEM;
-
-        *ret_persistent = TAKE_PTR(a);
-        *ret_runtime = TAKE_PTR(b);
-
-        return 0;
 }
 
 static int patch_root_prefix(char **p, const char *root_dir) {
@@ -489,16 +443,24 @@ int lookup_paths_init(
         }
 
         /* Note: when XDG_RUNTIME_DIR is not set this will not return -ENXIO, but simply set runtime_config to NULL */
-        r = acquire_config_dirs(scope, &persistent_config, &runtime_config);
+        r = acquire_lookup_dirs(LOOKUP_DIR_CONFIG, scope, &persistent_config, &runtime_config);
         if (r < 0)
                 return r;
 
         if (scope == RUNTIME_SCOPE_USER) {
-                r = acquire_config_dirs(RUNTIME_SCOPE_GLOBAL, &global_persistent_config, &global_runtime_config);
+                r = acquire_lookup_dirs(LOOKUP_DIR_CONFIG, RUNTIME_SCOPE_GLOBAL, &global_persistent_config, &global_runtime_config);
                 if (r < 0)
                         return r;
         }
 
+        r = acquire_lookup_dirs(LOOKUP_DIR_CONTROL, scope, &persistent_control, &runtime_control);
+        if (r < 0 && r != -EOPNOTSUPP)
+                return r;
+
+        r = acquire_lookup_dirs(LOOKUP_DIR_ATTACHED, scope, &persistent_attached, &runtime_attached);
+        if (r < 0 && r != -EOPNOTSUPP)
+                return r;
+
         if ((flags & LOOKUP_PATHS_EXCLUDE_GENERATED) == 0) {
                 /* Note: if XDG_RUNTIME_DIR is not set, this will fail completely with ENXIO */
                 r = acquire_generator_dirs(scope, tempdir,
@@ -512,15 +474,6 @@ int lookup_paths_init(
         if (r < 0 && !IN_SET(r, -EOPNOTSUPP, -ENXIO))
                 return r;
 
-        /* Note: when XDG_RUNTIME_DIR is not set this will not return -ENXIO, but simply set runtime_control to NULL */
-        r = acquire_control_dirs(scope, &persistent_control, &runtime_control);
-        if (r < 0 && r != -EOPNOTSUPP)
-                return r;
-
-        r = acquire_attached_dirs(scope, &persistent_attached, &runtime_attached);
-        if (r < 0 && r != -EOPNOTSUPP)
-                return r;
-
         /* First priority is whatever has been passed to us via env vars */
         r = get_paths_from_environ("SYSTEMD_UNIT_PATH", &paths, &append);
         if (r < 0)