]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/partition/repart.c
Merge pull request #20893 from poettering/per-user-oom-score
[thirdparty/systemd.git] / src / partition / repart.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
e594a3b1
LP
2
3#if HAVE_VALGRIND_MEMCHECK_H
4#include <valgrind/memcheck.h>
5#endif
6
7#include <fcntl.h>
8#include <getopt.h>
9#include <libfdisk.h>
10#include <linux/fs.h>
11#include <linux/loop.h>
12#include <sys/file.h>
13#include <sys/ioctl.h>
14#include <sys/stat.h>
15
16#include <openssl/hmac.h>
17#include <openssl/sha.h>
18
19#include "sd-id128.h"
20
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"
1e2f3230 27#include "cryptsetup-util.h"
e594a3b1 28#include "def.h"
5c08da58 29#include "dirent-util.h"
e594a3b1
LP
30#include "efivars.h"
31#include "errno-util.h"
32#include "fd-util.h"
b9df3536 33#include "fileio.h"
e594a3b1
LP
34#include "format-table.h"
35#include "format-util.h"
36#include "fs-util.h"
37#include "gpt.h"
889914ef 38#include "hexdecoct.h"
e594a3b1 39#include "id128-util.h"
a015fbe7 40#include "json.h"
e594a3b1
LP
41#include "list.h"
42#include "locale-util.h"
53171c04 43#include "loop-util.h"
e594a3b1 44#include "main-func.h"
8a794850 45#include "mkdir.h"
53171c04 46#include "mkfs-util.h"
8a794850 47#include "mount-util.h"
5c08da58 48#include "mountpoint-util.h"
614b022c 49#include "parse-argument.h"
599c7c54 50#include "parse-util.h"
e594a3b1
LP
51#include "path-util.h"
52#include "pretty-print.h"
53#include "proc-cmdline.h"
8a794850 54#include "process-util.h"
b9df3536 55#include "random-util.h"
170c9823 56#include "resize-fs.h"
e594a3b1 57#include "sort-util.h"
e031166e 58#include "specifier.h"
e594a3b1
LP
59#include "stat-util.h"
60#include "stdio-util.h"
889914ef 61#include "string-table.h"
e594a3b1
LP
62#include "string-util.h"
63#include "strv.h"
64#include "terminal-util.h"
889914ef 65#include "tpm2-util.h"
8a794850 66#include "user-util.h"
e594a3b1
LP
67#include "utf8.h"
68
fb08381c
LP
69/* If not configured otherwise use a minimal partition size of 10M */
70#define DEFAULT_MIN_SIZE (10*1024*1024)
71
72/* Hard lower limit for new partition sizes */
73#define HARD_MIN_SIZE 4096
74
69e3234d 75/* libfdisk takes off slightly more than 1M of the disk size when creating a GPT disk label */
170c9823
LP
76#define GPT_METADATA_SIZE (1044*1024)
77
78/* LUKS2 takes off 16M of the partition size with its metadata by default */
79#define LUKS2_METADATA_SIZE (16*1024*1024)
80
e594a3b1
LP
81/* Note: When growing and placing new partitions we always align to 4K sector size. It's how newer hard disks
82 * are designed, and if everything is aligned to that performance is best. And for older hard disks with 512B
83 * sector size devices were generally assumed to have an even number of sectors, hence at the worst we'll
84 * waste 3K per partition, which is probably fine. */
85
86static enum {
87 EMPTY_REFUSE, /* refuse empty disks, never create a partition table */
88 EMPTY_ALLOW, /* allow empty disks, create partition table if necessary */
89 EMPTY_REQUIRE, /* require an empty disk, create a partition table */
90 EMPTY_FORCE, /* make disk empty, erase everything, create a partition table always */
a26f4a49 91 EMPTY_CREATE, /* create disk as loopback file, create a partition table always */
e594a3b1
LP
92} arg_empty = EMPTY_REFUSE;
93
94static bool arg_dry_run = true;
95static const char *arg_node = NULL;
96static char *arg_root = NULL;
252d6267 97static char *arg_image = NULL;
e594a3b1
LP
98static char *arg_definitions = NULL;
99static bool arg_discard = true;
100static bool arg_can_factory_reset = false;
101static int arg_factory_reset = -1;
102static sd_id128_t arg_seed = SD_ID128_NULL;
103static bool arg_randomize = false;
104static int arg_pretty = -1;
a26f4a49 105static uint64_t arg_size = UINT64_MAX;
170c9823 106static bool arg_size_auto = false;
6a01ea4a 107static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
896e678b
LP
108static PagerFlags arg_pager_flags = 0;
109static bool arg_legend = true;
b9df3536
LP
110static void *arg_key = NULL;
111static size_t arg_key_size = 0;
889914ef
LP
112static char *arg_tpm2_device = NULL;
113static uint32_t arg_tpm2_pcr_mask = UINT32_MAX;
e594a3b1
LP
114
115STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
252d6267 116STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
e594a3b1 117STATIC_DESTRUCTOR_REGISTER(arg_definitions, freep);
b9df3536 118STATIC_DESTRUCTOR_REGISTER(arg_key, erase_and_freep);
889914ef 119STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
e594a3b1
LP
120
121typedef struct Partition Partition;
122typedef struct FreeArea FreeArea;
123typedef struct Context Context;
124
889914ef
LP
125typedef enum EncryptMode {
126 ENCRYPT_OFF,
127 ENCRYPT_KEY_FILE,
128 ENCRYPT_TPM2,
129 ENCRYPT_KEY_FILE_TPM2,
130 _ENCRYPT_MODE_MAX,
2d93c20e 131 _ENCRYPT_MODE_INVALID = -EINVAL,
889914ef
LP
132} EncryptMode;
133
e594a3b1
LP
134struct Partition {
135 char *definition_path;
136
137 sd_id128_t type_uuid;
138 sd_id128_t current_uuid, new_uuid;
139 char *current_label, *new_label;
140
141 bool dropped;
142 bool factory_reset;
143 int32_t priority;
144
145 uint32_t weight, padding_weight;
146
147 uint64_t current_size, new_size;
148 uint64_t size_min, size_max;
149
150 uint64_t current_padding, new_padding;
151 uint64_t padding_min, padding_max;
152
153 uint64_t partno;
154 uint64_t offset;
155
156 struct fdisk_partition *current_partition;
157 struct fdisk_partition *new_partition;
158 FreeArea *padding_area;
159 FreeArea *allocated_to_area;
160
757bc2e4 161 char *copy_blocks_path;
5c08da58 162 bool copy_blocks_auto;
757bc2e4
LP
163 int copy_blocks_fd;
164 uint64_t copy_blocks_size;
165
53171c04 166 char *format;
8a794850 167 char **copy_files;
d83d8048 168 char **make_directories;
889914ef 169 EncryptMode encrypt;
53171c04 170
e73309c5 171 uint64_t gpt_flags;
ff0771bf 172 int no_auto;
e73309c5 173 int read_only;
1c41c1dc 174 int growfs;
e73309c5 175
e594a3b1
LP
176 LIST_FIELDS(Partition, partitions);
177};
178
179#define PARTITION_IS_FOREIGN(p) (!(p)->definition_path)
180#define PARTITION_EXISTS(p) (!!(p)->current_partition)
181
182struct FreeArea {
183 Partition *after;
184 uint64_t size;
185 uint64_t allocated;
186};
187
188struct Context {
189 LIST_HEAD(Partition, partitions);
190 size_t n_partitions;
191
192 FreeArea **free_areas;
319a4f4b 193 size_t n_free_areas;
e594a3b1
LP
194
195 uint64_t start, end, total;
196
197 struct fdisk_context *fdisk_context;
198
199 sd_id128_t seed;
200};
201
889914ef
LP
202static const char *encrypt_mode_table[_ENCRYPT_MODE_MAX] = {
203 [ENCRYPT_OFF] = "off",
204 [ENCRYPT_KEY_FILE] = "key-file",
205 [ENCRYPT_TPM2] = "tpm2",
206 [ENCRYPT_KEY_FILE_TPM2] = "key-file+tpm2",
207};
208
2709d029 209#if HAVE_LIBCRYPTSETUP
889914ef 210DEFINE_PRIVATE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(encrypt_mode, EncryptMode, ENCRYPT_KEY_FILE);
2709d029
MH
211#else
212DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(encrypt_mode, EncryptMode, ENCRYPT_KEY_FILE);
213#endif
214
889914ef 215
e594a3b1
LP
216static uint64_t round_down_size(uint64_t v, uint64_t p) {
217 return (v / p) * p;
218}
219
220static uint64_t round_up_size(uint64_t v, uint64_t p) {
221
222 v = DIV_ROUND_UP(v, p);
223
224 if (v > UINT64_MAX / p)
225 return UINT64_MAX; /* overflow */
226
227 return v * p;
228}
229
230static Partition *partition_new(void) {
231 Partition *p;
232
233 p = new(Partition, 1);
234 if (!p)
235 return NULL;
236
237 *p = (Partition) {
238 .weight = 1000,
239 .padding_weight = 0,
240 .current_size = UINT64_MAX,
241 .new_size = UINT64_MAX,
242 .size_min = UINT64_MAX,
243 .size_max = UINT64_MAX,
244 .current_padding = UINT64_MAX,
245 .new_padding = UINT64_MAX,
246 .padding_min = UINT64_MAX,
247 .padding_max = UINT64_MAX,
248 .partno = UINT64_MAX,
249 .offset = UINT64_MAX,
757bc2e4
LP
250 .copy_blocks_fd = -1,
251 .copy_blocks_size = UINT64_MAX,
ff0771bf 252 .no_auto = -1,
e73309c5 253 .read_only = -1,
1c41c1dc 254 .growfs = -1,
e594a3b1
LP
255 };
256
257 return p;
258}
259
260static Partition* partition_free(Partition *p) {
261 if (!p)
262 return NULL;
263
264 free(p->current_label);
265 free(p->new_label);
266 free(p->definition_path);
267
268 if (p->current_partition)
269 fdisk_unref_partition(p->current_partition);
270 if (p->new_partition)
271 fdisk_unref_partition(p->new_partition);
272
757bc2e4
LP
273 free(p->copy_blocks_path);
274 safe_close(p->copy_blocks_fd);
275
53171c04 276 free(p->format);
8a794850 277 strv_free(p->copy_files);
d83d8048 278 strv_free(p->make_directories);
53171c04 279
e594a3b1
LP
280 return mfree(p);
281}
282
283static Partition* partition_unlink_and_free(Context *context, Partition *p) {
284 if (!p)
285 return NULL;
286
287 LIST_REMOVE(partitions, context->partitions, p);
288
289 assert(context->n_partitions > 0);
290 context->n_partitions--;
291
292 return partition_free(p);
293}
294
295DEFINE_TRIVIAL_CLEANUP_FUNC(Partition*, partition_free);
296
297static Context *context_new(sd_id128_t seed) {
298 Context *context;
299
300 context = new(Context, 1);
301 if (!context)
302 return NULL;
303
304 *context = (Context) {
305 .start = UINT64_MAX,
306 .end = UINT64_MAX,
307 .total = UINT64_MAX,
308 .seed = seed,
309 };
310
311 return context;
312}
313
314static void context_free_free_areas(Context *context) {
315 assert(context);
316
317 for (size_t i = 0; i < context->n_free_areas; i++)
318 free(context->free_areas[i]);
319
320 context->free_areas = mfree(context->free_areas);
321 context->n_free_areas = 0;
e594a3b1
LP
322}
323
324static Context *context_free(Context *context) {
325 if (!context)
326 return NULL;
327
328 while (context->partitions)
329 partition_unlink_and_free(context, context->partitions);
330 assert(context->n_partitions == 0);
331
332 context_free_free_areas(context);
333
334 if (context->fdisk_context)
335 fdisk_unref_context(context->fdisk_context);
336
337 return mfree(context);
338}
339
340DEFINE_TRIVIAL_CLEANUP_FUNC(Context*, context_free);
341
342static int context_add_free_area(
343 Context *context,
344 uint64_t size,
345 Partition *after) {
346
347 FreeArea *a;
348
349 assert(context);
350 assert(!after || !after->padding_area);
351
319a4f4b 352 if (!GREEDY_REALLOC(context->free_areas, context->n_free_areas + 1))
e594a3b1
LP
353 return -ENOMEM;
354
355 a = new(FreeArea, 1);
356 if (!a)
357 return -ENOMEM;
358
359 *a = (FreeArea) {
360 .size = size,
361 .after = after,
362 };
363
364 context->free_areas[context->n_free_areas++] = a;
365
366 if (after)
367 after->padding_area = a;
368
369 return 0;
370}
371
372static bool context_drop_one_priority(Context *context) {
373 int32_t priority = 0;
374 Partition *p;
375 bool exists = false;
376
377 LIST_FOREACH(partitions, p, context->partitions) {
378 if (p->dropped)
379 continue;
380 if (p->priority < priority)
381 continue;
382 if (p->priority == priority) {
383 exists = exists || PARTITION_EXISTS(p);
384 continue;
385 }
386
387 priority = p->priority;
388 exists = PARTITION_EXISTS(p);
389 }
390
391 /* Refuse to drop partitions with 0 or negative priorities or partitions of priorities that have at
392 * least one existing priority */
393 if (priority <= 0 || exists)
394 return false;
395
396 LIST_FOREACH(partitions, p, context->partitions) {
397 if (p->priority < priority)
398 continue;
399
400 if (p->dropped)
401 continue;
402
403 p->dropped = true;
404 log_info("Can't fit partition %s of priority %" PRIi32 ", dropping.", p->definition_path, p->priority);
405 }
406
407 return true;
408}
409
410static uint64_t partition_min_size(const Partition *p) {
411 uint64_t sz;
412
413 /* Calculate the disk space we really need at minimum for this partition. If the partition already
414 * exists the current size is what we really need. If it doesn't exist yet refuse to allocate less
fb08381c
LP
415 * than 4K.
416 *
417 * DEFAULT_MIN_SIZE is the default SizeMin= we configure if nothing else is specified. */
e594a3b1
LP
418
419 if (PARTITION_IS_FOREIGN(p)) {
420 /* Don't allow changing size of partitions not managed by us */
421 assert(p->current_size != UINT64_MAX);
422 return p->current_size;
423 }
424
fb08381c 425 sz = p->current_size != UINT64_MAX ? p->current_size : HARD_MIN_SIZE;
757bc2e4 426
170c9823
LP
427 if (!PARTITION_EXISTS(p)) {
428 uint64_t d = 0;
429
889914ef 430 if (p->encrypt != ENCRYPT_OFF)
170c9823
LP
431 d += round_up_size(LUKS2_METADATA_SIZE, 4096);
432
433 if (p->copy_blocks_size != UINT64_MAX)
434 d += round_up_size(p->copy_blocks_size, 4096);
889914ef 435 else if (p->format || p->encrypt != ENCRYPT_OFF) {
170c9823
LP
436 uint64_t f;
437
438 /* If we shall synthesize a file system, take minimal fs size into account (assumed to be 4K if not known) */
439 f = p->format ? minimal_size_by_fs_name(p->format) : UINT64_MAX;
440 d += f == UINT64_MAX ? 4096 : f;
441 }
442
443 if (d > sz)
444 sz = d;
445 }
757bc2e4
LP
446
447 return MAX(p->size_min != UINT64_MAX ? p->size_min : DEFAULT_MIN_SIZE, sz);
e594a3b1
LP
448}
449
450static uint64_t partition_max_size(const Partition *p) {
451 /* Calculate how large the partition may become at max. This is generally the configured maximum
452 * size, except when it already exists and is larger than that. In that case it's the existing size,
453 * since we never want to shrink partitions. */
454
455 if (PARTITION_IS_FOREIGN(p)) {
456 /* Don't allow changing size of partitions not managed by us */
457 assert(p->current_size != UINT64_MAX);
458 return p->current_size;
459 }
460
461 if (p->current_size != UINT64_MAX)
462 return MAX(p->current_size, p->size_max);
463
464 return p->size_max;
465}
466
467static uint64_t partition_min_size_with_padding(const Partition *p) {
468 uint64_t sz;
469
470 /* Calculate the disk space we need for this partition plus any free space coming after it. This
471 * takes user configured padding into account as well as any additional whitespace needed to align
472 * the next partition to 4K again. */
473
474 sz = partition_min_size(p);
475
476 if (p->padding_min != UINT64_MAX)
477 sz += p->padding_min;
478
479 if (PARTITION_EXISTS(p)) {
480 /* If the partition wasn't aligned, add extra space so that any we might add will be aligned */
481 assert(p->offset != UINT64_MAX);
482 return round_up_size(p->offset + sz, 4096) - p->offset;
483 }
484
485 /* If this is a new partition we'll place it aligned, hence we just need to round up the required size here */
486 return round_up_size(sz, 4096);
487}
488
489static uint64_t free_area_available(const FreeArea *a) {
490 assert(a);
491
492 /* Determines how much of this free area is not allocated yet */
493
494 assert(a->size >= a->allocated);
495 return a->size - a->allocated;
496}
497
498static uint64_t free_area_available_for_new_partitions(const FreeArea *a) {
499 uint64_t avail;
500
501 /* Similar to free_area_available(), but takes into account that the required size and padding of the
162392b7 502 * preceding partition is honoured. */
e594a3b1
LP
503
504 avail = free_area_available(a);
505 if (a->after) {
506 uint64_t need, space;
507
508 need = partition_min_size_with_padding(a->after);
509
510 assert(a->after->offset != UINT64_MAX);
511 assert(a->after->current_size != UINT64_MAX);
512
513 space = round_up_size(a->after->offset + a->after->current_size, 4096) - a->after->offset + avail;
514 if (need >= space)
515 return 0;
516
517 return space - need;
518 }
519
520 return avail;
521}
522
523static int free_area_compare(FreeArea *const *a, FreeArea *const*b) {
524 return CMP(free_area_available_for_new_partitions(*a),
525 free_area_available_for_new_partitions(*b));
526}
527
528static uint64_t charge_size(uint64_t total, uint64_t amount) {
529 uint64_t rounded;
530
531 assert(amount <= total);
532
533 /* Subtract the specified amount from total, rounding up to multiple of 4K if there's room */
534 rounded = round_up_size(amount, 4096);
535 if (rounded >= total)
536 return 0;
537
538 return total - rounded;
539}
540
541static uint64_t charge_weight(uint64_t total, uint64_t amount) {
542 assert(amount <= total);
543 return total - amount;
544}
545
14a4c4ed 546static bool context_allocate_partitions(Context *context, uint64_t *ret_largest_free_area) {
e594a3b1
LP
547 Partition *p;
548
549 assert(context);
550
14a4c4ed
LP
551 /* Sort free areas by size, putting smallest first */
552 typesafe_qsort(context->free_areas, context->n_free_areas, free_area_compare);
e594a3b1 553
14a4c4ed
LP
554 /* In any case return size of the largest free area (i.e. not the size of all free areas
555 * combined!) */
556 if (ret_largest_free_area)
557 *ret_largest_free_area =
558 context->n_free_areas == 0 ? 0 :
559 free_area_available_for_new_partitions(context->free_areas[context->n_free_areas-1]);
560
561 /* A simple first-fit algorithm. We return true if we can fit the partitions in, otherwise false. */
e594a3b1
LP
562 LIST_FOREACH(partitions, p, context->partitions) {
563 bool fits = false;
564 uint64_t required;
565 FreeArea *a = NULL;
566
567 /* Skip partitions we already dropped or that already exist */
568 if (p->dropped || PARTITION_EXISTS(p))
569 continue;
570
e594a3b1
LP
571 /* How much do we need to fit? */
572 required = partition_min_size_with_padding(p);
573 assert(required % 4096 == 0);
574
575 for (size_t i = 0; i < context->n_free_areas; i++) {
576 a = context->free_areas[i];
577
578 if (free_area_available_for_new_partitions(a) >= required) {
579 fits = true;
580 break;
581 }
582 }
583
584 if (!fits)
585 return false; /* 😢 Oh no! We can't fit this partition into any free area! */
586
587 /* Assign the partition to this free area */
588 p->allocated_to_area = a;
589
590 /* Budget the minimal partition size */
591 a->allocated += required;
592 }
593
594 return true;
595}
596
597static int context_sum_weights(Context *context, FreeArea *a, uint64_t *ret) {
598 uint64_t weight_sum = 0;
599 Partition *p;
600
601 assert(context);
602 assert(a);
603 assert(ret);
604
605 /* Determine the sum of the weights of all partitions placed in or before the specified free area */
606
607 LIST_FOREACH(partitions, p, context->partitions) {
608 if (p->padding_area != a && p->allocated_to_area != a)
609 continue;
610
611 if (p->weight > UINT64_MAX - weight_sum)
612 goto overflow_sum;
613 weight_sum += p->weight;
614
615 if (p->padding_weight > UINT64_MAX - weight_sum)
616 goto overflow_sum;
617 weight_sum += p->padding_weight;
618 }
619
620 *ret = weight_sum;
621 return 0;
622
623overflow_sum:
624 return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "Combined weight of partition exceeds unsigned 64bit range, refusing.");
625}
626
627static int scale_by_weight(uint64_t value, uint64_t weight, uint64_t weight_sum, uint64_t *ret) {
628 assert(weight_sum >= weight);
629 assert(ret);
630
631 if (weight == 0) {
632 *ret = 0;
633 return 0;
634 }
635
636 if (value > UINT64_MAX / weight)
637 return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "Scaling by weight of partition exceeds unsigned 64bit range, refusing.");
638
639 *ret = value * weight / weight_sum;
640 return 0;
641}
642
643typedef enum GrowPartitionPhase {
644 /* The first phase: we charge partitions which need more (according to constraints) than their weight-based share. */
645 PHASE_OVERCHARGE,
646
647 /* The second phase: we charge partitions which need less (according to constraints) than their weight-based share. */
648 PHASE_UNDERCHARGE,
649
650 /* The third phase: we distribute what remains among the remaining partitions, according to the weights */
651 PHASE_DISTRIBUTE,
652} GrowPartitionPhase;
653
654static int context_grow_partitions_phase(
655 Context *context,
656 FreeArea *a,
657 GrowPartitionPhase phase,
658 uint64_t *span,
659 uint64_t *weight_sum) {
660
661 Partition *p;
662 int r;
663
664 assert(context);
665 assert(a);
666
667 /* Now let's look at the intended weights and adjust them taking the minimum space assignments into
668 * account. i.e. if a partition has a small weight but a high minimum space value set it should not
669 * get any additional room from the left-overs. Similar, if two partitions have the same weight they
670 * should get the same space if possible, even if one has a smaller minimum size than the other. */
671 LIST_FOREACH(partitions, p, context->partitions) {
672
673 /* Look only at partitions associated with this free area, i.e. immediately
162392b7 674 * preceding it, or allocated into it */
e594a3b1
LP
675 if (p->allocated_to_area != a && p->padding_area != a)
676 continue;
677
678 if (p->new_size == UINT64_MAX) {
679 bool charge = false, try_again = false;
680 uint64_t share, rsz, xsz;
681
682 /* Calculate how much this space this partition needs if everyone would get
683 * the weight based share */
684 r = scale_by_weight(*span, p->weight, *weight_sum, &share);
685 if (r < 0)
686 return r;
687
688 rsz = partition_min_size(p);
689 xsz = partition_max_size(p);
690
691 if (phase == PHASE_OVERCHARGE && rsz > share) {
692 /* This partition needs more than its calculated share. Let's assign
693 * it that, and take this partition out of all calculations and start
694 * again. */
695
696 p->new_size = rsz;
697 charge = try_again = true;
698
699 } else if (phase == PHASE_UNDERCHARGE && xsz != UINT64_MAX && xsz < share) {
700 /* This partition accepts less than its calculated
701 * share. Let's assign it that, and take this partition out
702 * of all calculations and start again. */
703
704 p->new_size = xsz;
705 charge = try_again = true;
706
707 } else if (phase == PHASE_DISTRIBUTE) {
708 /* This partition can accept its calculated share. Let's
709 * assign it. There's no need to restart things here since
710 * assigning this shouldn't impact the shares of the other
711 * partitions. */
712
713 if (PARTITION_IS_FOREIGN(p))
714 /* Never change of foreign partitions (i.e. those we don't manage) */
715 p->new_size = p->current_size;
716 else
717 p->new_size = MAX(round_down_size(share, 4096), rsz);
718
719 charge = true;
720 }
721
722 if (charge) {
723 *span = charge_size(*span, p->new_size);
724 *weight_sum = charge_weight(*weight_sum, p->weight);
725 }
726
727 if (try_again)
728 return 0; /* try again */
729 }
730
731 if (p->new_padding == UINT64_MAX) {
732 bool charge = false, try_again = false;
733 uint64_t share;
734
735 r = scale_by_weight(*span, p->padding_weight, *weight_sum, &share);
736 if (r < 0)
737 return r;
738
739 if (phase == PHASE_OVERCHARGE && p->padding_min != UINT64_MAX && p->padding_min > share) {
740 p->new_padding = p->padding_min;
741 charge = try_again = true;
742 } else if (phase == PHASE_UNDERCHARGE && p->padding_max != UINT64_MAX && p->padding_max < share) {
743 p->new_padding = p->padding_max;
744 charge = try_again = true;
745 } else if (phase == PHASE_DISTRIBUTE) {
746
747 p->new_padding = round_down_size(share, 4096);
748 if (p->padding_min != UINT64_MAX && p->new_padding < p->padding_min)
749 p->new_padding = p->padding_min;
750
751 charge = true;
752 }
753
754 if (charge) {
755 *span = charge_size(*span, p->new_padding);
756 *weight_sum = charge_weight(*weight_sum, p->padding_weight);
757 }
758
759 if (try_again)
760 return 0; /* try again */
761 }
762 }
763
764 return 1; /* done */
765}
766
767static int context_grow_partitions_on_free_area(Context *context, FreeArea *a) {
768 uint64_t weight_sum = 0, span;
769 int r;
770
771 assert(context);
772 assert(a);
773
774 r = context_sum_weights(context, a, &weight_sum);
775 if (r < 0)
776 return r;
777
778 /* Let's calculate the total area covered by this free area and the partition before it */
779 span = a->size;
780 if (a->after) {
781 assert(a->after->offset != UINT64_MAX);
782 assert(a->after->current_size != UINT64_MAX);
783
784 span += round_up_size(a->after->offset + a->after->current_size, 4096) - a->after->offset;
785 }
786
787 GrowPartitionPhase phase = PHASE_OVERCHARGE;
788 for (;;) {
789 r = context_grow_partitions_phase(context, a, phase, &span, &weight_sum);
790 if (r < 0)
791 return r;
792 if (r == 0) /* not done yet, re-run this phase */
793 continue;
794
795 if (phase == PHASE_OVERCHARGE)
796 phase = PHASE_UNDERCHARGE;
797 else if (phase == PHASE_UNDERCHARGE)
798 phase = PHASE_DISTRIBUTE;
799 else if (phase == PHASE_DISTRIBUTE)
800 break;
801 }
802
162392b7 803 /* We still have space left over? Donate to preceding partition if we have one */
e594a3b1
LP
804 if (span > 0 && a->after && !PARTITION_IS_FOREIGN(a->after)) {
805 uint64_t m, xsz;
806
807 assert(a->after->new_size != UINT64_MAX);
808 m = a->after->new_size + span;
809
810 xsz = partition_max_size(a->after);
811 if (xsz != UINT64_MAX && m > xsz)
812 m = xsz;
813
814 span = charge_size(span, m - a->after->new_size);
815 a->after->new_size = m;
816 }
817
162392b7 818 /* What? Even still some space left (maybe because there was no preceding partition, or it had a
e594a3b1
LP
819 * size limit), then let's donate it to whoever wants it. */
820 if (span > 0) {
821 Partition *p;
822
823 LIST_FOREACH(partitions, p, context->partitions) {
824 uint64_t m, xsz;
825
826 if (p->allocated_to_area != a)
827 continue;
828
829 if (PARTITION_IS_FOREIGN(p))
830 continue;
831
832 assert(p->new_size != UINT64_MAX);
833 m = p->new_size + span;
834
db144226 835 xsz = partition_max_size(p);
e594a3b1
LP
836 if (xsz != UINT64_MAX && m > xsz)
837 m = xsz;
838
839 span = charge_size(span, m - p->new_size);
840 p->new_size = m;
841
842 if (span == 0)
843 break;
844 }
845 }
846
162392b7 847 /* Yuck, still no one? Then make it padding */
e594a3b1
LP
848 if (span > 0 && a->after) {
849 assert(a->after->new_padding != UINT64_MAX);
850 a->after->new_padding += span;
851 }
852
853 return 0;
854}
855
856static int context_grow_partitions(Context *context) {
857 Partition *p;
858 int r;
859
860 assert(context);
861
862 for (size_t i = 0; i < context->n_free_areas; i++) {
863 r = context_grow_partitions_on_free_area(context, context->free_areas[i]);
864 if (r < 0)
865 return r;
866 }
867
868 /* All existing partitions that have no free space after them can't change size */
869 LIST_FOREACH(partitions, p, context->partitions) {
870 if (p->dropped)
871 continue;
872
873 if (!PARTITION_EXISTS(p) || p->padding_area) {
874 /* The algorithm above must have initialized this already */
875 assert(p->new_size != UINT64_MAX);
876 continue;
877 }
878
879 assert(p->new_size == UINT64_MAX);
880 p->new_size = p->current_size;
881
882 assert(p->new_padding == UINT64_MAX);
883 p->new_padding = p->current_padding;
884 }
885
886 return 0;
887}
888
889static void context_place_partitions(Context *context) {
890 uint64_t partno = 0;
891 Partition *p;
892
893 assert(context);
894
895 /* Determine next partition number to assign */
896 LIST_FOREACH(partitions, p, context->partitions) {
897 if (!PARTITION_EXISTS(p))
898 continue;
899
900 assert(p->partno != UINT64_MAX);
901 if (p->partno >= partno)
902 partno = p->partno + 1;
903 }
904
905 for (size_t i = 0; i < context->n_free_areas; i++) {
906 FreeArea *a = context->free_areas[i];
2ea7eb00
FS
907 _unused_ uint64_t left;
908 uint64_t start;
e594a3b1
LP
909
910 if (a->after) {
911 assert(a->after->offset != UINT64_MAX);
912 assert(a->after->new_size != UINT64_MAX);
913 assert(a->after->new_padding != UINT64_MAX);
914
915 start = a->after->offset + a->after->new_size + a->after->new_padding;
916 } else
917 start = context->start;
918
919 start = round_up_size(start, 4096);
920 left = a->size;
921
922 LIST_FOREACH(partitions, p, context->partitions) {
923 if (p->allocated_to_area != a)
924 continue;
925
926 p->offset = start;
927 p->partno = partno++;
928
929 assert(left >= p->new_size);
930 start += p->new_size;
931 left -= p->new_size;
932
933 assert(left >= p->new_padding);
934 start += p->new_padding;
935 left -= p->new_padding;
936 }
937 }
938}
939
e594a3b1
LP
940static int config_parse_type(
941 const char *unit,
942 const char *filename,
943 unsigned line,
944 const char *section,
945 unsigned section_line,
946 const char *lvalue,
947 int ltype,
948 const char *rvalue,
949 void *data,
950 void *userdata) {
951
952 sd_id128_t *type_uuid = data;
953 int r;
954
955 assert(rvalue);
956 assert(type_uuid);
957
958 r = gpt_partition_type_uuid_from_string(rvalue, type_uuid);
959 if (r < 0)
960 return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse partition type: %s", rvalue);
961
962 return 0;
963}
964
965static int config_parse_label(
966 const char *unit,
967 const char *filename,
968 unsigned line,
969 const char *section,
970 unsigned section_line,
971 const char *lvalue,
972 int ltype,
973 const char *rvalue,
974 void *data,
975 void *userdata) {
976
e031166e 977 _cleanup_free_ char *resolved = NULL;
e594a3b1
LP
978 char **label = data;
979 int r;
980
981 assert(rvalue);
982 assert(label);
983
be9ce018
LP
984 /* Nota bene: the empty label is a totally valid one. Let's hence not follow our usual rule of
985 * assigning the empty string to reset to default here, but really accept it as label to set. */
986
de61a04b 987 r = specifier_printf(rvalue, GPT_LABEL_MAX, system_and_tmp_specifier_table, arg_root, NULL, &resolved);
e031166e 988 if (r < 0) {
e459258f 989 log_syntax(unit, LOG_WARNING, filename, line, r,
e031166e
LP
990 "Failed to expand specifiers in Label=, ignoring: %s", rvalue);
991 return 0;
992 }
993
994 if (!utf8_is_valid(resolved)) {
e594a3b1
LP
995 log_syntax(unit, LOG_WARNING, filename, line, 0,
996 "Partition label not valid UTF-8, ignoring: %s", rvalue);
997 return 0;
998 }
999
22a0a36e
LP
1000 r = gpt_partition_label_valid(resolved);
1001 if (r < 0) {
1002 log_syntax(unit, LOG_WARNING, filename, line, r,
1003 "Failed to check if string is valid as GPT partition label, ignoring: \"%s\" (from \"%s\")",
1004 resolved, rvalue);
1005 return 0;
1006 }
1007 if (!r) {
e594a3b1 1008 log_syntax(unit, LOG_WARNING, filename, line, 0,
46072ae3
ZJS
1009 "Partition label too long for GPT table, ignoring: \"%s\" (from \"%s\")",
1010 resolved, rvalue);
e594a3b1
LP
1011 return 0;
1012 }
1013
e031166e 1014 free_and_replace(*label, resolved);
e594a3b1
LP
1015 return 0;
1016}
1017
1018static int config_parse_weight(
1019 const char *unit,
1020 const char *filename,
1021 unsigned line,
1022 const char *section,
1023 unsigned section_line,
1024 const char *lvalue,
1025 int ltype,
1026 const char *rvalue,
1027 void *data,
1028 void *userdata) {
1029
1030 uint32_t *priority = data, v;
1031 int r;
1032
1033 assert(rvalue);
1034 assert(priority);
1035
1036 r = safe_atou32(rvalue, &v);
1037 if (r < 0) {
1038 log_syntax(unit, LOG_WARNING, filename, line, r,
1039 "Failed to parse weight value, ignoring: %s", rvalue);
1040 return 0;
1041 }
1042
1043 if (v > 1000U*1000U) {
c8f3d767 1044 log_syntax(unit, LOG_WARNING, filename, line, 0,
e594a3b1
LP
1045 "Weight needs to be in range 0…10000000, ignoring: %" PRIu32, v);
1046 return 0;
1047 }
1048
1049 *priority = v;
1050 return 0;
1051}
1052
1053static int config_parse_size4096(
1054 const char *unit,
1055 const char *filename,
1056 unsigned line,
1057 const char *section,
1058 unsigned section_line,
1059 const char *lvalue,
1060 int ltype,
1061 const char *rvalue,
1062 void *data,
1063 void *userdata) {
1064
1065 uint64_t *sz = data, parsed;
1066 int r;
1067
1068 assert(rvalue);
1069 assert(data);
1070
1071 r = parse_size(rvalue, 1024, &parsed);
1072 if (r < 0)
c8f3d767 1073 return log_syntax(unit, LOG_ERR, filename, line, r,
e594a3b1
LP
1074 "Failed to parse size value: %s", rvalue);
1075
1076 if (ltype > 0)
1077 *sz = round_up_size(parsed, 4096);
1078 else if (ltype < 0)
1079 *sz = round_down_size(parsed, 4096);
1080 else
1081 *sz = parsed;
1082
1083 if (*sz != parsed)
1084 log_syntax(unit, LOG_NOTICE, filename, line, r, "Rounded %s= size %" PRIu64 " → %" PRIu64 ", a multiple of 4096.", lvalue, parsed, *sz);
1085
1086 return 0;
1087}
1088
53171c04
LP
1089static int config_parse_fstype(
1090 const char *unit,
1091 const char *filename,
1092 unsigned line,
1093 const char *section,
1094 unsigned section_line,
1095 const char *lvalue,
1096 int ltype,
1097 const char *rvalue,
1098 void *data,
1099 void *userdata) {
1100
1101 char **fstype = data;
1102
1103 assert(rvalue);
1104 assert(data);
1105
1106 if (!filename_is_valid(rvalue))
1107 return log_syntax(unit, LOG_ERR, filename, line, 0,
1108 "File system type is not valid, refusing: %s", rvalue);
1109
1110 return free_and_strdup_warn(fstype, rvalue);
1111}
1112
8a794850
LP
1113static int config_parse_copy_files(
1114 const char *unit,
1115 const char *filename,
1116 unsigned line,
1117 const char *section,
1118 unsigned section_line,
1119 const char *lvalue,
1120 int ltype,
1121 const char *rvalue,
1122 void *data,
1123 void *userdata) {
1124
1125 _cleanup_free_ char *source = NULL, *buffer = NULL, *resolved_source = NULL, *resolved_target = NULL;
1126 const char *p = rvalue, *target;
1127 Partition *partition = data;
1128 int r;
1129
1130 assert(rvalue);
1131 assert(partition);
1132
1133 r = extract_first_word(&p, &source, ":", EXTRACT_CUNESCAPE|EXTRACT_DONT_COALESCE_SEPARATORS);
1134 if (r < 0)
1135 return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract source path: %s", rvalue);
1136 if (r == 0) {
1137 log_syntax(unit, LOG_WARNING, filename, line, 0, "No argument specified: %s", rvalue);
1138 return 0;
1139 }
1140
1141 r = extract_first_word(&p, &buffer, ":", EXTRACT_CUNESCAPE|EXTRACT_DONT_COALESCE_SEPARATORS);
1142 if (r < 0)
1143 return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract target path: %s", rvalue);
1144 if (r == 0)
1145 target = source; /* No target, then it's the same as the source */
1146 else
1147 target = buffer;
1148
1149 if (!isempty(p))
1150 return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "Too many arguments: %s", rvalue);
1151
de61a04b 1152 r = specifier_printf(source, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &resolved_source);
8a794850
LP
1153 if (r < 0) {
1154 log_syntax(unit, LOG_WARNING, filename, line, r,
1155 "Failed to expand specifiers in CopyFiles= source, ignoring: %s", rvalue);
1156 return 0;
1157 }
1158
0ade2213
LP
1159 r = path_simplify_and_warn(resolved_source, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
1160 if (r < 0)
8a794850 1161 return 0;
8a794850 1162
de61a04b 1163 r = specifier_printf(target, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &resolved_target);
8a794850
LP
1164 if (r < 0) {
1165 log_syntax(unit, LOG_WARNING, filename, line, r,
1166 "Failed to expand specifiers in CopyFiles= target, ignoring: %s", resolved_target);
1167 return 0;
1168 }
1169
0ade2213
LP
1170 r = path_simplify_and_warn(resolved_target, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
1171 if (r < 0)
8a794850 1172 return 0;
8a794850
LP
1173
1174 r = strv_consume_pair(&partition->copy_files, TAKE_PTR(resolved_source), TAKE_PTR(resolved_target));
1175 if (r < 0)
1176 return log_oom();
1177
1178 return 0;
1179}
1180
5c08da58
LP
1181static int config_parse_copy_blocks(
1182 const char *unit,
1183 const char *filename,
1184 unsigned line,
1185 const char *section,
1186 unsigned section_line,
1187 const char *lvalue,
1188 int ltype,
1189 const char *rvalue,
1190 void *data,
1191 void *userdata) {
1192
1193 _cleanup_free_ char *d = NULL;
1194 Partition *partition = data;
1195 int r;
1196
1197 assert(rvalue);
1198 assert(partition);
1199
1200 if (isempty(rvalue)) {
1201 partition->copy_blocks_path = mfree(partition->copy_blocks_path);
1202 partition->copy_blocks_auto = false;
1203 return 0;
1204 }
1205
1206 if (streq(rvalue, "auto")) {
1207 partition->copy_blocks_path = mfree(partition->copy_blocks_path);
1208 partition->copy_blocks_auto = true;
1209 return 0;
1210 }
1211
de61a04b 1212 r = specifier_printf(rvalue, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &d);
5c08da58
LP
1213 if (r < 0) {
1214 log_syntax(unit, LOG_WARNING, filename, line, r,
1215 "Failed to expand specifiers in CopyBlocks= source path, ignoring: %s", rvalue);
1216 return 0;
1217 }
1218
1219 r = path_simplify_and_warn(d, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
1220 if (r < 0)
1221 return 0;
1222
1223 free_and_replace(partition->copy_blocks_path, d);
1224 partition->copy_blocks_auto = false;
1225 return 0;
1226}
1227
d83d8048
LP
1228static int config_parse_make_dirs(
1229 const char *unit,
1230 const char *filename,
1231 unsigned line,
1232 const char *section,
1233 unsigned section_line,
1234 const char *lvalue,
1235 int ltype,
1236 const char *rvalue,
1237 void *data,
1238 void *userdata) {
1239
1240 Partition *partition = data;
1241 const char *p = rvalue;
1242 int r;
1243
1244 assert(rvalue);
1245 assert(partition);
1246
1247 for (;;) {
1248 _cleanup_free_ char *word = NULL, *d = NULL;
1249
1250 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
1251 if (r == -ENOMEM)
1252 return log_oom();
1253 if (r < 0) {
1254 log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
1255 return 0;
1256 }
1257 if (r == 0)
1258 return 0;
1259
de61a04b 1260 r = specifier_printf(word, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &d);
d83d8048
LP
1261 if (r < 0) {
1262 log_syntax(unit, LOG_WARNING, filename, line, r,
1263 "Failed to expand specifiers in MakeDirectories= parameter, ignoring: %s", word);
1264 continue;
1265 }
1266
1267 r = path_simplify_and_warn(d, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
1268 if (r < 0)
1269 continue;
1270
1271 r = strv_consume(&partition->make_directories, TAKE_PTR(d));
1272 if (r < 0)
1273 return log_oom();
1274 }
1275}
1276
889914ef
LP
1277static DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_encrypt, encrypt_mode, EncryptMode, ENCRYPT_OFF, "Invalid encryption mode");
1278
e73309c5
LP
1279static int config_parse_gpt_flags(
1280 const char *unit,
1281 const char *filename,
1282 unsigned line,
1283 const char *section,
1284 unsigned section_line,
1285 const char *lvalue,
1286 int ltype,
1287 const char *rvalue,
1288 void *data,
1289 void *userdata) {
1290
1291 uint64_t *gpt_flags = data;
1292 int r;
1293
1294 assert(rvalue);
1295 assert(gpt_flags);
1296
1297 r = safe_atou64(rvalue, gpt_flags);
1298 if (r < 0) {
1299 log_syntax(unit, LOG_WARNING, filename, line, r,
1300 "Failed to parse Flags= value, ignoring: %s", rvalue);
1301 return 0;
1302 }
1303
1304 return 0;
1305}
1306
e594a3b1
LP
1307static int partition_read_definition(Partition *p, const char *path) {
1308
1309 ConfigTableItem table[] = {
5c08da58
LP
1310 { "Partition", "Type", config_parse_type, 0, &p->type_uuid },
1311 { "Partition", "Label", config_parse_label, 0, &p->new_label },
1312 { "Partition", "UUID", config_parse_id128, 0, &p->new_uuid },
1313 { "Partition", "Priority", config_parse_int32, 0, &p->priority },
1314 { "Partition", "Weight", config_parse_weight, 0, &p->weight },
1315 { "Partition", "PaddingWeight", config_parse_weight, 0, &p->padding_weight },
1316 { "Partition", "SizeMinBytes", config_parse_size4096, 1, &p->size_min },
1317 { "Partition", "SizeMaxBytes", config_parse_size4096, -1, &p->size_max },
1318 { "Partition", "PaddingMinBytes", config_parse_size4096, 1, &p->padding_min },
1319 { "Partition", "PaddingMaxBytes", config_parse_size4096, -1, &p->padding_max },
1320 { "Partition", "FactoryReset", config_parse_bool, 0, &p->factory_reset },
1321 { "Partition", "CopyBlocks", config_parse_copy_blocks, 0, p },
1322 { "Partition", "Format", config_parse_fstype, 0, &p->format },
1323 { "Partition", "CopyFiles", config_parse_copy_files, 0, p },
1324 { "Partition", "MakeDirectories", config_parse_make_dirs, 0, p },
1325 { "Partition", "Encrypt", config_parse_encrypt, 0, &p->encrypt },
e73309c5
LP
1326 { "Partition", "Flags", config_parse_gpt_flags, 0, &p->gpt_flags },
1327 { "Partition", "ReadOnly", config_parse_tristate, 0, &p->read_only },
ff0771bf 1328 { "Partition", "NoAuto", config_parse_tristate, 0, &p->no_auto },
1c41c1dc 1329 { "Partition", "GrowFileSystem", config_parse_tristate, 0, &p->growfs },
e594a3b1
LP
1330 {}
1331 };
1332 int r;
1333
4f9ff96a
LP
1334 r = config_parse(NULL, path, NULL,
1335 "Partition\0",
1336 config_item_table_lookup, table,
1337 CONFIG_PARSE_WARN,
1338 p,
1339 NULL);
e594a3b1
LP
1340 if (r < 0)
1341 return r;
1342
1343 if (p->size_min != UINT64_MAX && p->size_max != UINT64_MAX && p->size_min > p->size_max)
1344 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1345 "SizeMinBytes= larger than SizeMaxBytes=, refusing.");
1346
1347 if (p->padding_min != UINT64_MAX && p->padding_max != UINT64_MAX && p->padding_min > p->padding_max)
1348 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1349 "PaddingMinBytes= larger than PaddingMaxBytes=, refusing.");
1350
1351 if (sd_id128_is_null(p->type_uuid))
1352 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1353 "Type= not defined, refusing.");
1354
5c08da58
LP
1355 if ((p->copy_blocks_path || p->copy_blocks_auto) &&
1356 (p->format || !strv_isempty(p->copy_files) || !strv_isempty(p->make_directories)))
53171c04 1357 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
5c08da58 1358 "Format=/CopyFiles=/MakeDirectories= and CopyBlocks= cannot be combined, refusing.");
53171c04 1359
d83d8048 1360 if ((!strv_isempty(p->copy_files) || !strv_isempty(p->make_directories)) && streq_ptr(p->format, "swap"))
8a794850
LP
1361 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1362 "Format=swap and CopyFiles= cannot be combined, refusing.");
1363
5c08da58 1364 if (!p->format && (!strv_isempty(p->copy_files) || !strv_isempty(p->make_directories) || (p->encrypt != ENCRYPT_OFF && !(p->copy_blocks_path || p->copy_blocks_auto)))) {
b9df3536 1365 /* Pick "ext4" as file system if we are configured to copy files or encrypt the device */
8a794850
LP
1366 p->format = strdup("ext4");
1367 if (!p->format)
1368 return log_oom();
1369 }
1370
e73309c5
LP
1371 /* Verity partitions are read only, let's imply the RO flag hence, unless explicitly configured otherwise. */
1372 if ((gpt_partition_type_is_root_verity(p->type_uuid) ||
1373 gpt_partition_type_is_usr_verity(p->type_uuid)) &&
1374 p->read_only < 0)
1375 p->read_only = true;
1376
1c41c1dc
LP
1377 /* Default to "growfs" on, unless read-only */
1378 if (gpt_partition_type_knows_growfs(p->type_uuid) &&
1379 p->read_only <= 0)
1380 p->growfs = true;
1381
e594a3b1
LP
1382 return 0;
1383}
1384
1385static int context_read_definitions(
1386 Context *context,
1387 const char *directory,
1388 const char *root) {
1389
1390 _cleanup_strv_free_ char **files = NULL;
1391 Partition *last = NULL;
1392 char **f;
1393 int r;
1394
1395 assert(context);
1396
1397 if (directory)
1398 r = conf_files_list_strv(&files, ".conf", NULL, CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED, (const char**) STRV_MAKE(directory));
1399 else
1400 r = conf_files_list_strv(&files, ".conf", root, CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED, (const char**) CONF_PATHS_STRV("repart.d"));
1401 if (r < 0)
1402 return log_error_errno(r, "Failed to enumerate *.conf files: %m");
1403
1404 STRV_FOREACH(f, files) {
1405 _cleanup_(partition_freep) Partition *p = NULL;
1406
1407 p = partition_new();
1408 if (!p)
1409 return log_oom();
1410
1411 p->definition_path = strdup(*f);
1412 if (!p->definition_path)
1413 return log_oom();
1414
1415 r = partition_read_definition(p, *f);
1416 if (r < 0)
1417 return r;
1418
1419 LIST_INSERT_AFTER(partitions, context->partitions, last, p);
1420 last = TAKE_PTR(p);
1421 context->n_partitions++;
1422 }
1423
1424 return 0;
1425}
1426
fd421c4a
ZJS
1427DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_context*, fdisk_unref_context, NULL);
1428DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_partition*, fdisk_unref_partition, NULL);
1429DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_parttype*, fdisk_unref_parttype, NULL);
1430DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_table*, fdisk_unref_table, NULL);
e594a3b1
LP
1431
1432static int determine_current_padding(
1433 struct fdisk_context *c,
1434 struct fdisk_table *t,
1435 struct fdisk_partition *p,
1436 uint64_t *ret) {
1437
1438 size_t n_partitions;
1439 uint64_t offset, next = UINT64_MAX;
1440
1441 assert(c);
1442 assert(t);
1443 assert(p);
1444
1445 if (!fdisk_partition_has_end(p))
1446 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Partition has no end!");
1447
1448 offset = fdisk_partition_get_end(p);
1449 assert(offset < UINT64_MAX / 512);
1450 offset *= 512;
1451
1452 n_partitions = fdisk_table_get_nents(t);
1453 for (size_t i = 0; i < n_partitions; i++) {
1454 struct fdisk_partition *q;
1455 uint64_t start;
1456
1457 q = fdisk_table_get_partition(t, i);
1458 if (!q)
1459 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read partition metadata: %m");
1460
1461 if (fdisk_partition_is_used(q) <= 0)
1462 continue;
1463
1464 if (!fdisk_partition_has_start(q))
1465 continue;
1466
1467 start = fdisk_partition_get_start(q);
1468 assert(start < UINT64_MAX / 512);
1469 start *= 512;
1470
1471 if (start >= offset && (next == UINT64_MAX || next > start))
1472 next = start;
1473 }
1474
1475 if (next == UINT64_MAX) {
1476 /* No later partition? In that case check the end of the usable area */
1477 next = fdisk_get_last_lba(c);
1478 assert(next < UINT64_MAX);
1479 next++; /* The last LBA is one sector before the end */
1480
1481 assert(next < UINT64_MAX / 512);
1482 next *= 512;
1483
1484 if (offset > next)
1485 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Partition end beyond disk end.");
1486 }
1487
1488 assert(next >= offset);
1489 offset = round_up_size(offset, 4096);
1490 next = round_down_size(next, 4096);
1491
1492 if (next >= offset) /* Check again, rounding might have fucked things up */
1493 *ret = next - offset;
1494 else
1495 *ret = 0;
1496
1497 return 0;
1498}
1499
1500static int fdisk_ask_cb(struct fdisk_context *c, struct fdisk_ask *ask, void *data) {
1501 _cleanup_free_ char *ids = NULL;
1502 int r;
1503
1504 if (fdisk_ask_get_type(ask) != FDISK_ASKTYPE_STRING)
1505 return -EINVAL;
1506
1507 ids = new(char, ID128_UUID_STRING_MAX);
1508 if (!ids)
1509 return -ENOMEM;
1510
1511 r = fdisk_ask_string_set_result(ask, id128_to_uuid_string(*(sd_id128_t*) data, ids));
1512 if (r < 0)
1513 return r;
1514
1515 TAKE_PTR(ids);
1516 return 0;
1517}
1518
1519static int fdisk_set_disklabel_id_by_uuid(struct fdisk_context *c, sd_id128_t id) {
1520 int r;
1521
1522 r = fdisk_set_ask(c, fdisk_ask_cb, &id);
1523 if (r < 0)
1524 return r;
1525
1526 r = fdisk_set_disklabel_id(c);
1527 if (r < 0)
1528 return r;
1529
1530 return fdisk_set_ask(c, NULL, NULL);
1531}
1532
53171c04 1533static int derive_uuid(sd_id128_t base, const char *token, sd_id128_t *ret) {
e594a3b1
LP
1534 union {
1535 unsigned char md[SHA256_DIGEST_LENGTH];
1536 sd_id128_t id;
1537 } result;
1538
53171c04 1539 assert(token);
e594a3b1
LP
1540 assert(ret);
1541
53171c04
LP
1542 /* Derive a new UUID from the specified UUID in a stable and reasonably safe way. Specifically, we
1543 * calculate the HMAC-SHA256 of the specified token string, keyed by the supplied base (typically the
1544 * machine ID). We use the machine ID as key (and not as cleartext!) of the HMAC operation since it's
1545 * the machine ID we don't want to leak. */
e594a3b1
LP
1546
1547 if (!HMAC(EVP_sha256(),
53171c04
LP
1548 &base, sizeof(base),
1549 (const unsigned char*) token, strlen(token),
e594a3b1
LP
1550 result.md, NULL))
1551 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "HMAC-SHA256 calculation failed.");
1552
1553 /* Take the first half, mark it as v4 UUID */
1554 assert_cc(sizeof(result.md) == sizeof(result.id) * 2);
1555 *ret = id128_make_v4_uuid(result.id);
1556 return 0;
1557}
1558
a26f4a49
LP
1559static int context_load_partition_table(
1560 Context *context,
1561 const char *node,
1562 int *backing_fd) {
1563
e594a3b1
LP
1564 _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
1565 _cleanup_(fdisk_unref_tablep) struct fdisk_table *t = NULL;
1566 uint64_t left_boundary = UINT64_MAX, first_lba, last_lba, nsectors;
1567 _cleanup_free_ char *disk_uuid_string = NULL;
1568 bool from_scratch = false;
1569 sd_id128_t disk_uuid;
1570 size_t n_partitions;
1571 int r;
1572
1573 assert(context);
1574 assert(node);
a26f4a49 1575 assert(backing_fd);
170c9823
LP
1576 assert(!context->fdisk_context);
1577 assert(!context->free_areas);
1578 assert(context->start == UINT64_MAX);
1579 assert(context->end == UINT64_MAX);
1580 assert(context->total == UINT64_MAX);
e594a3b1
LP
1581
1582 c = fdisk_new_context();
1583 if (!c)
1584 return log_oom();
1585
a26f4a49
LP
1586 /* libfdisk doesn't have an API to operate on arbitrary fds, hence reopen the fd going via the
1587 * /proc/self/fd/ magic path if we have an existing fd. Open the original file otherwise. */
1588 if (*backing_fd < 0)
1589 r = fdisk_assign_device(c, node, arg_dry_run);
ddb6eeaf
LP
1590 else
1591 r = fdisk_assign_device(c, FORMAT_PROC_FD_PATH(*backing_fd), arg_dry_run);
170c9823
LP
1592 if (r == -EINVAL && arg_size_auto) {
1593 struct stat st;
1594
1595 /* libfdisk returns EINVAL if opening a file of size zero. Let's check for that, and accept
1596 * it if automatic sizing is requested. */
1597
1598 if (*backing_fd < 0)
1599 r = stat(node, &st);
1600 else
1601 r = fstat(*backing_fd, &st);
1602 if (r < 0)
1603 return log_error_errno(errno, "Failed to stat block device '%s': %m", node);
1604
1605 if (S_ISREG(st.st_mode) && st.st_size == 0)
1606 return /* from_scratch = */ true;
1607
1608 r = -EINVAL;
1609 }
e594a3b1 1610 if (r < 0)
a26f4a49
LP
1611 return log_error_errno(r, "Failed to open device '%s': %m", node);
1612
1613 if (*backing_fd < 0) {
1614 /* If we have no fd referencing the device yet, make a copy of the fd now, so that we have one */
1615 *backing_fd = fcntl(fdisk_get_devfd(c), F_DUPFD_CLOEXEC, 3);
1616 if (*backing_fd < 0)
1617 return log_error_errno(errno, "Failed to duplicate fdisk fd: %m");
1618 }
e594a3b1
LP
1619
1620 /* Tell udev not to interfere while we are processing the device */
1621 if (flock(fdisk_get_devfd(c), arg_dry_run ? LOCK_SH : LOCK_EX) < 0)
1622 return log_error_errno(errno, "Failed to lock block device: %m");
1623
1624 switch (arg_empty) {
1625
1626 case EMPTY_REFUSE:
1627 /* Refuse empty disks, insist on an existing GPT partition table */
1628 if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
1629 return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has no GPT disk label, not repartitioning.", node);
1630
1631 break;
1632
1633 case EMPTY_REQUIRE:
1634 /* Require an empty disk, refuse any existing partition table */
1635 r = fdisk_has_label(c);
1636 if (r < 0)
1637 return log_error_errno(r, "Failed to determine whether disk %s has a disk label: %m", node);
1638 if (r > 0)
1639 return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s already has a disk label, refusing.", node);
1640
1641 from_scratch = true;
1642 break;
1643
1644 case EMPTY_ALLOW:
1645 /* Allow both an empty disk and an existing partition table, but only GPT */
1646 r = fdisk_has_label(c);
1647 if (r < 0)
1648 return log_error_errno(r, "Failed to determine whether disk %s has a disk label: %m", node);
1649 if (r > 0) {
1650 if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
1651 return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has non-GPT disk label, not repartitioning.", node);
1652 } else
1653 from_scratch = true;
1654
1655 break;
1656
1657 case EMPTY_FORCE:
a26f4a49 1658 case EMPTY_CREATE:
e594a3b1
LP
1659 /* Always reinitiaize the disk, don't consider what there was on the disk before */
1660 from_scratch = true;
1661 break;
1662 }
1663
1664 if (from_scratch) {
e594a3b1
LP
1665 r = fdisk_create_disklabel(c, "gpt");
1666 if (r < 0)
1667 return log_error_errno(r, "Failed to create GPT disk label: %m");
1668
53171c04 1669 r = derive_uuid(context->seed, "disk-uuid", &disk_uuid);
e594a3b1
LP
1670 if (r < 0)
1671 return log_error_errno(r, "Failed to acquire disk GPT uuid: %m");
1672
1673 r = fdisk_set_disklabel_id_by_uuid(c, disk_uuid);
1674 if (r < 0)
1675 return log_error_errno(r, "Failed to set GPT disk label: %m");
1676
1677 goto add_initial_free_area;
1678 }
1679
1680 r = fdisk_get_disklabel_id(c, &disk_uuid_string);
1681 if (r < 0)
1682 return log_error_errno(r, "Failed to get current GPT disk label UUID: %m");
1683
1684 r = sd_id128_from_string(disk_uuid_string, &disk_uuid);
1685 if (r < 0)
1686 return log_error_errno(r, "Failed to parse current GPT disk label UUID: %m");
1687
1688 if (sd_id128_is_null(disk_uuid)) {
53171c04 1689 r = derive_uuid(context->seed, "disk-uuid", &disk_uuid);
e594a3b1
LP
1690 if (r < 0)
1691 return log_error_errno(r, "Failed to acquire disk GPT uuid: %m");
1692
1693 r = fdisk_set_disklabel_id(c);
1694 if (r < 0)
1695 return log_error_errno(r, "Failed to set GPT disk label: %m");
1696 }
1697
1698 r = fdisk_get_partitions(c, &t);
1699 if (r < 0)
1700 return log_error_errno(r, "Failed to acquire partition table: %m");
1701
1702 n_partitions = fdisk_table_get_nents(t);
1703 for (size_t i = 0; i < n_partitions; i++) {
1704 _cleanup_free_ char *label_copy = NULL;
1705 Partition *pp, *last = NULL;
1706 struct fdisk_partition *p;
1707 struct fdisk_parttype *pt;
1708 const char *pts, *ids, *label;
1709 uint64_t sz, start;
1710 bool found = false;
1711 sd_id128_t ptid, id;
1712 size_t partno;
1713
1714 p = fdisk_table_get_partition(t, i);
1715 if (!p)
1716 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read partition metadata: %m");
1717
1718 if (fdisk_partition_is_used(p) <= 0)
1719 continue;
1720
1721 if (fdisk_partition_has_start(p) <= 0 ||
1722 fdisk_partition_has_size(p) <= 0 ||
1723 fdisk_partition_has_partno(p) <= 0)
1724 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Found a partition without a position, size or number.");
1725
1726 pt = fdisk_partition_get_type(p);
1727 if (!pt)
1728 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to acquire type of partition: %m");
1729
1730 pts = fdisk_parttype_get_string(pt);
1731 if (!pts)
1732 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to acquire type of partition as string: %m");
1733
1734 r = sd_id128_from_string(pts, &ptid);
1735 if (r < 0)
1736 return log_error_errno(r, "Failed to parse partition type UUID %s: %m", pts);
1737
1738 ids = fdisk_partition_get_uuid(p);
1739 if (!ids)
1740 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Found a partition without a UUID.");
1741
1742 r = sd_id128_from_string(ids, &id);
1743 if (r < 0)
1744 return log_error_errno(r, "Failed to parse partition UUID %s: %m", ids);
1745
1746 label = fdisk_partition_get_name(p);
1747 if (!isempty(label)) {
1748 label_copy = strdup(label);
1749 if (!label_copy)
1750 return log_oom();
1751 }
1752
1753 sz = fdisk_partition_get_size(p);
1754 assert_se(sz <= UINT64_MAX/512);
1755 sz *= 512;
1756
1757 start = fdisk_partition_get_start(p);
1758 assert_se(start <= UINT64_MAX/512);
1759 start *= 512;
1760
1761 partno = fdisk_partition_get_partno(p);
1762
1763 if (left_boundary == UINT64_MAX || left_boundary > start)
1764 left_boundary = start;
1765
1766 /* Assign this existing partition to the first partition of the right type that doesn't have
1767 * an existing one assigned yet. */
1768 LIST_FOREACH(partitions, pp, context->partitions) {
1769 last = pp;
1770
1771 if (!sd_id128_equal(pp->type_uuid, ptid))
1772 continue;
1773
1774 if (!pp->current_partition) {
1775 pp->current_uuid = id;
1776 pp->current_size = sz;
1777 pp->offset = start;
1778 pp->partno = partno;
1779 pp->current_label = TAKE_PTR(label_copy);
1780
1781 pp->current_partition = p;
1782 fdisk_ref_partition(p);
1783
1784 r = determine_current_padding(c, t, p, &pp->current_padding);
1785 if (r < 0)
1786 return r;
1787
1788 if (pp->current_padding > 0) {
1789 r = context_add_free_area(context, pp->current_padding, pp);
1790 if (r < 0)
1791 return r;
1792 }
1793
1794 found = true;
1795 break;
1796 }
1797 }
1798
1799 /* If we have no matching definition, create a new one. */
1800 if (!found) {
1801 _cleanup_(partition_freep) Partition *np = NULL;
1802
1803 np = partition_new();
1804 if (!np)
1805 return log_oom();
1806
1807 np->current_uuid = id;
1808 np->type_uuid = ptid;
1809 np->current_size = sz;
1810 np->offset = start;
1811 np->partno = partno;
1812 np->current_label = TAKE_PTR(label_copy);
1813
1814 np->current_partition = p;
1815 fdisk_ref_partition(p);
1816
1817 r = determine_current_padding(c, t, p, &np->current_padding);
1818 if (r < 0)
1819 return r;
1820
1821 if (np->current_padding > 0) {
1822 r = context_add_free_area(context, np->current_padding, np);
1823 if (r < 0)
1824 return r;
1825 }
1826
1827 LIST_INSERT_AFTER(partitions, context->partitions, last, TAKE_PTR(np));
1828 context->n_partitions++;
1829 }
1830 }
1831
1832add_initial_free_area:
1833 nsectors = fdisk_get_nsectors(c);
1834 assert(nsectors <= UINT64_MAX/512);
1835 nsectors *= 512;
1836
1837 first_lba = fdisk_get_first_lba(c);
1838 assert(first_lba <= UINT64_MAX/512);
1839 first_lba *= 512;
1840
1841 last_lba = fdisk_get_last_lba(c);
1842 assert(last_lba < UINT64_MAX);
1843 last_lba++;
1844 assert(last_lba <= UINT64_MAX/512);
1845 last_lba *= 512;
1846
1847 assert(last_lba >= first_lba);
1848
1849 if (left_boundary == UINT64_MAX) {
1850 /* No partitions at all? Then the whole disk is up for grabs. */
1851
1852 first_lba = round_up_size(first_lba, 4096);
1853 last_lba = round_down_size(last_lba, 4096);
1854
1855 if (last_lba > first_lba) {
1856 r = context_add_free_area(context, last_lba - first_lba, NULL);
1857 if (r < 0)
1858 return r;
1859 }
1860 } else {
1861 /* Add space left of first partition */
1862 assert(left_boundary >= first_lba);
1863
1864 first_lba = round_up_size(first_lba, 4096);
1865 left_boundary = round_down_size(left_boundary, 4096);
1866 last_lba = round_down_size(last_lba, 4096);
1867
1868 if (left_boundary > first_lba) {
1869 r = context_add_free_area(context, left_boundary - first_lba, NULL);
1870 if (r < 0)
1871 return r;
1872 }
1873 }
1874
1875 context->start = first_lba;
1876 context->end = last_lba;
1877 context->total = nsectors;
1878 context->fdisk_context = TAKE_PTR(c);
1879
1880 return from_scratch;
1881}
1882
1883static void context_unload_partition_table(Context *context) {
1884 Partition *p, *next;
1885
1886 assert(context);
1887
1888 LIST_FOREACH_SAFE(partitions, p, next, context->partitions) {
1889
1890 /* Entirely remove partitions that have no configuration */
1891 if (PARTITION_IS_FOREIGN(p)) {
1892 partition_unlink_and_free(context, p);
1893 continue;
1894 }
1895
1896 /* Otherwise drop all data we read off the block device and everything we might have
1897 * calculated based on it */
1898
1899 p->dropped = false;
1900 p->current_size = UINT64_MAX;
1901 p->new_size = UINT64_MAX;
1902 p->current_padding = UINT64_MAX;
1903 p->new_padding = UINT64_MAX;
1904 p->partno = UINT64_MAX;
1905 p->offset = UINT64_MAX;
1906
1907 if (p->current_partition) {
1908 fdisk_unref_partition(p->current_partition);
1909 p->current_partition = NULL;
1910 }
1911
1912 if (p->new_partition) {
1913 fdisk_unref_partition(p->new_partition);
1914 p->new_partition = NULL;
1915 }
1916
1917 p->padding_area = NULL;
1918 p->allocated_to_area = NULL;
1919
15d43e30
LP
1920 p->current_uuid = SD_ID128_NULL;
1921 p->current_label = mfree(p->current_label);
e594a3b1
LP
1922 }
1923
1924 context->start = UINT64_MAX;
1925 context->end = UINT64_MAX;
1926 context->total = UINT64_MAX;
1927
1928 if (context->fdisk_context) {
1929 fdisk_unref_context(context->fdisk_context);
1930 context->fdisk_context = NULL;
1931 }
1932
1933 context_free_free_areas(context);
1934}
1935
1936static int format_size_change(uint64_t from, uint64_t to, char **ret) {
2b59bf51 1937 char *t;
e594a3b1
LP
1938
1939 if (from != UINT64_MAX) {
1940 if (from == to || to == UINT64_MAX)
2b59bf51 1941 t = strdup(FORMAT_BYTES(from));
e594a3b1 1942 else
2b59bf51 1943 t = strjoin(FORMAT_BYTES(from), " ", special_glyph(SPECIAL_GLYPH_ARROW), " ", FORMAT_BYTES(to));
e594a3b1 1944 } else if (to != UINT64_MAX)
2b59bf51 1945 t = strjoin(special_glyph(SPECIAL_GLYPH_ARROW), " ", FORMAT_BYTES(to));
e594a3b1
LP
1946 else {
1947 *ret = NULL;
1948 return 0;
1949 }
1950
2b59bf51 1951 if (!t)
e594a3b1
LP
1952 return log_oom();
1953
2b59bf51 1954 *ret = t;
e594a3b1
LP
1955 return 1;
1956}
1957
1958static const char *partition_label(const Partition *p) {
1959 assert(p);
1960
1961 if (p->new_label)
1962 return p->new_label;
1963
1964 if (p->current_label)
1965 return p->current_label;
1966
1967 return gpt_partition_type_uuid_to_string(p->type_uuid);
1968}
1969
1970static int context_dump_partitions(Context *context, const char *node) {
1971 _cleanup_(table_unrefp) Table *t = NULL;
1972 uint64_t sum_padding = 0, sum_size = 0;
1973 Partition *p;
1974 int r;
1975
6a01ea4a 1976 if ((arg_json_format_flags & JSON_FORMAT_OFF) && context->n_partitions == 0) {
a015fbe7
TH
1977 log_info("Empty partition table.");
1978 return 0;
1979 }
1980
1981 t = table_new("type", "label", "uuid", "file", "node", "offset", "old size", "raw size", "size", "old padding", "raw padding", "padding", "activity");
e594a3b1
LP
1982 if (!t)
1983 return log_oom();
1984
a015fbe7 1985 if (!DEBUG_LOGGING) {
6a01ea4a 1986 if (arg_json_format_flags & JSON_FORMAT_OFF)
a015fbe7 1987 (void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4,
ef1e0b9a 1988 (size_t) 8, (size_t) 11);
a015fbe7
TH
1989 else
1990 (void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4,
ef1e0b9a 1991 (size_t) 5, (size_t) 6, (size_t) 7, (size_t) 9, (size_t) 10, (size_t) 12);
a015fbe7 1992 }
e594a3b1 1993
e594a3b1 1994 (void) table_set_align_percent(t, table_get_cell(t, 0, 5), 100);
9c07c9ec
LP
1995 (void) table_set_align_percent(t, table_get_cell(t, 0, 6), 100);
1996 (void) table_set_align_percent(t, table_get_cell(t, 0, 7), 100);
1997 (void) table_set_align_percent(t, table_get_cell(t, 0, 8), 100);
1998 (void) table_set_align_percent(t, table_get_cell(t, 0, 9), 100);
1999 (void) table_set_align_percent(t, table_get_cell(t, 0, 10), 100);
2000 (void) table_set_align_percent(t, table_get_cell(t, 0, 11), 100);
e594a3b1
LP
2001
2002 LIST_FOREACH(partitions, p, context->partitions) {
2003 _cleanup_free_ char *size_change = NULL, *padding_change = NULL, *partname = NULL;
2004 char uuid_buffer[ID128_UUID_STRING_MAX];
a015fbe7 2005 const char *label, *activity = NULL;
e594a3b1
LP
2006
2007 if (p->dropped)
2008 continue;
2009
a015fbe7
TH
2010 if (p->current_size == UINT64_MAX)
2011 activity = "create";
2012 else if (p->current_size != p->new_size)
2013 activity = "resize";
2014
e594a3b1
LP
2015 label = partition_label(p);
2016 partname = p->partno != UINT64_MAX ? fdisk_partname(node, p->partno+1) : NULL;
2017
2018 r = format_size_change(p->current_size, p->new_size, &size_change);
2019 if (r < 0)
2020 return r;
2021
2022 r = format_size_change(p->current_padding, p->new_padding, &padding_change);
2023 if (r < 0)
2024 return r;
2025
2026 if (p->new_size != UINT64_MAX)
2027 sum_size += p->new_size;
2028 if (p->new_padding != UINT64_MAX)
2029 sum_padding += p->new_padding;
2030
2031 r = table_add_many(
2032 t,
2033 TABLE_STRING, gpt_partition_type_uuid_to_string_harder(p->type_uuid, uuid_buffer),
be9ce018 2034 TABLE_STRING, empty_to_null(label) ?: "-", TABLE_SET_COLOR, empty_to_null(label) ? NULL : ansi_grey(),
e594a3b1
LP
2035 TABLE_UUID, sd_id128_is_null(p->new_uuid) ? p->current_uuid : p->new_uuid,
2036 TABLE_STRING, p->definition_path ? basename(p->definition_path) : "-", TABLE_SET_COLOR, p->definition_path ? NULL : ansi_grey(),
a015fbe7 2037 TABLE_STRING, partname ?: "-", TABLE_SET_COLOR, partname ? NULL : ansi_highlight(),
e594a3b1 2038 TABLE_UINT64, p->offset,
a015fbe7 2039 TABLE_UINT64, p->current_size == UINT64_MAX ? 0 : p->current_size,
e594a3b1
LP
2040 TABLE_UINT64, p->new_size,
2041 TABLE_STRING, size_change, TABLE_SET_COLOR, !p->partitions_next && sum_size > 0 ? ansi_underline() : NULL,
a015fbe7 2042 TABLE_UINT64, p->current_padding == UINT64_MAX ? 0 : p->current_padding,
e594a3b1 2043 TABLE_UINT64, p->new_padding,
a015fbe7 2044 TABLE_STRING, padding_change, TABLE_SET_COLOR, !p->partitions_next && sum_padding > 0 ? ansi_underline() : NULL,
05a2166a 2045 TABLE_STRING, activity ?: "unchanged");
e594a3b1 2046 if (r < 0)
f987a261 2047 return table_log_add_error(r);
e594a3b1
LP
2048 }
2049
6a01ea4a 2050 if ((arg_json_format_flags & JSON_FORMAT_OFF) && (sum_padding > 0 || sum_size > 0)) {
e594a3b1
LP
2051 const char *a, *b;
2052
2b59bf51
ZJS
2053 a = strjoina(special_glyph(SPECIAL_GLYPH_SIGMA), " = ", FORMAT_BYTES(sum_size));
2054 b = strjoina(special_glyph(SPECIAL_GLYPH_SIGMA), " = ", FORMAT_BYTES(sum_padding));
e594a3b1
LP
2055
2056 r = table_add_many(
2057 t,
2058 TABLE_EMPTY,
2059 TABLE_EMPTY,
2060 TABLE_EMPTY,
2061 TABLE_EMPTY,
2062 TABLE_EMPTY,
2063 TABLE_EMPTY,
2064 TABLE_EMPTY,
a015fbe7 2065 TABLE_EMPTY,
e594a3b1
LP
2066 TABLE_STRING, a,
2067 TABLE_EMPTY,
a015fbe7
TH
2068 TABLE_EMPTY,
2069 TABLE_STRING, b,
2070 TABLE_EMPTY);
e594a3b1 2071 if (r < 0)
f987a261 2072 return table_log_add_error(r);
e594a3b1
LP
2073 }
2074
896e678b 2075 return table_print_with_pager(t, arg_json_format_flags, arg_pager_flags, arg_legend);
e594a3b1
LP
2076}
2077
2078static void context_bar_char_process_partition(
2079 Context *context,
2080 Partition *bar[],
2081 size_t n,
2082 Partition *p,
2083 size_t *ret_start) {
2084
2085 uint64_t from, to, total;
2086 size_t x, y;
2087
2088 assert(context);
2089 assert(bar);
2090 assert(n > 0);
2091 assert(p);
2092
2093 if (p->dropped)
2094 return;
2095
2096 assert(p->offset != UINT64_MAX);
2097 assert(p->new_size != UINT64_MAX);
2098
2099 from = p->offset;
2100 to = from + p->new_size;
2101
2102 assert(context->end >= context->start);
2103 total = context->end - context->start;
2104
2105 assert(from >= context->start);
2106 assert(from <= context->end);
2107 x = (from - context->start) * n / total;
2108
2109 assert(to >= context->start);
2110 assert(to <= context->end);
2111 y = (to - context->start) * n / total;
2112
2113 assert(x <= y);
2114 assert(y <= n);
2115
2116 for (size_t i = x; i < y; i++)
2117 bar[i] = p;
2118
2119 *ret_start = x;
2120}
2121
2122static int partition_hint(const Partition *p, const char *node, char **ret) {
2123 _cleanup_free_ char *buf = NULL;
e594a3b1
LP
2124 const char *label;
2125 sd_id128_t id;
2126
2127 /* Tries really hard to find a suitable description for this partition */
2128
2129 if (p->definition_path) {
2130 buf = strdup(basename(p->definition_path));
2131 goto done;
2132 }
2133
2134 label = partition_label(p);
2135 if (!isempty(label)) {
2136 buf = strdup(label);
2137 goto done;
2138 }
2139
2140 if (p->partno != UINT64_MAX) {
2141 buf = fdisk_partname(node, p->partno+1);
2142 goto done;
2143 }
2144
2145 if (!sd_id128_is_null(p->new_uuid))
2146 id = p->new_uuid;
2147 else if (!sd_id128_is_null(p->current_uuid))
2148 id = p->current_uuid;
2149 else
2150 id = p->type_uuid;
2151
85b55869 2152 buf = strdup(ID128_TO_UUID_STRING(id));
e594a3b1
LP
2153
2154done:
2155 if (!buf)
2156 return -ENOMEM;
2157
2158 *ret = TAKE_PTR(buf);
2159 return 0;
2160}
2161
2162static int context_dump_partition_bar(Context *context, const char *node) {
2163 _cleanup_free_ Partition **bar = NULL;
2164 _cleanup_free_ size_t *start_array = NULL;
2165 Partition *p, *last = NULL;
2166 bool z = false;
2167 size_t c, j = 0;
2168
f391597c 2169 assert_se((c = columns()) >= 2);
e594a3b1
LP
2170 c -= 2; /* We do not use the leftmost and rightmost character cell */
2171
2172 bar = new0(Partition*, c);
2173 if (!bar)
2174 return log_oom();
2175
2176 start_array = new(size_t, context->n_partitions);
2177 if (!start_array)
2178 return log_oom();
2179
2180 LIST_FOREACH(partitions, p, context->partitions)
2181 context_bar_char_process_partition(context, bar, c, p, start_array + j++);
2182
2183 putc(' ', stdout);
2184
2185 for (size_t i = 0; i < c; i++) {
2186 if (bar[i]) {
2187 if (last != bar[i])
2188 z = !z;
2189
2190 fputs(z ? ansi_green() : ansi_yellow(), stdout);
2191 fputs(special_glyph(SPECIAL_GLYPH_DARK_SHADE), stdout);
2192 } else {
2193 fputs(ansi_normal(), stdout);
2194 fputs(special_glyph(SPECIAL_GLYPH_LIGHT_SHADE), stdout);
2195 }
2196
2197 last = bar[i];
2198 }
2199
2200 fputs(ansi_normal(), stdout);
2201 putc('\n', stdout);
2202
2203 for (size_t i = 0; i < context->n_partitions; i++) {
2204 _cleanup_free_ char **line = NULL;
2205
2206 line = new0(char*, c);
2207 if (!line)
2208 return log_oom();
2209
2210 j = 0;
2211 LIST_FOREACH(partitions, p, context->partitions) {
2212 _cleanup_free_ char *d = NULL;
2213 j++;
2214
2215 if (i < context->n_partitions - j) {
2216
2217 if (line[start_array[j-1]]) {
2218 const char *e;
2219
2220 /* Upgrade final corner to the right with a branch to the right */
2221 e = startswith(line[start_array[j-1]], special_glyph(SPECIAL_GLYPH_TREE_RIGHT));
2222 if (e) {
2223 d = strjoin(special_glyph(SPECIAL_GLYPH_TREE_BRANCH), e);
2224 if (!d)
2225 return log_oom();
2226 }
2227 }
2228
2229 if (!d) {
2230 d = strdup(special_glyph(SPECIAL_GLYPH_TREE_VERTICAL));
2231 if (!d)
2232 return log_oom();
2233 }
2234
2235 } else if (i == context->n_partitions - j) {
2236 _cleanup_free_ char *hint = NULL;
2237
2238 (void) partition_hint(p, node, &hint);
2239
2240 if (streq_ptr(line[start_array[j-1]], special_glyph(SPECIAL_GLYPH_TREE_VERTICAL)))
2241 d = strjoin(special_glyph(SPECIAL_GLYPH_TREE_BRANCH), " ", strna(hint));
2242 else
2243 d = strjoin(special_glyph(SPECIAL_GLYPH_TREE_RIGHT), " ", strna(hint));
2244
2245 if (!d)
2246 return log_oom();
2247 }
2248
2249 if (d)
2250 free_and_replace(line[start_array[j-1]], d);
2251 }
2252
2253 putc(' ', stdout);
2254
2255 j = 0;
2256 while (j < c) {
2257 if (line[j]) {
2258 fputs(line[j], stdout);
2259 j += utf8_console_width(line[j]);
2260 } else {
2261 putc(' ', stdout);
2262 j++;
2263 }
2264 }
2265
2266 putc('\n', stdout);
2267
2268 for (j = 0; j < c; j++)
2269 free(line[j]);
2270 }
2271
2272 return 0;
2273}
2274
2275static bool context_changed(const Context *context) {
2276 Partition *p;
2277
2278 LIST_FOREACH(partitions, p, context->partitions) {
2279 if (p->dropped)
2280 continue;
2281
2282 if (p->allocated_to_area)
2283 return true;
2284
2285 if (p->new_size != p->current_size)
2286 return true;
2287 }
2288
2289 return false;
2290}
2291
81873a6b 2292static int context_wipe_range(Context *context, uint64_t offset, uint64_t size) {
e594a3b1
LP
2293 _cleanup_(blkid_free_probep) blkid_probe probe = NULL;
2294 int r;
2295
2296 assert(context);
81873a6b
LP
2297 assert(offset != UINT64_MAX);
2298 assert(size != UINT64_MAX);
e594a3b1
LP
2299
2300 probe = blkid_new_probe();
2301 if (!probe)
2302 return log_oom();
2303
e594a3b1 2304 errno = 0;
81873a6b 2305 r = blkid_probe_set_device(probe, fdisk_get_devfd(context->fdisk_context), offset, size);
e594a3b1 2306 if (r < 0)
81873a6b 2307 return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to allocate device probe for wiping.");
e594a3b1
LP
2308
2309 errno = 0;
2310 if (blkid_probe_enable_superblocks(probe, true) < 0 ||
2311 blkid_probe_set_superblocks_flags(probe, BLKID_SUBLKS_MAGIC|BLKID_SUBLKS_BADCSUM) < 0 ||
2312 blkid_probe_enable_partitions(probe, true) < 0 ||
2313 blkid_probe_set_partitions_flags(probe, BLKID_PARTS_MAGIC) < 0)
81873a6b 2314 return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to enable superblock and partition probing.");
e594a3b1
LP
2315
2316 for (;;) {
2317 errno = 0;
2318 r = blkid_do_probe(probe);
2319 if (r < 0)
2320 return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe for file systems.");
2321 if (r > 0)
2322 break;
2323
2324 errno = 0;
2325 if (blkid_do_wipe(probe, false) < 0)
2326 return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to wipe file system signature.");
2327 }
2328
e594a3b1
LP
2329 return 0;
2330}
2331
81873a6b
LP
2332static int context_wipe_partition(Context *context, Partition *p) {
2333 int r;
2334
2335 assert(context);
2336 assert(p);
2337 assert(!PARTITION_EXISTS(p)); /* Safety check: never wipe existing partitions */
2338
2339 assert(p->offset != UINT64_MAX);
2340 assert(p->new_size != UINT64_MAX);
2341
2342 r = context_wipe_range(context, p->offset, p->new_size);
2343 if (r < 0)
2344 return r;
2345
2346 log_info("Successfully wiped file system signatures from future partition %" PRIu64 ".", p->partno);
2347 return 0;
2348}
2349
2350static int context_discard_range(
2351 Context *context,
2352 uint64_t offset,
2353 uint64_t size) {
2354
e594a3b1
LP
2355 struct stat st;
2356 int fd;
2357
2358 assert(context);
2359 assert(offset != UINT64_MAX);
2360 assert(size != UINT64_MAX);
2361
2362 if (size <= 0)
2363 return 0;
2364
a26f4a49 2365 assert_se((fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
e594a3b1
LP
2366
2367 if (fstat(fd, &st) < 0)
2368 return -errno;
2369
2370 if (S_ISREG(st.st_mode)) {
2371 if (fallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, offset, size) < 0) {
2372 if (ERRNO_IS_NOT_SUPPORTED(errno))
2373 return -EOPNOTSUPP;
2374
2375 return -errno;
2376 }
2377
2378 return 1;
2379 }
2380
2381 if (S_ISBLK(st.st_mode)) {
2382 uint64_t range[2], end;
2383
2384 range[0] = round_up_size(offset, 512);
2385
55d38014
LP
2386 if (offset > UINT64_MAX - size)
2387 return -ERANGE;
2388
e594a3b1
LP
2389 end = offset + size;
2390 if (end <= range[0])
2391 return 0;
2392
2393 range[1] = round_down_size(end - range[0], 512);
2394 if (range[1] <= 0)
2395 return 0;
2396
2397 if (ioctl(fd, BLKDISCARD, range) < 0) {
2398 if (ERRNO_IS_NOT_SUPPORTED(errno))
2399 return -EOPNOTSUPP;
2400
2401 return -errno;
2402 }
2403
2404 return 1;
2405 }
2406
2407 return -EOPNOTSUPP;
2408}
2409
2410static int context_discard_partition(Context *context, Partition *p) {
2411 int r;
2412
2413 assert(context);
2414 assert(p);
2415
2416 assert(p->offset != UINT64_MAX);
2417 assert(p->new_size != UINT64_MAX);
2418 assert(!PARTITION_EXISTS(p)); /* Safety check: never discard existing partitions */
2419
2420 if (!arg_discard)
2421 return 0;
2422
2423 r = context_discard_range(context, p->offset, p->new_size);
2424 if (r == -EOPNOTSUPP) {
5b5109e2 2425 log_info("Storage does not support discard, not discarding data in future partition %" PRIu64 ".", p->partno);
e594a3b1
LP
2426 return 0;
2427 }
22163eb5
LP
2428 if (r == -EBUSY) {
2429 /* Let's handle this gracefully: https://bugzilla.kernel.org/show_bug.cgi?id=211167 */
2430 log_info("Block device is busy, not discarding partition %" PRIu64 " because it probably is mounted.", p->partno);
2431 return 0;
2432 }
e594a3b1
LP
2433 if (r == 0) {
2434 log_info("Partition %" PRIu64 " too short for discard, skipping.", p->partno);
2435 return 0;
2436 }
2437 if (r < 0)
5b5109e2 2438 return log_error_errno(r, "Failed to discard data for future partition %" PRIu64 ".", p->partno);
e594a3b1 2439
5b5109e2 2440 log_info("Successfully discarded data from future partition %" PRIu64 ".", p->partno);
e594a3b1
LP
2441 return 1;
2442}
2443
2444static int context_discard_gap_after(Context *context, Partition *p) {
2445 uint64_t gap, next = UINT64_MAX;
2446 Partition *q;
2447 int r;
2448
2449 assert(context);
2450 assert(!p || (p->offset != UINT64_MAX && p->new_size != UINT64_MAX));
2451
2452 if (p)
2453 gap = p->offset + p->new_size;
2454 else
2455 gap = context->start;
2456
2457 LIST_FOREACH(partitions, q, context->partitions) {
2458 if (q->dropped)
2459 continue;
2460
2461 assert(q->offset != UINT64_MAX);
2462 assert(q->new_size != UINT64_MAX);
2463
2464 if (q->offset < gap)
2465 continue;
2466
2467 if (next == UINT64_MAX || q->offset < next)
2468 next = q->offset;
2469 }
2470
2471 if (next == UINT64_MAX) {
2472 next = context->end;
2473 if (gap > next)
2474 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Partition end beyond disk end.");
2475 }
2476
2477 assert(next >= gap);
2478 r = context_discard_range(context, gap, next - gap);
2479 if (r == -EOPNOTSUPP) {
2480 if (p)
5b5109e2 2481 log_info("Storage does not support discard, not discarding gap after partition %" PRIu64 ".", p->partno);
e594a3b1 2482 else
5b5109e2 2483 log_info("Storage does not support discard, not discarding gap at beginning of disk.");
e594a3b1
LP
2484 return 0;
2485 }
2486 if (r == 0) /* Too short */
2487 return 0;
2488 if (r < 0) {
2489 if (p)
2490 return log_error_errno(r, "Failed to discard gap after partition %" PRIu64 ".", p->partno);
2491 else
2492 return log_error_errno(r, "Failed to discard gap at beginning of disk.");
2493 }
2494
2495 if (p)
2496 log_info("Successfully discarded gap after partition %" PRIu64 ".", p->partno);
2497 else
2498 log_info("Successfully discarded gap at beginning of disk.");
2499
2500 return 0;
2501}
2502
2503static int context_wipe_and_discard(Context *context, bool from_scratch) {
2504 Partition *p;
2505 int r;
2506
2507 assert(context);
2508
2509 /* Wipe and discard the contents of all partitions we are about to create. We skip the discarding if
2510 * we were supposed to start from scratch anyway, as in that case we just discard the whole block
2511 * device in one go early on. */
2512
2513 LIST_FOREACH(partitions, p, context->partitions) {
2514
2515 if (!p->allocated_to_area)
2516 continue;
2517
e594a3b1
LP
2518 r = context_wipe_partition(context, p);
2519 if (r < 0)
2520 return r;
2521
2522 if (!from_scratch) {
f0cb1b95
LP
2523 r = context_discard_partition(context, p);
2524 if (r < 0)
2525 return r;
2526
e594a3b1
LP
2527 r = context_discard_gap_after(context, p);
2528 if (r < 0)
2529 return r;
2530 }
2531 }
2532
2533 if (!from_scratch) {
2534 r = context_discard_gap_after(context, NULL);
2535 if (r < 0)
2536 return r;
2537 }
2538
2539 return 0;
2540}
2541
b9df3536
LP
2542static int partition_encrypt(
2543 Partition *p,
2544 const char *node,
2545 struct crypt_device **ret_cd,
2546 char **ret_volume,
2547 int *ret_fd) {
3dd8ae5c 2548#if HAVE_LIBCRYPTSETUP
0d12936d 2549 _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
b9df3536
LP
2550 _cleanup_(erase_and_freep) void *volume_key = NULL;
2551 _cleanup_free_ char *dm_name = NULL, *vol = NULL;
b9df3536
LP
2552 size_t volume_key_size = 256 / 8;
2553 sd_id128_t uuid;
2554 int r;
2555
2556 assert(p);
889914ef
LP
2557 assert(p->encrypt != ENCRYPT_OFF);
2558
2559 log_debug("Encryption mode for partition %" PRIu64 ": %s", p->partno, encrypt_mode_to_string(p->encrypt));
b9df3536 2560
0d12936d
LP
2561 r = dlopen_cryptsetup();
2562 if (r < 0)
2563 return log_error_errno(r, "libcryptsetup not found, cannot encrypt: %m");
2564
b9df3536
LP
2565 if (asprintf(&dm_name, "luks-repart-%08" PRIx64, random_u64()) < 0)
2566 return log_oom();
2567
2568 if (ret_volume) {
2569 vol = path_join("/dev/mapper/", dm_name);
2570 if (!vol)
2571 return log_oom();
2572 }
2573
2574 r = derive_uuid(p->new_uuid, "luks-uuid", &uuid);
2575 if (r < 0)
2576 return r;
2577
2578 log_info("Encrypting future partition %" PRIu64 "...", p->partno);
2579
2580 volume_key = malloc(volume_key_size);
2581 if (!volume_key)
2582 return log_oom();
2583
2584 r = genuine_random_bytes(volume_key, volume_key_size, RANDOM_BLOCK);
2585 if (r < 0)
2586 return log_error_errno(r, "Failed to generate volume key: %m");
2587
0d12936d 2588 r = sym_crypt_init(&cd, node);
b9df3536
LP
2589 if (r < 0)
2590 return log_error_errno(r, "Failed to allocate libcryptsetup context: %m");
2591
2592 cryptsetup_enable_logging(cd);
2593
0d12936d 2594 r = sym_crypt_format(cd,
b9df3536
LP
2595 CRYPT_LUKS2,
2596 "aes",
2597 "xts-plain64",
85b55869 2598 ID128_TO_UUID_STRING(uuid),
b9df3536
LP
2599 volume_key,
2600 volume_key_size,
2601 &(struct crypt_params_luks2) {
be9ce018 2602 .label = strempty(p->new_label),
b9df3536
LP
2603 .sector_size = 512U,
2604 });
2605 if (r < 0)
2606 return log_error_errno(r, "Failed to LUKS2 format future partition: %m");
2607
889914ef
LP
2608 if (IN_SET(p->encrypt, ENCRYPT_KEY_FILE, ENCRYPT_KEY_FILE_TPM2)) {
2609 r = sym_crypt_keyslot_add_by_volume_key(
2610 cd,
2611 CRYPT_ANY_SLOT,
2612 volume_key,
2613 volume_key_size,
2614 strempty(arg_key),
2615 arg_key_size);
2616 if (r < 0)
2617 return log_error_errno(r, "Failed to add LUKS2 key: %m");
2618 }
2619
2620 if (IN_SET(p->encrypt, ENCRYPT_TPM2, ENCRYPT_KEY_FILE_TPM2)) {
2621#if HAVE_TPM2
2622 _cleanup_(erase_and_freep) char *base64_encoded = NULL;
2623 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
2624 _cleanup_(erase_and_freep) void *secret = NULL;
2625 _cleanup_free_ void *blob = NULL, *hash = NULL;
2626 size_t secret_size, blob_size, hash_size;
2b92a672 2627 uint16_t pcr_bank, primary_alg;
889914ef
LP
2628 int keyslot;
2629
2b92a672 2630 r = tpm2_seal(arg_tpm2_device, arg_tpm2_pcr_mask, &secret, &secret_size, &blob, &blob_size, &hash, &hash_size, &pcr_bank, &primary_alg);
889914ef
LP
2631 if (r < 0)
2632 return log_error_errno(r, "Failed to seal to TPM2: %m");
2633
2634 r = base64mem(secret, secret_size, &base64_encoded);
2635 if (r < 0)
2636 return log_error_errno(r, "Failed to base64 encode secret key: %m");
2637
2638 r = cryptsetup_set_minimal_pbkdf(cd);
2639 if (r < 0)
2640 return log_error_errno(r, "Failed to set minimal PBKDF: %m");
2641
2642 keyslot = sym_crypt_keyslot_add_by_volume_key(
2643 cd,
2644 CRYPT_ANY_SLOT,
2645 volume_key,
2646 volume_key_size,
2647 base64_encoded,
2648 strlen(base64_encoded));
2649 if (keyslot < 0)
2650 return log_error_errno(keyslot, "Failed to add new TPM2 key to %s: %m", node);
2651
2b92a672 2652 r = tpm2_make_luks2_json(keyslot, arg_tpm2_pcr_mask, pcr_bank, primary_alg, blob, blob_size, hash, hash_size, &v);
889914ef
LP
2653 if (r < 0)
2654 return log_error_errno(r, "Failed to prepare TPM2 JSON token object: %m");
2655
2656 r = cryptsetup_add_token_json(cd, v);
2657 if (r < 0)
2658 return log_error_errno(r, "Failed to add TPM2 JSON token to LUKS2 header: %m");
2659#else
2660 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2661 "Support for TPM2 enrollment not enabled.");
2662#endif
2663 }
b9df3536 2664
0d12936d 2665 r = sym_crypt_activate_by_volume_key(
b9df3536
LP
2666 cd,
2667 dm_name,
2668 volume_key,
2669 volume_key_size,
2670 arg_discard ? CRYPT_ACTIVATE_ALLOW_DISCARDS : 0);
2671 if (r < 0)
2672 return log_error_errno(r, "Failed to activate LUKS superblock: %m");
2673
2674 log_info("Successfully encrypted future partition %" PRIu64 ".", p->partno);
2675
2676 if (ret_fd) {
2677 _cleanup_close_ int dev_fd = -1;
2678
2679 dev_fd = open(vol, O_RDWR|O_CLOEXEC|O_NOCTTY);
2680 if (dev_fd < 0)
2681 return log_error_errno(errno, "Failed to open LUKS volume '%s': %m", vol);
2682
2683 *ret_fd = TAKE_FD(dev_fd);
2684 }
2685
2686 if (ret_cd)
2687 *ret_cd = TAKE_PTR(cd);
2688 if (ret_volume)
2689 *ret_volume = TAKE_PTR(vol);
2690
2691 return 0;
3dd8ae5c 2692#else
2693 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "libcryptsetup is not supported, cannot encrypt: %m");
2694#endif
b9df3536
LP
2695}
2696
2697static int deactivate_luks(struct crypt_device *cd, const char *node) {
3dd8ae5c 2698#if HAVE_LIBCRYPTSETUP
b9df3536
LP
2699 int r;
2700
2701 if (!cd)
2702 return 0;
2703
2704 assert(node);
2705
2706 /* udev or so might access out block device in the background while we are done. Let's hence force
2707 * detach the volume. We sync'ed before, hence this should be safe. */
2708
0d12936d 2709 r = sym_crypt_deactivate_by_name(cd, basename(node), CRYPT_DEACTIVATE_FORCE);
b9df3536
LP
2710 if (r < 0)
2711 return log_error_errno(r, "Failed to deactivate LUKS device: %m");
2712
2713 return 1;
3dd8ae5c 2714#else
2715 return 0;
2716#endif
b9df3536
LP
2717}
2718
757bc2e4
LP
2719static int context_copy_blocks(Context *context) {
2720 Partition *p;
b9df3536 2721 int whole_fd = -1, r;
757bc2e4
LP
2722
2723 assert(context);
2724
2725 /* Copy in file systems on the block level */
2726
2727 LIST_FOREACH(partitions, p, context->partitions) {
0d12936d 2728 _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
b9df3536
LP
2729 _cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
2730 _cleanup_free_ char *encrypted = NULL;
2731 _cleanup_close_ int encrypted_dev_fd = -1;
b9df3536 2732 int target_fd;
757bc2e4
LP
2733
2734 if (p->copy_blocks_fd < 0)
2735 continue;
2736
2737 if (p->dropped)
2738 continue;
2739
2740 if (PARTITION_EXISTS(p)) /* Never copy over existing partitions */
2741 continue;
2742
2743 assert(p->new_size != UINT64_MAX);
2744 assert(p->copy_blocks_size != UINT64_MAX);
2745 assert(p->new_size >= p->copy_blocks_size);
2746
b9df3536
LP
2747 if (whole_fd < 0)
2748 assert_se((whole_fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
2749
889914ef 2750 if (p->encrypt != ENCRYPT_OFF) {
b9df3536
LP
2751 r = loop_device_make(whole_fd, O_RDWR, p->offset, p->new_size, 0, &d);
2752 if (r < 0)
2753 return log_error_errno(r, "Failed to make loopback device of future partition %" PRIu64 ": %m", p->partno);
2754
2755 r = loop_device_flock(d, LOCK_EX);
2756 if (r < 0)
2757 return log_error_errno(r, "Failed to lock loopback device: %m");
2758
2759 r = partition_encrypt(p, d->node, &cd, &encrypted, &encrypted_dev_fd);
2760 if (r < 0)
2761 return log_error_errno(r, "Failed to encrypt device: %m");
757bc2e4 2762
b9df3536
LP
2763 if (flock(encrypted_dev_fd, LOCK_EX) < 0)
2764 return log_error_errno(errno, "Failed to lock LUKS device: %m");
2765
2766 target_fd = encrypted_dev_fd;
2767 } else {
2768 if (lseek(whole_fd, p->offset, SEEK_SET) == (off_t) -1)
2769 return log_error_errno(errno, "Failed to seek to partition offset: %m");
2770
2771 target_fd = whole_fd;
2772 }
757bc2e4 2773
2b59bf51
ZJS
2774 log_info("Copying in '%s' (%s) on block level into future partition %" PRIu64 ".",
2775 p->copy_blocks_path, FORMAT_BYTES(p->copy_blocks_size), p->partno);
757bc2e4 2776
b9df3536 2777 r = copy_bytes_full(p->copy_blocks_fd, target_fd, p->copy_blocks_size, 0, NULL, NULL, NULL, NULL);
757bc2e4
LP
2778 if (r < 0)
2779 return log_error_errno(r, "Failed to copy in data from '%s': %m", p->copy_blocks_path);
2780
b9df3536
LP
2781 if (fsync(target_fd) < 0)
2782 return log_error_errno(r, "Failed to synchronize copied data blocks: %m");
2783
889914ef 2784 if (p->encrypt != ENCRYPT_OFF) {
b9df3536
LP
2785 encrypted_dev_fd = safe_close(encrypted_dev_fd);
2786
2787 r = deactivate_luks(cd, encrypted);
2788 if (r < 0)
2789 return r;
2790
0d12936d 2791 sym_crypt_free(cd);
b9df3536
LP
2792 cd = NULL;
2793
2794 r = loop_device_sync(d);
2795 if (r < 0)
2796 return log_error_errno(r, "Failed to sync loopback device: %m");
2797 }
2798
757bc2e4
LP
2799 log_info("Copying in of '%s' on block level completed.", p->copy_blocks_path);
2800 }
2801
2802 return 0;
2803}
2804
8a794850
LP
2805static int do_copy_files(Partition *p, const char *fs) {
2806 char **source, **target;
2807 int r;
2808
2809 assert(p);
2810 assert(fs);
2811
2812 STRV_FOREACH_PAIR(source, target, p->copy_files) {
2813 _cleanup_close_ int sfd = -1, pfd = -1, tfd = -1;
8a794850
LP
2814
2815 sfd = chase_symlinks_and_open(*source, arg_root, CHASE_PREFIX_ROOT|CHASE_WARN, O_CLOEXEC|O_NOCTTY, NULL);
2816 if (sfd < 0)
2817 return log_error_errno(sfd, "Failed to open source file '%s%s': %m", strempty(arg_root), *source);
2818
2819 r = fd_verify_regular(sfd);
2820 if (r < 0) {
2821 if (r != -EISDIR)
2822 return log_error_errno(r, "Failed to check type of source file '%s': %m", *source);
2823
2824 /* We are looking at a directory */
2825 tfd = chase_symlinks_and_open(*target, fs, CHASE_PREFIX_ROOT|CHASE_WARN, O_RDONLY|O_DIRECTORY|O_CLOEXEC, NULL);
2826 if (tfd < 0) {
f21a3a82
LP
2827 _cleanup_free_ char *dn = NULL, *fn = NULL;
2828
8a794850
LP
2829 if (tfd != -ENOENT)
2830 return log_error_errno(tfd, "Failed to open target directory '%s': %m", *target);
2831
f21a3a82
LP
2832 r = path_extract_filename(*target, &fn);
2833 if (r < 0)
2834 return log_error_errno(r, "Failed to extract filename from '%s': %m", *target);
2835
2836 r = path_extract_directory(*target, &dn);
2837 if (r < 0)
2838 return log_error_errno(r, "Failed to extract directory from '%s': %m", *target);
2839
8a794850
LP
2840 r = mkdir_p_root(fs, dn, UID_INVALID, GID_INVALID, 0755);
2841 if (r < 0)
2842 return log_error_errno(r, "Failed to create parent directory '%s': %m", dn);
2843
2844 pfd = chase_symlinks_and_open(dn, fs, CHASE_PREFIX_ROOT|CHASE_WARN, O_RDONLY|O_DIRECTORY|O_CLOEXEC, NULL);
2845 if (pfd < 0)
2846 return log_error_errno(pfd, "Failed to open parent directory of target: %m");
2847
652d9040
LP
2848 r = copy_tree_at(
2849 sfd, ".",
6020d00d 2850 pfd, fn,
652d9040 2851 UID_INVALID, GID_INVALID,
23e026de 2852 COPY_REFLINK|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS);
8a794850 2853 } else
652d9040
LP
2854 r = copy_tree_at(
2855 sfd, ".",
2856 tfd, ".",
2857 UID_INVALID, GID_INVALID,
23e026de 2858 COPY_REFLINK|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS);
8a794850 2859 if (r < 0)
554a2b64 2860 return log_error_errno(r, "Failed to copy '%s' to '%s%s': %m", *source, strempty(arg_root), *target);
8a794850 2861 } else {
f21a3a82
LP
2862 _cleanup_free_ char *dn = NULL, *fn = NULL;
2863
8a794850
LP
2864 /* We are looking at a regular file */
2865
f21a3a82
LP
2866 r = path_extract_filename(*target, &fn);
2867 if (r == -EADDRNOTAVAIL || r == O_DIRECTORY)
2868 return log_error_errno(SYNTHETIC_ERRNO(EISDIR),
2869 "Target path '%s' refers to a directory, but source path '%s' refers to regular file, can't copy.", *target, *source);
2870 if (r < 0)
2871 return log_error_errno(r, "Failed to extract filename from '%s': %m", *target);
2872
2873 r = path_extract_directory(*target, &dn);
2874 if (r < 0)
2875 return log_error_errno(r, "Failed to extract directory from '%s': %m", *target);
2876
8a794850
LP
2877 r = mkdir_p_root(fs, dn, UID_INVALID, GID_INVALID, 0755);
2878 if (r < 0)
2879 return log_error_errno(r, "Failed to create parent directory: %m");
2880
2881 pfd = chase_symlinks_and_open(dn, fs, CHASE_PREFIX_ROOT|CHASE_WARN, O_RDONLY|O_DIRECTORY|O_CLOEXEC, NULL);
2882 if (pfd < 0)
a0ff9971 2883 return log_error_errno(pfd, "Failed to open parent directory of target: %m");
8a794850 2884
e2819067 2885 tfd = openat(pfd, fn, O_CREAT|O_EXCL|O_WRONLY|O_CLOEXEC, 0700);
8a794850
LP
2886 if (tfd < 0)
2887 return log_error_errno(errno, "Failed to create target file '%s': %m", *target);
2888
2889 r = copy_bytes(sfd, tfd, UINT64_MAX, COPY_REFLINK|COPY_SIGINT);
2890 if (r < 0)
554a2b64 2891 return log_error_errno(r, "Failed to copy '%s' to '%s%s': %m", *source, strempty(arg_root), *target);
8a794850 2892
23e026de 2893 (void) copy_xattr(sfd, tfd, COPY_ALL_XATTRS);
8a794850
LP
2894 (void) copy_access(sfd, tfd);
2895 (void) copy_times(sfd, tfd, 0);
2896 }
2897 }
2898
2899 return 0;
2900}
2901
d83d8048
LP
2902static int do_make_directories(Partition *p, const char *fs) {
2903 char **d;
2904 int r;
2905
2906 assert(p);
2907 assert(fs);
2908
2909 STRV_FOREACH(d, p->make_directories) {
2910
2911 r = mkdir_p_root(fs, *d, UID_INVALID, GID_INVALID, 0755);
2912 if (r < 0)
2913 return log_error_errno(r, "Failed to create directory '%s' in file system: %m", *d);
2914 }
2915
2916 return 0;
2917}
2918
2919static int partition_populate(Partition *p, const char *node) {
8a794850
LP
2920 int r;
2921
2922 assert(p);
2923 assert(node);
2924
d83d8048 2925 if (strv_isempty(p->copy_files) && strv_isempty(p->make_directories))
8a794850
LP
2926 return 0;
2927
2928 log_info("Populating partition %" PRIu64 " with files.", p->partno);
2929
2930 /* We copy in a child process, since we have to mount the fs for that, and we don't want that fs to
2931 * appear in the host namespace. Hence we fork a child that has its own file system namespace and
2932 * detached mount propagation. */
2933
2934 r = safe_fork("(sd-copy)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL);
2935 if (r < 0)
2936 return r;
2937 if (r == 0) {
2938 static const char fs[] = "/run/systemd/mount-root";
2939 /* This is a child process with its own mount namespace and propagation to host turned off */
2940
2941 r = mkdir_p(fs, 0700);
2942 if (r < 0) {
2943 log_error_errno(r, "Failed to create mount point: %m");
2944 _exit(EXIT_FAILURE);
2945 }
2946
511a8cfe 2947 if (mount_nofollow_verbose(LOG_ERR, node, fs, p->format, MS_NOATIME|MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL) < 0)
8a794850
LP
2948 _exit(EXIT_FAILURE);
2949
2950 if (do_copy_files(p, fs) < 0)
2951 _exit(EXIT_FAILURE);
2952
d83d8048
LP
2953 if (do_make_directories(p, fs) < 0)
2954 _exit(EXIT_FAILURE);
2955
8a794850
LP
2956 r = syncfs_path(AT_FDCWD, fs);
2957 if (r < 0) {
2958 log_error_errno(r, "Failed to synchronize written files: %m");
2959 _exit(EXIT_FAILURE);
2960 }
2961
2962 _exit(EXIT_SUCCESS);
2963 }
2964
2965 log_info("Successfully populated partition %" PRIu64 " with files.", p->partno);
2966 return 0;
2967}
2968
53171c04
LP
2969static int context_mkfs(Context *context) {
2970 Partition *p;
2971 int fd = -1, r;
2972
2973 assert(context);
2974
2975 /* Make a file system */
2976
2977 LIST_FOREACH(partitions, p, context->partitions) {
0d12936d 2978 _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
53171c04 2979 _cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
b9df3536
LP
2980 _cleanup_free_ char *encrypted = NULL;
2981 _cleanup_close_ int encrypted_dev_fd = -1;
2982 const char *fsdev;
53171c04
LP
2983 sd_id128_t fs_uuid;
2984
2985 if (p->dropped)
2986 continue;
2987
2988 if (PARTITION_EXISTS(p)) /* Never format existing partitions */
2989 continue;
2990
2991 if (!p->format)
2992 continue;
2993
2994 assert(p->offset != UINT64_MAX);
2995 assert(p->new_size != UINT64_MAX);
2996
2997 if (fd < 0)
2998 assert_se((fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
2999
3000 /* Loopback block devices are not only useful to turn regular files into block devices, but
3001 * also to cut out sections of block devices into new block devices. */
3002
3003 r = loop_device_make(fd, O_RDWR, p->offset, p->new_size, 0, &d);
3004 if (r < 0)
5b5109e2 3005 return log_error_errno(r, "Failed to make loopback device of future partition %" PRIu64 ": %m", p->partno);
53171c04
LP
3006
3007 r = loop_device_flock(d, LOCK_EX);
3008 if (r < 0)
3009 return log_error_errno(r, "Failed to lock loopback device: %m");
3010
889914ef 3011 if (p->encrypt != ENCRYPT_OFF) {
b9df3536
LP
3012 r = partition_encrypt(p, d->node, &cd, &encrypted, &encrypted_dev_fd);
3013 if (r < 0)
3014 return log_error_errno(r, "Failed to encrypt device: %m");
3015
3016 if (flock(encrypted_dev_fd, LOCK_EX) < 0)
3017 return log_error_errno(errno, "Failed to lock LUKS device: %m");
3018
3019 fsdev = encrypted;
3020 } else
3021 fsdev = d->node;
3022
53171c04
LP
3023 log_info("Formatting future partition %" PRIu64 ".", p->partno);
3024
3025 /* Calculate the UUID for the file system as HMAC-SHA256 of the string "file-system-uuid",
3026 * keyed off the partition UUID. */
3027 r = derive_uuid(p->new_uuid, "file-system-uuid", &fs_uuid);
3028 if (r < 0)
3029 return r;
3030
be9ce018 3031 r = make_filesystem(fsdev, p->format, strempty(p->new_label), fs_uuid, arg_discard);
b9df3536
LP
3032 if (r < 0) {
3033 encrypted_dev_fd = safe_close(encrypted_dev_fd);
3034 (void) deactivate_luks(cd, encrypted);
53171c04 3035 return r;
b9df3536 3036 }
53171c04
LP
3037
3038 log_info("Successfully formatted future partition %" PRIu64 ".", p->partno);
3039
b9df3536 3040 /* The file system is now created, no need to delay udev further */
889914ef 3041 if (p->encrypt != ENCRYPT_OFF)
b9df3536
LP
3042 if (flock(encrypted_dev_fd, LOCK_UN) < 0)
3043 return log_error_errno(errno, "Failed to unlock LUKS device: %m");
3044
d83d8048 3045 r = partition_populate(p, fsdev);
b9df3536
LP
3046 if (r < 0) {
3047 encrypted_dev_fd = safe_close(encrypted_dev_fd);
3048 (void) deactivate_luks(cd, encrypted);
8a794850 3049 return r;
b9df3536
LP
3050 }
3051
3052 /* Note that we always sync explicitly here, since mkfs.fat doesn't do that on its own, and
3053 * if we don't sync before detaching a block device the in-flight sectors possibly won't hit
3054 * the disk. */
3055
889914ef 3056 if (p->encrypt != ENCRYPT_OFF) {
b9df3536
LP
3057 if (fsync(encrypted_dev_fd) < 0)
3058 return log_error_errno(r, "Failed to synchronize LUKS volume: %m");
3059 encrypted_dev_fd = safe_close(encrypted_dev_fd);
3060
3061 r = deactivate_luks(cd, encrypted);
3062 if (r < 0)
3063 return r;
3064
0d12936d 3065 sym_crypt_free(cd);
b9df3536
LP
3066 cd = NULL;
3067 }
8a794850 3068
53171c04
LP
3069 r = loop_device_sync(d);
3070 if (r < 0)
3071 return log_error_errno(r, "Failed to sync loopback device: %m");
3072 }
3073
3074 return 0;
3075}
3076
e594a3b1
LP
3077static int partition_acquire_uuid(Context *context, Partition *p, sd_id128_t *ret) {
3078 struct {
3079 sd_id128_t type_uuid;
3080 uint64_t counter;
3081 } _packed_ plaintext = {};
3082 union {
3083 unsigned char md[SHA256_DIGEST_LENGTH];
3084 sd_id128_t id;
3085 } result;
3086
3087 uint64_t k = 0;
3088 Partition *q;
3089 int r;
3090
3091 assert(context);
3092 assert(p);
3093 assert(ret);
3094
3095 /* Calculate a good UUID for the indicated partition. We want a certain degree of reproducibility,
3096 * hence we won't generate the UUIDs randomly. Instead we use a cryptographic hash (precisely:
3097 * HMAC-SHA256) to derive them from a single seed. The seed is generally the machine ID of the
3098 * installation we are processing, but if random behaviour is desired can be random, too. We use the
3099 * seed value as key for the HMAC (since the machine ID is something we generally don't want to leak)
3100 * and the partition type as plaintext. The partition type is suffixed with a counter (only for the
3101 * second and later partition of the same type) if we have more than one partition of the same
3102 * time. Or in other words:
3103 *
3104 * With:
3105 * SEED := /etc/machine-id
3106 *
3107 * If first partition instance of type TYPE_UUID:
3108 * PARTITION_UUID := HMAC-SHA256(SEED, TYPE_UUID)
3109 *
3110 * For all later partition instances of type TYPE_UUID with INSTANCE being the LE64 encoded instance number:
3111 * PARTITION_UUID := HMAC-SHA256(SEED, TYPE_UUID || INSTANCE)
3112 */
3113
3114 LIST_FOREACH(partitions, q, context->partitions) {
3115 if (p == q)
3116 break;
3117
3118 if (!sd_id128_equal(p->type_uuid, q->type_uuid))
3119 continue;
3120
3121 k++;
3122 }
3123
3124 plaintext.type_uuid = p->type_uuid;
3125 plaintext.counter = htole64(k);
3126
3127 if (!HMAC(EVP_sha256(),
3128 &context->seed, sizeof(context->seed),
3129 (const unsigned char*) &plaintext, k == 0 ? sizeof(sd_id128_t) : sizeof(plaintext),
3130 result.md, NULL))
3131 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "SHA256 calculation failed.");
3132
3133 /* Take the first half, mark it as v4 UUID */
3134 assert_cc(sizeof(result.md) == sizeof(result.id) * 2);
3135 result.id = id128_make_v4_uuid(result.id);
3136
3137 /* Ensure this partition UUID is actually unique, and there's no remaining partition from an earlier run? */
3138 LIST_FOREACH(partitions, q, context->partitions) {
3139 if (p == q)
3140 continue;
3141
580f48cc 3142 if (sd_id128_in_set(result.id, q->current_uuid, q->new_uuid)) {
da1af43d 3143 log_warning("Partition UUID calculated from seed for partition %" PRIu64 " already used, reverting to randomized UUID.", p->partno);
e594a3b1
LP
3144
3145 r = sd_id128_randomize(&result.id);
3146 if (r < 0)
3147 return log_error_errno(r, "Failed to generate randomized UUID: %m");
3148
3149 break;
3150 }
3151 }
3152
3153 *ret = result.id;
3154 return 0;
3155}
3156
3157static int partition_acquire_label(Context *context, Partition *p, char **ret) {
3158 _cleanup_free_ char *label = NULL;
3159 const char *prefix;
3160 unsigned k = 1;
3161
3162 assert(context);
3163 assert(p);
3164 assert(ret);
3165
3166 prefix = gpt_partition_type_uuid_to_string(p->type_uuid);
3167 if (!prefix)
3168 prefix = "linux";
3169
3170 for (;;) {
3171 const char *ll = label ?: prefix;
3172 bool retry = false;
3173 Partition *q;
3174
3175 LIST_FOREACH(partitions, q, context->partitions) {
3176 if (p == q)
3177 break;
3178
3179 if (streq_ptr(ll, q->current_label) ||
3180 streq_ptr(ll, q->new_label)) {
3181 retry = true;
3182 break;
3183 }
3184 }
3185
3186 if (!retry)
3187 break;
3188
3189 label = mfree(label);
e594a3b1
LP
3190 if (asprintf(&label, "%s-%u", prefix, ++k) < 0)
3191 return log_oom();
3192 }
3193
3194 if (!label) {
3195 label = strdup(prefix);
3196 if (!label)
3197 return log_oom();
3198 }
3199
3200 *ret = TAKE_PTR(label);
3201 return 0;
3202}
3203
3204static int context_acquire_partition_uuids_and_labels(Context *context) {
3205 Partition *p;
3206 int r;
3207
3208 assert(context);
3209
3210 LIST_FOREACH(partitions, p, context->partitions) {
e594a3b1
LP
3211 /* Never touch foreign partitions */
3212 if (PARTITION_IS_FOREIGN(p)) {
3213 p->new_uuid = p->current_uuid;
3214
3215 if (p->current_label) {
78eee6ce
LP
3216 r = free_and_strdup_warn(&p->new_label, strempty(p->current_label));
3217 if (r < 0)
3218 return r;
e594a3b1
LP
3219 }
3220
3221 continue;
3222 }
3223
3224 if (!sd_id128_is_null(p->current_uuid))
3225 p->new_uuid = p->current_uuid; /* Never change initialized UUIDs */
12963533
TH
3226 else if (sd_id128_is_null(p->new_uuid)) {
3227 /* Not explicitly set by user! */
e594a3b1
LP
3228 r = partition_acquire_uuid(context, p, &p->new_uuid);
3229 if (r < 0)
3230 return r;
3231 }
3232
3233 if (!isempty(p->current_label)) {
78eee6ce
LP
3234 /* never change initialized labels */
3235 r = free_and_strdup_warn(&p->new_label, p->current_label);
3236 if (r < 0)
3237 return r;
12963533
TH
3238 } else if (!p->new_label) {
3239 /* Not explicitly set by user! */
3240
e594a3b1
LP
3241 r = partition_acquire_label(context, p, &p->new_label);
3242 if (r < 0)
3243 return r;
3244 }
3245 }
3246
3247 return 0;
3248}
3249
e73309c5
LP
3250static int set_gpt_flags(struct fdisk_partition *q, uint64_t flags) {
3251 _cleanup_free_ char *a = NULL;
3252
3253 for (unsigned i = 0; i < sizeof(flags) * 8; i++) {
3254 uint64_t bit = UINT64_C(1) << i;
3255 char buf[DECIMAL_STR_MAX(unsigned)+1];
3256
3257 if (!FLAGS_SET(flags, bit))
3258 continue;
3259
3260 xsprintf(buf, "%u", i);
3261 if (!strextend_with_separator(&a, ",", buf))
3262 return -ENOMEM;
3263 }
3264
3265 return fdisk_partition_set_attrs(q, a);
3266}
3267
1c41c1dc
LP
3268static uint64_t partition_merge_flags(Partition *p) {
3269 uint64_t f;
3270
3271 assert(p);
3272
3273 f = p->gpt_flags;
3274
ff0771bf
LP
3275 if (p->no_auto >= 0) {
3276 if (gpt_partition_type_knows_no_auto(p->type_uuid))
3277 SET_FLAG(f, GPT_FLAG_NO_AUTO, p->no_auto);
3278 else {
3279 char buffer[ID128_UUID_STRING_MAX];
3280 log_warning("Configured NoAuto=%s for partition type '%s' that doesn't support it, ignoring.",
3281 yes_no(p->no_auto),
3282 gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
3283 }
3284 }
3285
1c41c1dc
LP
3286 if (p->read_only >= 0) {
3287 if (gpt_partition_type_knows_read_only(p->type_uuid))
3288 SET_FLAG(f, GPT_FLAG_READ_ONLY, p->read_only);
3289 else {
3290 char buffer[ID128_UUID_STRING_MAX];
3291 log_warning("Configured ReadOnly=%s for partition type '%s' that doesn't support it, ignoring.",
3292 yes_no(p->read_only),
3293 gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
3294 }
3295 }
3296
3297 if (p->growfs >= 0) {
3298 if (gpt_partition_type_knows_growfs(p->type_uuid))
3299 SET_FLAG(f, GPT_FLAG_GROWFS, p->growfs);
3300 else {
3301 char buffer[ID128_UUID_STRING_MAX];
3302 log_warning("Configured GrowFileSystem=%s for partition type '%s' that doesn't support it, ignoring.",
3303 yes_no(p->growfs),
3304 gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
3305 }
3306 }
3307
3308 return f;
3309}
3310
f28d4f42 3311static int context_mangle_partitions(Context *context) {
e594a3b1 3312 Partition *p;
f28d4f42 3313 int r;
e594a3b1
LP
3314
3315 assert(context);
3316
e594a3b1
LP
3317 LIST_FOREACH(partitions, p, context->partitions) {
3318 if (p->dropped)
3319 continue;
3320
3321 assert(p->new_size != UINT64_MAX);
3322 assert(p->offset != UINT64_MAX);
3323 assert(p->partno != UINT64_MAX);
3324
3325 if (PARTITION_EXISTS(p)) {
3326 bool changed = false;
3327
3328 assert(p->current_partition);
3329
3330 if (p->new_size != p->current_size) {
3331 assert(p->new_size >= p->current_size);
3332 assert(p->new_size % 512 == 0);
3333
3334 r = fdisk_partition_size_explicit(p->current_partition, true);
3335 if (r < 0)
3336 return log_error_errno(r, "Failed to enable explicit sizing: %m");
3337
3338 r = fdisk_partition_set_size(p->current_partition, p->new_size / 512);
3339 if (r < 0)
3340 return log_error_errno(r, "Failed to grow partition: %m");
3341
3342 log_info("Growing existing partition %" PRIu64 ".", p->partno);
3343 changed = true;
3344 }
3345
3346 if (!sd_id128_equal(p->new_uuid, p->current_uuid)) {
e594a3b1
LP
3347 assert(!sd_id128_is_null(p->new_uuid));
3348
85b55869 3349 r = fdisk_partition_set_uuid(p->current_partition, ID128_TO_UUID_STRING(p->new_uuid));
e594a3b1
LP
3350 if (r < 0)
3351 return log_error_errno(r, "Failed to set partition UUID: %m");
3352
3353 log_info("Initializing UUID of existing partition %" PRIu64 ".", p->partno);
3354 changed = true;
3355 }
3356
3357 if (!streq_ptr(p->new_label, p->current_label)) {
be9ce018 3358 r = fdisk_partition_set_name(p->current_partition, strempty(p->new_label));
e594a3b1
LP
3359 if (r < 0)
3360 return log_error_errno(r, "Failed to set partition label: %m");
3361
3362 log_info("Setting partition label of existing partition %" PRIu64 ".", p->partno);
3363 changed = true;
3364 }
3365
3366 if (changed) {
3367 assert(!PARTITION_IS_FOREIGN(p)); /* never touch foreign partitions */
3368
3369 r = fdisk_set_partition(context->fdisk_context, p->partno, p->current_partition);
3370 if (r < 0)
3371 return log_error_errno(r, "Failed to update partition: %m");
3372 }
3373 } else {
3374 _cleanup_(fdisk_unref_partitionp) struct fdisk_partition *q = NULL;
3375 _cleanup_(fdisk_unref_parttypep) struct fdisk_parttype *t = NULL;
e594a3b1
LP
3376
3377 assert(!p->new_partition);
3378 assert(p->offset % 512 == 0);
3379 assert(p->new_size % 512 == 0);
3380 assert(!sd_id128_is_null(p->new_uuid));
be9ce018 3381 assert(p->new_label);
e594a3b1
LP
3382
3383 t = fdisk_new_parttype();
3384 if (!t)
3385 return log_oom();
3386
85b55869 3387 r = fdisk_parttype_set_typestr(t, ID128_TO_UUID_STRING(p->type_uuid));
e594a3b1
LP
3388 if (r < 0)
3389 return log_error_errno(r, "Failed to initialize partition type: %m");
3390
3391 q = fdisk_new_partition();
3392 if (!q)
3393 return log_oom();
3394
3395 r = fdisk_partition_set_type(q, t);
3396 if (r < 0)
3397 return log_error_errno(r, "Failed to set partition type: %m");
3398
3399 r = fdisk_partition_size_explicit(q, true);
3400 if (r < 0)
3401 return log_error_errno(r, "Failed to enable explicit sizing: %m");
3402
3403 r = fdisk_partition_set_start(q, p->offset / 512);
3404 if (r < 0)
3405 return log_error_errno(r, "Failed to position partition: %m");
3406
3407 r = fdisk_partition_set_size(q, p->new_size / 512);
3408 if (r < 0)
3409 return log_error_errno(r, "Failed to grow partition: %m");
3410
3411 r = fdisk_partition_set_partno(q, p->partno);
3412 if (r < 0)
3413 return log_error_errno(r, "Failed to set partition number: %m");
3414
85b55869 3415 r = fdisk_partition_set_uuid(q, ID128_TO_UUID_STRING(p->new_uuid));
e594a3b1
LP
3416 if (r < 0)
3417 return log_error_errno(r, "Failed to set partition UUID: %m");
3418
be9ce018 3419 r = fdisk_partition_set_name(q, strempty(p->new_label));
e594a3b1
LP
3420 if (r < 0)
3421 return log_error_errno(r, "Failed to set partition label: %m");
3422
ff0771bf 3423 /* Merge the no auto + read only + growfs setting with the literal flags, and set them for the partition */
1c41c1dc 3424 r = set_gpt_flags(q, partition_merge_flags(p));
e73309c5
LP
3425 if (r < 0)
3426 return log_error_errno(r, "Failed to set GPT partition flags: %m");
3427
5b5109e2 3428 log_info("Adding new partition %" PRIu64 " to partition table.", p->partno);
e594a3b1
LP
3429
3430 r = fdisk_add_partition(context->fdisk_context, q, NULL);
3431 if (r < 0)
3432 return log_error_errno(r, "Failed to add partition: %m");
3433
3434 assert(!p->new_partition);
3435 p->new_partition = TAKE_PTR(q);
3436 }
3437 }
3438
f28d4f42
LP
3439 return 0;
3440}
3441
3442static int context_write_partition_table(
3443 Context *context,
3444 const char *node,
3445 bool from_scratch) {
3446
3447 _cleanup_(fdisk_unref_tablep) struct fdisk_table *original_table = NULL;
3448 int capable, r;
3449
3450 assert(context);
3451
3452 if (arg_pretty > 0 ||
3453 (arg_pretty < 0 && isatty(STDOUT_FILENO) > 0) ||
6a01ea4a 3454 !FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF)) {
f28d4f42
LP
3455
3456 (void) context_dump_partitions(context, node);
3457
3458 putc('\n', stdout);
3459
6a01ea4a 3460 if (arg_json_format_flags & JSON_FORMAT_OFF)
f28d4f42
LP
3461 (void) context_dump_partition_bar(context, node);
3462 putc('\n', stdout);
3463 fflush(stdout);
3464 }
3465
3466 if (!from_scratch && !context_changed(context)) {
3467 log_info("No changes.");
3468 return 0;
3469 }
3470
3471 if (arg_dry_run) {
3472 log_notice("Refusing to repartition, please re-run with --dry-run=no.");
3473 return 0;
3474 }
3475
3476 log_info("Applying changes.");
3477
3478 if (from_scratch) {
81873a6b
LP
3479 r = context_wipe_range(context, 0, context->total);
3480 if (r < 0)
3481 return r;
3482
3483 log_info("Wiped block device.");
3484
f28d4f42
LP
3485 r = context_discard_range(context, 0, context->total);
3486 if (r == -EOPNOTSUPP)
5b5109e2 3487 log_info("Storage does not support discard, not discarding entire block device data.");
f28d4f42
LP
3488 else if (r < 0)
3489 return log_error_errno(r, "Failed to discard entire block device: %m");
3490 else if (r > 0)
3491 log_info("Discarded entire block device.");
3492 }
3493
3494 r = fdisk_get_partitions(context->fdisk_context, &original_table);
3495 if (r < 0)
3496 return log_error_errno(r, "Failed to acquire partition table: %m");
3497
3498 /* Wipe fs signatures and discard sectors where the new partitions are going to be placed and in the
3499 * gaps between partitions, just to be sure. */
3500 r = context_wipe_and_discard(context, from_scratch);
3501 if (r < 0)
3502 return r;
3503
3504 r = context_copy_blocks(context);
3505 if (r < 0)
3506 return r;
3507
3508 r = context_mkfs(context);
3509 if (r < 0)
3510 return r;
3511
3512 r = context_mangle_partitions(context);
3513 if (r < 0)
3514 return r;
3515
e594a3b1
LP
3516 log_info("Writing new partition table.");
3517
3518 r = fdisk_write_disklabel(context->fdisk_context);
3519 if (r < 0)
3520 return log_error_errno(r, "Failed to write partition table: %m");
3521
911ba624 3522 capable = blockdev_partscan_enabled(fdisk_get_devfd(context->fdisk_context));
9a1deb85
LP
3523 if (capable == -ENOTBLK)
3524 log_debug("Not telling kernel to reread partition table, since we are not operating on a block device.");
3525 else if (capable < 0)
911ba624 3526 return log_error_errno(capable, "Failed to check if block device supports partition scanning: %m");
9a1deb85 3527 else if (capable > 0) {
e594a3b1
LP
3528 log_info("Telling kernel to reread partition table.");
3529
3530 if (from_scratch)
3531 r = fdisk_reread_partition_table(context->fdisk_context);
3532 else
3533 r = fdisk_reread_changes(context->fdisk_context, original_table);
3534 if (r < 0)
3535 return log_error_errno(r, "Failed to reread partition table: %m");
3536 } else
3537 log_notice("Not telling kernel to reread partition table, because selected image does not support kernel partition block devices.");
3538
3539 log_info("All done.");
3540
3541 return 0;
3542}
3543
3544static int context_read_seed(Context *context, const char *root) {
3545 int r;
3546
3547 assert(context);
3548
3549 if (!sd_id128_is_null(context->seed))
3550 return 0;
3551
3552 if (!arg_randomize) {
3553 _cleanup_close_ int fd = -1;
3554
3555 fd = chase_symlinks_and_open("/etc/machine-id", root, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC, NULL);
3556 if (fd == -ENOENT)
3557 log_info("No machine ID set, using randomized partition UUIDs.");
3558 else if (fd < 0)
3559 return log_error_errno(fd, "Failed to determine machine ID of image: %m");
3560 else {
448b782c 3561 r = id128_read_fd(fd, ID128_PLAIN_OR_UNINIT, &context->seed);
e594a3b1
LP
3562 if (r == -ENOMEDIUM)
3563 log_info("No machine ID set, using randomized partition UUIDs.");
3564 else if (r < 0)
3565 return log_error_errno(r, "Failed to parse machine ID of image: %m");
3566
3567 return 0;
3568 }
3569 }
3570
3571 r = sd_id128_randomize(&context->seed);
3572 if (r < 0)
3573 return log_error_errno(r, "Failed to generate randomized seed: %m");
3574
3575 return 0;
3576}
3577
3578static int context_factory_reset(Context *context, bool from_scratch) {
3579 Partition *p;
3580 size_t n = 0;
3581 int r;
3582
3583 assert(context);
3584
3585 if (arg_factory_reset <= 0)
3586 return 0;
3587
3588 if (from_scratch) /* Nothing to reset if we start from scratch */
3589 return 0;
3590
3591 if (arg_dry_run) {
3592 log_notice("Refusing to factory reset, please re-run with --dry-run=no.");
3593 return 0;
3594 }
3595
3596 log_info("Applying factory reset.");
3597
3598 LIST_FOREACH(partitions, p, context->partitions) {
3599
3600 if (!p->factory_reset || !PARTITION_EXISTS(p))
3601 continue;
3602
3603 assert(p->partno != UINT64_MAX);
3604
3605 log_info("Removing partition %" PRIu64 " for factory reset.", p->partno);
3606
3607 r = fdisk_delete_partition(context->fdisk_context, p->partno);
3608 if (r < 0)
3609 return log_error_errno(r, "Failed to remove partition %" PRIu64 ": %m", p->partno);
3610
3611 n++;
3612 }
3613
3614 if (n == 0) {
3615 log_info("Factory reset requested, but no partitions to delete found.");
3616 return 0;
3617 }
3618
3619 r = fdisk_write_disklabel(context->fdisk_context);
3620 if (r < 0)
3621 return log_error_errno(r, "Failed to write disk label: %m");
3622
3623 log_info("Successfully deleted %zu partitions.", n);
3624 return 1;
3625}
3626
3627static int context_can_factory_reset(Context *context) {
3628 Partition *p;
3629
3630 assert(context);
3631
3632 LIST_FOREACH(partitions, p, context->partitions)
3633 if (p->factory_reset && PARTITION_EXISTS(p))
3634 return true;
3635
3636 return false;
3637}
3638
5c08da58
LP
3639static int resolve_copy_blocks_auto_candidate(
3640 dev_t partition_devno,
3641 sd_id128_t partition_type_uuid,
3642 dev_t restrict_devno,
3643 sd_id128_t *ret_uuid) {
3644
3645 _cleanup_(blkid_free_probep) blkid_probe b = NULL;
3646 _cleanup_free_ char *p = NULL;
3647 _cleanup_close_ int fd = -1;
3648 const char *pttype, *t;
3649 sd_id128_t pt_parsed, u;
3650 blkid_partition pp;
3651 dev_t whole_devno;
3652 blkid_partlist pl;
3653 struct stat st;
3654 int r;
3655
3656 /* Checks if the specified partition has the specified GPT type UUID, and is located on the specified
3657 * 'restrict_devno' device. The type check is particularly relevant if we have Verity volume which is
3658 * backed by two separate partitions: the data and the hash partitions, and we need to find the right
3659 * one of the two. */
3660
3661 r = block_get_whole_disk(partition_devno, &whole_devno);
3662 if (r < 0)
3663 return log_error_errno(
3664 r,
3665 "Unable to determine containing block device of partition %u:%u: %m",
3666 major(partition_devno), minor(partition_devno));
3667
3668 if (restrict_devno != (dev_t) -1 &&
3669 restrict_devno != whole_devno)
3670 return log_error_errno(
3671 SYNTHETIC_ERRNO(EPERM),
3672 "Partition %u:%u is located outside of block device %u:%u, refusing.",
3673 major(partition_devno), minor(partition_devno),
3674 major(restrict_devno), minor(restrict_devno));
3675
3676 r = device_path_make_major_minor(S_IFBLK, whole_devno, &p);
3677 if (r < 0)
3678 return log_error_errno(r, "Failed to convert block device to device node path: %m");
3679
3680 fd = open(p, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
3681 if (fd < 0)
3682 return log_error_errno(r, "Failed to open '%s': %m", p);
3683
3684 if (fstat(fd, &st) < 0)
3685 return log_error_errno(r, "Failed to stat '%s': %m", p);
3686
3687 if (!S_ISBLK(st.st_mode) || st.st_rdev != whole_devno)
3688 return log_error_errno(
3689 SYNTHETIC_ERRNO(EPERM),
3690 "Opened and determined block device don't match, refusing.");
3691
3692 b = blkid_new_probe();
3693 if (!b)
3694 return log_oom();
3695
3696 errno = 0;
3697 r = blkid_probe_set_device(b, fd, 0, 0);
3698 if (r != 0)
3699 return log_error_errno(errno_or_else(ENOMEM), "Failed to open block device '%s': %m", p);
3700
3701 (void) blkid_probe_enable_partitions(b, 1);
3702 (void) blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
3703
3704 errno = 0;
3705 r = blkid_do_safeprobe(b);
3706 if (IN_SET(r, -2, 1)) { /* nothing found or ambiguous result */
3707 log_debug("Didn't find partition table on block device '%s'.", p);
3708 return false;
3709 }
3710 if (r != 0)
3711 return log_error_errno(errno_or_else(EIO), "Unable to probe for partition table of '%s': %m", p);
3712
3713 (void) blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
3714 if (!streq_ptr(pttype, "gpt")) {
3715 log_debug("Didn't find a GPT partition table on '%s'.", p);
3716 return false;
3717 }
3718
3719 errno = 0;
3720 pl = blkid_probe_get_partitions(b);
3721 if (!pl)
3722 return log_error_errno(errno_or_else(EIO), "Unable read partition table of '%s': %m", p);
3723 errno = 0;
3724
3725 pp = blkid_partlist_devno_to_partition(pl, partition_devno);
3726 if (!pp) {
3727 log_debug("Partition %u:%u has no matching partition table entry on '%s'.",
3728 major(partition_devno), minor(partition_devno), p);
3729 return false;
3730 }
3731
3732 t = blkid_partition_get_type_string(pp);
3733 if (isempty(t)) {
3734 log_debug("Partition %u:%u has no type on '%s'.",
3735 major(partition_devno), minor(partition_devno), p);
3736 return false;
3737 }
3738
3739 r = sd_id128_from_string(t, &pt_parsed);
3740 if (r < 0) {
3741 log_debug_errno(r, "Failed to parse partition type \"%s\": %m", t);
3742 return false;
3743 }
3744
3745 if (!sd_id128_equal(pt_parsed, partition_type_uuid)) {
3746 log_debug("Partition %u:%u has non-matching partition type " SD_ID128_FORMAT_STR " (needed: " SD_ID128_FORMAT_STR "), ignoring.",
3747 major(partition_devno), minor(partition_devno),
3748 SD_ID128_FORMAT_VAL(pt_parsed), SD_ID128_FORMAT_VAL(partition_type_uuid));
3749 return false;
3750 }
3751
3752 t = blkid_partition_get_uuid(pp);
3753 if (isempty(t)) {
3754 log_debug("Partition %u:%u has no UUID.",
3755 major(partition_devno), minor(partition_devno));
3756 return false;
3757 }
3758
3759 r = sd_id128_from_string(t, &u);
3760 if (r < 0) {
3761 log_debug_errno(r, "Failed to parse partition UUID \"%s\": %m", t);
3762 return false;
3763 }
3764
3765 log_debug("Automatically found partition %u:%u of right type " SD_ID128_FORMAT_STR ".",
3766 major(partition_devno), minor(partition_devno),
3767 SD_ID128_FORMAT_VAL(pt_parsed));
3768
3769 if (ret_uuid)
3770 *ret_uuid = u;
3771
3772 return true;
3773}
3774
3775static int find_backing_devno(
3776 const char *path,
3777 const char *root,
3778 dev_t *ret) {
3779
3780 _cleanup_free_ char *resolved = NULL;
3781 int r;
3782
3783 assert(path);
3784
3785 r = chase_symlinks(path, root, CHASE_PREFIX_ROOT, &resolved, NULL);
3786 if (r < 0)
3787 return r;
3788
3789 r = path_is_mount_point(resolved, NULL, 0);
3790 if (r < 0)
3791 return r;
3792 if (r == 0) /* Not a mount point, then it's not a partition of its own, let's not automatically use it. */
3793 return -ENOENT;
3794
3795 r = get_block_device(resolved, ret);
3796 if (r < 0)
3797 return r;
3798 if (r == 0) /* Not backed by physical file system, we can't use this */
3799 return -ENOENT;
3800
3801 return 0;
3802}
3803
3804static int resolve_copy_blocks_auto(
3805 sd_id128_t type_uuid,
3806 const char *root,
3807 dev_t restrict_devno,
3808 char **ret_path,
3809 sd_id128_t *ret_uuid) {
3810
3811 const char *try1 = NULL, *try2 = NULL;
3812 char p[SYS_BLOCK_PATH_MAX("/slaves")];
3813 _cleanup_(closedirp) DIR *d = NULL;
3814 sd_id128_t found_uuid = SD_ID128_NULL;
3815 dev_t devno, found = 0;
3816 int r;
3817
3818 assert(ret_path);
3819
3820 /* Enforce some security restrictions: CopyBlocks=auto should not be an avenue to get outside of the
3821 * --root=/--image= confinement. Specifically, refuse CopyBlocks= in combination with --root= at all,
3822 * and restrict block device references in the --image= case to loopback block device we set up.
3823 *
3824 * restrict_devno contain the dev_t of the loop back device we operate on in case of --image=, and
3825 * thus declares which device (and its partition subdevices) we shall limit access to. If
3826 * restrict_devno is zero no device probing access shall be allowed at all (used for --root=) and if
3827 * it is (dev_t) -1 then free access shall be allowed (if neither switch is used). */
3828
3829 if (restrict_devno == 0)
3830 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
3831 "Automatic discovery of backing block devices not permitted in --root= mode, refusing.");
3832
3833 /* Handles CopyBlocks=auto, and finds the right source partition to copy from. We look for matching
3834 * partitions in the host, using the appropriate directory as key and ensuring that the partition
3835 * type matches. */
3836
3837 if (gpt_partition_type_is_root(type_uuid))
3838 try1 = "/";
3839 else if (gpt_partition_type_is_usr(type_uuid))
3840 try1 = "/usr/";
3841 else if (gpt_partition_type_is_root_verity(type_uuid))
3842 try1 = "/";
3843 else if (gpt_partition_type_is_usr_verity(type_uuid))
3844 try1 = "/usr/";
3845 else if (sd_id128_equal(type_uuid, GPT_ESP)) {
3846 try1 = "/efi/";
3847 try2 = "/boot/";
3848 } else if (sd_id128_equal(type_uuid, GPT_XBOOTLDR))
3849 try1 = "/boot/";
3850 else
3851 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3852 "Partition type " SD_ID128_FORMAT_STR " not supported from automatic source block device discovery.",
3853 SD_ID128_FORMAT_VAL(type_uuid));
3854
3855 r = find_backing_devno(try1, root, &devno);
3856 if (r == -ENOENT && try2)
3857 r = find_backing_devno(try2, root, &devno);
3858 if (r < 0)
3859 return log_error_errno(r, "Failed to resolve automatic CopyBlocks= path for partition type " SD_ID128_FORMAT_STR ", sorry: %m",
3860 SD_ID128_FORMAT_VAL(type_uuid));
3861
3862 xsprintf_sys_block_path(p, "/slaves", devno);
3863 d = opendir(p);
3864 if (d) {
3865 struct dirent *de;
3866
3867 for (;;) {
3868 _cleanup_free_ char *q = NULL, *t = NULL;
3869 sd_id128_t u;
3870 dev_t sl;
3871
3872 errno = 0;
3873 de = readdir_no_dot(d);
3874 if (!de) {
3875 if (errno != 0)
3876 return log_error_errno(errno, "Failed to read directory '%s': %m", p);
3877
3878 break;
3879 }
3880
3881 if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
3882 continue;
3883
3884 q = path_join(p, de->d_name, "/dev");
3885 if (!q)
3886 return log_oom();
3887
3888 r = read_one_line_file(q, &t);
3889 if (r < 0)
3890 return log_error_errno(r, "Failed to read %s: %m", q);
3891
3892 r = parse_dev(t, &sl);
3893 if (r < 0) {
3894 log_debug_errno(r, "Failed to parse %s, ignoring: %m", q);
3895 continue;
3896 }
3897 if (major(sl) == 0) {
3898 log_debug_errno(r, "Device backing %s is special, ignoring: %m", q);
3899 continue;
3900 }
3901
3902 r = resolve_copy_blocks_auto_candidate(sl, type_uuid, restrict_devno, &u);
3903 if (r < 0)
3904 return r;
3905 if (r > 0) {
3906 /* We found a matching one! */
3907 if (found != 0)
3908 return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
3909 "Multiple matching partitions found, refusing.");
3910
3911 found = sl;
3912 found_uuid = u;
3913 }
3914 }
3915 } else if (errno != ENOENT)
3916 return log_error_errno(errno, "Failed open %s: %m", p);
3917 else {
3918 r = resolve_copy_blocks_auto_candidate(devno, type_uuid, restrict_devno, &found_uuid);
3919 if (r < 0)
3920 return r;
3921 if (r > 0)
3922 found = devno;
3923 }
3924
3925 if (found == 0)
3926 return log_error_errno(SYNTHETIC_ERRNO(ENXIO),
3927 "Unable to automatically discover suitable partition to copy blocks from.");
3928
3929 r = device_path_make_major_minor(S_IFBLK, found, ret_path);
3930 if (r < 0)
3931 return log_error_errno(r, "Failed to convert dev_t to device node path: %m");
3932
3933 if (ret_uuid)
3934 *ret_uuid = found_uuid;
3935
3936 return 0;
3937}
3938
3939static int context_open_copy_block_paths(
3940 Context *context,
3941 const char *root,
3942 dev_t restrict_devno) {
3943
757bc2e4
LP
3944 Partition *p;
3945 int r;
3946
3947 assert(context);
3948
3949 LIST_FOREACH(partitions, p, context->partitions) {
3950 _cleanup_close_ int source_fd = -1;
5c08da58
LP
3951 _cleanup_free_ char *opened = NULL;
3952 sd_id128_t uuid = SD_ID128_NULL;
757bc2e4
LP
3953 uint64_t size;
3954 struct stat st;
3955
3956 assert(p->copy_blocks_fd < 0);
3957 assert(p->copy_blocks_size == UINT64_MAX);
3958
3959 if (PARTITION_EXISTS(p)) /* Never copy over partitions that already exist! */
3960 continue;
3961
5c08da58 3962 if (p->copy_blocks_path) {
757bc2e4 3963
5c08da58
LP
3964 source_fd = chase_symlinks_and_open(p->copy_blocks_path, root, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC|O_NONBLOCK, &opened);
3965 if (source_fd < 0)
3966 return log_error_errno(source_fd, "Failed to open '%s': %m", p->copy_blocks_path);
757bc2e4 3967
5c08da58
LP
3968 if (fstat(source_fd, &st) < 0)
3969 return log_error_errno(errno, "Failed to stat block copy file '%s': %m", opened);
3970
3971 if (!S_ISREG(st.st_mode) && restrict_devno != (dev_t) -1)
3972 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
3973 "Copying from block device node is not permitted in --image=/--root= mode, refusing.");
3974
3975 } else if (p->copy_blocks_auto) {
3976
3977 r = resolve_copy_blocks_auto(p->type_uuid, root, restrict_devno, &opened, &uuid);
3978 if (r < 0)
3979 return r;
3980
3981 source_fd = open(opened, O_RDONLY|O_CLOEXEC|O_NOCTTY);
3982 if (source_fd < 0)
3983 return log_error_errno(errno, "Failed to open automatically determined source block copy device '%s': %m", opened);
3984
3985 if (fstat(source_fd, &st) < 0)
3986 return log_error_errno(errno, "Failed to stat block copy file '%s': %m", opened);
3987
3988 /* If we found it automatically, it must be a block device, let's enforce that */
3989 if (!S_ISBLK(st.st_mode))
3990 return log_error_errno(SYNTHETIC_ERRNO(EBADF),
3991 "Automatically detected source block copy device '%s' is not a block device, refusing: %m", opened);
3992 } else
3993 continue;
757bc2e4
LP
3994
3995 if (S_ISDIR(st.st_mode)) {
3996 _cleanup_free_ char *bdev = NULL;
3997
3998 /* If the file is a directory, automatically find the backing block device */
3999
4000 if (major(st.st_dev) != 0)
4001 r = device_path_make_major_minor(S_IFBLK, st.st_dev, &bdev);
4002 else {
4003 dev_t devt;
4004
4005 /* Special support for btrfs */
4006
4007 r = btrfs_get_block_device_fd(source_fd, &devt);
67f0ac8c 4008 if (r == -EUCLEAN)
5c08da58 4009 return btrfs_log_dev_root(LOG_ERR, r, opened);
757bc2e4 4010 if (r < 0)
5c08da58 4011 return log_error_errno(r, "Unable to determine backing block device of '%s': %m", opened);
757bc2e4
LP
4012
4013 r = device_path_make_major_minor(S_IFBLK, devt, &bdev);
4014 }
4015 if (r < 0)
5c08da58 4016 return log_error_errno(r, "Failed to determine block device path for block device backing '%s': %m", opened);
757bc2e4
LP
4017
4018 safe_close(source_fd);
4019
4020 source_fd = open(bdev, O_RDONLY|O_CLOEXEC|O_NOCTTY);
4021 if (source_fd < 0)
4022 return log_error_errno(errno, "Failed to open block device '%s': %m", bdev);
4023
4024 if (fstat(source_fd, &st) < 0)
4025 return log_error_errno(errno, "Failed to stat block device '%s': %m", bdev);
4026
4027 if (!S_ISBLK(st.st_mode))
4028 return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "Block device '%s' is not actually a block device, refusing.", bdev);
4029 }
4030
4031 if (S_ISREG(st.st_mode))
4032 size = st.st_size;
4033 else if (S_ISBLK(st.st_mode)) {
4034 if (ioctl(source_fd, BLKGETSIZE64, &size) != 0)
4035 return log_error_errno(errno, "Failed to determine size of block device to copy from: %m");
4036 } else
5c08da58 4037 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", opened);
757bc2e4
LP
4038
4039 if (size <= 0)
5c08da58 4040 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has zero size, refusing.", opened);
757bc2e4 4041 if (size % 512 != 0)
5c08da58 4042 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has size that is not multiple of 512, refusing.", opened);
757bc2e4
LP
4043
4044 p->copy_blocks_fd = TAKE_FD(source_fd);
4045 p->copy_blocks_size = size;
5c08da58
LP
4046
4047 free_and_replace(p->copy_blocks_path, opened);
4048
4049 /* When copying from an existing partition copy that partitions UUID if none is configured explicitly */
4050 if (sd_id128_is_null(p->new_uuid) && !sd_id128_is_null(uuid))
4051 p->new_uuid = uuid;
757bc2e4
LP
4052 }
4053
4054 return 0;
4055}
4056
e594a3b1
LP
4057static int help(void) {
4058 _cleanup_free_ char *link = NULL;
4059 int r;
4060
4061 r = terminal_urlify_man("systemd-repart", "1", &link);
4062 if (r < 0)
4063 return log_oom();
4064
4065 printf("%s [OPTIONS...] [DEVICE]\n"
4066 "\n%sGrow and add partitions to partition table.%s\n\n"
4067 " -h --help Show this help\n"
4068 " --version Show package version\n"
896e678b
LP
4069 " --no-pager Do not pipe output into a pager\n"
4070 " --no-legend Do not show the headers and footers\n"
e594a3b1 4071 " --dry-run=BOOL Whether to run dry-run operation\n"
a26f4a49
LP
4072 " --empty=MODE One of refuse, allow, require, force, create; controls\n"
4073 " how to handle empty disks lacking partition tables\n"
e594a3b1 4074 " --discard=BOOL Whether to discard backing blocks for new partitions\n"
2d2d0a57 4075 " --pretty=BOOL Whether to show pretty summary before doing changes\n"
e594a3b1
LP
4076 " --factory-reset=BOOL Whether to remove data partitions before recreating\n"
4077 " them\n"
4078 " --can-factory-reset Test whether factory reset is defined\n"
4079 " --root=PATH Operate relative to root path\n"
252d6267 4080 " --image=PATH Operate relative to image file\n"
9d252fbb 4081 " --definitions=DIR Find partition definitions in specified directory\n"
b9df3536 4082 " --key-file=PATH Key to use when encrypting partitions\n"
889914ef 4083 " --tpm2-device=PATH Path to TPM2 device node to use\n"
a1788a69 4084 " --tpm2-pcrs=PCR1+PCR2+PCR3+…\n"
889914ef 4085 " TPM2 PCR indexes to use for TPM2 enrollment\n"
e594a3b1 4086 " --seed=UUID 128bit seed UUID to derive all UUIDs from\n"
a26f4a49 4087 " --size=BYTES Grow loopback file to specified size\n"
2d2d0a57 4088 " --json=pretty|short|off\n"
de8231b0 4089 " Generate JSON output\n"
bc556335
DDM
4090 "\nSee the %s for details.\n",
4091 program_invocation_short_name,
4092 ansi_highlight(),
4093 ansi_normal(),
4094 link);
e594a3b1
LP
4095
4096 return 0;
4097}
4098
4099static int parse_argv(int argc, char *argv[]) {
4100
4101 enum {
4102 ARG_VERSION = 0x100,
896e678b
LP
4103 ARG_NO_PAGER,
4104 ARG_NO_LEGEND,
e594a3b1
LP
4105 ARG_DRY_RUN,
4106 ARG_EMPTY,
4107 ARG_DISCARD,
4108 ARG_FACTORY_RESET,
4109 ARG_CAN_FACTORY_RESET,
4110 ARG_ROOT,
252d6267 4111 ARG_IMAGE,
e594a3b1
LP
4112 ARG_SEED,
4113 ARG_PRETTY,
4114 ARG_DEFINITIONS,
a26f4a49 4115 ARG_SIZE,
a015fbe7 4116 ARG_JSON,
b9df3536 4117 ARG_KEY_FILE,
889914ef
LP
4118 ARG_TPM2_DEVICE,
4119 ARG_TPM2_PCRS,
e594a3b1
LP
4120 };
4121
4122 static const struct option options[] = {
4123 { "help", no_argument, NULL, 'h' },
4124 { "version", no_argument, NULL, ARG_VERSION },
896e678b
LP
4125 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4126 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
e594a3b1
LP
4127 { "dry-run", required_argument, NULL, ARG_DRY_RUN },
4128 { "empty", required_argument, NULL, ARG_EMPTY },
4129 { "discard", required_argument, NULL, ARG_DISCARD },
4130 { "factory-reset", required_argument, NULL, ARG_FACTORY_RESET },
4131 { "can-factory-reset", no_argument, NULL, ARG_CAN_FACTORY_RESET },
4132 { "root", required_argument, NULL, ARG_ROOT },
252d6267 4133 { "image", required_argument, NULL, ARG_IMAGE },
e594a3b1
LP
4134 { "seed", required_argument, NULL, ARG_SEED },
4135 { "pretty", required_argument, NULL, ARG_PRETTY },
4136 { "definitions", required_argument, NULL, ARG_DEFINITIONS },
a26f4a49 4137 { "size", required_argument, NULL, ARG_SIZE },
a015fbe7 4138 { "json", required_argument, NULL, ARG_JSON },
b9df3536 4139 { "key-file", required_argument, NULL, ARG_KEY_FILE },
889914ef
LP
4140 { "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE },
4141 { "tpm2-pcrs", required_argument, NULL, ARG_TPM2_PCRS },
e594a3b1
LP
4142 {}
4143 };
4144
a26f4a49 4145 int c, r, dry_run = -1;
e594a3b1
LP
4146
4147 assert(argc >= 0);
4148 assert(argv);
4149
4150 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
4151
4152 switch (c) {
4153
4154 case 'h':
4155 return help();
4156
4157 case ARG_VERSION:
4158 return version();
4159
896e678b
LP
4160 case ARG_NO_PAGER:
4161 arg_pager_flags |= PAGER_DISABLE;
4162 break;
4163
4164 case ARG_NO_LEGEND:
4165 arg_legend = false;
4166 break;
4167
e594a3b1 4168 case ARG_DRY_RUN:
599c7c54 4169 r = parse_boolean_argument("--dry-run=", optarg, &arg_dry_run);
e594a3b1 4170 if (r < 0)
599c7c54 4171 return r;
e594a3b1
LP
4172 break;
4173
4174 case ARG_EMPTY:
4175 if (isempty(optarg) || streq(optarg, "refuse"))
4176 arg_empty = EMPTY_REFUSE;
4177 else if (streq(optarg, "allow"))
4178 arg_empty = EMPTY_ALLOW;
4179 else if (streq(optarg, "require"))
4180 arg_empty = EMPTY_REQUIRE;
4181 else if (streq(optarg, "force"))
4182 arg_empty = EMPTY_FORCE;
a26f4a49
LP
4183 else if (streq(optarg, "create")) {
4184 arg_empty = EMPTY_CREATE;
4185
4186 if (dry_run < 0)
4187 dry_run = false; /* Imply --dry-run=no if we create the loopback file
4188 * anew. After all we cannot really break anyone's
4189 * partition tables that way. */
4190 } else
e594a3b1
LP
4191 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
4192 "Failed to parse --empty= parameter: %s", optarg);
4193 break;
4194
4195 case ARG_DISCARD:
599c7c54 4196 r = parse_boolean_argument("--discard=", optarg, &arg_discard);
e594a3b1 4197 if (r < 0)
599c7c54 4198 return r;
e594a3b1
LP
4199 break;
4200
4201 case ARG_FACTORY_RESET:
c3470872 4202 r = parse_boolean_argument("--factory-reset=", optarg, NULL);
e594a3b1 4203 if (r < 0)
c3470872 4204 return r;
e594a3b1
LP
4205 arg_factory_reset = r;
4206 break;
4207
4208 case ARG_CAN_FACTORY_RESET:
4209 arg_can_factory_reset = true;
4210 break;
4211
4212 case ARG_ROOT:
252d6267
LP
4213 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_root);
4214 if (r < 0)
4215 return r;
4216 break;
4217
4218 case ARG_IMAGE:
4219 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image);
e594a3b1
LP
4220 if (r < 0)
4221 return r;
4222 break;
4223
4224 case ARG_SEED:
4225 if (isempty(optarg)) {
4226 arg_seed = SD_ID128_NULL;
4227 arg_randomize = false;
4228 } else if (streq(optarg, "random"))
4229 arg_randomize = true;
4230 else {
4231 r = sd_id128_from_string(optarg, &arg_seed);
4232 if (r < 0)
4233 return log_error_errno(r, "Failed to parse seed: %s", optarg);
4234
4235 arg_randomize = false;
4236 }
4237
4238 break;
4239
4240 case ARG_PRETTY:
c3470872 4241 r = parse_boolean_argument("--pretty=", optarg, NULL);
e594a3b1 4242 if (r < 0)
c3470872 4243 return r;
e594a3b1
LP
4244 arg_pretty = r;
4245 break;
4246
4247 case ARG_DEFINITIONS:
614b022c 4248 r = parse_path_argument(optarg, false, &arg_definitions);
e594a3b1
LP
4249 if (r < 0)
4250 return r;
4251 break;
4252
a26f4a49
LP
4253 case ARG_SIZE: {
4254 uint64_t parsed, rounded;
4255
170c9823
LP
4256 if (streq(optarg, "auto")) {
4257 arg_size = UINT64_MAX;
4258 arg_size_auto = true;
4259 break;
4260 }
4261
a26f4a49
LP
4262 r = parse_size(optarg, 1024, &parsed);
4263 if (r < 0)
4264 return log_error_errno(r, "Failed to parse --size= parameter: %s", optarg);
4265
4266 rounded = round_up_size(parsed, 4096);
4267 if (rounded == 0)
4268 return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Specified image size too small, refusing.");
4269 if (rounded == UINT64_MAX)
4270 return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Specified image size too large, refusing.");
4271
4272 if (rounded != parsed)
4273 log_warning("Specified size is not a multiple of 4096, rounding up automatically. (%" PRIu64 " → %" PRIu64 ")",
4274 parsed, rounded);
4275
4276 arg_size = rounded;
170c9823 4277 arg_size_auto = false;
a26f4a49
LP
4278 break;
4279 }
b9df3536 4280
a015fbe7 4281 case ARG_JSON:
b1e8f46c 4282 r = parse_json_argument(optarg, &arg_json_format_flags);
6a01ea4a
LP
4283 if (r <= 0)
4284 return r;
a015fbe7
TH
4285
4286 break;
4287
b9df3536
LP
4288 case ARG_KEY_FILE: {
4289 _cleanup_(erase_and_freep) char *k = NULL;
4290 size_t n = 0;
4291
8b3c3a49 4292 r = read_full_file_full(
986311c2 4293 AT_FDCWD, optarg, UINT64_MAX, SIZE_MAX,
8b3c3a49
LP
4294 READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
4295 NULL,
4296 &k, &n);
b9df3536
LP
4297 if (r < 0)
4298 return log_error_errno(r, "Failed to read key file '%s': %m", optarg);
4299
4300 erase_and_free(arg_key);
4301 arg_key = TAKE_PTR(k);
4302 arg_key_size = n;
4303 break;
4304 }
a26f4a49 4305
889914ef
LP
4306 case ARG_TPM2_DEVICE: {
4307 _cleanup_free_ char *device = NULL;
4308
4309 if (streq(optarg, "list"))
4310 return tpm2_list_devices();
4311
4312 if (!streq(optarg, "auto")) {
4313 device = strdup(optarg);
4314 if (!device)
4315 return log_oom();
4316 }
4317
4318 free(arg_tpm2_device);
4319 arg_tpm2_device = TAKE_PTR(device);
4320 break;
4321 }
4322
4323 case ARG_TPM2_PCRS: {
4324 uint32_t mask;
4325
4326 if (isempty(optarg)) {
4327 arg_tpm2_pcr_mask = 0;
4328 break;
4329 }
4330
4331 r = tpm2_parse_pcrs(optarg, &mask);
4332 if (r < 0)
4333 return r;
4334
4335 if (arg_tpm2_pcr_mask == UINT32_MAX)
4336 arg_tpm2_pcr_mask = mask;
4337 else
4338 arg_tpm2_pcr_mask |= mask;
4339
4340 break;
4341 }
4342
e594a3b1
LP
4343 case '?':
4344 return -EINVAL;
4345
4346 default:
04499a70 4347 assert_not_reached();
e594a3b1
LP
4348 }
4349
4350 if (argc - optind > 1)
4351 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
4352 "Expected at most one argument, the path to the block device.");
4353
a26f4a49 4354 if (arg_factory_reset > 0 && IN_SET(arg_empty, EMPTY_FORCE, EMPTY_REQUIRE, EMPTY_CREATE))
e594a3b1 4355 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
a26f4a49 4356 "Combination of --factory-reset=yes and --empty=force/--empty=require/--empty=create is invalid.");
e594a3b1
LP
4357
4358 if (arg_can_factory_reset)
a26f4a49
LP
4359 arg_dry_run = true; /* When --can-factory-reset is specified we don't make changes, hence
4360 * non-dry-run mode makes no sense. Thus, imply dry run mode so that we
4361 * open things strictly read-only. */
4362 else if (dry_run >= 0)
4363 arg_dry_run = dry_run;
4364
170c9823 4365 if (arg_empty == EMPTY_CREATE && (arg_size == UINT64_MAX && !arg_size_auto))
a26f4a49
LP
4366 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
4367 "If --empty=create is specified, --size= must be specified, too.");
e594a3b1 4368
252d6267
LP
4369 if (arg_image && arg_root)
4370 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported.");
4371 else if (!arg_image && !arg_root && in_initrd()) {
8f47e32a
LP
4372
4373 /* By default operate on /sysusr/ or /sysroot/ when invoked in the initrd. We prefer the
4374 * former, if it is mounted, so that we have deterministic behaviour on systems where /usr/
4375 * is vendor-supplied but the root fs formatted on first boot. */
4376 r = path_is_mount_point("/sysusr/usr", NULL, 0);
4377 if (r <= 0) {
4378 if (r < 0 && r != -ENOENT)
4379 log_debug_errno(r, "Unable to determine whether /sysusr/usr is a mount point, assuming it is not: %m");
4380
4381 arg_root = strdup("/sysroot");
4382 } else
4383 arg_root = strdup("/sysusr");
252d6267
LP
4384 if (!arg_root)
4385 return log_oom();
4386 }
4387
e594a3b1 4388 arg_node = argc > optind ? argv[optind] : NULL;
a26f4a49 4389
252d6267 4390 if (IN_SET(arg_empty, EMPTY_FORCE, EMPTY_REQUIRE, EMPTY_CREATE) && !arg_node && !arg_image)
a26f4a49
LP
4391 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
4392 "A path to a device node or loopback file must be specified when --empty=force, --empty=require or --empty=create are used.");
4393
889914ef
LP
4394 if (arg_tpm2_pcr_mask == UINT32_MAX)
4395 arg_tpm2_pcr_mask = TPM2_PCR_MASK_DEFAULT;
4396
e594a3b1
LP
4397 return 1;
4398}
4399
4400static int parse_proc_cmdline_factory_reset(void) {
4401 bool b;
4402 int r;
4403
4404 if (arg_factory_reset >= 0) /* Never override what is specified on the process command line */
4405 return 0;
4406
4407 if (!in_initrd()) /* Never honour kernel command line factory reset request outside of the initrd */
4408 return 0;
4409
4410 r = proc_cmdline_get_bool("systemd.factory_reset", &b);
4411 if (r < 0)
4412 return log_error_errno(r, "Failed to parse systemd.factory_reset kernel command line argument: %m");
4413 if (r > 0) {
4414 arg_factory_reset = b;
4415
4416 if (b)
4417 log_notice("Honouring factory reset requested via kernel command line.");
4418 }
4419
4420 return 0;
4421}
4422
4423static int parse_efi_variable_factory_reset(void) {
4424 _cleanup_free_ char *value = NULL;
4425 int r;
4426
4427 if (arg_factory_reset >= 0) /* Never override what is specified on the process command line */
4428 return 0;
4429
4430 if (!in_initrd()) /* Never honour EFI variable factory reset request outside of the initrd */
4431 return 0;
4432
e6f055cb 4433 r = efi_get_variable_string(EFI_SYSTEMD_VARIABLE(FactoryReset), &value);
e594a3b1
LP
4434 if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r))
4435 return 0;
4436 if (r < 0)
4437 return log_error_errno(r, "Failed to read EFI variable FactoryReset: %m");
4438
4439 r = parse_boolean(value);
4440 if (r < 0)
4441 return log_error_errno(r, "Failed to parse EFI variable FactoryReset: %m");
4442
4443 arg_factory_reset = r;
4444 if (r)
111a3aae 4445 log_notice("Factory reset requested via EFI variable FactoryReset.");
e594a3b1
LP
4446
4447 return 0;
4448}
4449
4450static int remove_efi_variable_factory_reset(void) {
4451 int r;
4452
e6f055cb 4453 r = efi_set_variable(EFI_SYSTEMD_VARIABLE(FactoryReset), NULL, 0);
e594a3b1
LP
4454 if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r))
4455 return 0;
4456 if (r < 0)
4457 return log_error_errno(r, "Failed to remove EFI variable FactoryReset: %m");
4458
4459 log_info("Successfully unset EFI variable FactoryReset.");
4460 return 0;
4461}
4462
252d6267
LP
4463static int acquire_root_devno(
4464 const char *p,
4465 const char *root,
4466 int mode,
4467 char **ret,
4468 int *ret_fd) {
4469
4470 _cleanup_free_ char *found_path = NULL;
4471 dev_t devno, fd_devno = MODE_INVALID;
e594a3b1
LP
4472 _cleanup_close_ int fd = -1;
4473 struct stat st;
e594a3b1
LP
4474 int r;
4475
a26f4a49
LP
4476 assert(p);
4477 assert(ret);
4478 assert(ret_fd);
4479
252d6267 4480 fd = chase_symlinks_and_open(p, root, CHASE_PREFIX_ROOT, mode, &found_path);
e594a3b1 4481 if (fd < 0)
252d6267 4482 return fd;
e594a3b1
LP
4483
4484 if (fstat(fd, &st) < 0)
4485 return -errno;
4486
4487 if (S_ISREG(st.st_mode)) {
252d6267 4488 *ret = TAKE_PTR(found_path);
a26f4a49 4489 *ret_fd = TAKE_FD(fd);
e594a3b1
LP
4490 return 0;
4491 }
4492
252d6267
LP
4493 if (S_ISBLK(st.st_mode)) {
4494 /* Refuse referencing explicit block devices if a root dir is specified, after all we should
5c08da58 4495 * not be able to leave the image the root path constrains us to. */
252d6267
LP
4496 if (root)
4497 return -EPERM;
4498
a26f4a49 4499 fd_devno = devno = st.st_rdev;
252d6267 4500 } else if (S_ISDIR(st.st_mode)) {
e594a3b1
LP
4501
4502 devno = st.st_dev;
a26f4a49 4503 if (major(devno) == 0) {
e594a3b1
LP
4504 r = btrfs_get_block_device_fd(fd, &devno);
4505 if (r == -ENOTTY) /* not btrfs */
4506 return -ENODEV;
4507 if (r < 0)
4508 return r;
4509 }
e594a3b1
LP
4510 } else
4511 return -ENOTBLK;
4512
4513 /* From dm-crypt to backing partition */
4514 r = block_get_originating(devno, &devno);
8e5f3cec
LP
4515 if (r == -ENOENT)
4516 log_debug_errno(r, "Device '%s' has no dm-crypt/dm-verity device, no need to look for underlying block device.", p);
4517 else if (r < 0)
e594a3b1
LP
4518 log_debug_errno(r, "Failed to find underlying block device for '%s', ignoring: %m", p);
4519
4520 /* From partition to whole disk containing it */
4521 r = block_get_whole_disk(devno, &devno);
4522 if (r < 0)
162392b7 4523 log_debug_errno(r, "Failed to find whole disk block device for '%s', ignoring: %m", p);
e594a3b1 4524
a26f4a49
LP
4525 r = device_path_make_canonical(S_IFBLK, devno, ret);
4526 if (r < 0)
4527 return log_debug_errno(r, "Failed to determine canonical path for '%s': %m", p);
4528
6bbae9f8 4529 /* Only if we still look at the same block device we can reuse the fd. Otherwise return an
a26f4a49 4530 * invalidated fd. */
f5fbe71d 4531 *ret_fd = fd_devno != MODE_INVALID && fd_devno == devno ? TAKE_FD(fd) : -1;
a26f4a49 4532 return 0;
e594a3b1
LP
4533}
4534
a26f4a49 4535static int find_root(char **ret, int *ret_fd) {
6bbae9f8 4536 const char *p;
e594a3b1 4537 int r;
54632d2e 4538 _cleanup_free_ char *device = NULL;
e594a3b1 4539
a26f4a49
LP
4540 assert(ret);
4541 assert(ret_fd);
4542
e594a3b1 4543 if (arg_node) {
a26f4a49
LP
4544 if (arg_empty == EMPTY_CREATE) {
4545 _cleanup_close_ int fd = -1;
4546 _cleanup_free_ char *s = NULL;
4547
4548 s = strdup(arg_node);
4549 if (!s)
4550 return log_oom();
4551
5332d7c6 4552 fd = open(arg_node, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOFOLLOW, 0666);
a26f4a49
LP
4553 if (fd < 0)
4554 return log_error_errno(errno, "Failed to create '%s': %m", arg_node);
4555
4556 *ret = TAKE_PTR(s);
4557 *ret_fd = TAKE_FD(fd);
4558 return 0;
4559 }
4560
252d6267
LP
4561 /* Note that we don't specify a root argument here: if the user explicitly configured a node
4562 * we'll take it relative to the host, not the image */
4563 r = acquire_root_devno(arg_node, NULL, O_RDONLY|O_CLOEXEC, ret, ret_fd);
67f0ac8c
LP
4564 if (r == -EUCLEAN)
4565 return btrfs_log_dev_root(LOG_ERR, r, arg_node);
e594a3b1 4566 if (r < 0)
aa2a74ad 4567 return log_error_errno(r, "Failed to open file or determine backing device of %s: %m", arg_node);
e594a3b1
LP
4568
4569 return 0;
4570 }
4571
a26f4a49
LP
4572 assert(IN_SET(arg_empty, EMPTY_REFUSE, EMPTY_ALLOW));
4573
54632d2e
KK
4574 /* If the root mount has been replaced by some form of volatile file system (overlayfs), the
4575 * original root block device node is symlinked in /run/systemd/volatile-root. Let's read that
4576 * here. */
4577 r = readlink_malloc("/run/systemd/volatile-root", &device);
4578 if (r == -ENOENT) { /* volatile-root not found */
4579 /* Let's search for the root device. We look for two cases here: first in /, and then in /usr. The
4580 * latter we check for cases where / is a tmpfs and only /usr is an actual persistent block device
4581 * (think: volatile setups) */
e594a3b1 4582
54632d2e 4583 FOREACH_STRING(p, "/", "/usr") {
e594a3b1 4584
54632d2e
KK
4585 r = acquire_root_devno(p, arg_root, O_RDONLY|O_DIRECTORY|O_CLOEXEC, ret, ret_fd);
4586 if (r < 0) {
4587 if (r == -EUCLEAN)
4588 return btrfs_log_dev_root(LOG_ERR, r, p);
4589 if (r != -ENODEV)
4590 return log_error_errno(r, "Failed to determine backing device of %s: %m", p);
4591 } else
4592 return 0;
4593 }
4594 } else if (r < 0)
4595 return log_error_errno(r, "Failed to read symlink /run/systemd/volatile-root: %m");
4596 else {
4597 r = acquire_root_devno(device, NULL, O_RDONLY|O_CLOEXEC, ret, ret_fd);
4598 if (r == -EUCLEAN)
4599 return btrfs_log_dev_root(LOG_ERR, r, device);
4600 if (r < 0)
4601 return log_error_errno(r, "Failed to open file or determine backing device of %s: %m", device);
4602
4603 return 0;
e594a3b1
LP
4604 }
4605
4606 return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "Failed to discover root block device.");
4607}
4608
f9b3afae 4609static int resize_pt(int fd) {
f9b3afae
LP
4610 _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
4611 int r;
4612
4613 /* After resizing the backing file we need to resize the partition table itself too, so that it takes
4614 * possession of the enlarged backing file. For this it suffices to open the device with libfdisk and
4615 * immediately write it again, with no changes. */
4616
4617 c = fdisk_new_context();
4618 if (!c)
4619 return log_oom();
4620
ddb6eeaf 4621 r = fdisk_assign_device(c, FORMAT_PROC_FD_PATH(fd), 0);
f9b3afae 4622 if (r < 0)
ddb6eeaf 4623 return log_error_errno(r, "Failed to open device '%s': %m", FORMAT_PROC_FD_PATH(fd));
f9b3afae
LP
4624
4625 r = fdisk_has_label(c);
4626 if (r < 0)
ddb6eeaf 4627 return log_error_errno(r, "Failed to determine whether disk '%s' has a disk label: %m", FORMAT_PROC_FD_PATH(fd));
f9b3afae
LP
4628 if (r == 0) {
4629 log_debug("Not resizing partition table, as there currently is none.");
4630 return 0;
4631 }
4632
4633 r = fdisk_write_disklabel(c);
4634 if (r < 0)
4635 return log_error_errno(r, "Failed to write resized partition table: %m");
4636
4637 log_info("Resized partition table.");
4638 return 1;
4639}
4640
252d6267
LP
4641static int resize_backing_fd(
4642 const char *node, /* The primary way we access the disk image to operate on */
4643 int *fd, /* An O_RDONLY fd referring to that inode */
4644 const char *backing_file, /* If the above refers to a loopback device, the backing regular file for that, which we can grow */
4645 LoopDevice *loop_device) {
4646
a26f4a49 4647 _cleanup_close_ int writable_fd = -1;
252d6267 4648 uint64_t current_size;
a26f4a49
LP
4649 struct stat st;
4650 int r;
4651
4652 assert(node);
4653 assert(fd);
4654
4655 if (arg_size == UINT64_MAX) /* Nothing to do */
4656 return 0;
4657
4658 if (*fd < 0) {
4659 /* Open the file if we haven't opened it yet. Note that we open it read-only here, just to
4660 * keep a reference to the file we can pass around. */
4661 *fd = open(node, O_RDONLY|O_CLOEXEC);
4662 if (*fd < 0)
4663 return log_error_errno(errno, "Failed to open '%s' in order to adjust size: %m", node);
4664 }
4665
4666 if (fstat(*fd, &st) < 0)
4667 return log_error_errno(errno, "Failed to stat '%s': %m", node);
4668
252d6267
LP
4669 if (S_ISBLK(st.st_mode)) {
4670 if (!backing_file)
4671 return log_error_errno(SYNTHETIC_ERRNO(EBADF), "Cannot resize block device '%s'.", node);
4672
4673 assert(loop_device);
a26f4a49 4674
252d6267
LP
4675 if (ioctl(*fd, BLKGETSIZE64, &current_size) < 0)
4676 return log_error_errno(errno, "Failed to determine size of block device %s: %m", node);
4677 } else {
4678 r = stat_verify_regular(&st);
4679 if (r < 0)
4680 return log_error_errno(r, "Specified path '%s' is not a regular file or loopback block device, cannot resize: %m", node);
4681
4682 assert(!backing_file);
4683 assert(!loop_device);
4684 current_size = st.st_size;
4685 }
4686
252d6267 4687 if (current_size >= arg_size) {
2b59bf51
ZJS
4688 log_info("File '%s' already is of requested size or larger, not growing. (%s >= %s)",
4689 node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
a26f4a49
LP
4690 return 0;
4691 }
4692
252d6267
LP
4693 if (S_ISBLK(st.st_mode)) {
4694 assert(backing_file);
4695
4696 /* This is a loopback device. We can't really grow those directly, but we can grow the
4697 * backing file, hence let's do that. */
4698
4699 writable_fd = open(backing_file, O_WRONLY|O_CLOEXEC|O_NONBLOCK);
4700 if (writable_fd < 0)
4701 return log_error_errno(errno, "Failed to open backing file '%s': %m", backing_file);
4702
4703 if (fstat(writable_fd, &st) < 0)
4704 return log_error_errno(errno, "Failed to stat() backing file '%s': %m", backing_file);
4705
4706 r = stat_verify_regular(&st);
4707 if (r < 0)
4708 return log_error_errno(r, "Backing file '%s' of block device is not a regular file: %m", backing_file);
4709
4710 if ((uint64_t) st.st_size != current_size)
4711 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2b59bf51
ZJS
4712 "Size of backing file '%s' of loopback block device '%s' don't match, refusing.",
4713 node, backing_file);
252d6267
LP
4714 } else {
4715 assert(S_ISREG(st.st_mode));
4716 assert(!backing_file);
a26f4a49 4717
252d6267
LP
4718 /* The file descriptor is read-only. In order to grow the file we need to have a writable fd. We
4719 * reopen the file for that temporarily. We keep the writable fd only open for this operation though,
4720 * as fdisk can't accept it anyway. */
4721
4722 writable_fd = fd_reopen(*fd, O_WRONLY|O_CLOEXEC);
4723 if (writable_fd < 0)
4724 return log_error_errno(writable_fd, "Failed to reopen backing file '%s' writable: %m", node);
4725 }
a26f4a49
LP
4726
4727 if (!arg_discard) {
4728 if (fallocate(writable_fd, 0, 0, arg_size) < 0) {
4729 if (!ERRNO_IS_NOT_SUPPORTED(errno))
4730 return log_error_errno(errno, "Failed to grow '%s' from %s to %s by allocation: %m",
2b59bf51 4731 node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
a26f4a49
LP
4732
4733 /* Fallback to truncation, if fallocate() is not supported. */
4734 log_debug("Backing file system does not support fallocate(), falling back to ftruncate().");
4735 } else {
252d6267 4736 if (current_size == 0) /* Likely regular file just created by us */
2b59bf51 4737 log_info("Allocated %s for '%s'.", FORMAT_BYTES(arg_size), node);
a26f4a49 4738 else
2b59bf51
ZJS
4739 log_info("File '%s' grown from %s to %s by allocation.",
4740 node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
a26f4a49 4741
252d6267 4742 goto done;
a26f4a49
LP
4743 }
4744 }
4745
4746 if (ftruncate(writable_fd, arg_size) < 0)
4747 return log_error_errno(errno, "Failed to grow '%s' from %s to %s by truncation: %m",
2b59bf51 4748 node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
a26f4a49 4749
252d6267 4750 if (current_size == 0) /* Likely regular file just created by us */
2b59bf51 4751 log_info("Sized '%s' to %s.", node, FORMAT_BYTES(arg_size));
252d6267 4752 else
2b59bf51
ZJS
4753 log_info("File '%s' grown from %s to %s by truncation.",
4754 node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
252d6267
LP
4755
4756done:
f9b3afae
LP
4757 r = resize_pt(writable_fd);
4758 if (r < 0)
4759 return r;
4760
252d6267
LP
4761 if (loop_device) {
4762 r = loop_device_refresh_size(loop_device, UINT64_MAX, arg_size);
4763 if (r < 0)
4764 return log_error_errno(r, "Failed to update loop device size: %m");
4765 }
a26f4a49
LP
4766
4767 return 1;
4768}
4769
170c9823
LP
4770static int determine_auto_size(Context *c) {
4771 uint64_t sum = round_up_size(GPT_METADATA_SIZE, 4096);
170c9823
LP
4772 Partition *p;
4773
4774 assert_se(c);
170c9823
LP
4775
4776 LIST_FOREACH(partitions, p, c->partitions) {
4777 uint64_t m;
4778
4779 if (p->dropped)
4780 continue;
4781
4782 m = partition_min_size_with_padding(p);
4783 if (m > UINT64_MAX - sum)
4784 return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "Image would grow too large, refusing.");
4785
4786 sum += m;
4787 }
4788
2b59bf51
ZJS
4789 if (c->total != UINT64_MAX)
4790 /* Image already allocated? Then show its size. */
4791 log_info("Automatically determined minimal disk image size as %s, current image size is %s.",
4792 FORMAT_BYTES(sum), FORMAT_BYTES(c->total));
4793 else
4794 /* If the image is being created right now, then it has no previous size, suppress any comment about it hence. */
4795 log_info("Automatically determined minimal disk image size as %s.",
4796 FORMAT_BYTES(sum));
170c9823
LP
4797
4798 arg_size = sum;
4799 return 0;
4800}
4801
e594a3b1 4802static int run(int argc, char *argv[]) {
252d6267
LP
4803 _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
4804 _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
4805 _cleanup_(umount_and_rmdir_and_freep) char *mounted_dir = NULL;
e594a3b1
LP
4806 _cleanup_(context_freep) Context* context = NULL;
4807 _cleanup_free_ char *node = NULL;
a26f4a49 4808 _cleanup_close_ int backing_fd = -1;
252d6267 4809 bool from_scratch, node_is_our_loop = false;
e594a3b1
LP
4810 int r;
4811
4812 log_show_color(true);
4813 log_parse_environment();
4814 log_open();
4815
e594a3b1
LP
4816 r = parse_argv(argc, argv);
4817 if (r <= 0)
4818 return r;
4819
4820 r = parse_proc_cmdline_factory_reset();
4821 if (r < 0)
4822 return r;
4823
4824 r = parse_efi_variable_factory_reset();
4825 if (r < 0)
4826 return r;
4827
252d6267
LP
4828 if (arg_image) {
4829 assert(!arg_root);
4830
4831 /* Mount this strictly read-only: we shall modify the partition table, not the file
4832 * systems */
4833 r = mount_image_privately_interactively(
4834 arg_image,
4835 DISSECT_IMAGE_MOUNT_READ_ONLY |
4836 (arg_node ? DISSECT_IMAGE_DEVICE_READ_ONLY : 0) | /* If a different node to make changes to is specified let's open the device in read-only mode) */
4837 DISSECT_IMAGE_GPT_ONLY |
4838 DISSECT_IMAGE_RELAX_VAR_CHECK |
4839 DISSECT_IMAGE_USR_NO_ROOT |
4840 DISSECT_IMAGE_REQUIRE_ROOT,
4841 &mounted_dir,
4842 &loop_device,
4843 &decrypted_image);
4844 if (r < 0)
4845 return r;
4846
4847 arg_root = strdup(mounted_dir);
4848 if (!arg_root)
4849 return log_oom();
4850
4851 if (!arg_node) {
4852 arg_node = strdup(loop_device->node);
4853 if (!arg_node)
4854 return log_oom();
4855
3d62af7d 4856 /* Remember that the device we are about to manipulate is actually the one we
252d6267
LP
4857 * allocated here, and thus to increase its backing file we know what to do */
4858 node_is_our_loop = true;
4859 }
4860 }
4861
e594a3b1
LP
4862 context = context_new(arg_seed);
4863 if (!context)
4864 return log_oom();
4865
4866 r = context_read_definitions(context, arg_definitions, arg_root);
4867 if (r < 0)
4868 return r;
4869
a26f4a49 4870 if (context->n_partitions <= 0 && arg_empty == EMPTY_REFUSE) {
e2d65cd2 4871 log_info("Didn't find any partition definition files, nothing to do.");
0ae5ffe0 4872 return 0;
e2d65cd2 4873 }
0ae5ffe0 4874
a26f4a49 4875 r = find_root(&node, &backing_fd);
0ae5ffe0
YW
4876 if (r < 0)
4877 return r;
4878
a26f4a49 4879 if (arg_size != UINT64_MAX) {
252d6267
LP
4880 r = resize_backing_fd(
4881 node,
4882 &backing_fd,
4883 node_is_our_loop ? arg_image : NULL,
4884 node_is_our_loop ? loop_device : NULL);
a26f4a49
LP
4885 if (r < 0)
4886 return r;
4887 }
4888
4889 r = context_load_partition_table(context, node, &backing_fd);
e594a3b1
LP
4890 if (r == -EHWPOISON)
4891 return 77; /* Special return value which means "Not GPT, so not doing anything". This isn't
4892 * really an error when called at boot. */
4893 if (r < 0)
4894 return r;
4895 from_scratch = r > 0; /* Starting from scratch */
4896
4897 if (arg_can_factory_reset) {
4898 r = context_can_factory_reset(context);
4899 if (r < 0)
4900 return r;
4901 if (r == 0)
4902 return EXIT_FAILURE;
4903
4904 return 0;
4905 }
4906
4907 r = context_factory_reset(context, from_scratch);
4908 if (r < 0)
4909 return r;
4910 if (r > 0) {
4911 /* We actually did a factory reset! */
4912 r = remove_efi_variable_factory_reset();
4913 if (r < 0)
4914 return r;
4915
4916 /* Reload the reduced partition table */
4917 context_unload_partition_table(context);
a26f4a49 4918 r = context_load_partition_table(context, node, &backing_fd);
e594a3b1
LP
4919 if (r < 0)
4920 return r;
4921 }
4922
4923#if 0
4924 (void) context_dump_partitions(context, node);
4925 putchar('\n');
4926#endif
4927
4928 r = context_read_seed(context, arg_root);
4929 if (r < 0)
4930 return r;
4931
757bc2e4 4932 /* Open all files to copy blocks from now, since we want to take their size into consideration */
5c08da58
LP
4933 r = context_open_copy_block_paths(
4934 context,
4935 arg_root,
7802194a 4936 loop_device ? loop_device->devno : /* if --image= is specified, only allow partitions on the loopback device */
5c08da58
LP
4937 arg_root && !arg_image ? 0 : /* if --root= is specified, don't accept any block device */
4938 (dev_t) -1); /* if neither is specified, make no restrictions */
757bc2e4
LP
4939 if (r < 0)
4940 return r;
4941
170c9823
LP
4942 if (arg_size_auto) {
4943 r = determine_auto_size(context);
4944 if (r < 0)
4945 return r;
4946
4947 /* Flush out everything again, and let's grow the file first, then start fresh */
4948 context_unload_partition_table(context);
4949
4950 assert_se(arg_size != UINT64_MAX);
252d6267
LP
4951 r = resize_backing_fd(
4952 node,
4953 &backing_fd,
4954 node_is_our_loop ? arg_image : NULL,
4955 node_is_our_loop ? loop_device : NULL);
170c9823
LP
4956 if (r < 0)
4957 return r;
4958
4959 r = context_load_partition_table(context, node, &backing_fd);
4960 if (r < 0)
4961 return r;
4962 }
4963
e594a3b1
LP
4964 /* First try to fit new partitions in, dropping by priority until it fits */
4965 for (;;) {
14a4c4ed
LP
4966 uint64_t largest_free_area;
4967
4968 if (context_allocate_partitions(context, &largest_free_area))
e594a3b1
LP
4969 break; /* Success! */
4970
d17db7b2
LP
4971 if (!context_drop_one_priority(context)) {
4972 r = log_error_errno(SYNTHETIC_ERRNO(ENOSPC),
14a4c4ed 4973 "Can't fit requested partitions into available free space (%s), refusing.",
2b59bf51 4974 FORMAT_BYTES(largest_free_area));
d17db7b2
LP
4975 determine_auto_size(context);
4976 return r;
4977 }
e594a3b1
LP
4978 }
4979
4980 /* Now assign free space according to the weight logic */
4981 r = context_grow_partitions(context);
4982 if (r < 0)
4983 return r;
4984
4985 /* Now calculate where each partition gets placed */
4986 context_place_partitions(context);
4987
4988 /* Make sure each partition has a unique UUID and unique label */
4989 r = context_acquire_partition_uuids_and_labels(context);
4990 if (r < 0)
4991 return r;
4992
4993 r = context_write_partition_table(context, node, from_scratch);
4994 if (r < 0)
4995 return r;
4996
4997 return 0;
4998}
4999
5000DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);