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