/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "alloc-util.h"
-#include "fileio.h"
#include "fs-util.h"
#include "install.h"
#include "log.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
+#include "tmpfile-util.h"
#include "user-util.h"
#include "util.h"
data_dirs = strv_split(e, ":");
else
data_dirs = strv_new("/usr/local/share",
- "/usr/share",
- NULL);
+ "/usr/share");
if (!data_dirs)
return -ENOMEM;
- *ret_config_dirs = config_dirs;
- *ret_data_dirs = data_dirs;
- config_dirs = data_dirs = NULL;
+ *ret_config_dirs = TAKE_PTR(config_dirs);
+ *ret_data_dirs = TAKE_PTR(data_dirs);
+
return 0;
}
if (tempdir)
prefix = tempdir;
-
else if (scope == UNIT_FILE_SYSTEM)
prefix = "/run/systemd";
-
- else if (scope == UNIT_FILE_USER) {
+ else {
+ /* UNIT_FILE_USER */
const char *e;
e = getenv("XDG_RUNTIME_DIR");
return 0;
}
+static int acquire_attached_dirs(
+ UnitFileScope 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 != UNIT_FILE_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) {
char *c;
*global_persistent_config = NULL, *global_runtime_config = NULL,
*generator = NULL, *generator_early = NULL, *generator_late = NULL,
*transient = NULL,
- *persistent_control = NULL, *runtime_control = NULL;
+ *persistent_control = NULL, *runtime_control = NULL,
+ *persistent_attached = NULL, *runtime_attached = NULL;
bool append = false; /* Add items from SYSTEMD_UNIT_PATH before normal directories */
_cleanup_strv_free_ char **paths = NULL;
const char *e;
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
+#if HAVE_SPLIT_USR
+ flags |= LOOKUP_PATHS_SPLIT_USR;
+#endif
+
if (!empty_or_root(root_dir)) {
if (scope == UNIT_FILE_USER)
return -EINVAL;
if (flags & LOOKUP_PATHS_TEMPORARY_GENERATED) {
r = mkdtemp_malloc("/tmp/systemd-temporary-XXXXXX", &tempdir);
if (r < 0)
- return log_error_errno(r, "Failed to create temporary directory: %m");
+ return log_debug_errno(r, "Failed to create temporary directory: %m");
}
/* Note: when XDG_RUNTIME_DIR is not set this will not return -ENXIO, but simply set runtime_config to NULL */
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 */
e = getenv("SYSTEMD_UNIT_PATH");
if (e) {
persistent_config,
SYSTEM_CONFIG_UNIT_PATH,
"/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_PATH,
"/usr/lib/systemd/system",
-#if HAVE_SPLIT_USR
- "/lib/systemd/system",
-#endif
- STRV_IFNOTNULL(generator_late),
- NULL);
+ STRV_IFNOTNULL(flags & LOOKUP_PATHS_SPLIT_USR ? "/lib/systemd/system" : NULL),
+ STRV_IFNOTNULL(generator_late));
break;
case UNIT_FILE_GLOBAL:
"/usr/local/lib/systemd/user",
USER_DATA_UNIT_PATH,
"/usr/lib/systemd/user",
- STRV_IFNOTNULL(generator_late),
- NULL);
+ STRV_IFNOTNULL(generator_late));
break;
case UNIT_FILE_USER:
r = patch_root_prefix(&persistent_control, root);
if (r < 0)
return r;
-
r = patch_root_prefix(&runtime_control, root);
if (r < 0)
return r;
+ r = patch_root_prefix(&persistent_attached, root);
+ if (r < 0)
+ return r;
+ r = patch_root_prefix(&runtime_attached, root);
+ if (r < 0)
+ return r;
+
r = patch_root_prefix_strv(paths, root);
if (r < 0)
return -ENOMEM;
- p->search_path = strv_uniq(paths);
- paths = NULL;
+ *p = (LookupPaths) {
+ .search_path = strv_uniq(paths),
+
+ .persistent_config = TAKE_PTR(persistent_config),
+ .runtime_config = TAKE_PTR(runtime_config),
- p->persistent_config = TAKE_PTR(persistent_config);
- p->runtime_config = TAKE_PTR(runtime_config);
+ .generator = TAKE_PTR(generator),
+ .generator_early = TAKE_PTR(generator_early),
+ .generator_late = TAKE_PTR(generator_late),
- p->generator = TAKE_PTR(generator);
- p->generator_early = TAKE_PTR(generator_early);
- p->generator_late = TAKE_PTR(generator_late);
+ .transient = TAKE_PTR(transient),
- p->transient = TAKE_PTR(transient);
+ .persistent_control = TAKE_PTR(persistent_control),
+ .runtime_control = TAKE_PTR(runtime_control),
- p->persistent_control = TAKE_PTR(persistent_control);
- p->runtime_control = TAKE_PTR(runtime_control);
+ .persistent_attached = TAKE_PTR(persistent_attached),
+ .runtime_attached = TAKE_PTR(runtime_attached),
- p->root_dir = TAKE_PTR(root);
- p->temporary_dir = TAKE_PTR(tempdir);
+ .root_dir = TAKE_PTR(root),
+ .temporary_dir = TAKE_PTR(tempdir),
+ };
+ paths = NULL;
return 0;
}
p->persistent_config = mfree(p->persistent_config);
p->runtime_config = mfree(p->runtime_config);
+ p->persistent_attached = mfree(p->persistent_attached);
+ p->runtime_attached = mfree(p->runtime_attached);
+
p->generator = mfree(p->generator);
p->generator_early = mfree(p->generator_early);
p->generator_late = mfree(p->generator_late);
int lookup_paths_reduce(LookupPaths *p) {
_cleanup_free_ struct stat *stats = NULL;
size_t n_stats = 0, allocated = 0;
- unsigned c = 0;
+ size_t c = 0;
int r;
assert(p);
while (p->search_path[c]) {
struct stat st;
- unsigned k;
+ size_t k;
/* Never strip the transient and control directories from the path */
if (path_equal_ptr(p->search_path[c], p->transient) ||
/* Flush the generated unit files in full */
if (p->generator)
- (void) rm_rf(p->generator, REMOVE_ROOT);
+ (void) rm_rf(p->generator, REMOVE_ROOT|REMOVE_PHYSICAL);
if (p->generator_early)
- (void) rm_rf(p->generator_early, REMOVE_ROOT);
+ (void) rm_rf(p->generator_early, REMOVE_ROOT|REMOVE_PHYSICAL);
if (p->generator_late)
- (void) rm_rf(p->generator_late, REMOVE_ROOT);
+ (void) rm_rf(p->generator_late, REMOVE_ROOT|REMOVE_PHYSICAL);
if (p->temporary_dir)
- (void) rm_rf(p->temporary_dir, REMOVE_ROOT);
+ (void) rm_rf(p->temporary_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
}
char **generator_binary_paths(UnitFileScope scope) {
return strv_new("/run/systemd/system-generators",
"/etc/systemd/system-generators",
"/usr/local/lib/systemd/system-generators",
- SYSTEM_GENERATOR_PATH,
- NULL);
+ SYSTEM_GENERATOR_PATH);
case UNIT_FILE_GLOBAL:
case UNIT_FILE_USER:
return strv_new("/run/systemd/user-generators",
"/etc/systemd/user-generators",
"/usr/local/lib/systemd/user-generators",
- USER_GENERATOR_PATH,
- NULL);
+ USER_GENERATOR_PATH);
default:
assert_not_reached("Hmm, unexpected scope.");