<term><option>--copy-from=</option><arg>IMAGE</arg></term>
<listitem><para>Instructs <command>systemd-repart</command> to synthesize partition definitions from
- the partition table in the given image. The generated definitions will copy the partitions into the
- destination partition table. The copied partitions will have the same size, metadata and contents but
- might have a different partition number and might be located at a different offset in the destination
- partition table. These definitions can be combined with partition definitions read from regular
- partition definition files. The synthesized definitions take precedence over the definitions read
- from partition definition files.</para></listitem>
+ the partition table in the given image. This option can be specified multiple times to synthesize
+ definitions from each of the given images. The generated definitions will copy the partitions into
+ the destination partition table. The copied partitions will have the same size, metadata and contents
+ but might have a different partition number and might be located at a different offset in the
+ destination partition table. These definitions can be combined with partition definitions read from
+ regular partition definition files. The synthesized definitions take precedence over the definitions
+ read from partition definition files.</para></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="help" />
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_from = NULL;
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
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, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_copy_from, strv_freep);
typedef struct FreeArea FreeArea;
return 0;
}
-static int context_copy_from(Context *context) {
+static int context_copy_from_one(Context *context, const char *src) {
_cleanup_close_ int fd = -EBADF;
_cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
_cleanup_(fdisk_unref_tablep) struct fdisk_table *t = NULL;
size_t n_partitions;
int r;
- if (!arg_copy_from)
- return 0;
+ assert(src);
- r = context_open_and_lock_backing_fd(arg_copy_from, LOCK_SH, &fd);
+ r = context_open_and_lock_backing_fd(src, LOCK_SH, &fd);
if (r < 0)
return r;
r = fd_verify_regular(fd);
if (r < 0)
- return log_error_errno(r, "%s is not a file: %m", arg_copy_from);
+ return log_error_errno(r, "%s is not a file: %m", src);
r = fdisk_new_context_fd(fd, /* read_only = */ true, /* sector_size = */ UINT32_MAX, &c);
if (r < 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Sector size %lu is not a power of two larger than 512? Refusing.", secsz);
if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
- return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON), "Cannot copy from disk %s with no GPT disk label.", arg_copy_from);
+ return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON), "Cannot copy from disk %s with no GPT disk label.", src);
r = fdisk_get_partitions(c, &t);
if (r < 0)
np->size_min = np->size_max = sz;
np->new_label = TAKE_PTR(label_copy);
- np->definition_path = strdup(arg_copy_from);
+ np->definition_path = strdup(src);
if (!np->definition_path)
return log_oom();
np->padding_min = np->padding_max = padding;
- np->copy_blocks_path = strdup(arg_copy_from);
+ np->copy_blocks_path = strdup(src);
if (!np->copy_blocks_path)
return log_oom();
np->copy_blocks_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
if (np->copy_blocks_fd < 0)
- return log_error_errno(r, "Failed to duplicate file descriptor of %s: %m", arg_copy_from);
+ return log_error_errno(r, "Failed to duplicate file descriptor of %s: %m", src);
np->copy_blocks_offset = start;
np->copy_blocks_size = sz;
return 0;
}
+static int context_copy_from(Context *context) {
+ int r;
+
+ assert(context);
+
+ STRV_FOREACH(src, arg_copy_from) {
+ r = context_copy_from_one(context, *src);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
static int context_read_definitions(Context *context) {
_cleanup_strv_free_ char **files = NULL;
Partition *last = LIST_FIND_TAIL(partitions, context->partitions);
" --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"
- " --copy-from=IMAGE Copy partitions from the given image\n"
+ " --copy-from=IMAGE Copy partitions from the given image(s)\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
ansi_highlight(),
break;
- case ARG_COPY_FROM:
- r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_copy_from);
+ case ARG_COPY_FROM: {
+ _cleanup_free_ char *p = NULL;
+
+ r = parse_path_argument(optarg, /* suppress_root= */ false, &p);
if (r < 0)
return r;
+
+ if (strv_consume(&arg_copy_from, TAKE_PTR(p)) < 0)
+ return log_oom();
+
break;
+ }
case '?':
return -EINVAL;
$imgs/zzz1 : start= 2048, size= 1775576, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
$imgs/zzz2 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\""
+ systemd-repart --offline="$OFFLINE" \
+ --definitions="$defs" \
+ --empty=create \
+ --size=50M \
+ --seed="$seed" \
+ --include-partitions=root,home \
+ "$imgs/qqq"
+
+ sfdisk -d "$imgs/qqq" | grep -v -e 'sector-size' -e '^$'
+
systemd-repart --offline="$OFFLINE" \
--empty=create \
--size=1G \
--dry-run=no \
--seed="$seed" \
- --copy-from="$imgs/zzz" \
+ --definitions "" \
+ --copy-from="$imgs/qqq" \
+ --copy-from="$imgs/qqq" \
"$imgs/copy"
output=$(sfdisk -d "$imgs/copy" | grep -v -e 'sector-size' -e '^$')
unit: sectors
first-lba: 2048
last-lba: 2097118
-$imgs/copy1 : start= 2048, size= 1775576, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
-$imgs/copy2 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\""
-
- rm "$imgs/copy" # Save disk space
+$imgs/copy1 : start= 2048, size= 33432, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
+$imgs/copy2 : start= 35480, size= 33440, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=60F33797-1D71-4DCB-AA6F-20564F036CD0, name=\"root-x86-64\", attrs=\"GUID:59\"
+$imgs/copy3 : start= 68920, size= 33440, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=73A4CCD2-EAF5-44DA-A366-F99188210FDC, name=\"root-x86-64-2\", attrs=\"GUID:59\"
+$imgs/copy4 : start= 102360, size= 33432, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
+$imgs/copy5 : start= 135792, size= 33440, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=60F33797-1D71-4DCB-AA6F-20564F036CD0, name=\"root-x86-64\", attrs=\"GUID:59\"
+$imgs/copy6 : start= 169232, size= 33440, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=73A4CCD2-EAF5-44DA-A366-F99188210FDC, name=\"root-x86-64-2\", attrs=\"GUID:59\""
+
+ rm "$imgs/qqq" "$imgs/copy" # Save disk space
systemd-repart --offline="$OFFLINE" \
--definitions="$defs" \