repart: Allow devices as sources for --copy-from

Implements #37208
This commit is contained in:
Nick Labich
2025-04-21 20:03:46 -04:00
committed by Yu Watanabe
parent a31777df99
commit 5d49aec4c1
2 changed files with 30 additions and 10 deletions

View File

@@ -551,16 +551,16 @@
</varlistentry>
<varlistentry>
<term><option>--copy-from=<replaceable>IMAGE</replaceable></option></term>
<term><option>--copy-from=<replaceable>PATH</replaceable></option></term>
<listitem><para>Instructs <command>systemd-repart</command> to synthesize partition definitions from
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>
the partition table in the given image or device. This option can be specified multiple times to
synthesize definitions from each of the given images or devices. 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>
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
</varlistentry>

View File

@@ -2676,6 +2676,26 @@ static int determine_current_padding(
return 0;
}
static int verify_regular_or_block(int fd) {
struct stat st;
assert(fd >= 0);
if (fstat(fd, &st) < 0)
return -errno;
if (S_ISDIR(st.st_mode))
return -EISDIR;
if (S_ISLNK(st.st_mode))
return -ELOOP;
if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode))
return -EBADFD;
return 0;
}
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;
@@ -2691,9 +2711,9 @@ static int context_copy_from_one(Context *context, const char *src) {
if (r < 0)
return r;
r = fd_verify_regular(fd);
r = verify_regular_or_block(fd);
if (r < 0)
return log_error_errno(r, "%s is not a file: %m", src);
return log_error_errno(r, "%s is not a file nor a block device: %m", src);
r = fdisk_new_context_at(fd, /* path = */ NULL, /* read_only = */ true, /* sector_size = */ UINT32_MAX, &c);
if (r < 0)