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