]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
repart: allow reading from char device for CopyBlocks=
authorLennart Poettering <lennart@poettering.net>
Fri, 24 May 2024 11:57:56 +0000 (13:57 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 25 Jun 2024 08:05:07 +0000 (10:05 +0200)
Sometimes it is useful to allow initializing a partition with randomized
data, hence allow reading from a char device as source for CopyBlocks=

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

index 52e6b97240552fe761b8fe0650e19f3f6812994f..b107b20c1ceace9eee007112be02a8de4586f908 100644 (file)
       <varlistentry>
         <term><varname>CopyBlocks=</varname></term>
 
-        <listitem><para>Takes a path to a regular file, block device node or directory, or the special value
-        <literal>auto</literal>. If specified and the partition is newly created, the data from the specified
-        path is written to the newly created partition, on the block level. If a directory is specified, the
-        backing block device of the file system the directory is on is determined, and the data read directly
-        from that. This option is useful to efficiently replicate existing file systems onto new partitions
-        on the block level — for example to build a simple OS installer or an OS image builder.</para>
+        <listitem><para>Takes a path to a regular file, block device node, char device node or directory, or
+        the special value <literal>auto</literal>. If specified and the partition is newly created, the data
+        from the specified path is written to the newly created partition, on the block level. If a directory
+        is specified, the backing block device of the file system the directory is on is determined, and the
+        data read directly from that. This option is useful to efficiently replicate existing file systems
+        onto new partitions on the block level — for example to build a simple OS installer or an OS image
+        builder. Specify <filename>/dev/urandom</filename> as value to initialize a partition with random
+        data.</para>
 
         <para>If the special value <literal>auto</literal> is specified, the source to copy from is
         automatically picked up from the running system (or the image specified with
index bee48b770c3a6521a917ec894c2d0d8dc8e033a1..17ebcbe9efa573fb23208376878ba167f89576ea 100644 (file)
@@ -4522,8 +4522,13 @@ static int context_copy_blocks(Context *context) {
                         continue;
 
                 assert(p->new_size != UINT64_MAX);
-                assert(p->copy_blocks_size != UINT64_MAX);
-                assert(p->new_size >= p->copy_blocks_size + (p->encrypt != ENCRYPT_OFF ? LUKS2_METADATA_KEEP_FREE : 0));
+
+                size_t extra = p->encrypt != ENCRYPT_OFF ? LUKS2_METADATA_KEEP_FREE : 0;
+
+                if (p->copy_blocks_size == UINT64_MAX)
+                        p->copy_blocks_size = LESS_BY(p->new_size, extra);
+
+                assert(p->new_size >= p->copy_blocks_size + extra);
 
                 usec_t start_timestamp = now(CLOCK_MONOTONIC);
 
@@ -6350,13 +6355,17 @@ static int context_open_copy_block_paths(
                         r = blockdev_get_device_size(source_fd, &size);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to determine size of block device to copy from: %m");
-                } else
+                } else if (S_ISCHR(st.st_mode))
+                        size = UINT64_MAX;
+                else
                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specified path to copy blocks from '%s' is not a regular file, block device or directory, refusing.", opened);
 
-                if (size <= 0)
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has zero size, refusing.", opened);
-                if (size % 512 != 0)
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has size that is not multiple of 512, refusing.", opened);
+                if (size != UINT64_MAX) {
+                        if (size <= 0)
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has zero size, refusing.", opened);
+                        if (size % 512 != 0)
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has size that is not multiple of 512, refusing.", opened);
+                }
 
                 p->copy_blocks_fd = TAKE_FD(source_fd);
                 p->copy_blocks_size = size;