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