]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
repart: add new --copy-source= switch
authorLennart Poettering <lennart@poettering.net>
Fri, 29 Sep 2023 14:24:48 +0000 (16:24 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 5 Oct 2023 17:07:19 +0000 (19:07 +0200)
This specifies a directory to which CopyFiles= is considered relative.
If unset defaults to the --root=/--image= setting, or host / otherwise.

This is very similar to --root= but is much more focussed: it is really
and exclusively about CopyFiles= (and related settings such as
ExcludeFiles=) and does not affect any of the settings, i.e. it doesn't
affect CopyBlocks=, the machine ID/seed handling, or where definitions
are read from.

In fact, --root= and --copy-source= may be combined for example to
use the machine ID and similar from one tree, but the copy the files
from another.

man/repart.d.xml
man/systemd-repart.xml
src/partition/repart.c

index cfdd39d5eb50e1693593fa24390eae7271391992..79908a0805458350e75c2a54e440d7a9fcfae8ae 100644 (file)
         <para>This option cannot be combined with <varname>CopyBlocks=</varname>.</para>
 
         <para>When
-        <citerefentry><refentrytitle>systemd-repart</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-        is invoked with the <option>--image=</option> or <option>--root=</option> command line switches the
-        source paths specified are taken relative to the specified root directory or disk image root.
-        </para>
+        <citerefentry><refentrytitle>systemd-repart</refentrytitle><manvolnum>8</manvolnum></citerefentry> is
+        invoked with the <option>--copy-source=</option> command line switch the file paths are taken
+        relative to the specified directory. If <option>--copy-source=</option> is not used, but the
+        <option>--image=</option> or <option>--root=</option> switches are used, the source paths are taken
+        relative to the specified root directory or disk image root.</para>
 
         <xi:include href="version-info.xml" xpointer="v247"/></listitem>
       </varlistentry>
index 89d7f2c285b707d88637ecd2519c6a8ebe62e145..fb7b5496af54718944067430d3ec5e57e04f13eb 100644 (file)
         so that the tool operates on the configuration and machine ID stored in the root file system later
         transitioned into itself.</para>
 
+        <para>See <option>--copy-source=</option> for a more restricted option that only affects
+        <varname>CopyFiles=</varname>.</para>
+
         <xi:include href="version-info.xml" xpointer="v245"/></listitem>
       </varlistentry>
 
         <xi:include href="version-info.xml" xpointer="v255"/></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--copy-source=</option><replaceable>PATH</replaceable></term>
+        <term><option>-s</option> <replaceable>PATH</replaceable></term>
+
+        <listitem><para>Specifies a source directory all <varname>CopyFiles=</varname> source paths shall be
+        considered relative to. This is similar to <option>--root=</option>, but exclusively applies to the
+        <varname>CopyFiles=</varname> setting. If <option>--root=</option> and
+        <option>--copy-source=</option> are used in combination the former applies as usual, except for
+        <varname>CopyFiles=</varname> where the latter takes precedence.</para>
+
+        <xi:include href="version-info.xml" xpointer="v255"/></listitem>
+      </varlistentry>
+
       <xi:include href="standard-options.xml" xpointer="help" />
       <xi:include href="standard-options.xml" xpointer="version" />
       <xi:include href="standard-options.xml" xpointer="no-pager" />
index 1fdc628f951d879a1412c087bb1faef713c0cf42..770f7c48ff9a5f92225d438a4126cbb6744261a3 100644 (file)
@@ -162,6 +162,7 @@ static ImagePolicy *arg_image_policy = NULL;
 static Architecture arg_architecture = _ARCHITECTURE_INVALID;
 static int arg_offline = -1;
 static char **arg_copy_from = NULL;
+static char *arg_copy_source = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
@@ -175,6 +176,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_tpm2_public_key, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_filter_partitions, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_copy_from, strv_freep);
+STATIC_DESTRUCTOR_REGISTER(arg_copy_source, freep);
 
 typedef struct FreeArea FreeArea;
 
@@ -4274,11 +4276,11 @@ static int add_exclude_path(const char *path, Hashmap **denylist, DenyType type)
         if (!st)
                 return log_oom();
 
-        r = chase_and_stat(path, arg_root, CHASE_PREFIX_ROOT, NULL, st);
+        r = chase_and_stat(path, arg_copy_source, CHASE_PREFIX_ROOT, NULL, st);
         if (r == -ENOENT)
                 return 0;
         if (r < 0)
-                return log_error_errno(r, "Failed to stat source file '%s/%s': %m", strempty(arg_root), path);
+                return log_error_errno(r, "Failed to stat source file '%s/%s': %m", strempty(arg_copy_source), path);
 
         r = hashmap_ensure_put(denylist, &inode_hash_ops, st, INT_TO_PTR(type));
         if (r == -EEXIST)
