84b277
From 14f32b5e62d7f0973302080488a0f0fce897b2d0 Mon Sep 17 00:00:00 2001
84b277
From: Michael Marineau <michael.marineau@coreos.com>
84b277
Date: Thu, 13 Mar 2014 21:32:13 -0700
84b277
Subject: [PATCH] tmpfiles: add --root option to operate on an alternate fs
84b277
 tree
84b277
84b277
This makes it possible to initialize or cleanup an arbitrary filesystem
84b277
hierarchy in the same way that it would be during system boot.
84b277
84b277
Conflicts:
84b277
	src/tmpfiles/tmpfiles.c
84b277
84b277
(cherry picked from commit cf9a4abdc24c43565d0890fcb88c00169057c0c4)
84b277
84b277
Resolves: #1111199
84b277
---
84b277
 man/systemd-tmpfiles.xml | 12 ++++++++++--
84b277
 src/tmpfiles/tmpfiles.c  | 29 +++++++++++++++++++++++++----
84b277
 2 files changed, 35 insertions(+), 6 deletions(-)
84b277
84b277
diff --git a/man/systemd-tmpfiles.xml b/man/systemd-tmpfiles.xml
84b277
index 64f9cf9..8d1db16 100644
84b277
--- a/man/systemd-tmpfiles.xml
84b277
+++ b/man/systemd-tmpfiles.xml
84b277
@@ -139,19 +139,27 @@
84b277
                                 </para></listitem>
84b277
                         </varlistentry>
84b277
                         <varlistentry>
84b277
-                                <term><option>--prefix=PATH</option></term>
84b277
+                                <term><option>--prefix=<replaceable>path</replaceable></option></term>
84b277
                                 <listitem><para>Only apply rules that
84b277
                                 apply to paths with the specified
84b277
                                 prefix. This option can be specified
84b277
                                 multiple times.</para></listitem>
84b277
                         </varlistentry>
84b277
                         <varlistentry>
84b277
-                                <term><option>--exclude-prefix=PATH</option></term>
84b277
+                                <term><option>--exclude-prefix=<replaceable>path</replaceable></option></term>
84b277
                                 <listitem><para>Ignore rules that
84b277
                                 apply to paths with the specified
84b277
                                 prefix. This option can be specified
84b277
                                 multiple times.</para></listitem>
84b277
                         </varlistentry>
84b277
+                        <varlistentry>
84b277
+                                <term><option>--root=<replaceable>root</replaceable></option></term>
84b277
+                                <listitem><para>Takes a directory path
84b277
+                                as an argument. All paths will be
84b277
+                                prefixed with the given alternate <replaceable>root</replaceable>
84b277
+                                path, including config search paths.
84b277
+                                </para></listitem>
84b277
+                        </varlistentry>
84b277
 
84b277
 
84b277
                         <varlistentry>
84b277
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
84b277
index 1337d02..ff51062 100644
84b277
--- a/src/tmpfiles/tmpfiles.c
84b277
+++ b/src/tmpfiles/tmpfiles.c
84b277
@@ -110,6 +110,7 @@ static bool arg_boot = false;
84b277
 
84b277
 static char **include_prefixes = NULL;
84b277
 static char **exclude_prefixes = NULL;
84b277
+static char *arg_root = NULL;
84b277
 
84b277
 static const char conf_file_dirs[] =
84b277
         "/etc/tmpfiles.d\0"
84b277
@@ -1186,6 +1187,15 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
84b277
         if (!should_include_path(i->path))
84b277
                 return 0;
84b277
 
84b277
+        if (arg_root) {
84b277
+                char *p = strappend(arg_root, i->path);
84b277
+                if (!p)
84b277
+                        return log_oom();
84b277
+
84b277
+                free(i->path);
84b277
+                i->path = p;
84b277
+        }
84b277
+
84b277
         if (user && !streq(user, "-")) {
84b277
                 const char *u = user;
84b277
 
84b277
@@ -1274,7 +1284,8 @@ static int help(void) {
84b277
                "     --remove               Remove marked files/directories\n"
84b277
                "     --boot                 Execute actions only safe at boot\n"
84b277
                "     --prefix=PATH          Only apply rules that apply to paths with the specified prefix\n"
84b277
-               "     --exclude-prefix=PATH  Ignore rules that apply to paths with the specified prefix\n",
84b277
+               "     --exclude-prefix=PATH  Ignore rules that apply to paths with the specified prefix\n"
84b277
+               "     --root=PATH            Operate on an alternate filesystem root\n",
84b277
                program_invocation_short_name);
84b277
 
84b277
         return 0;
84b277
@@ -1289,6 +1300,7 @@ static int parse_argv(int argc, char *argv[]) {
84b277
                 ARG_BOOT,
84b277
                 ARG_PREFIX,
84b277
                 ARG_EXCLUDE_PREFIX,
84b277
+                ARG_ROOT,
84b277
         };
84b277
 
84b277
         static const struct option options[] = {
84b277
@@ -1299,7 +1311,8 @@ static int parse_argv(int argc, char *argv[]) {
84b277
                 { "boot",           no_argument,         NULL, ARG_BOOT           },
84b277
                 { "prefix",         required_argument,   NULL, ARG_PREFIX         },
84b277
                 { "exclude-prefix", required_argument,   NULL, ARG_EXCLUDE_PREFIX },
84b277
-                { NULL,             0,                   NULL, 0                  }
84b277
+                { "root",           required_argument,   NULL, ARG_ROOT           },
84b277
+                {}
84b277
         };
84b277
 
84b277
         int c;
84b277
@@ -1341,6 +1354,13 @@ static int parse_argv(int argc, char *argv[]) {
84b277
                                 return log_oom();
84b277
                         break;
84b277
 
84b277
+                case ARG_ROOT:
84b277
+                        arg_root = path_make_absolute_cwd(optarg);
84b277
+                        if (!arg_root)
84b277
+                                return log_oom();
84b277
+                        path_kill_slashes(arg_root);
84b277
+                        break;
84b277
+
84b277
                 case '?':
84b277
                         return -EINVAL;
84b277
 
84b277
@@ -1368,7 +1388,7 @@ static int read_config_file(const char *fn, bool ignore_enoent) {
84b277
 
84b277
         assert(fn);
84b277
 
84b277
-        r = search_and_fopen_nulstr(fn, "re", NULL, conf_file_dirs, &f);
84b277
+        r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
84b277
         if (r < 0) {
84b277
                 if (ignore_enoent && r == -ENOENT)
84b277
                         return 0;
84b277
@@ -1469,7 +1489,7 @@ int main(int argc, char *argv[]) {
84b277
                 _cleanup_strv_free_ char **files = NULL;
84b277
                 char **f;
84b277
 
84b277
-                r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
84b277
+                r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
84b277
                 if (r < 0) {
84b277
                         log_error("Failed to enumerate tmpfiles.d files: %s", strerror(-r));
84b277
                         goto finish;
84b277
@@ -1500,6 +1520,7 @@ finish:
84b277
 
84b277
         free(include_prefixes);
84b277
         free(exclude_prefixes);
84b277
+        free(arg_root);
84b277
 
84b277
         set_free_free(unix_sockets);
84b277