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