@@ -4402,11 +4404,11 @@ static int add_subvolume_path(const char *path, Set **subvolumes) {
         if (!st)
                 return log_oom();
 
-        r = chase_and_stat(path, arg_root, CHASE_PREFIX_ROOT, NULL, st);
+        r = chase_and_stat(path, arg_copy_source, CHASE_PREFIX_ROOT, NULL, st);
         if (r == -ENOENT)
                 return 0;
         if (r < 0)
-                return log_error_errno(r, "Failed to stat source file '%s/%s': %m", strempty(arg_root), path);
+                return log_error_errno(r, "Failed to stat source file '%s/%s': %m", strempty(arg_copy_source), path);
 
         r = set_ensure_consume(subvolumes, &inode_hash_ops, TAKE_PTR(st));
         if (r < 0)
@@ -4469,9 +4471,9 @@ static int do_copy_files(Context *context, Partition *p, const char *root) {
                 if (rfd < 0)
                         return rfd;
 
-                sfd = chase_and_open(*source, arg_root, CHASE_PREFIX_ROOT, O_PATH|O_DIRECTORY|O_CLOEXEC|O_NOCTTY, NULL);
+                sfd = chase_and_open(*source, arg_copy_source, CHASE_PREFIX_ROOT, O_PATH|O_DIRECTORY|O_CLOEXEC|O_NOCTTY, NULL);
                 if (sfd < 0)
-                        return log_error_errno(sfd, "Failed to open source file '%s%s': %m", strempty(arg_root), *source);
+                        return log_error_errno(sfd, "Failed to open source file '%s%s': %m", strempty(arg_copy_source), *source);
 
                 (void) copy_xattr(sfd, NULL, rfd, NULL, COPY_ALL_XATTRS);
                 (void) copy_access(sfd, rfd);
@@ -4493,9 +4495,9 @@ static int do_copy_files(Context *context, Partition *p, const char *root) {
                 if (r < 0)
                         return r;
 
-                sfd = chase_and_open(*source, arg_root, CHASE_PREFIX_ROOT, O_CLOEXEC|O_NOCTTY, NULL);
+                sfd = chase_and_open(*source, arg_copy_source, CHASE_PREFIX_ROOT, O_CLOEXEC|O_NOCTTY, NULL);
                 if (sfd < 0)
-                        return log_error_errno(sfd, "Failed to open source file '%s%s': %m", strempty(arg_root), *source);
+                        return log_error_errno(sfd, "Failed to open source file '%s%s': %m", strempty(arg_copy_source), *source);
 
                 r = fd_verify_regular(sfd);
                 if (r < 0) {
@@ -4541,7 +4543,7 @@ static int do_copy_files(Context *context, Partition *p, const char *root) {
                                                 denylist, subvolumes_by_source_inode);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to copy '%s%s' to '%s%s': %m",
-                                                       strempty(arg_root), *source, strempty(root), *target);
+                                                       strempty(arg_copy_source), *source, strempty(root), *target);
                 } else {
                         _cleanup_free_ char *dn = NULL, *fn = NULL;
 
@@ -4572,7 +4574,7 @@ static int do_copy_files(Context *context, Partition *p, const char *root) {
 
                         r = copy_bytes(sfd, tfd, UINT64_MAX, COPY_REFLINK|COPY_HOLES|COPY_SIGINT|COPY_TRUNCATE);
                         if (r < 0)
-                                return log_error_errno(r, "Failed to copy '%s' to '%s%s': %m", *source, strempty(arg_root), *target);
+                                return log_error_errno(r, "Failed to copy '%s' to '%s%s': %m", *source, strempty(arg_copy_source), *target);
 
                         (void) copy_xattr(sfd, NULL, tfd, NULL, COPY_ALL_XATTRS);
                         (void) copy_access(sfd, tfd);
@@ -6372,6 +6374,7 @@ static int help(void) {
                "     --sector-size=SIZE   Set the logical sector size for the image\n"
                "     --architecture=ARCH  Set the generic architecture for the image\n"
                "     --offline=BOOL       Whether to build the image offline\n"
+               "  -s --copy-source=PATH   Specify the primary source tree to copy files from\n"
                "     --copy-from=IMAGE    Copy partitions from the given image(s)\n"
                "\nSee the %s for details.\n",
                program_invocation_short_name,
@@ -6417,6 +6420,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_ARCHITECTURE,
                 ARG_OFFLINE,
                 ARG_COPY_FROM,
+                ARG_COPY_SOURCE,
         };
 
         static const struct option options[] = {
@@ -6452,6 +6456,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "architecture",         required_argument, NULL, ARG_ARCHITECTURE         },
                 { "offline",              required_argument, NULL, ARG_OFFLINE              },
                 { "copy-from",            required_argument, NULL, ARG_COPY_FROM            },
+                { "copy-source",          required_argument, NULL, 's'                      },
                 {}
         };
 
@@ -6460,7 +6465,7 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+        while ((c = getopt_long(argc, argv, "hs:", options, NULL)) >= 0)
 
                 switch (c) {
 
@@ -6785,6 +6790,12 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
                 }
 
+                case 's':
+                        r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_copy_source);
+                        if (r < 0)
+                                return r;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -7345,6 +7356,13 @@ static int run(int argc, char *argv[]) {
                 }
         }
 
+        if (!arg_copy_source && arg_root) {
+                /* If no explicit copy source is specified, then use --root=/--image= */
+                arg_copy_source = strdup(arg_root);
+                if (!arg_copy_source)
+                        return log_oom();
+        }
+
         context = context_new(arg_seed);
         if (!context)
                 return log_oom();