1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #if HAVE_VALGRIND_MEMCHECK_H
4 #include <valgrind/memcheck.h>
11 #include <linux/loop.h>
13 #include <sys/ioctl.h>
16 #include <openssl/hmac.h>
17 #include <openssl/sha.h>
21 #include "alloc-util.h"
22 #include "blkid-util.h"
23 #include "blockdev-util.h"
24 #include "btrfs-util.h"
25 #include "conf-files.h"
26 #include "conf-parser.h"
27 #include "cryptsetup-util.h"
30 #include "errno-util.h"
33 #include "format-table.h"
34 #include "format-util.h"
37 #include "hexdecoct.h"
38 #include "id128-util.h"
41 #include "locale-util.h"
42 #include "loop-util.h"
43 #include "main-func.h"
45 #include "mkfs-util.h"
46 #include "mount-util.h"
47 #include "parse-argument.h"
48 #include "parse-util.h"
49 #include "path-util.h"
50 #include "pretty-print.h"
51 #include "proc-cmdline.h"
52 #include "process-util.h"
53 #include "random-util.h"
54 #include "resize-fs.h"
55 #include "sort-util.h"
56 #include "specifier.h"
57 #include "stat-util.h"
58 #include "stdio-util.h"
59 #include "string-table.h"
60 #include "string-util.h"
62 #include "terminal-util.h"
63 #include "tpm2-util.h"
64 #include "user-util.h"
67 /* If not configured otherwise use a minimal partition size of 10M */
68 #define DEFAULT_MIN_SIZE (10*1024*1024)
70 /* Hard lower limit for new partition sizes */
71 #define HARD_MIN_SIZE 4096
73 /* libfdisk takes off slightly more than 1M of the disk size when creating a GPT disk label */
74 #define GPT_METADATA_SIZE (1044*1024)
76 /* LUKS2 takes off 16M of the partition size with its metadata by default */
77 #define LUKS2_METADATA_SIZE (16*1024*1024)
79 #if !HAVE_LIBCRYPTSETUP
81 static inline void sym_crypt_free(struct crypt_device
* cd
) {}
82 static inline void sym_crypt_freep(struct crypt_device
** cd
) {}
85 /* Note: When growing and placing new partitions we always align to 4K sector size. It's how newer hard disks
86 * are designed, and if everything is aligned to that performance is best. And for older hard disks with 512B
87 * sector size devices were generally assumed to have an even number of sectors, hence at the worst we'll
88 * waste 3K per partition, which is probably fine. */
91 EMPTY_REFUSE
, /* refuse empty disks, never create a partition table */
92 EMPTY_ALLOW
, /* allow empty disks, create partition table if necessary */
93 EMPTY_REQUIRE
, /* require an empty disk, create a partition table */
94 EMPTY_FORCE
, /* make disk empty, erase everything, create a partition table always */
95 EMPTY_CREATE
, /* create disk as loopback file, create a partition table always */
96 } arg_empty
= EMPTY_REFUSE
;
98 static bool arg_dry_run
= true;
99 static const char *arg_node
= NULL
;
100 static char *arg_root
= NULL
;
101 static char *arg_definitions
= NULL
;
102 static bool arg_discard
= true;
103 static bool arg_can_factory_reset
= false;
104 static int arg_factory_reset
= -1;
105 static sd_id128_t arg_seed
= SD_ID128_NULL
;
106 static bool arg_randomize
= false;
107 static int arg_pretty
= -1;
108 static uint64_t arg_size
= UINT64_MAX
;
109 static bool arg_size_auto
= false;
110 static JsonFormatFlags arg_json_format_flags
= JSON_FORMAT_OFF
;
111 static PagerFlags arg_pager_flags
= 0;
112 static bool arg_legend
= true;
113 static void *arg_key
= NULL
;
114 static size_t arg_key_size
= 0;
115 static char *arg_tpm2_device
= NULL
;
116 static uint32_t arg_tpm2_pcr_mask
= UINT32_MAX
;
118 STATIC_DESTRUCTOR_REGISTER(arg_root
, freep
);
119 STATIC_DESTRUCTOR_REGISTER(arg_definitions
, freep
);
120 STATIC_DESTRUCTOR_REGISTER(arg_key
, erase_and_freep
);
121 STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device
, freep
);
123 typedef struct Partition Partition
;
124 typedef struct FreeArea FreeArea
;
125 typedef struct Context Context
;
127 typedef enum EncryptMode
{
131 ENCRYPT_KEY_FILE_TPM2
,
133 _ENCRYPT_MODE_INVALID
= -EINVAL
,
137 char *definition_path
;
139 sd_id128_t type_uuid
;
140 sd_id128_t current_uuid
, new_uuid
;
141 char *current_label
, *new_label
;
147 uint32_t weight
, padding_weight
;
149 uint64_t current_size
, new_size
;
150 uint64_t size_min
, size_max
;
152 uint64_t current_padding
, new_padding
;
153 uint64_t padding_min
, padding_max
;
158 struct fdisk_partition
*current_partition
;
159 struct fdisk_partition
*new_partition
;
160 FreeArea
*padding_area
;
161 FreeArea
*allocated_to_area
;
163 char *copy_blocks_path
;
165 uint64_t copy_blocks_size
;
171 LIST_FIELDS(Partition
, partitions
);
174 #define PARTITION_IS_FOREIGN(p) (!(p)->definition_path)
175 #define PARTITION_EXISTS(p) (!!(p)->current_partition)
184 LIST_HEAD(Partition
, partitions
);
187 FreeArea
**free_areas
;
188 size_t n_free_areas
, n_allocated_free_areas
;
190 uint64_t start
, end
, total
;
192 struct fdisk_context
*fdisk_context
;
197 static const char *encrypt_mode_table
[_ENCRYPT_MODE_MAX
] = {
198 [ENCRYPT_OFF
] = "off",
199 [ENCRYPT_KEY_FILE
] = "key-file",
200 [ENCRYPT_TPM2
] = "tpm2",
201 [ENCRYPT_KEY_FILE_TPM2
] = "key-file+tpm2",
204 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(encrypt_mode
, EncryptMode
, ENCRYPT_KEY_FILE
);
206 static uint64_t round_down_size(uint64_t v
, uint64_t p
) {
210 static uint64_t round_up_size(uint64_t v
, uint64_t p
) {
212 v
= DIV_ROUND_UP(v
, p
);
214 if (v
> UINT64_MAX
/ p
)
215 return UINT64_MAX
; /* overflow */
220 static Partition
*partition_new(void) {
223 p
= new(Partition
, 1);
230 .current_size
= UINT64_MAX
,
231 .new_size
= UINT64_MAX
,
232 .size_min
= UINT64_MAX
,
233 .size_max
= UINT64_MAX
,
234 .current_padding
= UINT64_MAX
,
235 .new_padding
= UINT64_MAX
,
236 .padding_min
= UINT64_MAX
,
237 .padding_max
= UINT64_MAX
,
238 .partno
= UINT64_MAX
,
239 .offset
= UINT64_MAX
,
240 .copy_blocks_fd
= -1,
241 .copy_blocks_size
= UINT64_MAX
,
247 static Partition
* partition_free(Partition
*p
) {
251 free(p
->current_label
);
253 free(p
->definition_path
);
255 if (p
->current_partition
)
256 fdisk_unref_partition(p
->current_partition
);
257 if (p
->new_partition
)
258 fdisk_unref_partition(p
->new_partition
);
260 free(p
->copy_blocks_path
);
261 safe_close(p
->copy_blocks_fd
);
264 strv_free(p
->copy_files
);
269 static Partition
* partition_unlink_and_free(Context
*context
, Partition
*p
) {
273 LIST_REMOVE(partitions
, context
->partitions
, p
);
275 assert(context
->n_partitions
> 0);
276 context
->n_partitions
--;
278 return partition_free(p
);
281 DEFINE_TRIVIAL_CLEANUP_FUNC(Partition
*, partition_free
);
283 static Context
*context_new(sd_id128_t seed
) {
286 context
= new(Context
, 1);
290 *context
= (Context
) {
300 static void context_free_free_areas(Context
*context
) {
303 for (size_t i
= 0; i
< context
->n_free_areas
; i
++)
304 free(context
->free_areas
[i
]);
306 context
->free_areas
= mfree(context
->free_areas
);
307 context
->n_free_areas
= 0;
308 context
->n_allocated_free_areas
= 0;
311 static Context
*context_free(Context
*context
) {
315 while (context
->partitions
)
316 partition_unlink_and_free(context
, context
->partitions
);
317 assert(context
->n_partitions
== 0);
319 context_free_free_areas(context
);
321 if (context
->fdisk_context
)
322 fdisk_unref_context(context
->fdisk_context
);
324 return mfree(context
);
327 DEFINE_TRIVIAL_CLEANUP_FUNC(Context
*, context_free
);
329 static int context_add_free_area(
337 assert(!after
|| !after
->padding_area
);
339 if (!GREEDY_REALLOC(context
->free_areas
, context
->n_allocated_free_areas
, context
->n_free_areas
+ 1))
342 a
= new(FreeArea
, 1);
351 context
->free_areas
[context
->n_free_areas
++] = a
;
354 after
->padding_area
= a
;
359 static bool context_drop_one_priority(Context
*context
) {
360 int32_t priority
= 0;
364 LIST_FOREACH(partitions
, p
, context
->partitions
) {
367 if (p
->priority
< priority
)
369 if (p
->priority
== priority
) {
370 exists
= exists
|| PARTITION_EXISTS(p
);
374 priority
= p
->priority
;
375 exists
= PARTITION_EXISTS(p
);
378 /* Refuse to drop partitions with 0 or negative priorities or partitions of priorities that have at
379 * least one existing priority */
380 if (priority
<= 0 || exists
)
383 LIST_FOREACH(partitions
, p
, context
->partitions
) {
384 if (p
->priority
< priority
)
391 log_info("Can't fit partition %s of priority %" PRIi32
", dropping.", p
->definition_path
, p
->priority
);
397 static uint64_t partition_min_size(const Partition
*p
) {
400 /* Calculate the disk space we really need at minimum for this partition. If the partition already
401 * exists the current size is what we really need. If it doesn't exist yet refuse to allocate less
404 * DEFAULT_MIN_SIZE is the default SizeMin= we configure if nothing else is specified. */
406 if (PARTITION_IS_FOREIGN(p
)) {
407 /* Don't allow changing size of partitions not managed by us */
408 assert(p
->current_size
!= UINT64_MAX
);
409 return p
->current_size
;
412 sz
= p
->current_size
!= UINT64_MAX
? p
->current_size
: HARD_MIN_SIZE
;
414 if (!PARTITION_EXISTS(p
)) {
417 if (p
->encrypt
!= ENCRYPT_OFF
)
418 d
+= round_up_size(LUKS2_METADATA_SIZE
, 4096);
420 if (p
->copy_blocks_size
!= UINT64_MAX
)
421 d
+= round_up_size(p
->copy_blocks_size
, 4096);
422 else if (p
->format
|| p
->encrypt
!= ENCRYPT_OFF
) {
425 /* If we shall synthesize a file system, take minimal fs size into account (assumed to be 4K if not known) */
426 f
= p
->format
? minimal_size_by_fs_name(p
->format
) : UINT64_MAX
;
427 d
+= f
== UINT64_MAX
? 4096 : f
;
434 return MAX(p
->size_min
!= UINT64_MAX
? p
->size_min
: DEFAULT_MIN_SIZE
, sz
);
437 static uint64_t partition_max_size(const Partition
*p
) {
438 /* Calculate how large the partition may become at max. This is generally the configured maximum
439 * size, except when it already exists and is larger than that. In that case it's the existing size,
440 * since we never want to shrink partitions. */
442 if (PARTITION_IS_FOREIGN(p
)) {
443 /* Don't allow changing size of partitions not managed by us */
444 assert(p
->current_size
!= UINT64_MAX
);
445 return p
->current_size
;
448 if (p
->current_size
!= UINT64_MAX
)
449 return MAX(p
->current_size
, p
->size_max
);
454 static uint64_t partition_min_size_with_padding(const Partition
*p
) {
457 /* Calculate the disk space we need for this partition plus any free space coming after it. This
458 * takes user configured padding into account as well as any additional whitespace needed to align
459 * the next partition to 4K again. */
461 sz
= partition_min_size(p
);
463 if (p
->padding_min
!= UINT64_MAX
)
464 sz
+= p
->padding_min
;
466 if (PARTITION_EXISTS(p
)) {
467 /* If the partition wasn't aligned, add extra space so that any we might add will be aligned */
468 assert(p
->offset
!= UINT64_MAX
);
469 return round_up_size(p
->offset
+ sz
, 4096) - p
->offset
;
472 /* If this is a new partition we'll place it aligned, hence we just need to round up the required size here */
473 return round_up_size(sz
, 4096);
476 static uint64_t free_area_available(const FreeArea
*a
) {
479 /* Determines how much of this free area is not allocated yet */
481 assert(a
->size
>= a
->allocated
);
482 return a
->size
- a
->allocated
;
485 static uint64_t free_area_available_for_new_partitions(const FreeArea
*a
) {
488 /* Similar to free_area_available(), but takes into account that the required size and padding of the
489 * preceding partition is honoured. */
491 avail
= free_area_available(a
);
493 uint64_t need
, space
;
495 need
= partition_min_size_with_padding(a
->after
);
497 assert(a
->after
->offset
!= UINT64_MAX
);
498 assert(a
->after
->current_size
!= UINT64_MAX
);
500 space
= round_up_size(a
->after
->offset
+ a
->after
->current_size
, 4096) - a
->after
->offset
+ avail
;
510 static int free_area_compare(FreeArea
*const *a
, FreeArea
*const*b
) {
511 return CMP(free_area_available_for_new_partitions(*a
),
512 free_area_available_for_new_partitions(*b
));
515 static uint64_t charge_size(uint64_t total
, uint64_t amount
) {
518 assert(amount
<= total
);
520 /* Subtract the specified amount from total, rounding up to multiple of 4K if there's room */
521 rounded
= round_up_size(amount
, 4096);
522 if (rounded
>= total
)
525 return total
- rounded
;
528 static uint64_t charge_weight(uint64_t total
, uint64_t amount
) {
529 assert(amount
<= total
);
530 return total
- amount
;
533 static bool context_allocate_partitions(Context
*context
) {
538 /* A simple first-fit algorithm, assuming the array of free areas is sorted by size in decreasing
541 LIST_FOREACH(partitions
, p
, context
->partitions
) {
546 /* Skip partitions we already dropped or that already exist */
547 if (p
->dropped
|| PARTITION_EXISTS(p
))
551 typesafe_qsort(context
->free_areas
, context
->n_free_areas
, free_area_compare
);
553 /* How much do we need to fit? */
554 required
= partition_min_size_with_padding(p
);
555 assert(required
% 4096 == 0);
557 for (size_t i
= 0; i
< context
->n_free_areas
; i
++) {
558 a
= context
->free_areas
[i
];
560 if (free_area_available_for_new_partitions(a
) >= required
) {
567 return false; /* 😢 Oh no! We can't fit this partition into any free area! */
569 /* Assign the partition to this free area */
570 p
->allocated_to_area
= a
;
572 /* Budget the minimal partition size */
573 a
->allocated
+= required
;
579 static int context_sum_weights(Context
*context
, FreeArea
*a
, uint64_t *ret
) {
580 uint64_t weight_sum
= 0;
587 /* Determine the sum of the weights of all partitions placed in or before the specified free area */
589 LIST_FOREACH(partitions
, p
, context
->partitions
) {
590 if (p
->padding_area
!= a
&& p
->allocated_to_area
!= a
)
593 if (p
->weight
> UINT64_MAX
- weight_sum
)
595 weight_sum
+= p
->weight
;
597 if (p
->padding_weight
> UINT64_MAX
- weight_sum
)
599 weight_sum
+= p
->padding_weight
;
606 return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW
), "Combined weight of partition exceeds unsigned 64bit range, refusing.");
609 static int scale_by_weight(uint64_t value
, uint64_t weight
, uint64_t weight_sum
, uint64_t *ret
) {
610 assert(weight_sum
>= weight
);
618 if (value
> UINT64_MAX
/ weight
)
619 return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW
), "Scaling by weight of partition exceeds unsigned 64bit range, refusing.");
621 *ret
= value
* weight
/ weight_sum
;
625 typedef enum GrowPartitionPhase
{
626 /* The first phase: we charge partitions which need more (according to constraints) than their weight-based share. */
629 /* The second phase: we charge partitions which need less (according to constraints) than their weight-based share. */
632 /* The third phase: we distribute what remains among the remaining partitions, according to the weights */
634 } GrowPartitionPhase
;
636 static int context_grow_partitions_phase(
639 GrowPartitionPhase phase
,
641 uint64_t *weight_sum
) {
649 /* Now let's look at the intended weights and adjust them taking the minimum space assignments into
650 * account. i.e. if a partition has a small weight but a high minimum space value set it should not
651 * get any additional room from the left-overs. Similar, if two partitions have the same weight they
652 * should get the same space if possible, even if one has a smaller minimum size than the other. */
653 LIST_FOREACH(partitions
, p
, context
->partitions
) {
655 /* Look only at partitions associated with this free area, i.e. immediately
656 * preceding it, or allocated into it */
657 if (p
->allocated_to_area
!= a
&& p
->padding_area
!= a
)
660 if (p
->new_size
== UINT64_MAX
) {
661 bool charge
= false, try_again
= false;
662 uint64_t share
, rsz
, xsz
;
664 /* Calculate how much this space this partition needs if everyone would get
665 * the weight based share */
666 r
= scale_by_weight(*span
, p
->weight
, *weight_sum
, &share
);
670 rsz
= partition_min_size(p
);
671 xsz
= partition_max_size(p
);
673 if (phase
== PHASE_OVERCHARGE
&& rsz
> share
) {
674 /* This partition needs more than its calculated share. Let's assign
675 * it that, and take this partition out of all calculations and start
679 charge
= try_again
= true;
681 } else if (phase
== PHASE_UNDERCHARGE
&& xsz
!= UINT64_MAX
&& xsz
< share
) {
682 /* This partition accepts less than its calculated
683 * share. Let's assign it that, and take this partition out
684 * of all calculations and start again. */
687 charge
= try_again
= true;
689 } else if (phase
== PHASE_DISTRIBUTE
) {
690 /* This partition can accept its calculated share. Let's
691 * assign it. There's no need to restart things here since
692 * assigning this shouldn't impact the shares of the other
695 if (PARTITION_IS_FOREIGN(p
))
696 /* Never change of foreign partitions (i.e. those we don't manage) */
697 p
->new_size
= p
->current_size
;
699 p
->new_size
= MAX(round_down_size(share
, 4096), rsz
);
705 *span
= charge_size(*span
, p
->new_size
);
706 *weight_sum
= charge_weight(*weight_sum
, p
->weight
);
710 return 0; /* try again */
713 if (p
->new_padding
== UINT64_MAX
) {
714 bool charge
= false, try_again
= false;
717 r
= scale_by_weight(*span
, p
->padding_weight
, *weight_sum
, &share
);
721 if (phase
== PHASE_OVERCHARGE
&& p
->padding_min
!= UINT64_MAX
&& p
->padding_min
> share
) {
722 p
->new_padding
= p
->padding_min
;
723 charge
= try_again
= true;
724 } else if (phase
== PHASE_UNDERCHARGE
&& p
->padding_max
!= UINT64_MAX
&& p
->padding_max
< share
) {
725 p
->new_padding
= p
->padding_max
;
726 charge
= try_again
= true;
727 } else if (phase
== PHASE_DISTRIBUTE
) {
729 p
->new_padding
= round_down_size(share
, 4096);
730 if (p
->padding_min
!= UINT64_MAX
&& p
->new_padding
< p
->padding_min
)
731 p
->new_padding
= p
->padding_min
;
737 *span
= charge_size(*span
, p
->new_padding
);
738 *weight_sum
= charge_weight(*weight_sum
, p
->padding_weight
);
742 return 0; /* try again */
749 static int context_grow_partitions_on_free_area(Context
*context
, FreeArea
*a
) {
750 uint64_t weight_sum
= 0, span
;
756 r
= context_sum_weights(context
, a
, &weight_sum
);
760 /* Let's calculate the total area covered by this free area and the partition before it */
763 assert(a
->after
->offset
!= UINT64_MAX
);
764 assert(a
->after
->current_size
!= UINT64_MAX
);
766 span
+= round_up_size(a
->after
->offset
+ a
->after
->current_size
, 4096) - a
->after
->offset
;
769 GrowPartitionPhase phase
= PHASE_OVERCHARGE
;
771 r
= context_grow_partitions_phase(context
, a
, phase
, &span
, &weight_sum
);
774 if (r
== 0) /* not done yet, re-run this phase */
777 if (phase
== PHASE_OVERCHARGE
)
778 phase
= PHASE_UNDERCHARGE
;
779 else if (phase
== PHASE_UNDERCHARGE
)
780 phase
= PHASE_DISTRIBUTE
;
781 else if (phase
== PHASE_DISTRIBUTE
)
785 /* We still have space left over? Donate to preceding partition if we have one */
786 if (span
> 0 && a
->after
&& !PARTITION_IS_FOREIGN(a
->after
)) {
789 assert(a
->after
->new_size
!= UINT64_MAX
);
790 m
= a
->after
->new_size
+ span
;
792 xsz
= partition_max_size(a
->after
);
793 if (xsz
!= UINT64_MAX
&& m
> xsz
)
796 span
= charge_size(span
, m
- a
->after
->new_size
);
797 a
->after
->new_size
= m
;
800 /* What? Even still some space left (maybe because there was no preceding partition, or it had a
801 * size limit), then let's donate it to whoever wants it. */
805 LIST_FOREACH(partitions
, p
, context
->partitions
) {
808 if (p
->allocated_to_area
!= a
)
811 if (PARTITION_IS_FOREIGN(p
))
814 assert(p
->new_size
!= UINT64_MAX
);
815 m
= p
->new_size
+ span
;
817 xsz
= partition_max_size(p
);
818 if (xsz
!= UINT64_MAX
&& m
> xsz
)
821 span
= charge_size(span
, m
- p
->new_size
);
829 /* Yuck, still no one? Then make it padding */
830 if (span
> 0 && a
->after
) {
831 assert(a
->after
->new_padding
!= UINT64_MAX
);
832 a
->after
->new_padding
+= span
;
838 static int context_grow_partitions(Context
*context
) {
844 for (size_t i
= 0; i
< context
->n_free_areas
; i
++) {
845 r
= context_grow_partitions_on_free_area(context
, context
->free_areas
[i
]);
850 /* All existing partitions that have no free space after them can't change size */
851 LIST_FOREACH(partitions
, p
, context
->partitions
) {
855 if (!PARTITION_EXISTS(p
) || p
->padding_area
) {
856 /* The algorithm above must have initialized this already */
857 assert(p
->new_size
!= UINT64_MAX
);
861 assert(p
->new_size
== UINT64_MAX
);
862 p
->new_size
= p
->current_size
;
864 assert(p
->new_padding
== UINT64_MAX
);
865 p
->new_padding
= p
->current_padding
;
871 static void context_place_partitions(Context
*context
) {
877 /* Determine next partition number to assign */
878 LIST_FOREACH(partitions
, p
, context
->partitions
) {
879 if (!PARTITION_EXISTS(p
))
882 assert(p
->partno
!= UINT64_MAX
);
883 if (p
->partno
>= partno
)
884 partno
= p
->partno
+ 1;
887 for (size_t i
= 0; i
< context
->n_free_areas
; i
++) {
888 FreeArea
*a
= context
->free_areas
[i
];
889 uint64_t start
, left
;
892 assert(a
->after
->offset
!= UINT64_MAX
);
893 assert(a
->after
->new_size
!= UINT64_MAX
);
894 assert(a
->after
->new_padding
!= UINT64_MAX
);
896 start
= a
->after
->offset
+ a
->after
->new_size
+ a
->after
->new_padding
;
898 start
= context
->start
;
900 start
= round_up_size(start
, 4096);
903 LIST_FOREACH(partitions
, p
, context
->partitions
) {
904 if (p
->allocated_to_area
!= a
)
908 p
->partno
= partno
++;
910 assert(left
>= p
->new_size
);
911 start
+= p
->new_size
;
914 assert(left
>= p
->new_padding
);
915 start
+= p
->new_padding
;
916 left
-= p
->new_padding
;
921 static int config_parse_type(
923 const char *filename
,
926 unsigned section_line
,
933 sd_id128_t
*type_uuid
= data
;
939 r
= gpt_partition_type_uuid_from_string(rvalue
, type_uuid
);
941 return log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse partition type: %s", rvalue
);
946 static const Specifier specifier_table
[] = {
947 COMMON_SYSTEM_SPECIFIERS
,
951 static int config_parse_label(
953 const char *filename
,
956 unsigned section_line
,
963 _cleanup_free_ char16_t
*recoded
= NULL
;
964 _cleanup_free_
char *resolved
= NULL
;
971 r
= specifier_printf(rvalue
, specifier_table
, NULL
, &resolved
);
973 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
974 "Failed to expand specifiers in Label=, ignoring: %s", rvalue
);
978 if (!utf8_is_valid(resolved
)) {
979 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
980 "Partition label not valid UTF-8, ignoring: %s", rvalue
);
984 recoded
= utf8_to_utf16(resolved
, strlen(resolved
));
988 if (char16_strlen(recoded
) > 36) {
989 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
990 "Partition label too long for GPT table, ignoring: \"%s\" (from \"%s\")",
995 free_and_replace(*label
, resolved
);
999 static int config_parse_weight(
1001 const char *filename
,
1003 const char *section
,
1004 unsigned section_line
,
1011 uint32_t *priority
= data
, v
;
1017 r
= safe_atou32(rvalue
, &v
);
1019 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1020 "Failed to parse weight value, ignoring: %s", rvalue
);
1024 if (v
> 1000U*1000U) {
1025 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1026 "Weight needs to be in range 0…10000000, ignoring: %" PRIu32
, v
);
1034 static int config_parse_size4096(
1036 const char *filename
,
1038 const char *section
,
1039 unsigned section_line
,
1046 uint64_t *sz
= data
, parsed
;
1052 r
= parse_size(rvalue
, 1024, &parsed
);
1054 return log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1055 "Failed to parse size value: %s", rvalue
);
1058 *sz
= round_up_size(parsed
, 4096);
1060 *sz
= round_down_size(parsed
, 4096);
1065 log_syntax(unit
, LOG_NOTICE
, filename
, line
, r
, "Rounded %s= size %" PRIu64
" → %" PRIu64
", a multiple of 4096.", lvalue
, parsed
, *sz
);
1070 static int config_parse_fstype(
1072 const char *filename
,
1074 const char *section
,
1075 unsigned section_line
,
1082 char **fstype
= data
;
1087 if (!filename_is_valid(rvalue
))
1088 return log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1089 "File system type is not valid, refusing: %s", rvalue
);
1091 return free_and_strdup_warn(fstype
, rvalue
);
1094 static int config_parse_copy_files(
1096 const char *filename
,
1098 const char *section
,
1099 unsigned section_line
,
1106 _cleanup_free_
char *source
= NULL
, *buffer
= NULL
, *resolved_source
= NULL
, *resolved_target
= NULL
;
1107 const char *p
= rvalue
, *target
;
1108 Partition
*partition
= data
;
1114 r
= extract_first_word(&p
, &source
, ":", EXTRACT_CUNESCAPE
|EXTRACT_DONT_COALESCE_SEPARATORS
);
1116 return log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract source path: %s", rvalue
);
1118 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0, "No argument specified: %s", rvalue
);
1122 r
= extract_first_word(&p
, &buffer
, ":", EXTRACT_CUNESCAPE
|EXTRACT_DONT_COALESCE_SEPARATORS
);
1124 return log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract target path: %s", rvalue
);
1126 target
= source
; /* No target, then it's the same as the source */
1131 return log_syntax(unit
, LOG_ERR
, filename
, line
, SYNTHETIC_ERRNO(EINVAL
), "Too many arguments: %s", rvalue
);
1133 r
= specifier_printf(source
, specifier_table
, NULL
, &resolved_source
);
1135 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1136 "Failed to expand specifiers in CopyFiles= source, ignoring: %s", rvalue
);
1140 if (!path_is_absolute(resolved_source
) || !path_is_normalized(resolved_source
)) {
1141 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1142 "Invalid path name in CopyFiles= source, ignoring: %s", resolved_source
);
1146 r
= specifier_printf(target
, specifier_table
, NULL
, &resolved_target
);
1148 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1149 "Failed to expand specifiers in CopyFiles= target, ignoring: %s", resolved_target
);
1153 if (!path_is_absolute(resolved_target
) || !path_is_normalized(resolved_target
)) {
1154 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1155 "Invalid path name in CopyFiles= source, ignoring: %s", resolved_target
);
1159 r
= strv_consume_pair(&partition
->copy_files
, TAKE_PTR(resolved_source
), TAKE_PTR(resolved_target
));
1166 static DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_encrypt
, encrypt_mode
, EncryptMode
, ENCRYPT_OFF
, "Invalid encryption mode");
1168 static int partition_read_definition(Partition
*p
, const char *path
) {
1170 ConfigTableItem table
[] = {
1171 { "Partition", "Type", config_parse_type
, 0, &p
->type_uuid
},
1172 { "Partition", "Label", config_parse_label
, 0, &p
->new_label
},
1173 { "Partition", "UUID", config_parse_id128
, 0, &p
->new_uuid
},
1174 { "Partition", "Priority", config_parse_int32
, 0, &p
->priority
},
1175 { "Partition", "Weight", config_parse_weight
, 0, &p
->weight
},
1176 { "Partition", "PaddingWeight", config_parse_weight
, 0, &p
->padding_weight
},
1177 { "Partition", "SizeMinBytes", config_parse_size4096
, 1, &p
->size_min
},
1178 { "Partition", "SizeMaxBytes", config_parse_size4096
, -1, &p
->size_max
},
1179 { "Partition", "PaddingMinBytes", config_parse_size4096
, 1, &p
->padding_min
},
1180 { "Partition", "PaddingMaxBytes", config_parse_size4096
, -1, &p
->padding_max
},
1181 { "Partition", "FactoryReset", config_parse_bool
, 0, &p
->factory_reset
},
1182 { "Partition", "CopyBlocks", config_parse_path
, 0, &p
->copy_blocks_path
},
1183 { "Partition", "Format", config_parse_fstype
, 0, &p
->format
},
1184 { "Partition", "CopyFiles", config_parse_copy_files
, 0, p
},
1185 { "Partition", "Encrypt", config_parse_encrypt
, 0, &p
->encrypt
},
1190 r
= config_parse(NULL
, path
, NULL
,
1192 config_item_table_lookup
, table
,
1199 if (p
->size_min
!= UINT64_MAX
&& p
->size_max
!= UINT64_MAX
&& p
->size_min
> p
->size_max
)
1200 return log_syntax(NULL
, LOG_ERR
, path
, 1, SYNTHETIC_ERRNO(EINVAL
),
1201 "SizeMinBytes= larger than SizeMaxBytes=, refusing.");
1203 if (p
->padding_min
!= UINT64_MAX
&& p
->padding_max
!= UINT64_MAX
&& p
->padding_min
> p
->padding_max
)
1204 return log_syntax(NULL
, LOG_ERR
, path
, 1, SYNTHETIC_ERRNO(EINVAL
),
1205 "PaddingMinBytes= larger than PaddingMaxBytes=, refusing.");
1207 if (sd_id128_is_null(p
->type_uuid
))
1208 return log_syntax(NULL
, LOG_ERR
, path
, 1, SYNTHETIC_ERRNO(EINVAL
),
1209 "Type= not defined, refusing.");
1211 if (p
->copy_blocks_path
&& (p
->format
|| !strv_isempty(p
->copy_files
)))
1212 return log_syntax(NULL
, LOG_ERR
, path
, 1, SYNTHETIC_ERRNO(EINVAL
),
1213 "Format= and CopyBlocks= cannot be combined, refusing.");
1215 if (!strv_isempty(p
->copy_files
) && streq_ptr(p
->format
, "swap"))
1216 return log_syntax(NULL
, LOG_ERR
, path
, 1, SYNTHETIC_ERRNO(EINVAL
),
1217 "Format=swap and CopyFiles= cannot be combined, refusing.");
1219 if (!p
->format
&& (!strv_isempty(p
->copy_files
) || (p
->encrypt
!= ENCRYPT_OFF
&& !p
->copy_blocks_path
))) {
1220 /* Pick "ext4" as file system if we are configured to copy files or encrypt the device */
1221 p
->format
= strdup("ext4");
1229 static int context_read_definitions(
1231 const char *directory
,
1234 _cleanup_strv_free_
char **files
= NULL
;
1235 Partition
*last
= NULL
;
1242 r
= conf_files_list_strv(&files
, ".conf", NULL
, CONF_FILES_REGULAR
|CONF_FILES_FILTER_MASKED
, (const char**) STRV_MAKE(directory
));
1244 r
= conf_files_list_strv(&files
, ".conf", root
, CONF_FILES_REGULAR
|CONF_FILES_FILTER_MASKED
, (const char**) CONF_PATHS_STRV("repart.d"));
1246 return log_error_errno(r
, "Failed to enumerate *.conf files: %m");
1248 STRV_FOREACH(f
, files
) {
1249 _cleanup_(partition_freep
) Partition
*p
= NULL
;
1251 p
= partition_new();
1255 p
->definition_path
= strdup(*f
);
1256 if (!p
->definition_path
)
1259 r
= partition_read_definition(p
, *f
);
1263 LIST_INSERT_AFTER(partitions
, context
->partitions
, last
, p
);
1265 context
->n_partitions
++;
1271 DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_context
*, fdisk_unref_context
, NULL
);
1272 DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_partition
*, fdisk_unref_partition
, NULL
);
1273 DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_parttype
*, fdisk_unref_parttype
, NULL
);
1274 DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_table
*, fdisk_unref_table
, NULL
);
1276 static int determine_current_padding(
1277 struct fdisk_context
*c
,
1278 struct fdisk_table
*t
,
1279 struct fdisk_partition
*p
,
1282 size_t n_partitions
;
1283 uint64_t offset
, next
= UINT64_MAX
;
1289 if (!fdisk_partition_has_end(p
))
1290 return log_error_errno(SYNTHETIC_ERRNO(EIO
), "Partition has no end!");
1292 offset
= fdisk_partition_get_end(p
);
1293 assert(offset
< UINT64_MAX
/ 512);
1296 n_partitions
= fdisk_table_get_nents(t
);
1297 for (size_t i
= 0; i
< n_partitions
; i
++) {
1298 struct fdisk_partition
*q
;
1301 q
= fdisk_table_get_partition(t
, i
);
1303 return log_error_errno(SYNTHETIC_ERRNO(EIO
), "Failed to read partition metadata: %m");
1305 if (fdisk_partition_is_used(q
) <= 0)
1308 if (!fdisk_partition_has_start(q
))
1311 start
= fdisk_partition_get_start(q
);
1312 assert(start
< UINT64_MAX
/ 512);
1315 if (start
>= offset
&& (next
== UINT64_MAX
|| next
> start
))
1319 if (next
== UINT64_MAX
) {
1320 /* No later partition? In that case check the end of the usable area */
1321 next
= fdisk_get_last_lba(c
);
1322 assert(next
< UINT64_MAX
);
1323 next
++; /* The last LBA is one sector before the end */
1325 assert(next
< UINT64_MAX
/ 512);
1329 return log_error_errno(SYNTHETIC_ERRNO(EIO
), "Partition end beyond disk end.");
1332 assert(next
>= offset
);
1333 offset
= round_up_size(offset
, 4096);
1334 next
= round_down_size(next
, 4096);
1336 if (next
>= offset
) /* Check again, rounding might have fucked things up */
1337 *ret
= next
- offset
;
1344 static int fdisk_ask_cb(struct fdisk_context
*c
, struct fdisk_ask
*ask
, void *data
) {
1345 _cleanup_free_
char *ids
= NULL
;
1348 if (fdisk_ask_get_type(ask
) != FDISK_ASKTYPE_STRING
)
1351 ids
= new(char, ID128_UUID_STRING_MAX
);
1355 r
= fdisk_ask_string_set_result(ask
, id128_to_uuid_string(*(sd_id128_t
*) data
, ids
));
1363 static int fdisk_set_disklabel_id_by_uuid(struct fdisk_context
*c
, sd_id128_t id
) {
1366 r
= fdisk_set_ask(c
, fdisk_ask_cb
, &id
);
1370 r
= fdisk_set_disklabel_id(c
);
1374 return fdisk_set_ask(c
, NULL
, NULL
);
1377 static int derive_uuid(sd_id128_t base
, const char *token
, sd_id128_t
*ret
) {
1379 unsigned char md
[SHA256_DIGEST_LENGTH
];
1386 /* Derive a new UUID from the specified UUID in a stable and reasonably safe way. Specifically, we
1387 * calculate the HMAC-SHA256 of the specified token string, keyed by the supplied base (typically the
1388 * machine ID). We use the machine ID as key (and not as cleartext!) of the HMAC operation since it's
1389 * the machine ID we don't want to leak. */
1391 if (!HMAC(EVP_sha256(),
1392 &base
, sizeof(base
),
1393 (const unsigned char*) token
, strlen(token
),
1395 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "HMAC-SHA256 calculation failed.");
1397 /* Take the first half, mark it as v4 UUID */
1398 assert_cc(sizeof(result
.md
) == sizeof(result
.id
) * 2);
1399 *ret
= id128_make_v4_uuid(result
.id
);
1403 static int context_load_partition_table(
1408 _cleanup_(fdisk_unref_contextp
) struct fdisk_context
*c
= NULL
;
1409 _cleanup_(fdisk_unref_tablep
) struct fdisk_table
*t
= NULL
;
1410 uint64_t left_boundary
= UINT64_MAX
, first_lba
, last_lba
, nsectors
;
1411 _cleanup_free_
char *disk_uuid_string
= NULL
;
1412 bool from_scratch
= false;
1413 sd_id128_t disk_uuid
;
1414 size_t n_partitions
;
1420 assert(!context
->fdisk_context
);
1421 assert(!context
->free_areas
);
1422 assert(context
->start
== UINT64_MAX
);
1423 assert(context
->end
== UINT64_MAX
);
1424 assert(context
->total
== UINT64_MAX
);
1426 c
= fdisk_new_context();
1430 /* libfdisk doesn't have an API to operate on arbitrary fds, hence reopen the fd going via the
1431 * /proc/self/fd/ magic path if we have an existing fd. Open the original file otherwise. */
1432 if (*backing_fd
< 0)
1433 r
= fdisk_assign_device(c
, node
, arg_dry_run
);
1435 char procfs_path
[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
1436 xsprintf(procfs_path
, "/proc/self/fd/%i", *backing_fd
);
1438 r
= fdisk_assign_device(c
, procfs_path
, arg_dry_run
);
1440 if (r
== -EINVAL
&& arg_size_auto
) {
1443 /* libfdisk returns EINVAL if opening a file of size zero. Let's check for that, and accept
1444 * it if automatic sizing is requested. */
1446 if (*backing_fd
< 0)
1447 r
= stat(node
, &st
);
1449 r
= fstat(*backing_fd
, &st
);
1451 return log_error_errno(errno
, "Failed to stat block device '%s': %m", node
);
1453 if (S_ISREG(st
.st_mode
) && st
.st_size
== 0)
1454 return /* from_scratch = */ true;
1459 return log_error_errno(r
, "Failed to open device '%s': %m", node
);
1461 if (*backing_fd
< 0) {
1462 /* If we have no fd referencing the device yet, make a copy of the fd now, so that we have one */
1463 *backing_fd
= fcntl(fdisk_get_devfd(c
), F_DUPFD_CLOEXEC
, 3);
1464 if (*backing_fd
< 0)
1465 return log_error_errno(errno
, "Failed to duplicate fdisk fd: %m");
1468 /* Tell udev not to interfere while we are processing the device */
1469 if (flock(fdisk_get_devfd(c
), arg_dry_run
? LOCK_SH
: LOCK_EX
) < 0)
1470 return log_error_errno(errno
, "Failed to lock block device: %m");
1472 switch (arg_empty
) {
1475 /* Refuse empty disks, insist on an existing GPT partition table */
1476 if (!fdisk_is_labeltype(c
, FDISK_DISKLABEL_GPT
))
1477 return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON
), "Disk %s has no GPT disk label, not repartitioning.", node
);
1482 /* Require an empty disk, refuse any existing partition table */
1483 r
= fdisk_has_label(c
);
1485 return log_error_errno(r
, "Failed to determine whether disk %s has a disk label: %m", node
);
1487 return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON
), "Disk %s already has a disk label, refusing.", node
);
1489 from_scratch
= true;
1493 /* Allow both an empty disk and an existing partition table, but only GPT */
1494 r
= fdisk_has_label(c
);
1496 return log_error_errno(r
, "Failed to determine whether disk %s has a disk label: %m", node
);
1498 if (!fdisk_is_labeltype(c
, FDISK_DISKLABEL_GPT
))
1499 return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON
), "Disk %s has non-GPT disk label, not repartitioning.", node
);
1501 from_scratch
= true;
1507 /* Always reinitiaize the disk, don't consider what there was on the disk before */
1508 from_scratch
= true;
1513 r
= fdisk_create_disklabel(c
, "gpt");
1515 return log_error_errno(r
, "Failed to create GPT disk label: %m");
1517 r
= derive_uuid(context
->seed
, "disk-uuid", &disk_uuid
);
1519 return log_error_errno(r
, "Failed to acquire disk GPT uuid: %m");
1521 r
= fdisk_set_disklabel_id_by_uuid(c
, disk_uuid
);
1523 return log_error_errno(r
, "Failed to set GPT disk label: %m");
1525 goto add_initial_free_area
;
1528 r
= fdisk_get_disklabel_id(c
, &disk_uuid_string
);
1530 return log_error_errno(r
, "Failed to get current GPT disk label UUID: %m");
1532 r
= sd_id128_from_string(disk_uuid_string
, &disk_uuid
);
1534 return log_error_errno(r
, "Failed to parse current GPT disk label UUID: %m");
1536 if (sd_id128_is_null(disk_uuid
)) {
1537 r
= derive_uuid(context
->seed
, "disk-uuid", &disk_uuid
);
1539 return log_error_errno(r
, "Failed to acquire disk GPT uuid: %m");
1541 r
= fdisk_set_disklabel_id(c
);
1543 return log_error_errno(r
, "Failed to set GPT disk label: %m");
1546 r
= fdisk_get_partitions(c
, &t
);
1548 return log_error_errno(r
, "Failed to acquire partition table: %m");
1550 n_partitions
= fdisk_table_get_nents(t
);
1551 for (size_t i
= 0; i
< n_partitions
; i
++) {
1552 _cleanup_free_
char *label_copy
= NULL
;
1553 Partition
*pp
, *last
= NULL
;
1554 struct fdisk_partition
*p
;
1555 struct fdisk_parttype
*pt
;
1556 const char *pts
, *ids
, *label
;
1559 sd_id128_t ptid
, id
;
1562 p
= fdisk_table_get_partition(t
, i
);
1564 return log_error_errno(SYNTHETIC_ERRNO(EIO
), "Failed to read partition metadata: %m");
1566 if (fdisk_partition_is_used(p
) <= 0)
1569 if (fdisk_partition_has_start(p
) <= 0 ||
1570 fdisk_partition_has_size(p
) <= 0 ||
1571 fdisk_partition_has_partno(p
) <= 0)
1572 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Found a partition without a position, size or number.");
1574 pt
= fdisk_partition_get_type(p
);
1576 return log_error_errno(SYNTHETIC_ERRNO(EIO
), "Failed to acquire type of partition: %m");
1578 pts
= fdisk_parttype_get_string(pt
);
1580 return log_error_errno(SYNTHETIC_ERRNO(EIO
), "Failed to acquire type of partition as string: %m");
1582 r
= sd_id128_from_string(pts
, &ptid
);
1584 return log_error_errno(r
, "Failed to parse partition type UUID %s: %m", pts
);
1586 ids
= fdisk_partition_get_uuid(p
);
1588 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Found a partition without a UUID.");
1590 r
= sd_id128_from_string(ids
, &id
);
1592 return log_error_errno(r
, "Failed to parse partition UUID %s: %m", ids
);
1594 label
= fdisk_partition_get_name(p
);
1595 if (!isempty(label
)) {
1596 label_copy
= strdup(label
);
1601 sz
= fdisk_partition_get_size(p
);
1602 assert_se(sz
<= UINT64_MAX
/512);
1605 start
= fdisk_partition_get_start(p
);
1606 assert_se(start
<= UINT64_MAX
/512);
1609 partno
= fdisk_partition_get_partno(p
);
1611 if (left_boundary
== UINT64_MAX
|| left_boundary
> start
)
1612 left_boundary
= start
;
1614 /* Assign this existing partition to the first partition of the right type that doesn't have
1615 * an existing one assigned yet. */
1616 LIST_FOREACH(partitions
, pp
, context
->partitions
) {
1619 if (!sd_id128_equal(pp
->type_uuid
, ptid
))
1622 if (!pp
->current_partition
) {
1623 pp
->current_uuid
= id
;
1624 pp
->current_size
= sz
;
1626 pp
->partno
= partno
;
1627 pp
->current_label
= TAKE_PTR(label_copy
);
1629 pp
->current_partition
= p
;
1630 fdisk_ref_partition(p
);
1632 r
= determine_current_padding(c
, t
, p
, &pp
->current_padding
);
1636 if (pp
->current_padding
> 0) {
1637 r
= context_add_free_area(context
, pp
->current_padding
, pp
);
1647 /* If we have no matching definition, create a new one. */
1649 _cleanup_(partition_freep
) Partition
*np
= NULL
;
1651 np
= partition_new();
1655 np
->current_uuid
= id
;
1656 np
->type_uuid
= ptid
;
1657 np
->current_size
= sz
;
1659 np
->partno
= partno
;
1660 np
->current_label
= TAKE_PTR(label_copy
);
1662 np
->current_partition
= p
;
1663 fdisk_ref_partition(p
);
1665 r
= determine_current_padding(c
, t
, p
, &np
->current_padding
);
1669 if (np
->current_padding
> 0) {
1670 r
= context_add_free_area(context
, np
->current_padding
, np
);
1675 LIST_INSERT_AFTER(partitions
, context
->partitions
, last
, TAKE_PTR(np
));
1676 context
->n_partitions
++;
1680 add_initial_free_area
:
1681 nsectors
= fdisk_get_nsectors(c
);
1682 assert(nsectors
<= UINT64_MAX
/512);
1685 first_lba
= fdisk_get_first_lba(c
);
1686 assert(first_lba
<= UINT64_MAX
/512);
1689 last_lba
= fdisk_get_last_lba(c
);
1690 assert(last_lba
< UINT64_MAX
);
1692 assert(last_lba
<= UINT64_MAX
/512);
1695 assert(last_lba
>= first_lba
);
1697 if (left_boundary
== UINT64_MAX
) {
1698 /* No partitions at all? Then the whole disk is up for grabs. */
1700 first_lba
= round_up_size(first_lba
, 4096);
1701 last_lba
= round_down_size(last_lba
, 4096);
1703 if (last_lba
> first_lba
) {
1704 r
= context_add_free_area(context
, last_lba
- first_lba
, NULL
);
1709 /* Add space left of first partition */
1710 assert(left_boundary
>= first_lba
);
1712 first_lba
= round_up_size(first_lba
, 4096);
1713 left_boundary
= round_down_size(left_boundary
, 4096);
1714 last_lba
= round_down_size(last_lba
, 4096);
1716 if (left_boundary
> first_lba
) {
1717 r
= context_add_free_area(context
, left_boundary
- first_lba
, NULL
);
1723 context
->start
= first_lba
;
1724 context
->end
= last_lba
;
1725 context
->total
= nsectors
;
1726 context
->fdisk_context
= TAKE_PTR(c
);
1728 return from_scratch
;
1731 static void context_unload_partition_table(Context
*context
) {
1732 Partition
*p
, *next
;
1736 LIST_FOREACH_SAFE(partitions
, p
, next
, context
->partitions
) {
1738 /* Entirely remove partitions that have no configuration */
1739 if (PARTITION_IS_FOREIGN(p
)) {
1740 partition_unlink_and_free(context
, p
);
1744 /* Otherwise drop all data we read off the block device and everything we might have
1745 * calculated based on it */
1748 p
->current_size
= UINT64_MAX
;
1749 p
->new_size
= UINT64_MAX
;
1750 p
->current_padding
= UINT64_MAX
;
1751 p
->new_padding
= UINT64_MAX
;
1752 p
->partno
= UINT64_MAX
;
1753 p
->offset
= UINT64_MAX
;
1755 if (p
->current_partition
) {
1756 fdisk_unref_partition(p
->current_partition
);
1757 p
->current_partition
= NULL
;
1760 if (p
->new_partition
) {
1761 fdisk_unref_partition(p
->new_partition
);
1762 p
->new_partition
= NULL
;
1765 p
->padding_area
= NULL
;
1766 p
->allocated_to_area
= NULL
;
1768 p
->current_uuid
= SD_ID128_NULL
;
1769 p
->current_label
= mfree(p
->current_label
);
1772 context
->start
= UINT64_MAX
;
1773 context
->end
= UINT64_MAX
;
1774 context
->total
= UINT64_MAX
;
1776 if (context
->fdisk_context
) {
1777 fdisk_unref_context(context
->fdisk_context
);
1778 context
->fdisk_context
= NULL
;
1781 context_free_free_areas(context
);
1784 static int format_size_change(uint64_t from
, uint64_t to
, char **ret
) {
1785 char format_buffer1
[FORMAT_BYTES_MAX
], format_buffer2
[FORMAT_BYTES_MAX
], *buf
;
1787 if (from
!= UINT64_MAX
)
1788 format_bytes(format_buffer1
, sizeof(format_buffer1
), from
);
1789 if (to
!= UINT64_MAX
)
1790 format_bytes(format_buffer2
, sizeof(format_buffer2
), to
);
1792 if (from
!= UINT64_MAX
) {
1793 if (from
== to
|| to
== UINT64_MAX
)
1794 buf
= strdup(format_buffer1
);
1796 buf
= strjoin(format_buffer1
, " ", special_glyph(SPECIAL_GLYPH_ARROW
), " ", format_buffer2
);
1797 } else if (to
!= UINT64_MAX
)
1798 buf
= strjoin(special_glyph(SPECIAL_GLYPH_ARROW
), " ", format_buffer2
);
1807 *ret
= TAKE_PTR(buf
);
1811 static const char *partition_label(const Partition
*p
) {
1815 return p
->new_label
;
1817 if (p
->current_label
)
1818 return p
->current_label
;
1820 return gpt_partition_type_uuid_to_string(p
->type_uuid
);
1823 static int context_dump_partitions(Context
*context
, const char *node
) {
1824 _cleanup_(table_unrefp
) Table
*t
= NULL
;
1825 uint64_t sum_padding
= 0, sum_size
= 0;
1829 if ((arg_json_format_flags
& JSON_FORMAT_OFF
) && context
->n_partitions
== 0) {
1830 log_info("Empty partition table.");
1834 t
= table_new("type", "label", "uuid", "file", "node", "offset", "old size", "raw size", "size", "old padding", "raw padding", "padding", "activity");
1838 if (!DEBUG_LOGGING
) {
1839 if (arg_json_format_flags
& JSON_FORMAT_OFF
)
1840 (void) table_set_display(t
, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4,
1841 (size_t) 8, (size_t) 11, (size_t) -1);
1843 (void) table_set_display(t
, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4,
1844 (size_t) 5, (size_t) 6, (size_t) 7, (size_t) 9, (size_t) 10, (size_t) 12, (size_t) -1);
1847 (void) table_set_align_percent(t
, table_get_cell(t
, 0, 4), 100);
1848 (void) table_set_align_percent(t
, table_get_cell(t
, 0, 5), 100);
1850 LIST_FOREACH(partitions
, p
, context
->partitions
) {
1851 _cleanup_free_
char *size_change
= NULL
, *padding_change
= NULL
, *partname
= NULL
;
1852 char uuid_buffer
[ID128_UUID_STRING_MAX
];
1853 const char *label
, *activity
= NULL
;
1858 if (p
->current_size
== UINT64_MAX
)
1859 activity
= "create";
1860 else if (p
->current_size
!= p
->new_size
)
1861 activity
= "resize";
1863 label
= partition_label(p
);
1864 partname
= p
->partno
!= UINT64_MAX
? fdisk_partname(node
, p
->partno
+1) : NULL
;
1866 r
= format_size_change(p
->current_size
, p
->new_size
, &size_change
);
1870 r
= format_size_change(p
->current_padding
, p
->new_padding
, &padding_change
);
1874 if (p
->new_size
!= UINT64_MAX
)
1875 sum_size
+= p
->new_size
;
1876 if (p
->new_padding
!= UINT64_MAX
)
1877 sum_padding
+= p
->new_padding
;
1881 TABLE_STRING
, gpt_partition_type_uuid_to_string_harder(p
->type_uuid
, uuid_buffer
),
1882 TABLE_STRING
, label
?: "-", TABLE_SET_COLOR
, label
? NULL
: ansi_grey(),
1883 TABLE_UUID
, sd_id128_is_null(p
->new_uuid
) ? p
->current_uuid
: p
->new_uuid
,
1884 TABLE_STRING
, p
->definition_path
? basename(p
->definition_path
) : "-", TABLE_SET_COLOR
, p
->definition_path
? NULL
: ansi_grey(),
1885 TABLE_STRING
, partname
?: "-", TABLE_SET_COLOR
, partname
? NULL
: ansi_highlight(),
1886 TABLE_UINT64
, p
->offset
,
1887 TABLE_UINT64
, p
->current_size
== UINT64_MAX
? 0 : p
->current_size
,
1888 TABLE_UINT64
, p
->new_size
,
1889 TABLE_STRING
, size_change
, TABLE_SET_COLOR
, !p
->partitions_next
&& sum_size
> 0 ? ansi_underline() : NULL
,
1890 TABLE_UINT64
, p
->current_padding
== UINT64_MAX
? 0 : p
->current_padding
,
1891 TABLE_UINT64
, p
->new_padding
,
1892 TABLE_STRING
, padding_change
, TABLE_SET_COLOR
, !p
->partitions_next
&& sum_padding
> 0 ? ansi_underline() : NULL
,
1893 TABLE_STRING
, activity
?: "unknown");
1895 return table_log_add_error(r
);
1898 if ((arg_json_format_flags
& JSON_FORMAT_OFF
) && (sum_padding
> 0 || sum_size
> 0)) {
1899 char s
[FORMAT_BYTES_MAX
];
1902 a
= strjoina(special_glyph(SPECIAL_GLYPH_SIGMA
), " = ", format_bytes(s
, sizeof(s
), sum_size
));
1903 b
= strjoina(special_glyph(SPECIAL_GLYPH_SIGMA
), " = ", format_bytes(s
, sizeof(s
), sum_padding
));
1921 return table_log_add_error(r
);
1924 return table_print_with_pager(t
, arg_json_format_flags
, arg_pager_flags
, arg_legend
);
1927 static void context_bar_char_process_partition(
1932 size_t *ret_start
) {
1934 uint64_t from
, to
, total
;
1945 assert(p
->offset
!= UINT64_MAX
);
1946 assert(p
->new_size
!= UINT64_MAX
);
1949 to
= from
+ p
->new_size
;
1951 assert(context
->end
>= context
->start
);
1952 total
= context
->end
- context
->start
;
1954 assert(from
>= context
->start
);
1955 assert(from
<= context
->end
);
1956 x
= (from
- context
->start
) * n
/ total
;
1958 assert(to
>= context
->start
);
1959 assert(to
<= context
->end
);
1960 y
= (to
- context
->start
) * n
/ total
;
1965 for (size_t i
= x
; i
< y
; i
++)
1971 static int partition_hint(const Partition
*p
, const char *node
, char **ret
) {
1972 _cleanup_free_
char *buf
= NULL
;
1973 char ids
[ID128_UUID_STRING_MAX
];
1977 /* Tries really hard to find a suitable description for this partition */
1979 if (p
->definition_path
) {
1980 buf
= strdup(basename(p
->definition_path
));
1984 label
= partition_label(p
);
1985 if (!isempty(label
)) {
1986 buf
= strdup(label
);
1990 if (p
->partno
!= UINT64_MAX
) {
1991 buf
= fdisk_partname(node
, p
->partno
+1);
1995 if (!sd_id128_is_null(p
->new_uuid
))
1997 else if (!sd_id128_is_null(p
->current_uuid
))
1998 id
= p
->current_uuid
;
2002 buf
= strdup(id128_to_uuid_string(id
, ids
));
2008 *ret
= TAKE_PTR(buf
);
2012 static int context_dump_partition_bar(Context
*context
, const char *node
) {
2013 _cleanup_free_ Partition
**bar
= NULL
;
2014 _cleanup_free_
size_t *start_array
= NULL
;
2015 Partition
*p
, *last
= NULL
;
2019 assert_se((c
= columns()) >= 2);
2020 c
-= 2; /* We do not use the leftmost and rightmost character cell */
2022 bar
= new0(Partition
*, c
);
2026 start_array
= new(size_t, context
->n_partitions
);
2030 LIST_FOREACH(partitions
, p
, context
->partitions
)
2031 context_bar_char_process_partition(context
, bar
, c
, p
, start_array
+ j
++);
2035 for (size_t i
= 0; i
< c
; i
++) {
2040 fputs(z
? ansi_green() : ansi_yellow(), stdout
);
2041 fputs(special_glyph(SPECIAL_GLYPH_DARK_SHADE
), stdout
);
2043 fputs(ansi_normal(), stdout
);
2044 fputs(special_glyph(SPECIAL_GLYPH_LIGHT_SHADE
), stdout
);
2050 fputs(ansi_normal(), stdout
);
2053 for (size_t i
= 0; i
< context
->n_partitions
; i
++) {
2054 _cleanup_free_
char **line
= NULL
;
2056 line
= new0(char*, c
);
2061 LIST_FOREACH(partitions
, p
, context
->partitions
) {
2062 _cleanup_free_
char *d
= NULL
;
2065 if (i
< context
->n_partitions
- j
) {
2067 if (line
[start_array
[j
-1]]) {
2070 /* Upgrade final corner to the right with a branch to the right */
2071 e
= startswith(line
[start_array
[j
-1]], special_glyph(SPECIAL_GLYPH_TREE_RIGHT
));
2073 d
= strjoin(special_glyph(SPECIAL_GLYPH_TREE_BRANCH
), e
);
2080 d
= strdup(special_glyph(SPECIAL_GLYPH_TREE_VERTICAL
));
2085 } else if (i
== context
->n_partitions
- j
) {
2086 _cleanup_free_
char *hint
= NULL
;
2088 (void) partition_hint(p
, node
, &hint
);
2090 if (streq_ptr(line
[start_array
[j
-1]], special_glyph(SPECIAL_GLYPH_TREE_VERTICAL
)))
2091 d
= strjoin(special_glyph(SPECIAL_GLYPH_TREE_BRANCH
), " ", strna(hint
));
2093 d
= strjoin(special_glyph(SPECIAL_GLYPH_TREE_RIGHT
), " ", strna(hint
));
2100 free_and_replace(line
[start_array
[j
-1]], d
);
2108 fputs(line
[j
], stdout
);
2109 j
+= utf8_console_width(line
[j
]);
2118 for (j
= 0; j
< c
; j
++)
2125 static bool context_changed(const Context
*context
) {
2128 LIST_FOREACH(partitions
, p
, context
->partitions
) {
2132 if (p
->allocated_to_area
)
2135 if (p
->new_size
!= p
->current_size
)
2142 static int context_wipe_range(Context
*context
, uint64_t offset
, uint64_t size
) {
2143 _cleanup_(blkid_free_probep
) blkid_probe probe
= NULL
;
2147 assert(offset
!= UINT64_MAX
);
2148 assert(size
!= UINT64_MAX
);
2150 probe
= blkid_new_probe();
2155 r
= blkid_probe_set_device(probe
, fdisk_get_devfd(context
->fdisk_context
), offset
, size
);
2157 return log_error_errno(errno
?: SYNTHETIC_ERRNO(EIO
), "Failed to allocate device probe for wiping.");
2160 if (blkid_probe_enable_superblocks(probe
, true) < 0 ||
2161 blkid_probe_set_superblocks_flags(probe
, BLKID_SUBLKS_MAGIC
|BLKID_SUBLKS_BADCSUM
) < 0 ||
2162 blkid_probe_enable_partitions(probe
, true) < 0 ||
2163 blkid_probe_set_partitions_flags(probe
, BLKID_PARTS_MAGIC
) < 0)
2164 return log_error_errno(errno
?: SYNTHETIC_ERRNO(EIO
), "Failed to enable superblock and partition probing.");
2168 r
= blkid_do_probe(probe
);
2170 return log_error_errno(errno
?: SYNTHETIC_ERRNO(EIO
), "Failed to probe for file systems.");
2175 if (blkid_do_wipe(probe
, false) < 0)
2176 return log_error_errno(errno
?: SYNTHETIC_ERRNO(EIO
), "Failed to wipe file system signature.");
2182 static int context_wipe_partition(Context
*context
, Partition
*p
) {
2187 assert(!PARTITION_EXISTS(p
)); /* Safety check: never wipe existing partitions */
2189 assert(p
->offset
!= UINT64_MAX
);
2190 assert(p
->new_size
!= UINT64_MAX
);
2192 r
= context_wipe_range(context
, p
->offset
, p
->new_size
);
2196 log_info("Successfully wiped file system signatures from future partition %" PRIu64
".", p
->partno
);
2200 static int context_discard_range(
2209 assert(offset
!= UINT64_MAX
);
2210 assert(size
!= UINT64_MAX
);
2215 assert_se((fd
= fdisk_get_devfd(context
->fdisk_context
)) >= 0);
2217 if (fstat(fd
, &st
) < 0)
2220 if (S_ISREG(st
.st_mode
)) {
2221 if (fallocate(fd
, FALLOC_FL_PUNCH_HOLE
|FALLOC_FL_KEEP_SIZE
, offset
, size
) < 0) {
2222 if (ERRNO_IS_NOT_SUPPORTED(errno
))
2231 if (S_ISBLK(st
.st_mode
)) {
2232 uint64_t range
[2], end
;
2234 range
[0] = round_up_size(offset
, 512);
2236 end
= offset
+ size
;
2237 if (end
<= range
[0])
2240 range
[1] = round_down_size(end
- range
[0], 512);
2244 if (ioctl(fd
, BLKDISCARD
, range
) < 0) {
2245 if (ERRNO_IS_NOT_SUPPORTED(errno
))
2257 static int context_discard_partition(Context
*context
, Partition
*p
) {
2263 assert(p
->offset
!= UINT64_MAX
);
2264 assert(p
->new_size
!= UINT64_MAX
);
2265 assert(!PARTITION_EXISTS(p
)); /* Safety check: never discard existing partitions */
2270 r
= context_discard_range(context
, p
->offset
, p
->new_size
);
2271 if (r
== -EOPNOTSUPP
) {
2272 log_info("Storage does not support discard, not discarding data in future partition %" PRIu64
".", p
->partno
);
2276 log_info("Partition %" PRIu64
" too short for discard, skipping.", p
->partno
);
2280 return log_error_errno(r
, "Failed to discard data for future partition %" PRIu64
".", p
->partno
);
2282 log_info("Successfully discarded data from future partition %" PRIu64
".", p
->partno
);
2286 static int context_discard_gap_after(Context
*context
, Partition
*p
) {
2287 uint64_t gap
, next
= UINT64_MAX
;
2292 assert(!p
|| (p
->offset
!= UINT64_MAX
&& p
->new_size
!= UINT64_MAX
));
2295 gap
= p
->offset
+ p
->new_size
;
2297 gap
= context
->start
;
2299 LIST_FOREACH(partitions
, q
, context
->partitions
) {
2303 assert(q
->offset
!= UINT64_MAX
);
2304 assert(q
->new_size
!= UINT64_MAX
);
2306 if (q
->offset
< gap
)
2309 if (next
== UINT64_MAX
|| q
->offset
< next
)
2313 if (next
== UINT64_MAX
) {
2314 next
= context
->end
;
2316 return log_error_errno(SYNTHETIC_ERRNO(EIO
), "Partition end beyond disk end.");
2319 assert(next
>= gap
);
2320 r
= context_discard_range(context
, gap
, next
- gap
);
2321 if (r
== -EOPNOTSUPP
) {
2323 log_info("Storage does not support discard, not discarding gap after partition %" PRIu64
".", p
->partno
);
2325 log_info("Storage does not support discard, not discarding gap at beginning of disk.");
2328 if (r
== 0) /* Too short */
2332 return log_error_errno(r
, "Failed to discard gap after partition %" PRIu64
".", p
->partno
);
2334 return log_error_errno(r
, "Failed to discard gap at beginning of disk.");
2338 log_info("Successfully discarded gap after partition %" PRIu64
".", p
->partno
);
2340 log_info("Successfully discarded gap at beginning of disk.");
2345 static int context_wipe_and_discard(Context
*context
, bool from_scratch
) {
2351 /* Wipe and discard the contents of all partitions we are about to create. We skip the discarding if
2352 * we were supposed to start from scratch anyway, as in that case we just discard the whole block
2353 * device in one go early on. */
2355 LIST_FOREACH(partitions
, p
, context
->partitions
) {
2357 if (!p
->allocated_to_area
)
2360 r
= context_wipe_partition(context
, p
);
2364 if (!from_scratch
) {
2365 r
= context_discard_partition(context
, p
);
2369 r
= context_discard_gap_after(context
, p
);
2375 if (!from_scratch
) {
2376 r
= context_discard_gap_after(context
, NULL
);
2384 static int partition_encrypt(
2387 struct crypt_device
**ret_cd
,
2390 #if HAVE_LIBCRYPTSETUP
2391 _cleanup_(sym_crypt_freep
) struct crypt_device
*cd
= NULL
;
2392 _cleanup_(erase_and_freep
) void *volume_key
= NULL
;
2393 _cleanup_free_
char *dm_name
= NULL
, *vol
= NULL
;
2394 char suuid
[ID128_UUID_STRING_MAX
];
2395 size_t volume_key_size
= 256 / 8;
2400 assert(p
->encrypt
!= ENCRYPT_OFF
);
2402 log_debug("Encryption mode for partition %" PRIu64
": %s", p
->partno
, encrypt_mode_to_string(p
->encrypt
));
2404 r
= dlopen_cryptsetup();
2406 return log_error_errno(r
, "libcryptsetup not found, cannot encrypt: %m");
2408 if (asprintf(&dm_name
, "luks-repart-%08" PRIx64
, random_u64()) < 0)
2412 vol
= path_join("/dev/mapper/", dm_name
);
2417 r
= derive_uuid(p
->new_uuid
, "luks-uuid", &uuid
);
2421 log_info("Encrypting future partition %" PRIu64
"...", p
->partno
);
2423 volume_key
= malloc(volume_key_size
);
2427 r
= genuine_random_bytes(volume_key
, volume_key_size
, RANDOM_BLOCK
);
2429 return log_error_errno(r
, "Failed to generate volume key: %m");
2431 r
= sym_crypt_init(&cd
, node
);
2433 return log_error_errno(r
, "Failed to allocate libcryptsetup context: %m");
2435 cryptsetup_enable_logging(cd
);
2437 r
= sym_crypt_format(cd
,
2441 id128_to_uuid_string(uuid
, suuid
),
2444 &(struct crypt_params_luks2
) {
2445 .label
= p
->new_label
,
2446 .sector_size
= 512U,
2449 return log_error_errno(r
, "Failed to LUKS2 format future partition: %m");
2451 if (IN_SET(p
->encrypt
, ENCRYPT_KEY_FILE
, ENCRYPT_KEY_FILE_TPM2
)) {
2452 r
= sym_crypt_keyslot_add_by_volume_key(
2460 return log_error_errno(r
, "Failed to add LUKS2 key: %m");
2463 if (IN_SET(p
->encrypt
, ENCRYPT_TPM2
, ENCRYPT_KEY_FILE_TPM2
)) {
2465 _cleanup_(erase_and_freep
) char *base64_encoded
= NULL
;
2466 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
2467 _cleanup_(erase_and_freep
) void *secret
= NULL
;
2468 _cleanup_free_
void *blob
= NULL
, *hash
= NULL
;
2469 size_t secret_size
, blob_size
, hash_size
;
2472 r
= tpm2_seal(arg_tpm2_device
, arg_tpm2_pcr_mask
, &secret
, &secret_size
, &blob
, &blob_size
, &hash
, &hash_size
);
2474 return log_error_errno(r
, "Failed to seal to TPM2: %m");
2476 r
= base64mem(secret
, secret_size
, &base64_encoded
);
2478 return log_error_errno(r
, "Failed to base64 encode secret key: %m");
2480 r
= cryptsetup_set_minimal_pbkdf(cd
);
2482 return log_error_errno(r
, "Failed to set minimal PBKDF: %m");
2484 keyslot
= sym_crypt_keyslot_add_by_volume_key(
2490 strlen(base64_encoded
));
2492 return log_error_errno(keyslot
, "Failed to add new TPM2 key to %s: %m", node
);
2494 r
= tpm2_make_luks2_json(keyslot
, arg_tpm2_pcr_mask
, blob
, blob_size
, hash
, hash_size
, &v
);
2496 return log_error_errno(r
, "Failed to prepare TPM2 JSON token object: %m");
2498 r
= cryptsetup_add_token_json(cd
, v
);
2500 return log_error_errno(r
, "Failed to add TPM2 JSON token to LUKS2 header: %m");
2502 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
2503 "Support for TPM2 enrollment not enabled.");
2507 r
= sym_crypt_activate_by_volume_key(
2512 arg_discard
? CRYPT_ACTIVATE_ALLOW_DISCARDS
: 0);
2514 return log_error_errno(r
, "Failed to activate LUKS superblock: %m");
2516 log_info("Successfully encrypted future partition %" PRIu64
".", p
->partno
);
2519 _cleanup_close_
int dev_fd
= -1;
2521 dev_fd
= open(vol
, O_RDWR
|O_CLOEXEC
|O_NOCTTY
);
2523 return log_error_errno(errno
, "Failed to open LUKS volume '%s': %m", vol
);
2525 *ret_fd
= TAKE_FD(dev_fd
);
2529 *ret_cd
= TAKE_PTR(cd
);
2531 *ret_volume
= TAKE_PTR(vol
);
2535 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "libcryptsetup is not supported, cannot encrypt: %m");
2539 static int deactivate_luks(struct crypt_device
*cd
, const char *node
) {
2540 #if HAVE_LIBCRYPTSETUP
2548 /* udev or so might access out block device in the background while we are done. Let's hence force
2549 * detach the volume. We sync'ed before, hence this should be safe. */
2551 r
= sym_crypt_deactivate_by_name(cd
, basename(node
), CRYPT_DEACTIVATE_FORCE
);
2553 return log_error_errno(r
, "Failed to deactivate LUKS device: %m");
2561 static int context_copy_blocks(Context
*context
) {
2563 int whole_fd
= -1, r
;
2567 /* Copy in file systems on the block level */
2569 LIST_FOREACH(partitions
, p
, context
->partitions
) {
2570 _cleanup_(sym_crypt_freep
) struct crypt_device
*cd
= NULL
;
2571 _cleanup_(loop_device_unrefp
) LoopDevice
*d
= NULL
;
2572 _cleanup_free_
char *encrypted
= NULL
;
2573 _cleanup_close_
int encrypted_dev_fd
= -1;
2574 char buf
[FORMAT_BYTES_MAX
];
2577 if (p
->copy_blocks_fd
< 0)
2583 if (PARTITION_EXISTS(p
)) /* Never copy over existing partitions */
2586 assert(p
->new_size
!= UINT64_MAX
);
2587 assert(p
->copy_blocks_size
!= UINT64_MAX
);
2588 assert(p
->new_size
>= p
->copy_blocks_size
);
2591 assert_se((whole_fd
= fdisk_get_devfd(context
->fdisk_context
)) >= 0);
2593 if (p
->encrypt
!= ENCRYPT_OFF
) {
2594 r
= loop_device_make(whole_fd
, O_RDWR
, p
->offset
, p
->new_size
, 0, &d
);
2596 return log_error_errno(r
, "Failed to make loopback device of future partition %" PRIu64
": %m", p
->partno
);
2598 r
= loop_device_flock(d
, LOCK_EX
);
2600 return log_error_errno(r
, "Failed to lock loopback device: %m");
2602 r
= partition_encrypt(p
, d
->node
, &cd
, &encrypted
, &encrypted_dev_fd
);
2604 return log_error_errno(r
, "Failed to encrypt device: %m");
2606 if (flock(encrypted_dev_fd
, LOCK_EX
) < 0)
2607 return log_error_errno(errno
, "Failed to lock LUKS device: %m");
2609 target_fd
= encrypted_dev_fd
;
2611 if (lseek(whole_fd
, p
->offset
, SEEK_SET
) == (off_t
) -1)
2612 return log_error_errno(errno
, "Failed to seek to partition offset: %m");
2614 target_fd
= whole_fd
;
2617 log_info("Copying in '%s' (%s) on block level into future partition %" PRIu64
".", p
->copy_blocks_path
, format_bytes(buf
, sizeof(buf
), p
->copy_blocks_size
), p
->partno
);
2619 r
= copy_bytes_full(p
->copy_blocks_fd
, target_fd
, p
->copy_blocks_size
, 0, NULL
, NULL
, NULL
, NULL
);
2621 return log_error_errno(r
, "Failed to copy in data from '%s': %m", p
->copy_blocks_path
);
2623 if (fsync(target_fd
) < 0)
2624 return log_error_errno(r
, "Failed to synchronize copied data blocks: %m");
2626 if (p
->encrypt
!= ENCRYPT_OFF
) {
2627 encrypted_dev_fd
= safe_close(encrypted_dev_fd
);
2629 r
= deactivate_luks(cd
, encrypted
);
2636 r
= loop_device_sync(d
);
2638 return log_error_errno(r
, "Failed to sync loopback device: %m");
2641 log_info("Copying in of '%s' on block level completed.", p
->copy_blocks_path
);
2647 static int do_copy_files(Partition
*p
, const char *fs
) {
2648 char **source
, **target
;
2654 STRV_FOREACH_PAIR(source
, target
, p
->copy_files
) {
2655 _cleanup_close_
int sfd
= -1, pfd
= -1, tfd
= -1;
2656 _cleanup_free_
char *dn
= NULL
;
2658 dn
= dirname_malloc(*target
);
2662 sfd
= chase_symlinks_and_open(*source
, arg_root
, CHASE_PREFIX_ROOT
|CHASE_WARN
, O_CLOEXEC
|O_NOCTTY
, NULL
);
2664 return log_error_errno(sfd
, "Failed to open source file '%s%s': %m", strempty(arg_root
), *source
);
2666 r
= fd_verify_regular(sfd
);
2669 return log_error_errno(r
, "Failed to check type of source file '%s': %m", *source
);
2671 /* We are looking at a directory */
2672 tfd
= chase_symlinks_and_open(*target
, fs
, CHASE_PREFIX_ROOT
|CHASE_WARN
, O_RDONLY
|O_DIRECTORY
|O_CLOEXEC
, NULL
);
2675 return log_error_errno(tfd
, "Failed to open target directory '%s': %m", *target
);
2677 r
= mkdir_p_root(fs
, dn
, UID_INVALID
, GID_INVALID
, 0755);
2679 return log_error_errno(r
, "Failed to create parent directory '%s': %m", dn
);
2681 pfd
= chase_symlinks_and_open(dn
, fs
, CHASE_PREFIX_ROOT
|CHASE_WARN
, O_RDONLY
|O_DIRECTORY
|O_CLOEXEC
, NULL
);
2683 return log_error_errno(pfd
, "Failed to open parent directory of target: %m");
2687 pfd
, basename(*target
),
2688 UID_INVALID
, GID_INVALID
,
2689 COPY_REFLINK
|COPY_MERGE
|COPY_REPLACE
|COPY_SIGINT
|COPY_HARDLINKS
);
2694 UID_INVALID
, GID_INVALID
,
2695 COPY_REFLINK
|COPY_MERGE
|COPY_REPLACE
|COPY_SIGINT
|COPY_HARDLINKS
);
2697 return log_error_errno(r
, "Failed to copy %s%s to %s: %m", strempty(arg_root
), *source
, *target
);
2699 /* We are looking at a regular file */
2701 r
= mkdir_p_root(fs
, dn
, UID_INVALID
, GID_INVALID
, 0755);
2703 return log_error_errno(r
, "Failed to create parent directory: %m");
2705 pfd
= chase_symlinks_and_open(dn
, fs
, CHASE_PREFIX_ROOT
|CHASE_WARN
, O_RDONLY
|O_DIRECTORY
|O_CLOEXEC
, NULL
);
2707 return log_error_errno(tfd
, "Failed to open parent directory of target: %m");
2709 tfd
= openat(pfd
, basename(*target
), O_CREAT
|O_EXCL
|O_WRONLY
|O_CLOEXEC
, 0700);
2711 return log_error_errno(errno
, "Failed to create target file '%s': %m", *target
);
2713 r
= copy_bytes(sfd
, tfd
, UINT64_MAX
, COPY_REFLINK
|COPY_SIGINT
);
2715 return log_error_errno(r
, "Failed to copy '%s%s' to '%s': %m", strempty(arg_root
), *source
, *target
);
2717 (void) copy_xattr(sfd
, tfd
);
2718 (void) copy_access(sfd
, tfd
);
2719 (void) copy_times(sfd
, tfd
, 0);
2726 static int partition_copy_files(Partition
*p
, const char *node
) {
2732 if (strv_isempty(p
->copy_files
))
2735 log_info("Populating partition %" PRIu64
" with files.", p
->partno
);
2737 /* We copy in a child process, since we have to mount the fs for that, and we don't want that fs to
2738 * appear in the host namespace. Hence we fork a child that has its own file system namespace and
2739 * detached mount propagation. */
2741 r
= safe_fork("(sd-copy)", FORK_DEATHSIG
|FORK_LOG
|FORK_WAIT
|FORK_NEW_MOUNTNS
|FORK_MOUNTNS_SLAVE
, NULL
);
2745 static const char fs
[] = "/run/systemd/mount-root";
2746 /* This is a child process with its own mount namespace and propagation to host turned off */
2748 r
= mkdir_p(fs
, 0700);
2750 log_error_errno(r
, "Failed to create mount point: %m");
2751 _exit(EXIT_FAILURE
);
2754 if (mount_nofollow_verbose(LOG_ERR
, node
, fs
, p
->format
, MS_NOATIME
|MS_NODEV
|MS_NOEXEC
|MS_NOSUID
, NULL
) < 0)
2755 _exit(EXIT_FAILURE
);
2757 if (do_copy_files(p
, fs
) < 0)
2758 _exit(EXIT_FAILURE
);
2760 r
= syncfs_path(AT_FDCWD
, fs
);
2762 log_error_errno(r
, "Failed to synchronize written files: %m");
2763 _exit(EXIT_FAILURE
);
2766 _exit(EXIT_SUCCESS
);
2769 log_info("Successfully populated partition %" PRIu64
" with files.", p
->partno
);
2773 static int context_mkfs(Context
*context
) {
2779 /* Make a file system */
2781 LIST_FOREACH(partitions
, p
, context
->partitions
) {
2782 _cleanup_(sym_crypt_freep
) struct crypt_device
*cd
= NULL
;
2783 _cleanup_(loop_device_unrefp
) LoopDevice
*d
= NULL
;
2784 _cleanup_free_
char *encrypted
= NULL
;
2785 _cleanup_close_
int encrypted_dev_fd
= -1;
2792 if (PARTITION_EXISTS(p
)) /* Never format existing partitions */
2798 assert(p
->offset
!= UINT64_MAX
);
2799 assert(p
->new_size
!= UINT64_MAX
);
2802 assert_se((fd
= fdisk_get_devfd(context
->fdisk_context
)) >= 0);
2804 /* Loopback block devices are not only useful to turn regular files into block devices, but
2805 * also to cut out sections of block devices into new block devices. */
2807 r
= loop_device_make(fd
, O_RDWR
, p
->offset
, p
->new_size
, 0, &d
);
2809 return log_error_errno(r
, "Failed to make loopback device of future partition %" PRIu64
": %m", p
->partno
);
2811 r
= loop_device_flock(d
, LOCK_EX
);
2813 return log_error_errno(r
, "Failed to lock loopback device: %m");
2815 if (p
->encrypt
!= ENCRYPT_OFF
) {
2816 r
= partition_encrypt(p
, d
->node
, &cd
, &encrypted
, &encrypted_dev_fd
);
2818 return log_error_errno(r
, "Failed to encrypt device: %m");
2820 if (flock(encrypted_dev_fd
, LOCK_EX
) < 0)
2821 return log_error_errno(errno
, "Failed to lock LUKS device: %m");
2827 log_info("Formatting future partition %" PRIu64
".", p
->partno
);
2829 /* Calculate the UUID for the file system as HMAC-SHA256 of the string "file-system-uuid",
2830 * keyed off the partition UUID. */
2831 r
= derive_uuid(p
->new_uuid
, "file-system-uuid", &fs_uuid
);
2835 r
= make_filesystem(fsdev
, p
->format
, p
->new_label
, fs_uuid
, arg_discard
);
2837 encrypted_dev_fd
= safe_close(encrypted_dev_fd
);
2838 (void) deactivate_luks(cd
, encrypted
);
2842 log_info("Successfully formatted future partition %" PRIu64
".", p
->partno
);
2844 /* The file system is now created, no need to delay udev further */
2845 if (p
->encrypt
!= ENCRYPT_OFF
)
2846 if (flock(encrypted_dev_fd
, LOCK_UN
) < 0)
2847 return log_error_errno(errno
, "Failed to unlock LUKS device: %m");
2849 r
= partition_copy_files(p
, fsdev
);
2851 encrypted_dev_fd
= safe_close(encrypted_dev_fd
);
2852 (void) deactivate_luks(cd
, encrypted
);
2856 /* Note that we always sync explicitly here, since mkfs.fat doesn't do that on its own, and
2857 * if we don't sync before detaching a block device the in-flight sectors possibly won't hit
2860 if (p
->encrypt
!= ENCRYPT_OFF
) {
2861 if (fsync(encrypted_dev_fd
) < 0)
2862 return log_error_errno(r
, "Failed to synchronize LUKS volume: %m");
2863 encrypted_dev_fd
= safe_close(encrypted_dev_fd
);
2865 r
= deactivate_luks(cd
, encrypted
);
2873 r
= loop_device_sync(d
);
2875 return log_error_errno(r
, "Failed to sync loopback device: %m");
2881 static int partition_acquire_uuid(Context
*context
, Partition
*p
, sd_id128_t
*ret
) {
2883 sd_id128_t type_uuid
;
2885 } _packed_ plaintext
= {};
2887 unsigned char md
[SHA256_DIGEST_LENGTH
];
2899 /* Calculate a good UUID for the indicated partition. We want a certain degree of reproducibility,
2900 * hence we won't generate the UUIDs randomly. Instead we use a cryptographic hash (precisely:
2901 * HMAC-SHA256) to derive them from a single seed. The seed is generally the machine ID of the
2902 * installation we are processing, but if random behaviour is desired can be random, too. We use the
2903 * seed value as key for the HMAC (since the machine ID is something we generally don't want to leak)
2904 * and the partition type as plaintext. The partition type is suffixed with a counter (only for the
2905 * second and later partition of the same type) if we have more than one partition of the same
2906 * time. Or in other words:
2909 * SEED := /etc/machine-id
2911 * If first partition instance of type TYPE_UUID:
2912 * PARTITION_UUID := HMAC-SHA256(SEED, TYPE_UUID)
2914 * For all later partition instances of type TYPE_UUID with INSTANCE being the LE64 encoded instance number:
2915 * PARTITION_UUID := HMAC-SHA256(SEED, TYPE_UUID || INSTANCE)
2918 LIST_FOREACH(partitions
, q
, context
->partitions
) {
2922 if (!sd_id128_equal(p
->type_uuid
, q
->type_uuid
))
2928 plaintext
.type_uuid
= p
->type_uuid
;
2929 plaintext
.counter
= htole64(k
);
2931 if (!HMAC(EVP_sha256(),
2932 &context
->seed
, sizeof(context
->seed
),
2933 (const unsigned char*) &plaintext
, k
== 0 ? sizeof(sd_id128_t
) : sizeof(plaintext
),
2935 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "SHA256 calculation failed.");
2937 /* Take the first half, mark it as v4 UUID */
2938 assert_cc(sizeof(result
.md
) == sizeof(result
.id
) * 2);
2939 result
.id
= id128_make_v4_uuid(result
.id
);
2941 /* Ensure this partition UUID is actually unique, and there's no remaining partition from an earlier run? */
2942 LIST_FOREACH(partitions
, q
, context
->partitions
) {
2946 if (sd_id128_equal(q
->current_uuid
, result
.id
) ||
2947 sd_id128_equal(q
->new_uuid
, result
.id
)) {
2948 log_warning("Partition UUID calculated from seed for partition %" PRIu64
" exists already, reverting to randomized UUID.", p
->partno
);
2950 r
= sd_id128_randomize(&result
.id
);
2952 return log_error_errno(r
, "Failed to generate randomized UUID: %m");
2962 static int partition_acquire_label(Context
*context
, Partition
*p
, char **ret
) {
2963 _cleanup_free_
char *label
= NULL
;
2971 prefix
= gpt_partition_type_uuid_to_string(p
->type_uuid
);
2976 const char *ll
= label
?: prefix
;
2980 LIST_FOREACH(partitions
, q
, context
->partitions
) {
2984 if (streq_ptr(ll
, q
->current_label
) ||
2985 streq_ptr(ll
, q
->new_label
)) {
2994 label
= mfree(label
);
2997 if (asprintf(&label
, "%s-%u", prefix
, ++k
) < 0)
3002 label
= strdup(prefix
);
3007 *ret
= TAKE_PTR(label
);
3011 static int context_acquire_partition_uuids_and_labels(Context
*context
) {
3017 LIST_FOREACH(partitions
, p
, context
->partitions
) {
3018 /* Never touch foreign partitions */
3019 if (PARTITION_IS_FOREIGN(p
)) {
3020 p
->new_uuid
= p
->current_uuid
;
3022 if (p
->current_label
) {
3024 p
->new_label
= strdup(p
->current_label
);
3032 if (!sd_id128_is_null(p
->current_uuid
))
3033 p
->new_uuid
= p
->current_uuid
; /* Never change initialized UUIDs */
3034 else if (sd_id128_is_null(p
->new_uuid
)) {
3035 /* Not explicitly set by user! */
3036 r
= partition_acquire_uuid(context
, p
, &p
->new_uuid
);
3041 if (!isempty(p
->current_label
)) {
3043 p
->new_label
= strdup(p
->current_label
); /* never change initialized labels */
3046 } else if (!p
->new_label
) {
3047 /* Not explicitly set by user! */
3049 r
= partition_acquire_label(context
, p
, &p
->new_label
);
3058 static int context_mangle_partitions(Context
*context
) {
3064 LIST_FOREACH(partitions
, p
, context
->partitions
) {
3068 assert(p
->new_size
!= UINT64_MAX
);
3069 assert(p
->offset
!= UINT64_MAX
);
3070 assert(p
->partno
!= UINT64_MAX
);
3072 if (PARTITION_EXISTS(p
)) {
3073 bool changed
= false;
3075 assert(p
->current_partition
);
3077 if (p
->new_size
!= p
->current_size
) {
3078 assert(p
->new_size
>= p
->current_size
);
3079 assert(p
->new_size
% 512 == 0);
3081 r
= fdisk_partition_size_explicit(p
->current_partition
, true);
3083 return log_error_errno(r
, "Failed to enable explicit sizing: %m");
3085 r
= fdisk_partition_set_size(p
->current_partition
, p
->new_size
/ 512);
3087 return log_error_errno(r
, "Failed to grow partition: %m");
3089 log_info("Growing existing partition %" PRIu64
".", p
->partno
);
3093 if (!sd_id128_equal(p
->new_uuid
, p
->current_uuid
)) {
3094 char buf
[ID128_UUID_STRING_MAX
];
3096 assert(!sd_id128_is_null(p
->new_uuid
));
3098 r
= fdisk_partition_set_uuid(p
->current_partition
, id128_to_uuid_string(p
->new_uuid
, buf
));
3100 return log_error_errno(r
, "Failed to set partition UUID: %m");
3102 log_info("Initializing UUID of existing partition %" PRIu64
".", p
->partno
);
3106 if (!streq_ptr(p
->new_label
, p
->current_label
)) {
3107 assert(!isempty(p
->new_label
));
3109 r
= fdisk_partition_set_name(p
->current_partition
, p
->new_label
);
3111 return log_error_errno(r
, "Failed to set partition label: %m");
3113 log_info("Setting partition label of existing partition %" PRIu64
".", p
->partno
);
3118 assert(!PARTITION_IS_FOREIGN(p
)); /* never touch foreign partitions */
3120 r
= fdisk_set_partition(context
->fdisk_context
, p
->partno
, p
->current_partition
);
3122 return log_error_errno(r
, "Failed to update partition: %m");
3125 _cleanup_(fdisk_unref_partitionp
) struct fdisk_partition
*q
= NULL
;
3126 _cleanup_(fdisk_unref_parttypep
) struct fdisk_parttype
*t
= NULL
;
3127 char ids
[ID128_UUID_STRING_MAX
];
3129 assert(!p
->new_partition
);
3130 assert(p
->offset
% 512 == 0);
3131 assert(p
->new_size
% 512 == 0);
3132 assert(!sd_id128_is_null(p
->new_uuid
));
3133 assert(!isempty(p
->new_label
));
3135 t
= fdisk_new_parttype();
3139 r
= fdisk_parttype_set_typestr(t
, id128_to_uuid_string(p
->type_uuid
, ids
));
3141 return log_error_errno(r
, "Failed to initialize partition type: %m");
3143 q
= fdisk_new_partition();
3147 r
= fdisk_partition_set_type(q
, t
);
3149 return log_error_errno(r
, "Failed to set partition type: %m");
3151 r
= fdisk_partition_size_explicit(q
, true);
3153 return log_error_errno(r
, "Failed to enable explicit sizing: %m");
3155 r
= fdisk_partition_set_start(q
, p
->offset
/ 512);
3157 return log_error_errno(r
, "Failed to position partition: %m");
3159 r
= fdisk_partition_set_size(q
, p
->new_size
/ 512);
3161 return log_error_errno(r
, "Failed to grow partition: %m");
3163 r
= fdisk_partition_set_partno(q
, p
->partno
);
3165 return log_error_errno(r
, "Failed to set partition number: %m");
3167 r
= fdisk_partition_set_uuid(q
, id128_to_uuid_string(p
->new_uuid
, ids
));
3169 return log_error_errno(r
, "Failed to set partition UUID: %m");
3171 r
= fdisk_partition_set_name(q
, p
->new_label
);
3173 return log_error_errno(r
, "Failed to set partition label: %m");
3175 log_info("Adding new partition %" PRIu64
" to partition table.", p
->partno
);
3177 r
= fdisk_add_partition(context
->fdisk_context
, q
, NULL
);
3179 return log_error_errno(r
, "Failed to add partition: %m");
3181 assert(!p
->new_partition
);
3182 p
->new_partition
= TAKE_PTR(q
);
3189 static int context_write_partition_table(
3192 bool from_scratch
) {
3194 _cleanup_(fdisk_unref_tablep
) struct fdisk_table
*original_table
= NULL
;
3199 if (arg_pretty
> 0 ||
3200 (arg_pretty
< 0 && isatty(STDOUT_FILENO
) > 0) ||
3201 !FLAGS_SET(arg_json_format_flags
, JSON_FORMAT_OFF
)) {
3203 (void) context_dump_partitions(context
, node
);
3207 if (arg_json_format_flags
& JSON_FORMAT_OFF
)
3208 (void) context_dump_partition_bar(context
, node
);
3213 if (!from_scratch
&& !context_changed(context
)) {
3214 log_info("No changes.");
3219 log_notice("Refusing to repartition, please re-run with --dry-run=no.");
3223 log_info("Applying changes.");
3226 r
= context_wipe_range(context
, 0, context
->total
);
3230 log_info("Wiped block device.");
3232 r
= context_discard_range(context
, 0, context
->total
);
3233 if (r
== -EOPNOTSUPP
)
3234 log_info("Storage does not support discard, not discarding entire block device data.");
3236 return log_error_errno(r
, "Failed to discard entire block device: %m");
3238 log_info("Discarded entire block device.");
3241 r
= fdisk_get_partitions(context
->fdisk_context
, &original_table
);
3243 return log_error_errno(r
, "Failed to acquire partition table: %m");
3245 /* Wipe fs signatures and discard sectors where the new partitions are going to be placed and in the
3246 * gaps between partitions, just to be sure. */
3247 r
= context_wipe_and_discard(context
, from_scratch
);
3251 r
= context_copy_blocks(context
);
3255 r
= context_mkfs(context
);
3259 r
= context_mangle_partitions(context
);
3263 log_info("Writing new partition table.");
3265 r
= fdisk_write_disklabel(context
->fdisk_context
);
3267 return log_error_errno(r
, "Failed to write partition table: %m");
3269 capable
= blockdev_partscan_enabled(fdisk_get_devfd(context
->fdisk_context
));
3270 if (capable
== -ENOTBLK
)
3271 log_debug("Not telling kernel to reread partition table, since we are not operating on a block device.");
3272 else if (capable
< 0)
3273 return log_error_errno(capable
, "Failed to check if block device supports partition scanning: %m");
3274 else if (capable
> 0) {
3275 log_info("Telling kernel to reread partition table.");
3278 r
= fdisk_reread_partition_table(context
->fdisk_context
);
3280 r
= fdisk_reread_changes(context
->fdisk_context
, original_table
);
3282 return log_error_errno(r
, "Failed to reread partition table: %m");
3284 log_notice("Not telling kernel to reread partition table, because selected image does not support kernel partition block devices.");
3286 log_info("All done.");
3291 static int context_read_seed(Context
*context
, const char *root
) {
3296 if (!sd_id128_is_null(context
->seed
))
3299 if (!arg_randomize
) {
3300 _cleanup_close_
int fd
= -1;
3302 fd
= chase_symlinks_and_open("/etc/machine-id", root
, CHASE_PREFIX_ROOT
, O_RDONLY
|O_CLOEXEC
, NULL
);
3304 log_info("No machine ID set, using randomized partition UUIDs.");
3306 return log_error_errno(fd
, "Failed to determine machine ID of image: %m");
3308 r
= id128_read_fd(fd
, ID128_PLAIN_OR_UNINIT
, &context
->seed
);
3309 if (r
== -ENOMEDIUM
)
3310 log_info("No machine ID set, using randomized partition UUIDs.");
3312 return log_error_errno(r
, "Failed to parse machine ID of image: %m");
3318 r
= sd_id128_randomize(&context
->seed
);
3320 return log_error_errno(r
, "Failed to generate randomized seed: %m");
3325 static int context_factory_reset(Context
*context
, bool from_scratch
) {
3332 if (arg_factory_reset
<= 0)
3335 if (from_scratch
) /* Nothing to reset if we start from scratch */
3339 log_notice("Refusing to factory reset, please re-run with --dry-run=no.");
3343 log_info("Applying factory reset.");
3345 LIST_FOREACH(partitions
, p
, context
->partitions
) {
3347 if (!p
->factory_reset
|| !PARTITION_EXISTS(p
))
3350 assert(p
->partno
!= UINT64_MAX
);
3352 log_info("Removing partition %" PRIu64
" for factory reset.", p
->partno
);
3354 r
= fdisk_delete_partition(context
->fdisk_context
, p
->partno
);
3356 return log_error_errno(r
, "Failed to remove partition %" PRIu64
": %m", p
->partno
);
3362 log_info("Factory reset requested, but no partitions to delete found.");
3366 r
= fdisk_write_disklabel(context
->fdisk_context
);
3368 return log_error_errno(r
, "Failed to write disk label: %m");
3370 log_info("Successfully deleted %zu partitions.", n
);
3374 static int context_can_factory_reset(Context
*context
) {
3379 LIST_FOREACH(partitions
, p
, context
->partitions
)
3380 if (p
->factory_reset
&& PARTITION_EXISTS(p
))
3386 static int context_open_copy_block_paths(Context
*context
) {
3392 LIST_FOREACH(partitions
, p
, context
->partitions
) {
3393 _cleanup_close_
int source_fd
= -1;
3397 assert(p
->copy_blocks_fd
< 0);
3398 assert(p
->copy_blocks_size
== UINT64_MAX
);
3400 if (PARTITION_EXISTS(p
)) /* Never copy over partitions that already exist! */
3403 if (!p
->copy_blocks_path
)
3406 source_fd
= open(p
->copy_blocks_path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
3408 return log_error_errno(errno
, "Failed to open block copy file '%s': %m", p
->copy_blocks_path
);
3410 if (fstat(source_fd
, &st
) < 0)
3411 return log_error_errno(errno
, "Failed to stat block copy file '%s': %m", p
->copy_blocks_path
);
3413 if (S_ISDIR(st
.st_mode
)) {
3414 _cleanup_free_
char *bdev
= NULL
;
3416 /* If the file is a directory, automatically find the backing block device */
3418 if (major(st
.st_dev
) != 0)
3419 r
= device_path_make_major_minor(S_IFBLK
, st
.st_dev
, &bdev
);
3423 /* Special support for btrfs */
3425 r
= btrfs_get_block_device_fd(source_fd
, &devt
);
3427 return btrfs_log_dev_root(LOG_ERR
, r
, p
->copy_blocks_path
);
3429 return log_error_errno(r
, "Unable to determine backing block device of '%s': %m", p
->copy_blocks_path
);
3431 r
= device_path_make_major_minor(S_IFBLK
, devt
, &bdev
);
3434 return log_error_errno(r
, "Failed to determine block device path for block device backing '%s': %m", p
->copy_blocks_path
);
3436 safe_close(source_fd
);
3438 source_fd
= open(bdev
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
3440 return log_error_errno(errno
, "Failed to open block device '%s': %m", bdev
);
3442 if (fstat(source_fd
, &st
) < 0)
3443 return log_error_errno(errno
, "Failed to stat block device '%s': %m", bdev
);
3445 if (!S_ISBLK(st
.st_mode
))
3446 return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK
), "Block device '%s' is not actually a block device, refusing.", bdev
);
3449 if (S_ISREG(st
.st_mode
))
3451 else if (S_ISBLK(st
.st_mode
)) {
3452 if (ioctl(source_fd
, BLKGETSIZE64
, &size
) != 0)
3453 return log_error_errno(errno
, "Failed to determine size of block device to copy from: %m");
3455 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Specified path to copy blocks from '%s' is not a regular file, block device or directory, refusing: %m", p
->copy_blocks_path
);
3458 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "File to copy bytes from '%s' has zero size, refusing.", p
->copy_blocks_path
);
3459 if (size
% 512 != 0)
3460 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "File to copy bytes from '%s' has size that is not multiple of 512, refusing.", p
->copy_blocks_path
);
3462 p
->copy_blocks_fd
= TAKE_FD(source_fd
);
3463 p
->copy_blocks_size
= size
;
3469 static int help(void) {
3470 _cleanup_free_
char *link
= NULL
;
3473 r
= terminal_urlify_man("systemd-repart", "1", &link
);
3477 printf("%s [OPTIONS...] [DEVICE]\n"
3478 "\n%sGrow and add partitions to partition table.%s\n\n"
3479 " -h --help Show this help\n"
3480 " --version Show package version\n"
3481 " --no-pager Do not pipe output into a pager\n"
3482 " --no-legend Do not show the headers and footers\n"
3483 " --dry-run=BOOL Whether to run dry-run operation\n"
3484 " --empty=MODE One of refuse, allow, require, force, create; controls\n"
3485 " how to handle empty disks lacking partition tables\n"
3486 " --discard=BOOL Whether to discard backing blocks for new partitions\n"
3487 " --pretty=BOOL Whether to show pretty summary before doing changes\n"
3488 " --factory-reset=BOOL Whether to remove data partitions before recreating\n"
3490 " --can-factory-reset Test whether factory reset is defined\n"
3491 " --root=PATH Operate relative to root path\n"
3492 " --definitions=DIR Find partition definitions in specified directory\n"
3493 " --key-file=PATH Key to use when encrypting partitions\n"
3494 " --tpm2-device=PATH Path to TPM2 device node to use\n"
3495 " --tpm2-pcrs=PCR1,PCR2,…\n"
3496 " TPM2 PCR indexes to use for TPM2 enrollment\n"
3497 " --seed=UUID 128bit seed UUID to derive all UUIDs from\n"
3498 " --size=BYTES Grow loopback file to specified size\n"
3499 " --json=pretty|short|off\n"
3500 " Generate JSON output\n"
3501 "\nSee the %s for details.\n",
3502 program_invocation_short_name
,
3510 static int parse_argv(int argc
, char *argv
[]) {
3513 ARG_VERSION
= 0x100,
3520 ARG_CAN_FACTORY_RESET
,
3532 static const struct option options
[] = {
3533 { "help", no_argument
, NULL
, 'h' },
3534 { "version", no_argument
, NULL
, ARG_VERSION
},
3535 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
3536 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
3537 { "dry-run", required_argument
, NULL
, ARG_DRY_RUN
},
3538 { "empty", required_argument
, NULL
, ARG_EMPTY
},
3539 { "discard", required_argument
, NULL
, ARG_DISCARD
},
3540 { "factory-reset", required_argument
, NULL
, ARG_FACTORY_RESET
},
3541 { "can-factory-reset", no_argument
, NULL
, ARG_CAN_FACTORY_RESET
},
3542 { "root", required_argument
, NULL
, ARG_ROOT
},
3543 { "seed", required_argument
, NULL
, ARG_SEED
},
3544 { "pretty", required_argument
, NULL
, ARG_PRETTY
},
3545 { "definitions", required_argument
, NULL
, ARG_DEFINITIONS
},
3546 { "size", required_argument
, NULL
, ARG_SIZE
},
3547 { "json", required_argument
, NULL
, ARG_JSON
},
3548 { "key-file", required_argument
, NULL
, ARG_KEY_FILE
},
3549 { "tpm2-device", required_argument
, NULL
, ARG_TPM2_DEVICE
},
3550 { "tpm2-pcrs", required_argument
, NULL
, ARG_TPM2_PCRS
},
3554 int c
, r
, dry_run
= -1;
3559 while ((c
= getopt_long(argc
, argv
, "h", options
, NULL
)) >= 0)
3570 arg_pager_flags
|= PAGER_DISABLE
;
3578 r
= parse_boolean_argument("--dry-run=", optarg
, &arg_dry_run
);
3584 if (isempty(optarg
) || streq(optarg
, "refuse"))
3585 arg_empty
= EMPTY_REFUSE
;
3586 else if (streq(optarg
, "allow"))
3587 arg_empty
= EMPTY_ALLOW
;
3588 else if (streq(optarg
, "require"))
3589 arg_empty
= EMPTY_REQUIRE
;
3590 else if (streq(optarg
, "force"))
3591 arg_empty
= EMPTY_FORCE
;
3592 else if (streq(optarg
, "create")) {
3593 arg_empty
= EMPTY_CREATE
;
3596 dry_run
= false; /* Imply --dry-run=no if we create the loopback file
3597 * anew. After all we cannot really break anyone's
3598 * partition tables that way. */
3600 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
3601 "Failed to parse --empty= parameter: %s", optarg
);
3605 r
= parse_boolean_argument("--discard=", optarg
, &arg_discard
);
3610 case ARG_FACTORY_RESET
:
3611 r
= parse_boolean_argument("--factory-reset=", optarg
, NULL
);
3614 arg_factory_reset
= r
;
3617 case ARG_CAN_FACTORY_RESET
:
3618 arg_can_factory_reset
= true;
3622 r
= parse_path_argument(optarg
, false, &arg_root
);
3628 if (isempty(optarg
)) {
3629 arg_seed
= SD_ID128_NULL
;
3630 arg_randomize
= false;
3631 } else if (streq(optarg
, "random"))
3632 arg_randomize
= true;
3634 r
= sd_id128_from_string(optarg
, &arg_seed
);
3636 return log_error_errno(r
, "Failed to parse seed: %s", optarg
);
3638 arg_randomize
= false;
3644 r
= parse_boolean_argument("--pretty=", optarg
, NULL
);
3650 case ARG_DEFINITIONS
:
3651 r
= parse_path_argument(optarg
, false, &arg_definitions
);
3657 uint64_t parsed
, rounded
;
3659 if (streq(optarg
, "auto")) {
3660 arg_size
= UINT64_MAX
;
3661 arg_size_auto
= true;
3665 r
= parse_size(optarg
, 1024, &parsed
);
3667 return log_error_errno(r
, "Failed to parse --size= parameter: %s", optarg
);
3669 rounded
= round_up_size(parsed
, 4096);
3671 return log_error_errno(SYNTHETIC_ERRNO(ERANGE
), "Specified image size too small, refusing.");
3672 if (rounded
== UINT64_MAX
)
3673 return log_error_errno(SYNTHETIC_ERRNO(ERANGE
), "Specified image size too large, refusing.");
3675 if (rounded
!= parsed
)
3676 log_warning("Specified size is not a multiple of 4096, rounding up automatically. (%" PRIu64
" → %" PRIu64
")",
3680 arg_size_auto
= false;
3685 r
= parse_json_argument(optarg
, &arg_json_format_flags
);
3691 case ARG_KEY_FILE
: {
3692 _cleanup_(erase_and_freep
) char *k
= NULL
;
3695 r
= read_full_file_full(
3696 AT_FDCWD
, optarg
, UINT64_MAX
, SIZE_MAX
,
3697 READ_FULL_FILE_SECURE
|READ_FULL_FILE_WARN_WORLD_READABLE
|READ_FULL_FILE_CONNECT_SOCKET
,
3701 return log_error_errno(r
, "Failed to read key file '%s': %m", optarg
);
3703 erase_and_free(arg_key
);
3704 arg_key
= TAKE_PTR(k
);
3709 case ARG_TPM2_DEVICE
: {
3710 _cleanup_free_
char *device
= NULL
;
3712 if (streq(optarg
, "list"))
3713 return tpm2_list_devices();
3715 if (!streq(optarg
, "auto")) {
3716 device
= strdup(optarg
);
3721 free(arg_tpm2_device
);
3722 arg_tpm2_device
= TAKE_PTR(device
);
3726 case ARG_TPM2_PCRS
: {
3729 if (isempty(optarg
)) {
3730 arg_tpm2_pcr_mask
= 0;
3734 r
= tpm2_parse_pcrs(optarg
, &mask
);
3738 if (arg_tpm2_pcr_mask
== UINT32_MAX
)
3739 arg_tpm2_pcr_mask
= mask
;
3741 arg_tpm2_pcr_mask
|= mask
;
3750 assert_not_reached("Unhandled option");
3753 if (argc
- optind
> 1)
3754 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
3755 "Expected at most one argument, the path to the block device.");
3757 if (arg_factory_reset
> 0 && IN_SET(arg_empty
, EMPTY_FORCE
, EMPTY_REQUIRE
, EMPTY_CREATE
))
3758 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
3759 "Combination of --factory-reset=yes and --empty=force/--empty=require/--empty=create is invalid.");
3761 if (arg_can_factory_reset
)
3762 arg_dry_run
= true; /* When --can-factory-reset is specified we don't make changes, hence
3763 * non-dry-run mode makes no sense. Thus, imply dry run mode so that we
3764 * open things strictly read-only. */
3765 else if (dry_run
>= 0)
3766 arg_dry_run
= dry_run
;
3768 if (arg_empty
== EMPTY_CREATE
&& (arg_size
== UINT64_MAX
&& !arg_size_auto
))
3769 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
3770 "If --empty=create is specified, --size= must be specified, too.");
3772 arg_node
= argc
> optind
? argv
[optind
] : NULL
;
3774 if (IN_SET(arg_empty
, EMPTY_FORCE
, EMPTY_REQUIRE
, EMPTY_CREATE
) && !arg_node
)
3775 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
3776 "A path to a device node or loopback file must be specified when --empty=force, --empty=require or --empty=create are used.");
3778 if (arg_tpm2_pcr_mask
== UINT32_MAX
)
3779 arg_tpm2_pcr_mask
= TPM2_PCR_MASK_DEFAULT
;
3784 static int parse_proc_cmdline_factory_reset(void) {
3788 if (arg_factory_reset
>= 0) /* Never override what is specified on the process command line */
3791 if (!in_initrd()) /* Never honour kernel command line factory reset request outside of the initrd */
3794 r
= proc_cmdline_get_bool("systemd.factory_reset", &b
);
3796 return log_error_errno(r
, "Failed to parse systemd.factory_reset kernel command line argument: %m");
3798 arg_factory_reset
= b
;
3801 log_notice("Honouring factory reset requested via kernel command line.");
3807 static int parse_efi_variable_factory_reset(void) {
3808 _cleanup_free_
char *value
= NULL
;
3811 if (arg_factory_reset
>= 0) /* Never override what is specified on the process command line */
3814 if (!in_initrd()) /* Never honour EFI variable factory reset request outside of the initrd */
3817 r
= efi_get_variable_string(EFI_VENDOR_SYSTEMD
, "FactoryReset", &value
);
3818 if (r
== -ENOENT
|| ERRNO_IS_NOT_SUPPORTED(r
))
3821 return log_error_errno(r
, "Failed to read EFI variable FactoryReset: %m");
3823 r
= parse_boolean(value
);
3825 return log_error_errno(r
, "Failed to parse EFI variable FactoryReset: %m");
3827 arg_factory_reset
= r
;
3829 log_notice("Honouring factory reset requested via EFI variable FactoryReset: %m");
3834 static int remove_efi_variable_factory_reset(void) {
3837 r
= efi_set_variable(EFI_VENDOR_SYSTEMD
, "FactoryReset", NULL
, 0);
3838 if (r
== -ENOENT
|| ERRNO_IS_NOT_SUPPORTED(r
))
3841 return log_error_errno(r
, "Failed to remove EFI variable FactoryReset: %m");
3843 log_info("Successfully unset EFI variable FactoryReset.");
3847 static int acquire_root_devno(const char *p
, int mode
, char **ret
, int *ret_fd
) {
3848 _cleanup_close_
int fd
= -1;
3850 dev_t devno
, fd_devno
= (mode_t
) -1;
3861 if (fstat(fd
, &st
) < 0)
3864 if (S_ISREG(st
.st_mode
)) {
3872 *ret_fd
= TAKE_FD(fd
);
3877 if (S_ISBLK(st
.st_mode
))
3878 fd_devno
= devno
= st
.st_rdev
;
3879 else if (S_ISDIR(st
.st_mode
)) {
3882 if (major(devno
) == 0) {
3883 r
= btrfs_get_block_device_fd(fd
, &devno
);
3884 if (r
== -ENOTTY
) /* not btrfs */
3892 /* From dm-crypt to backing partition */
3893 r
= block_get_originating(devno
, &devno
);
3895 log_debug_errno(r
, "Failed to find underlying block device for '%s', ignoring: %m", p
);
3897 /* From partition to whole disk containing it */
3898 r
= block_get_whole_disk(devno
, &devno
);
3900 log_debug_errno(r
, "Failed to find whole disk block device for '%s', ignoring: %m", p
);
3902 r
= device_path_make_canonical(S_IFBLK
, devno
, ret
);
3904 return log_debug_errno(r
, "Failed to determine canonical path for '%s': %m", p
);
3906 /* Only if we still lock at the same block device we can reuse the fd. Otherwise return an
3907 * invalidated fd. */
3908 *ret_fd
= fd_devno
!= (mode_t
) -1 && fd_devno
== devno
? TAKE_FD(fd
) : -1;
3912 static int find_root(char **ret
, int *ret_fd
) {
3920 if (arg_empty
== EMPTY_CREATE
) {
3921 _cleanup_close_
int fd
= -1;
3922 _cleanup_free_
char *s
= NULL
;
3924 s
= strdup(arg_node
);
3928 fd
= open(arg_node
, O_RDONLY
|O_CREAT
|O_EXCL
|O_CLOEXEC
|O_NOFOLLOW
, 0666);
3930 return log_error_errno(errno
, "Failed to create '%s': %m", arg_node
);
3933 *ret_fd
= TAKE_FD(fd
);
3937 r
= acquire_root_devno(arg_node
, O_RDONLY
|O_CLOEXEC
, ret
, ret_fd
);
3939 return btrfs_log_dev_root(LOG_ERR
, r
, arg_node
);
3941 return log_error_errno(r
, "Failed to open file or determine backing device of %s: %m", arg_node
);
3946 assert(IN_SET(arg_empty
, EMPTY_REFUSE
, EMPTY_ALLOW
));
3948 /* Let's search for the root device. We look for two cases here: first in /, and then in /usr. The
3949 * latter we check for cases where / is a tmpfs and only /usr is an actual persistent block device
3950 * (think: volatile setups) */
3952 FOREACH_STRING(t
, "/", "/usr") {
3953 _cleanup_free_
char *j
= NULL
;
3957 j
= path_join("/sysroot", t
);
3965 r
= acquire_root_devno(p
, O_RDONLY
|O_DIRECTORY
|O_CLOEXEC
, ret
, ret_fd
);
3968 return btrfs_log_dev_root(LOG_ERR
, r
, p
);
3970 return log_error_errno(r
, "Failed to determine backing device of %s: %m", p
);
3975 return log_error_errno(SYNTHETIC_ERRNO(ENODEV
), "Failed to discover root block device.");
3978 static int resize_backing_fd(const char *node
, int *fd
) {
3979 char buf1
[FORMAT_BYTES_MAX
], buf2
[FORMAT_BYTES_MAX
];
3980 _cleanup_close_
int writable_fd
= -1;
3987 if (arg_size
== UINT64_MAX
) /* Nothing to do */
3991 /* Open the file if we haven't opened it yet. Note that we open it read-only here, just to
3992 * keep a reference to the file we can pass around. */
3993 *fd
= open(node
, O_RDONLY
|O_CLOEXEC
);
3995 return log_error_errno(errno
, "Failed to open '%s' in order to adjust size: %m", node
);
3998 if (fstat(*fd
, &st
) < 0)
3999 return log_error_errno(errno
, "Failed to stat '%s': %m", node
);
4001 r
= stat_verify_regular(&st
);
4003 return log_error_errno(r
, "Specified path '%s' is not a regular file, cannot resize: %m", node
);
4005 assert_se(format_bytes(buf1
, sizeof(buf1
), st
.st_size
));
4006 assert_se(format_bytes(buf2
, sizeof(buf2
), arg_size
));
4008 if ((uint64_t) st
.st_size
>= arg_size
) {
4009 log_info("File '%s' already is of requested size or larger, not growing. (%s >= %s)", node
, buf1
, buf2
);
4013 /* The file descriptor is read-only. In order to grow the file we need to have a writable fd. We
4014 * reopen the file for that temporarily. We keep the writable fd only open for this operation though,
4015 * as fdisk can't accept it anyway. */
4017 writable_fd
= fd_reopen(*fd
, O_WRONLY
|O_CLOEXEC
);
4018 if (writable_fd
< 0)
4019 return log_error_errno(writable_fd
, "Failed to reopen backing file '%s' writable: %m", node
);
4022 if (fallocate(writable_fd
, 0, 0, arg_size
) < 0) {
4023 if (!ERRNO_IS_NOT_SUPPORTED(errno
))
4024 return log_error_errno(errno
, "Failed to grow '%s' from %s to %s by allocation: %m",
4027 /* Fallback to truncation, if fallocate() is not supported. */
4028 log_debug("Backing file system does not support fallocate(), falling back to ftruncate().");
4030 if (st
.st_size
== 0) /* Likely regular file just created by us */
4031 log_info("Allocated %s for '%s'.", buf2
, node
);
4033 log_info("File '%s' grown from %s to %s by allocation.", node
, buf1
, buf2
);
4039 if (ftruncate(writable_fd
, arg_size
) < 0)
4040 return log_error_errno(errno
, "Failed to grow '%s' from %s to %s by truncation: %m",
4043 if (st
.st_size
== 0) /* Likely regular file just created by us */
4044 log_info("Sized '%s' to %s.", node
, buf2
);
4046 log_info("File '%s' grown from %s to %s by truncation.", node
, buf1
, buf2
);
4051 static int determine_auto_size(Context
*c
) {
4052 uint64_t sum
= round_up_size(GPT_METADATA_SIZE
, 4096);
4053 char buf
[FORMAT_BYTES_MAX
];
4057 assert_se(arg_size
== UINT64_MAX
);
4058 assert_se(arg_size_auto
);
4060 LIST_FOREACH(partitions
, p
, c
->partitions
) {
4066 m
= partition_min_size_with_padding(p
);
4067 if (m
> UINT64_MAX
- sum
)
4068 return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW
), "Image would grow too large, refusing.");
4073 assert_se(format_bytes(buf
, sizeof(buf
), sum
));
4074 log_info("Automatically determined minimal disk image size as %s.", buf
);
4080 static int run(int argc
, char *argv
[]) {
4081 _cleanup_(context_freep
) Context
* context
= NULL
;
4082 _cleanup_free_
char *node
= NULL
;
4083 _cleanup_close_
int backing_fd
= -1;
4087 log_show_color(true);
4088 log_parse_environment();
4092 /* Default to operation on /sysroot when invoked in the initrd! */
4093 arg_root
= strdup("/sysroot");
4098 r
= parse_argv(argc
, argv
);
4102 r
= parse_proc_cmdline_factory_reset();
4106 r
= parse_efi_variable_factory_reset();
4110 context
= context_new(arg_seed
);
4114 r
= context_read_definitions(context
, arg_definitions
, arg_root
);
4118 if (context
->n_partitions
<= 0 && arg_empty
== EMPTY_REFUSE
) {
4119 log_info("Didn't find any partition definition files, nothing to do.");
4123 r
= find_root(&node
, &backing_fd
);
4127 if (arg_size
!= UINT64_MAX
) {
4128 r
= resize_backing_fd(node
, &backing_fd
);
4133 r
= context_load_partition_table(context
, node
, &backing_fd
);
4134 if (r
== -EHWPOISON
)
4135 return 77; /* Special return value which means "Not GPT, so not doing anything". This isn't
4136 * really an error when called at boot. */
4139 from_scratch
= r
> 0; /* Starting from scratch */
4141 if (arg_can_factory_reset
) {
4142 r
= context_can_factory_reset(context
);
4146 return EXIT_FAILURE
;
4151 r
= context_factory_reset(context
, from_scratch
);
4155 /* We actually did a factory reset! */
4156 r
= remove_efi_variable_factory_reset();
4160 /* Reload the reduced partition table */
4161 context_unload_partition_table(context
);
4162 r
= context_load_partition_table(context
, node
, &backing_fd
);
4168 (void) context_dump_partitions(context
, node
);
4172 r
= context_read_seed(context
, arg_root
);
4176 /* Open all files to copy blocks from now, since we want to take their size into consideration */
4177 r
= context_open_copy_block_paths(context
);
4181 if (arg_size_auto
) {
4182 r
= determine_auto_size(context
);
4186 /* Flush out everything again, and let's grow the file first, then start fresh */
4187 context_unload_partition_table(context
);
4189 assert_se(arg_size
!= UINT64_MAX
);
4190 r
= resize_backing_fd(node
, &backing_fd
);
4194 r
= context_load_partition_table(context
, node
, &backing_fd
);
4199 /* First try to fit new partitions in, dropping by priority until it fits */
4201 if (context_allocate_partitions(context
))
4202 break; /* Success! */
4204 if (!context_drop_one_priority(context
))
4205 return log_error_errno(SYNTHETIC_ERRNO(ENOSPC
),
4206 "Can't fit requested partitions into free space, refusing.");
4209 /* Now assign free space according to the weight logic */
4210 r
= context_grow_partitions(context
);
4214 /* Now calculate where each partition gets placed */
4215 context_place_partitions(context
);
4217 /* Make sure each partition has a unique UUID and unique label */
4218 r
= context_acquire_partition_uuids_and_labels(context
);
4222 r
= context_write_partition_table(context
, node
, from_scratch
);
4229 DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run
);