1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-31 14:50:15 +03:00

Merge pull request #28766 from DaanDeMeyer/repart-copy-from

repart: Allow specifying --copy-from more than once
This commit is contained in:
Daan De Meyer 2023-08-11 14:51:24 +02:00 committed by GitHub
commit 9a441937e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 28 deletions

View File

@ -444,12 +444,13 @@
<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" />

View File

@ -156,7 +156,7 @@ static uint64_t arg_sector_size = 0;
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);
@ -169,7 +169,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_tpm2_hash_pcr_values, 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;
@ -1814,7 +1814,7 @@ static int find_verity_sibling(Context *context, Partition *p, VerityMode mode,
return 0;
}
static int context_open_and_lock_backing_fd(const char *node, int *backing_fd) {
static int context_open_and_lock_backing_fd(const char *node, int operation, int *backing_fd) {
_cleanup_close_ int fd = -EBADF;
assert(node);
@ -1828,7 +1828,7 @@ static int context_open_and_lock_backing_fd(const char *node, int *backing_fd) {
return log_error_errno(errno, "Failed to open device '%s': %m", node);
/* Tell udev not to interfere while we are processing the device */
if (flock(fd, arg_dry_run ? LOCK_SH : LOCK_EX) < 0)
if (flock(fd, operation) < 0)
return log_error_errno(errno, "Failed to lock device '%s': %m", node);
log_debug("Device %s opened and locked.", node);
@ -1905,7 +1905,7 @@ static int determine_current_padding(
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;
@ -1914,16 +1914,15 @@ static int context_copy_from(Context *context) {
size_t n_partitions;
int r;
if (!arg_copy_from)
return 0;
assert(src);
r = context_open_and_lock_backing_fd(arg_copy_from, &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)
@ -1937,7 +1936,7 @@ static int context_copy_from(Context *context) {
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)
@ -2003,7 +2002,7 @@ static int context_copy_from(Context *context) {
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();
@ -2013,13 +2012,13 @@ static int context_copy_from(Context *context) {
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;
@ -2036,6 +2035,20 @@ static int context_copy_from(Context *context) {
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);
@ -2223,7 +2236,8 @@ static int context_load_partition_table(Context *context) {
else {
uint32_t ssz;
r = context_open_and_lock_backing_fd(context->node, &context->backing_fd);
r = context_open_and_lock_backing_fd(context->node, arg_dry_run ? LOCK_SH : LOCK_EX,
&context->backing_fd);
if (r < 0)
return r;
@ -2270,7 +2284,9 @@ static int context_load_partition_table(Context *context) {
if (context->backing_fd < 0) {
/* If we have no fd referencing the device yet, make a copy of the fd now, so that we have one */
r = context_open_and_lock_backing_fd(FORMAT_PROC_FD_PATH(fdisk_get_devfd(c)), &context->backing_fd);
r = context_open_and_lock_backing_fd(FORMAT_PROC_FD_PATH(fdisk_get_devfd(c)),
arg_dry_run ? LOCK_SH : LOCK_EX,
&context->backing_fd);
if (r < 0)
return r;
}
@ -6192,7 +6208,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"
" --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(),
@ -6595,11 +6611,18 @@ static int parse_argv(int argc, char *argv[]) {
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;

View File

@ -160,12 +160,24 @@ last-lba: 2097118
$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 '^$')
@ -176,10 +188,14 @@ device: $imgs/copy
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\""
$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/copy" # Save disk space
rm "$imgs/qqq" "$imgs/copy" # Save disk space
systemd-repart --offline="$OFFLINE" \
--definitions="$defs" \