diff --git a/man/systemd-tmpfiles.xml b/man/systemd-tmpfiles.xml index 0b6264033d..fad2cbbb1a 100644 --- a/man/systemd-tmpfiles.xml +++ b/man/systemd-tmpfiles.xml @@ -139,19 +139,27 @@ - + Only apply rules that apply to paths with the specified prefix. This option can be specified multiple times. - + Ignore rules that apply to paths with the specified prefix. This option can be specified multiple times. + + + Takes a directory path + as an argument. All paths will be + prefixed with the given alternate root + path, including config search paths. + + diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 36842898ab..52f80379e3 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -111,6 +111,7 @@ static bool arg_boot = false; static char **include_prefixes = NULL; static char **exclude_prefixes = NULL; +static char *arg_root = NULL; static const char conf_file_dirs[] = "/etc/tmpfiles.d\0" @@ -1188,6 +1189,15 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { if (!should_include_path(i->path)) return 0; + if (arg_root) { + char *p = strappend(arg_root, i->path); + if (!p) + return log_oom(); + + free(i->path); + i->path = p; + } + if (user && !streq(user, "-")) { const char *u = user; @@ -1277,7 +1287,8 @@ static int help(void) { " --remove Remove marked files/directories\n" " --boot Execute actions only safe at boot\n" " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n" - " --exclude-prefix=PATH Ignore rules that apply to paths with the specified prefix\n", + " --exclude-prefix=PATH Ignore rules that apply to paths with the specified prefix\n" + " --root=PATH Operate on an alternate filesystem root\n", program_invocation_short_name); return 0; @@ -1293,6 +1304,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_BOOT, ARG_PREFIX, ARG_EXCLUDE_PREFIX, + ARG_ROOT, }; static const struct option options[] = { @@ -1304,6 +1316,7 @@ static int parse_argv(int argc, char *argv[]) { { "boot", no_argument, NULL, ARG_BOOT }, { "prefix", required_argument, NULL, ARG_PREFIX }, { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX }, + { "root", required_argument, NULL, ARG_ROOT }, {} }; @@ -1350,6 +1363,13 @@ static int parse_argv(int argc, char *argv[]) { return log_oom(); break; + case ARG_ROOT: + arg_root = path_make_absolute_cwd(optarg); + if (!arg_root) + return log_oom(); + path_kill_slashes(arg_root); + break; + case '?': return -EINVAL; @@ -1376,7 +1396,7 @@ static int read_config_file(const char *fn, bool ignore_enoent) { assert(fn); - r = search_and_fopen_nulstr(fn, "re", NULL, conf_file_dirs, &f); + r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f); if (r < 0) { if (ignore_enoent && r == -ENOENT) return 0; @@ -1477,7 +1497,7 @@ int main(int argc, char *argv[]) { _cleanup_strv_free_ char **files = NULL; char **f; - r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs); + r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs); if (r < 0) { log_error("Failed to enumerate tmpfiles.d files: %s", strerror(-r)); goto finish; @@ -1508,6 +1528,7 @@ finish: free(include_prefixes); free(exclude_prefixes); + free(arg_root); set_free_free(unix_sockets);