]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/partition/repart.c
portabled: implement container host os-release interface
[thirdparty/systemd.git] / src / partition / repart.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
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"
27 #include "def.h"
28 #include "efivars.h"
29 #include "errno-util.h"
30 #include "fd-util.h"
31 #include "format-table.h"
32 #include "format-util.h"
33 #include "fs-util.h"
34 #include "gpt.h"
35 #include "id128-util.h"
36 #include "list.h"
37 #include "locale-util.h"
38 #include "main-func.h"
39 #include "parse-util.h"
40 #include "path-util.h"
41 #include "pretty-print.h"
42 #include "proc-cmdline.h"
43 #include "sort-util.h"
44 #include "specifier.h"
45 #include "stat-util.h"
46 #include "stdio-util.h"
47 #include "string-util.h"
48 #include "strv.h"
49 #include "terminal-util.h"
50 #include "utf8.h"
51
52 /* If not configured otherwise use a minimal partition size of 10M */
53 #define DEFAULT_MIN_SIZE (10*1024*1024)
54
55 /* Hard lower limit for new partition sizes */
56 #define HARD_MIN_SIZE 4096
57
58 /* Note: When growing and placing new partitions we always align to 4K sector size. It's how newer hard disks
59 * are designed, and if everything is aligned to that performance is best. And for older hard disks with 512B
60 * sector size devices were generally assumed to have an even number of sectors, hence at the worst we'll
61 * waste 3K per partition, which is probably fine. */
62
63 static enum {
64 EMPTY_REFUSE, /* refuse empty disks, never create a partition table */
65 EMPTY_ALLOW, /* allow empty disks, create partition table if necessary */
66 EMPTY_REQUIRE, /* require an empty disk, create a partition table */
67 EMPTY_FORCE, /* make disk empty, erase everything, create a partition table always */
68 EMPTY_CREATE, /* create disk as loopback file, create a partition table always */
69 } arg_empty = EMPTY_REFUSE;
70
71 static bool arg_dry_run = true;
72 static const char *arg_node = NULL;
73 static char *arg_root = NULL;
74 static char *arg_definitions = NULL;
75 static bool arg_discard = true;
76 static bool arg_can_factory_reset = false;
77 static int arg_factory_reset = -1;
78 static sd_id128_t arg_seed = SD_ID128_NULL;
79 static bool arg_randomize = false;
80 static int arg_pretty = -1;
81 static uint64_t arg_size = UINT64_MAX;
82
83 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
84 STATIC_DESTRUCTOR_REGISTER(arg_definitions, freep);
85
86 typedef struct Partition Partition;
87 typedef struct FreeArea FreeArea;
88 typedef struct Context Context;
89
90 struct Partition {
91 char *definition_path;
92
93 sd_id128_t type_uuid;
94 sd_id128_t current_uuid, new_uuid;
95 char *current_label, *new_label;
96
97 bool dropped;
98 bool factory_reset;
99 int32_t priority;
100
101 uint32_t weight, padding_weight;
102
103 uint64_t current_size, new_size;
104 uint64_t size_min, size_max;
105
106 uint64_t current_padding, new_padding;
107 uint64_t padding_min, padding_max;
108
109 uint64_t partno;
110 uint64_t offset;
111
112 struct fdisk_partition *current_partition;
113 struct fdisk_partition *new_partition;
114 FreeArea *padding_area;
115 FreeArea *allocated_to_area;
116
117 LIST_FIELDS(Partition, partitions);
118 };
119
120 #define PARTITION_IS_FOREIGN(p) (!(p)->definition_path)
121 #define PARTITION_EXISTS(p) (!!(p)->current_partition)
122
123 struct FreeArea {
124 Partition *after;
125 uint64_t size;
126 uint64_t allocated;
127 };
128
129 struct Context {
130 LIST_HEAD(Partition, partitions);
131 size_t n_partitions;
132
133 FreeArea **free_areas;
134 size_t n_free_areas, n_allocated_free_areas;
135
136 uint64_t start, end, total;
137
138 struct fdisk_context *fdisk_context;
139
140 sd_id128_t seed;
141 };
142
143 static uint64_t round_down_size(uint64_t v, uint64_t p) {
144 return (v / p) * p;
145 }
146
147 static uint64_t round_up_size(uint64_t v, uint64_t p) {
148
149 v = DIV_ROUND_UP(v, p);
150
151 if (v > UINT64_MAX / p)
152 return UINT64_MAX; /* overflow */
153
154 return v * p;
155 }
156
157 static Partition *partition_new(void) {
158 Partition *p;
159
160 p = new(Partition, 1);
161 if (!p)
162 return NULL;
163
164 *p = (Partition) {
165 .weight = 1000,
166 .padding_weight = 0,
167 .current_size = UINT64_MAX,
168 .new_size = UINT64_MAX,
169 .size_min = UINT64_MAX,
170 .size_max = UINT64_MAX,
171 .current_padding = UINT64_MAX,
172 .new_padding = UINT64_MAX,
173 .padding_min = UINT64_MAX,
174 .padding_max = UINT64_MAX,
175 .partno = UINT64_MAX,
176 .offset = UINT64_MAX,
177 };
178
179 return p;
180 }
181
182 static Partition* partition_free(Partition *p) {
183 if (!p)
184 return NULL;
185
186 free(p->current_label);
187 free(p->new_label);
188 free(p->definition_path);
189
190 if (p->current_partition)
191 fdisk_unref_partition(p->current_partition);
192 if (p->new_partition)
193 fdisk_unref_partition(p->new_partition);
194
195 return mfree(p);
196 }
197
198 static Partition* partition_unlink_and_free(Context *context, Partition *p) {
199 if (!p)
200 return NULL;
201
202 LIST_REMOVE(partitions, context->partitions, p);
203
204 assert(context->n_partitions > 0);
205 context->n_partitions--;
206
207 return partition_free(p);
208 }
209
210 DEFINE_TRIVIAL_CLEANUP_FUNC(Partition*, partition_free);
211
212 static Context *context_new(sd_id128_t seed) {
213 Context *context;
214
215 context = new(Context, 1);
216 if (!context)
217 return NULL;
218
219 *context = (Context) {
220 .start = UINT64_MAX,
221 .end = UINT64_MAX,
222 .total = UINT64_MAX,
223 .seed = seed,
224 };
225
226 return context;
227 }
228
229 static void context_free_free_areas(Context *context) {
230 assert(context);
231
232 for (size_t i = 0; i < context->n_free_areas; i++)
233 free(context->free_areas[i]);
234
235 context->free_areas = mfree(context->free_areas);
236 context->n_free_areas = 0;
237 context->n_allocated_free_areas = 0;
238 }
239
240 static Context *context_free(Context *context) {
241 if (!context)
242 return NULL;
243
244 while (context->partitions)
245 partition_unlink_and_free(context, context->partitions);
246 assert(context->n_partitions == 0);
247
248 context_free_free_areas(context);
249
250 if (context->fdisk_context)
251 fdisk_unref_context(context->fdisk_context);
252
253 return mfree(context);
254 }
255
256 DEFINE_TRIVIAL_CLEANUP_FUNC(Context*, context_free);
257
258 static int context_add_free_area(
259 Context *context,
260 uint64_t size,
261 Partition *after) {
262
263 FreeArea *a;
264
265 assert(context);
266 assert(!after || !after->padding_area);
267
268 if (!GREEDY_REALLOC(context->free_areas, context->n_allocated_free_areas, context->n_free_areas + 1))
269 return -ENOMEM;
270
271 a = new(FreeArea, 1);
272 if (!a)
273 return -ENOMEM;
274
275 *a = (FreeArea) {
276 .size = size,
277 .after = after,
278 };
279
280 context->free_areas[context->n_free_areas++] = a;
281
282 if (after)
283 after->padding_area = a;
284
285 return 0;
286 }
287
288 static bool context_drop_one_priority(Context *context) {
289 int32_t priority = 0;
290 Partition *p;
291 bool exists = false;
292
293 LIST_FOREACH(partitions, p, context->partitions) {
294 if (p->dropped)
295 continue;
296 if (p->priority < priority)
297 continue;
298 if (p->priority == priority) {
299 exists = exists || PARTITION_EXISTS(p);
300 continue;
301 }
302
303 priority = p->priority;
304 exists = PARTITION_EXISTS(p);
305 }
306
307 /* Refuse to drop partitions with 0 or negative priorities or partitions of priorities that have at
308 * least one existing priority */
309 if (priority <= 0 || exists)
310 return false;
311
312 LIST_FOREACH(partitions, p, context->partitions) {
313 if (p->priority < priority)
314 continue;
315
316 if (p->dropped)
317 continue;
318
319 p->dropped = true;
320 log_info("Can't fit partition %s of priority %" PRIi32 ", dropping.", p->definition_path, p->priority);
321 }
322
323 return true;
324 }
325
326 static uint64_t partition_min_size(const Partition *p) {
327 uint64_t sz;
328
329 /* Calculate the disk space we really need at minimum for this partition. If the partition already
330 * exists the current size is what we really need. If it doesn't exist yet refuse to allocate less
331 * than 4K.
332 *
333 * DEFAULT_MIN_SIZE is the default SizeMin= we configure if nothing else is specified. */
334
335 if (PARTITION_IS_FOREIGN(p)) {
336 /* Don't allow changing size of partitions not managed by us */
337 assert(p->current_size != UINT64_MAX);
338 return p->current_size;
339 }
340
341 sz = p->current_size != UINT64_MAX ? p->current_size : HARD_MIN_SIZE;
342 return MAX(p->size_min == UINT64_MAX ? DEFAULT_MIN_SIZE : p->size_min, sz);
343 }
344
345 static uint64_t partition_max_size(const Partition *p) {
346 /* Calculate how large the partition may become at max. This is generally the configured maximum
347 * size, except when it already exists and is larger than that. In that case it's the existing size,
348 * since we never want to shrink partitions. */
349
350 if (PARTITION_IS_FOREIGN(p)) {
351 /* Don't allow changing size of partitions not managed by us */
352 assert(p->current_size != UINT64_MAX);
353 return p->current_size;
354 }
355
356 if (p->current_size != UINT64_MAX)
357 return MAX(p->current_size, p->size_max);
358
359 return p->size_max;
360 }
361
362 static uint64_t partition_min_size_with_padding(const Partition *p) {
363 uint64_t sz;
364
365 /* Calculate the disk space we need for this partition plus any free space coming after it. This
366 * takes user configured padding into account as well as any additional whitespace needed to align
367 * the next partition to 4K again. */
368
369 sz = partition_min_size(p);
370
371 if (p->padding_min != UINT64_MAX)
372 sz += p->padding_min;
373
374 if (PARTITION_EXISTS(p)) {
375 /* If the partition wasn't aligned, add extra space so that any we might add will be aligned */
376 assert(p->offset != UINT64_MAX);
377 return round_up_size(p->offset + sz, 4096) - p->offset;
378 }
379
380 /* If this is a new partition we'll place it aligned, hence we just need to round up the required size here */
381 return round_up_size(sz, 4096);
382 }
383
384 static uint64_t free_area_available(const FreeArea *a) {
385 assert(a);
386
387 /* Determines how much of this free area is not allocated yet */
388
389 assert(a->size >= a->allocated);
390 return a->size - a->allocated;
391 }
392
393 static uint64_t free_area_available_for_new_partitions(const FreeArea *a) {
394 uint64_t avail;
395
396 /* Similar to free_area_available(), but takes into account that the required size and padding of the
397 * preceding partition is honoured. */
398
399 avail = free_area_available(a);
400 if (a->after) {
401 uint64_t need, space;
402
403 need = partition_min_size_with_padding(a->after);
404
405 assert(a->after->offset != UINT64_MAX);
406 assert(a->after->current_size != UINT64_MAX);
407
408 space = round_up_size(a->after->offset + a->after->current_size, 4096) - a->after->offset + avail;
409 if (need >= space)
410 return 0;
411
412 return space - need;
413 }
414
415 return avail;
416 }
417
418 static int free_area_compare(FreeArea *const *a, FreeArea *const*b) {
419 return CMP(free_area_available_for_new_partitions(*a),
420 free_area_available_for_new_partitions(*b));
421 }
422
423 static uint64_t charge_size(uint64_t total, uint64_t amount) {
424 uint64_t rounded;
425
426 assert(amount <= total);
427
428 /* Subtract the specified amount from total, rounding up to multiple of 4K if there's room */
429 rounded = round_up_size(amount, 4096);
430 if (rounded >= total)
431 return 0;
432
433 return total - rounded;
434 }
435
436 static uint64_t charge_weight(uint64_t total, uint64_t amount) {
437 assert(amount <= total);
438 return total - amount;
439 }
440
441 static bool context_allocate_partitions(Context *context) {
442 Partition *p;
443
444 assert(context);
445
446 /* A simple first-fit algorithm, assuming the array of free areas is sorted by size in decreasing
447 * order. */
448
449 LIST_FOREACH(partitions, p, context->partitions) {
450 bool fits = false;
451 uint64_t required;
452 FreeArea *a = NULL;
453
454 /* Skip partitions we already dropped or that already exist */
455 if (p->dropped || PARTITION_EXISTS(p))
456 continue;
457
458 /* Sort by size */
459 typesafe_qsort(context->free_areas, context->n_free_areas, free_area_compare);
460
461 /* How much do we need to fit? */
462 required = partition_min_size_with_padding(p);
463 assert(required % 4096 == 0);
464
465 for (size_t i = 0; i < context->n_free_areas; i++) {
466 a = context->free_areas[i];
467
468 if (free_area_available_for_new_partitions(a) >= required) {
469 fits = true;
470 break;
471 }
472 }
473
474 if (!fits)
475 return false; /* 😢 Oh no! We can't fit this partition into any free area! */
476
477 /* Assign the partition to this free area */
478 p->allocated_to_area = a;
479
480 /* Budget the minimal partition size */
481 a->allocated += required;
482 }
483
484 return true;
485 }
486
487 static int context_sum_weights(Context *context, FreeArea *a, uint64_t *ret) {
488 uint64_t weight_sum = 0;
489 Partition *p;
490
491 assert(context);
492 assert(a);
493 assert(ret);
494
495 /* Determine the sum of the weights of all partitions placed in or before the specified free area */
496
497 LIST_FOREACH(partitions, p, context->partitions) {
498 if (p->padding_area != a && p->allocated_to_area != a)
499 continue;
500
501 if (p->weight > UINT64_MAX - weight_sum)
502 goto overflow_sum;
503 weight_sum += p->weight;
504
505 if (p->padding_weight > UINT64_MAX - weight_sum)
506 goto overflow_sum;
507 weight_sum += p->padding_weight;
508 }
509
510 *ret = weight_sum;
511 return 0;
512
513 overflow_sum:
514 return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "Combined weight of partition exceeds unsigned 64bit range, refusing.");
515 }
516
517 static int scale_by_weight(uint64_t value, uint64_t weight, uint64_t weight_sum, uint64_t *ret) {
518 assert(weight_sum >= weight);
519 assert(ret);
520
521 if (weight == 0) {
522 *ret = 0;
523 return 0;
524 }
525
526 if (value > UINT64_MAX / weight)
527 return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "Scaling by weight of partition exceeds unsigned 64bit range, refusing.");
528
529 *ret = value * weight / weight_sum;
530 return 0;
531 }
532
533 typedef enum GrowPartitionPhase {
534 /* The first phase: we charge partitions which need more (according to constraints) than their weight-based share. */
535 PHASE_OVERCHARGE,
536
537 /* The second phase: we charge partitions which need less (according to constraints) than their weight-based share. */
538 PHASE_UNDERCHARGE,
539
540 /* The third phase: we distribute what remains among the remaining partitions, according to the weights */
541 PHASE_DISTRIBUTE,
542 } GrowPartitionPhase;
543
544 static int context_grow_partitions_phase(
545 Context *context,
546 FreeArea *a,
547 GrowPartitionPhase phase,
548 uint64_t *span,
549 uint64_t *weight_sum) {
550
551 Partition *p;
552 int r;
553
554 assert(context);
555 assert(a);
556
557 /* Now let's look at the intended weights and adjust them taking the minimum space assignments into
558 * account. i.e. if a partition has a small weight but a high minimum space value set it should not
559 * get any additional room from the left-overs. Similar, if two partitions have the same weight they
560 * should get the same space if possible, even if one has a smaller minimum size than the other. */
561 LIST_FOREACH(partitions, p, context->partitions) {
562
563 /* Look only at partitions associated with this free area, i.e. immediately
564 * preceding it, or allocated into it */
565 if (p->allocated_to_area != a && p->padding_area != a)
566 continue;
567
568 if (p->new_size == UINT64_MAX) {
569 bool charge = false, try_again = false;
570 uint64_t share, rsz, xsz;
571
572 /* Calculate how much this space this partition needs if everyone would get
573 * the weight based share */
574 r = scale_by_weight(*span, p->weight, *weight_sum, &share);
575 if (r < 0)
576 return r;
577
578 rsz = partition_min_size(p);
579 xsz = partition_max_size(p);
580
581 if (phase == PHASE_OVERCHARGE && rsz > share) {
582 /* This partition needs more than its calculated share. Let's assign
583 * it that, and take this partition out of all calculations and start
584 * again. */
585
586 p->new_size = rsz;
587 charge = try_again = true;
588
589 } else if (phase == PHASE_UNDERCHARGE && xsz != UINT64_MAX && xsz < share) {
590 /* This partition accepts less than its calculated
591 * share. Let's assign it that, and take this partition out
592 * of all calculations and start again. */
593
594 p->new_size = xsz;
595 charge = try_again = true;
596
597 } else if (phase == PHASE_DISTRIBUTE) {
598 /* This partition can accept its calculated share. Let's
599 * assign it. There's no need to restart things here since
600 * assigning this shouldn't impact the shares of the other
601 * partitions. */
602
603 if (PARTITION_IS_FOREIGN(p))
604 /* Never change of foreign partitions (i.e. those we don't manage) */
605 p->new_size = p->current_size;
606 else
607 p->new_size = MAX(round_down_size(share, 4096), rsz);
608
609 charge = true;
610 }
611
612 if (charge) {
613 *span = charge_size(*span, p->new_size);
614 *weight_sum = charge_weight(*weight_sum, p->weight);
615 }
616
617 if (try_again)
618 return 0; /* try again */
619 }
620
621 if (p->new_padding == UINT64_MAX) {
622 bool charge = false, try_again = false;
623 uint64_t share;
624
625 r = scale_by_weight(*span, p->padding_weight, *weight_sum, &share);
626 if (r < 0)
627 return r;
628
629 if (phase == PHASE_OVERCHARGE && p->padding_min != UINT64_MAX && p->padding_min > share) {
630 p->new_padding = p->padding_min;
631 charge = try_again = true;
632 } else if (phase == PHASE_UNDERCHARGE && p->padding_max != UINT64_MAX && p->padding_max < share) {
633 p->new_padding = p->padding_max;
634 charge = try_again = true;
635 } else if (phase == PHASE_DISTRIBUTE) {
636
637 p->new_padding = round_down_size(share, 4096);
638 if (p->padding_min != UINT64_MAX && p->new_padding < p->padding_min)
639 p->new_padding = p->padding_min;
640
641 charge = true;
642 }
643
644 if (charge) {
645 *span = charge_size(*span, p->new_padding);
646 *weight_sum = charge_weight(*weight_sum, p->padding_weight);
647 }
648
649 if (try_again)
650 return 0; /* try again */
651 }
652 }
653
654 return 1; /* done */
655 }
656
657 static int context_grow_partitions_on_free_area(Context *context, FreeArea *a) {
658 uint64_t weight_sum = 0, span;
659 int r;
660
661 assert(context);
662 assert(a);
663
664 r = context_sum_weights(context, a, &weight_sum);
665 if (r < 0)
666 return r;
667
668 /* Let's calculate the total area covered by this free area and the partition before it */
669 span = a->size;
670 if (a->after) {
671 assert(a->after->offset != UINT64_MAX);
672 assert(a->after->current_size != UINT64_MAX);
673
674 span += round_up_size(a->after->offset + a->after->current_size, 4096) - a->after->offset;
675 }
676
677 GrowPartitionPhase phase = PHASE_OVERCHARGE;
678 for (;;) {
679 r = context_grow_partitions_phase(context, a, phase, &span, &weight_sum);
680 if (r < 0)
681 return r;
682 if (r == 0) /* not done yet, re-run this phase */
683 continue;
684
685 if (phase == PHASE_OVERCHARGE)
686 phase = PHASE_UNDERCHARGE;
687 else if (phase == PHASE_UNDERCHARGE)
688 phase = PHASE_DISTRIBUTE;
689 else if (phase == PHASE_DISTRIBUTE)
690 break;
691 }
692
693 /* We still have space left over? Donate to preceding partition if we have one */
694 if (span > 0 && a->after && !PARTITION_IS_FOREIGN(a->after)) {
695 uint64_t m, xsz;
696
697 assert(a->after->new_size != UINT64_MAX);
698 m = a->after->new_size + span;
699
700 xsz = partition_max_size(a->after);
701 if (xsz != UINT64_MAX && m > xsz)
702 m = xsz;
703
704 span = charge_size(span, m - a->after->new_size);
705 a->after->new_size = m;
706 }
707
708 /* What? Even still some space left (maybe because there was no preceding partition, or it had a
709 * size limit), then let's donate it to whoever wants it. */
710 if (span > 0) {
711 Partition *p;
712
713 LIST_FOREACH(partitions, p, context->partitions) {
714 uint64_t m, xsz;
715
716 if (p->allocated_to_area != a)
717 continue;
718
719 if (PARTITION_IS_FOREIGN(p))
720 continue;
721
722 assert(p->new_size != UINT64_MAX);
723 m = p->new_size + span;
724
725 xsz = partition_max_size(p);
726 if (xsz != UINT64_MAX && m > xsz)
727 m = xsz;
728
729 span = charge_size(span, m - p->new_size);
730 p->new_size = m;
731
732 if (span == 0)
733 break;
734 }
735 }
736
737 /* Yuck, still no one? Then make it padding */
738 if (span > 0 && a->after) {
739 assert(a->after->new_padding != UINT64_MAX);
740 a->after->new_padding += span;
741 }
742
743 return 0;
744 }
745
746 static int context_grow_partitions(Context *context) {
747 Partition *p;
748 int r;
749
750 assert(context);
751
752 for (size_t i = 0; i < context->n_free_areas; i++) {
753 r = context_grow_partitions_on_free_area(context, context->free_areas[i]);
754 if (r < 0)
755 return r;
756 }
757
758 /* All existing partitions that have no free space after them can't change size */
759 LIST_FOREACH(partitions, p, context->partitions) {
760 if (p->dropped)
761 continue;
762
763 if (!PARTITION_EXISTS(p) || p->padding_area) {
764 /* The algorithm above must have initialized this already */
765 assert(p->new_size != UINT64_MAX);
766 continue;
767 }
768
769 assert(p->new_size == UINT64_MAX);
770 p->new_size = p->current_size;
771
772 assert(p->new_padding == UINT64_MAX);
773 p->new_padding = p->current_padding;
774 }
775
776 return 0;
777 }
778
779 static void context_place_partitions(Context *context) {
780 uint64_t partno = 0;
781 Partition *p;
782
783 assert(context);
784
785 /* Determine next partition number to assign */
786 LIST_FOREACH(partitions, p, context->partitions) {
787 if (!PARTITION_EXISTS(p))
788 continue;
789
790 assert(p->partno != UINT64_MAX);
791 if (p->partno >= partno)
792 partno = p->partno + 1;
793 }
794
795 for (size_t i = 0; i < context->n_free_areas; i++) {
796 FreeArea *a = context->free_areas[i];
797 uint64_t start, left;
798
799 if (a->after) {
800 assert(a->after->offset != UINT64_MAX);
801 assert(a->after->new_size != UINT64_MAX);
802 assert(a->after->new_padding != UINT64_MAX);
803
804 start = a->after->offset + a->after->new_size + a->after->new_padding;
805 } else
806 start = context->start;
807
808 start = round_up_size(start, 4096);
809 left = a->size;
810
811 LIST_FOREACH(partitions, p, context->partitions) {
812 if (p->allocated_to_area != a)
813 continue;
814
815 p->offset = start;
816 p->partno = partno++;
817
818 assert(left >= p->new_size);
819 start += p->new_size;
820 left -= p->new_size;
821
822 assert(left >= p->new_padding);
823 start += p->new_padding;
824 left -= p->new_padding;
825 }
826 }
827 }
828
829 static int config_parse_type(
830 const char *unit,
831 const char *filename,
832 unsigned line,
833 const char *section,
834 unsigned section_line,
835 const char *lvalue,
836 int ltype,
837 const char *rvalue,
838 void *data,
839 void *userdata) {
840
841 sd_id128_t *type_uuid = data;
842 int r;
843
844 assert(rvalue);
845 assert(type_uuid);
846
847 r = gpt_partition_type_uuid_from_string(rvalue, type_uuid);
848 if (r < 0)
849 return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse partition type: %s", rvalue);
850
851 return 0;
852 }
853
854 static int config_parse_label(
855 const char *unit,
856 const char *filename,
857 unsigned line,
858 const char *section,
859 unsigned section_line,
860 const char *lvalue,
861 int ltype,
862 const char *rvalue,
863 void *data,
864 void *userdata) {
865
866 static const Specifier specifier_table[] = {
867 { 'm', specifier_machine_id, NULL },
868 { 'b', specifier_boot_id, NULL },
869 { 'H', specifier_host_name, NULL },
870 { 'l', specifier_short_host_name, NULL },
871 { 'v', specifier_kernel_release, NULL },
872 { 'a', specifier_architecture, NULL },
873 { 'o', specifier_os_id, NULL },
874 { 'w', specifier_os_version_id, NULL },
875 { 'B', specifier_os_build_id, NULL },
876 { 'W', specifier_os_variant_id, NULL },
877 {}
878 };
879
880 _cleanup_free_ char16_t *recoded = NULL;
881 _cleanup_free_ char *resolved = NULL;
882 char **label = data;
883 int r;
884
885 assert(rvalue);
886 assert(label);
887
888 r = specifier_printf(rvalue, specifier_table, NULL, &resolved);
889 if (r < 0) {
890 log_syntax(unit, LOG_ERR, filename, line, r,
891 "Failed to expand specifiers in Label=, ignoring: %s", rvalue);
892 return 0;
893 }
894
895 if (!utf8_is_valid(resolved)) {
896 log_syntax(unit, LOG_WARNING, filename, line, 0,
897 "Partition label not valid UTF-8, ignoring: %s", rvalue);
898 return 0;
899 }
900
901 recoded = utf8_to_utf16(resolved, strlen(resolved));
902 if (!recoded)
903 return log_oom();
904
905 if (char16_strlen(recoded) > 36) {
906 log_syntax(unit, LOG_WARNING, filename, line, 0,
907 "Partition label too long for GPT table, ignoring: %s", rvalue);
908 return 0;
909 }
910
911 free_and_replace(*label, resolved);
912 return 0;
913 }
914
915 static int config_parse_weight(
916 const char *unit,
917 const char *filename,
918 unsigned line,
919 const char *section,
920 unsigned section_line,
921 const char *lvalue,
922 int ltype,
923 const char *rvalue,
924 void *data,
925 void *userdata) {
926
927 uint32_t *priority = data, v;
928 int r;
929
930 assert(rvalue);
931 assert(priority);
932
933 r = safe_atou32(rvalue, &v);
934 if (r < 0) {
935 log_syntax(unit, LOG_WARNING, filename, line, r,
936 "Failed to parse weight value, ignoring: %s", rvalue);
937 return 0;
938 }
939
940 if (v > 1000U*1000U) {
941 log_syntax(unit, LOG_WARNING, filename, line, r,
942 "Weight needs to be in range 0…10000000, ignoring: %" PRIu32, v);
943 return 0;
944 }
945
946 *priority = v;
947 return 0;
948 }
949
950 static int config_parse_size4096(
951 const char *unit,
952 const char *filename,
953 unsigned line,
954 const char *section,
955 unsigned section_line,
956 const char *lvalue,
957 int ltype,
958 const char *rvalue,
959 void *data,
960 void *userdata) {
961
962 uint64_t *sz = data, parsed;
963 int r;
964
965 assert(rvalue);
966 assert(data);
967
968 r = parse_size(rvalue, 1024, &parsed);
969 if (r < 0)
970 return log_syntax(unit, LOG_WARNING, filename, line, r,
971 "Failed to parse size value: %s", rvalue);
972
973 if (ltype > 0)
974 *sz = round_up_size(parsed, 4096);
975 else if (ltype < 0)
976 *sz = round_down_size(parsed, 4096);
977 else
978 *sz = parsed;
979
980 if (*sz != parsed)
981 log_syntax(unit, LOG_NOTICE, filename, line, r, "Rounded %s= size %" PRIu64 " → %" PRIu64 ", a multiple of 4096.", lvalue, parsed, *sz);
982
983 return 0;
984 }
985
986 static int partition_read_definition(Partition *p, const char *path) {
987
988 ConfigTableItem table[] = {
989 { "Partition", "Type", config_parse_type, 0, &p->type_uuid },
990 { "Partition", "Label", config_parse_label, 0, &p->new_label },
991 { "Partition", "UUID", config_parse_id128, 0, &p->new_uuid },
992 { "Partition", "Priority", config_parse_int32, 0, &p->priority },
993 { "Partition", "Weight", config_parse_weight, 0, &p->weight },
994 { "Partition", "PaddingWeight", config_parse_weight, 0, &p->padding_weight },
995 { "Partition", "SizeMinBytes", config_parse_size4096, 1, &p->size_min },
996 { "Partition", "SizeMaxBytes", config_parse_size4096, -1, &p->size_max },
997 { "Partition", "PaddingMinBytes", config_parse_size4096, 1, &p->padding_min },
998 { "Partition", "PaddingMaxBytes", config_parse_size4096, -1, &p->padding_max },
999 { "Partition", "FactoryReset", config_parse_bool, 0, &p->factory_reset },
1000 {}
1001 };
1002 int r;
1003
1004 r = config_parse(NULL, path, NULL,
1005 "Partition\0",
1006 config_item_table_lookup, table,
1007 CONFIG_PARSE_WARN,
1008 p,
1009 NULL);
1010 if (r < 0)
1011 return r;
1012
1013 if (p->size_min != UINT64_MAX && p->size_max != UINT64_MAX && p->size_min > p->size_max)
1014 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1015 "SizeMinBytes= larger than SizeMaxBytes=, refusing.");
1016
1017 if (p->padding_min != UINT64_MAX && p->padding_max != UINT64_MAX && p->padding_min > p->padding_max)
1018 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1019 "PaddingMinBytes= larger than PaddingMaxBytes=, refusing.");
1020
1021 if (sd_id128_is_null(p->type_uuid))
1022 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1023 "Type= not defined, refusing.");
1024
1025 return 0;
1026 }
1027
1028 static int context_read_definitions(
1029 Context *context,
1030 const char *directory,
1031 const char *root) {
1032
1033 _cleanup_strv_free_ char **files = NULL;
1034 Partition *last = NULL;
1035 char **f;
1036 int r;
1037
1038 assert(context);
1039
1040 if (directory)
1041 r = conf_files_list_strv(&files, ".conf", NULL, CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED, (const char**) STRV_MAKE(directory));
1042 else
1043 r = conf_files_list_strv(&files, ".conf", root, CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED, (const char**) CONF_PATHS_STRV("repart.d"));
1044 if (r < 0)
1045 return log_error_errno(r, "Failed to enumerate *.conf files: %m");
1046
1047 STRV_FOREACH(f, files) {
1048 _cleanup_(partition_freep) Partition *p = NULL;
1049
1050 p = partition_new();
1051 if (!p)
1052 return log_oom();
1053
1054 p->definition_path = strdup(*f);
1055 if (!p->definition_path)
1056 return log_oom();
1057
1058 r = partition_read_definition(p, *f);
1059 if (r < 0)
1060 return r;
1061
1062 LIST_INSERT_AFTER(partitions, context->partitions, last, p);
1063 last = TAKE_PTR(p);
1064 context->n_partitions++;
1065 }
1066
1067 return 0;
1068 }
1069
1070 DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_context*, fdisk_unref_context);
1071 DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_partition*, fdisk_unref_partition);
1072 DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_parttype*, fdisk_unref_parttype);
1073 DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_table*, fdisk_unref_table);
1074
1075 static int determine_current_padding(
1076 struct fdisk_context *c,
1077 struct fdisk_table *t,
1078 struct fdisk_partition *p,
1079 uint64_t *ret) {
1080
1081 size_t n_partitions;
1082 uint64_t offset, next = UINT64_MAX;
1083
1084 assert(c);
1085 assert(t);
1086 assert(p);
1087
1088 if (!fdisk_partition_has_end(p))
1089 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Partition has no end!");
1090
1091 offset = fdisk_partition_get_end(p);
1092 assert(offset < UINT64_MAX / 512);
1093 offset *= 512;
1094
1095 n_partitions = fdisk_table_get_nents(t);
1096 for (size_t i = 0; i < n_partitions; i++) {
1097 struct fdisk_partition *q;
1098 uint64_t start;
1099
1100 q = fdisk_table_get_partition(t, i);
1101 if (!q)
1102 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read partition metadata: %m");
1103
1104 if (fdisk_partition_is_used(q) <= 0)
1105 continue;
1106
1107 if (!fdisk_partition_has_start(q))
1108 continue;
1109
1110 start = fdisk_partition_get_start(q);
1111 assert(start < UINT64_MAX / 512);
1112 start *= 512;
1113
1114 if (start >= offset && (next == UINT64_MAX || next > start))
1115 next = start;
1116 }
1117
1118 if (next == UINT64_MAX) {
1119 /* No later partition? In that case check the end of the usable area */
1120 next = fdisk_get_last_lba(c);
1121 assert(next < UINT64_MAX);
1122 next++; /* The last LBA is one sector before the end */
1123
1124 assert(next < UINT64_MAX / 512);
1125 next *= 512;
1126
1127 if (offset > next)
1128 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Partition end beyond disk end.");
1129 }
1130
1131 assert(next >= offset);
1132 offset = round_up_size(offset, 4096);
1133 next = round_down_size(next, 4096);
1134
1135 if (next >= offset) /* Check again, rounding might have fucked things up */
1136 *ret = next - offset;
1137 else
1138 *ret = 0;
1139
1140 return 0;
1141 }
1142
1143 static int fdisk_ask_cb(struct fdisk_context *c, struct fdisk_ask *ask, void *data) {
1144 _cleanup_free_ char *ids = NULL;
1145 int r;
1146
1147 if (fdisk_ask_get_type(ask) != FDISK_ASKTYPE_STRING)
1148 return -EINVAL;
1149
1150 ids = new(char, ID128_UUID_STRING_MAX);
1151 if (!ids)
1152 return -ENOMEM;
1153
1154 r = fdisk_ask_string_set_result(ask, id128_to_uuid_string(*(sd_id128_t*) data, ids));
1155 if (r < 0)
1156 return r;
1157
1158 TAKE_PTR(ids);
1159 return 0;
1160 }
1161
1162 static int fdisk_set_disklabel_id_by_uuid(struct fdisk_context *c, sd_id128_t id) {
1163 int r;
1164
1165 r = fdisk_set_ask(c, fdisk_ask_cb, &id);
1166 if (r < 0)
1167 return r;
1168
1169 r = fdisk_set_disklabel_id(c);
1170 if (r < 0)
1171 return r;
1172
1173 return fdisk_set_ask(c, NULL, NULL);
1174 }
1175
1176 #define DISK_UUID_TOKEN "disk-uuid"
1177
1178 static int disk_acquire_uuid(Context *context, sd_id128_t *ret) {
1179 union {
1180 unsigned char md[SHA256_DIGEST_LENGTH];
1181 sd_id128_t id;
1182 } result;
1183
1184 assert(context);
1185 assert(ret);
1186
1187 /* Calculate the HMAC-SHA256 of the string "disk-uuid", keyed off the machine ID. We use the machine
1188 * ID as key (and not as cleartext!) since it's the machine ID we don't want to leak. */
1189
1190 if (!HMAC(EVP_sha256(),
1191 &context->seed, sizeof(context->seed),
1192 (const unsigned char*) DISK_UUID_TOKEN, strlen(DISK_UUID_TOKEN),
1193 result.md, NULL))
1194 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "HMAC-SHA256 calculation failed.");
1195
1196 /* Take the first half, mark it as v4 UUID */
1197 assert_cc(sizeof(result.md) == sizeof(result.id) * 2);
1198 *ret = id128_make_v4_uuid(result.id);
1199 return 0;
1200 }
1201
1202 static int context_load_partition_table(
1203 Context *context,
1204 const char *node,
1205 int *backing_fd) {
1206
1207 _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
1208 _cleanup_(fdisk_unref_tablep) struct fdisk_table *t = NULL;
1209 uint64_t left_boundary = UINT64_MAX, first_lba, last_lba, nsectors;
1210 _cleanup_free_ char *disk_uuid_string = NULL;
1211 bool from_scratch = false;
1212 sd_id128_t disk_uuid;
1213 size_t n_partitions;
1214 int r;
1215
1216 assert(context);
1217 assert(node);
1218 assert(backing_fd);
1219
1220 c = fdisk_new_context();
1221 if (!c)
1222 return log_oom();
1223
1224 /* libfdisk doesn't have an API to operate on arbitrary fds, hence reopen the fd going via the
1225 * /proc/self/fd/ magic path if we have an existing fd. Open the original file otherwise. */
1226 if (*backing_fd < 0)
1227 r = fdisk_assign_device(c, node, arg_dry_run);
1228 else {
1229 char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
1230 xsprintf(procfs_path, "/proc/self/fd/%i", *backing_fd);
1231
1232 r = fdisk_assign_device(c, procfs_path, arg_dry_run);
1233 }
1234 if (r < 0)
1235 return log_error_errno(r, "Failed to open device '%s': %m", node);
1236
1237 if (*backing_fd < 0) {
1238 /* If we have no fd referencing the device yet, make a copy of the fd now, so that we have one */
1239 *backing_fd = fcntl(fdisk_get_devfd(c), F_DUPFD_CLOEXEC, 3);
1240 if (*backing_fd < 0)
1241 return log_error_errno(errno, "Failed to duplicate fdisk fd: %m");
1242 }
1243
1244 /* Tell udev not to interfere while we are processing the device */
1245 if (flock(fdisk_get_devfd(c), arg_dry_run ? LOCK_SH : LOCK_EX) < 0)
1246 return log_error_errno(errno, "Failed to lock block device: %m");
1247
1248 switch (arg_empty) {
1249
1250 case EMPTY_REFUSE:
1251 /* Refuse empty disks, insist on an existing GPT partition table */
1252 if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
1253 return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has no GPT disk label, not repartitioning.", node);
1254
1255 break;
1256
1257 case EMPTY_REQUIRE:
1258 /* Require an empty disk, refuse any existing partition table */
1259 r = fdisk_has_label(c);
1260 if (r < 0)
1261 return log_error_errno(r, "Failed to determine whether disk %s has a disk label: %m", node);
1262 if (r > 0)
1263 return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s already has a disk label, refusing.", node);
1264
1265 from_scratch = true;
1266 break;
1267
1268 case EMPTY_ALLOW:
1269 /* Allow both an empty disk and an existing partition table, but only GPT */
1270 r = fdisk_has_label(c);
1271 if (r < 0)
1272 return log_error_errno(r, "Failed to determine whether disk %s has a disk label: %m", node);
1273 if (r > 0) {
1274 if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
1275 return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has non-GPT disk label, not repartitioning.", node);
1276 } else
1277 from_scratch = true;
1278
1279 break;
1280
1281 case EMPTY_FORCE:
1282 case EMPTY_CREATE:
1283 /* Always reinitiaize the disk, don't consider what there was on the disk before */
1284 from_scratch = true;
1285 break;
1286 }
1287
1288 if (from_scratch) {
1289 r = fdisk_enable_wipe(c, true);
1290 if (r < 0)
1291 return log_error_errno(r, "Failed to enable wiping of disk signature: %m");
1292
1293 r = fdisk_create_disklabel(c, "gpt");
1294 if (r < 0)
1295 return log_error_errno(r, "Failed to create GPT disk label: %m");
1296
1297 r = disk_acquire_uuid(context, &disk_uuid);
1298 if (r < 0)
1299 return log_error_errno(r, "Failed to acquire disk GPT uuid: %m");
1300
1301 r = fdisk_set_disklabel_id_by_uuid(c, disk_uuid);
1302 if (r < 0)
1303 return log_error_errno(r, "Failed to set GPT disk label: %m");
1304
1305 goto add_initial_free_area;
1306 }
1307
1308 r = fdisk_get_disklabel_id(c, &disk_uuid_string);
1309 if (r < 0)
1310 return log_error_errno(r, "Failed to get current GPT disk label UUID: %m");
1311
1312 r = sd_id128_from_string(disk_uuid_string, &disk_uuid);
1313 if (r < 0)
1314 return log_error_errno(r, "Failed to parse current GPT disk label UUID: %m");
1315
1316 if (sd_id128_is_null(disk_uuid)) {
1317 r = disk_acquire_uuid(context, &disk_uuid);
1318 if (r < 0)
1319 return log_error_errno(r, "Failed to acquire disk GPT uuid: %m");
1320
1321 r = fdisk_set_disklabel_id(c);
1322 if (r < 0)
1323 return log_error_errno(r, "Failed to set GPT disk label: %m");
1324 }
1325
1326 r = fdisk_get_partitions(c, &t);
1327 if (r < 0)
1328 return log_error_errno(r, "Failed to acquire partition table: %m");
1329
1330 n_partitions = fdisk_table_get_nents(t);
1331 for (size_t i = 0; i < n_partitions; i++) {
1332 _cleanup_free_ char *label_copy = NULL;
1333 Partition *pp, *last = NULL;
1334 struct fdisk_partition *p;
1335 struct fdisk_parttype *pt;
1336 const char *pts, *ids, *label;
1337 uint64_t sz, start;
1338 bool found = false;
1339 sd_id128_t ptid, id;
1340 size_t partno;
1341
1342 p = fdisk_table_get_partition(t, i);
1343 if (!p)
1344 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read partition metadata: %m");
1345
1346 if (fdisk_partition_is_used(p) <= 0)
1347 continue;
1348
1349 if (fdisk_partition_has_start(p) <= 0 ||
1350 fdisk_partition_has_size(p) <= 0 ||
1351 fdisk_partition_has_partno(p) <= 0)
1352 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Found a partition without a position, size or number.");
1353
1354 pt = fdisk_partition_get_type(p);
1355 if (!pt)
1356 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to acquire type of partition: %m");
1357
1358 pts = fdisk_parttype_get_string(pt);
1359 if (!pts)
1360 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to acquire type of partition as string: %m");
1361
1362 r = sd_id128_from_string(pts, &ptid);
1363 if (r < 0)
1364 return log_error_errno(r, "Failed to parse partition type UUID %s: %m", pts);
1365
1366 ids = fdisk_partition_get_uuid(p);
1367 if (!ids)
1368 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Found a partition without a UUID.");
1369
1370 r = sd_id128_from_string(ids, &id);
1371 if (r < 0)
1372 return log_error_errno(r, "Failed to parse partition UUID %s: %m", ids);
1373
1374 label = fdisk_partition_get_name(p);
1375 if (!isempty(label)) {
1376 label_copy = strdup(label);
1377 if (!label_copy)
1378 return log_oom();
1379 }
1380
1381 sz = fdisk_partition_get_size(p);
1382 assert_se(sz <= UINT64_MAX/512);
1383 sz *= 512;
1384
1385 start = fdisk_partition_get_start(p);
1386 assert_se(start <= UINT64_MAX/512);
1387 start *= 512;
1388
1389 partno = fdisk_partition_get_partno(p);
1390
1391 if (left_boundary == UINT64_MAX || left_boundary > start)
1392 left_boundary = start;
1393
1394 /* Assign this existing partition to the first partition of the right type that doesn't have
1395 * an existing one assigned yet. */
1396 LIST_FOREACH(partitions, pp, context->partitions) {
1397 last = pp;
1398
1399 if (!sd_id128_equal(pp->type_uuid, ptid))
1400 continue;
1401
1402 if (!pp->current_partition) {
1403 pp->current_uuid = id;
1404 pp->current_size = sz;
1405 pp->offset = start;
1406 pp->partno = partno;
1407 pp->current_label = TAKE_PTR(label_copy);
1408
1409 pp->current_partition = p;
1410 fdisk_ref_partition(p);
1411
1412 r = determine_current_padding(c, t, p, &pp->current_padding);
1413 if (r < 0)
1414 return r;
1415
1416 if (pp->current_padding > 0) {
1417 r = context_add_free_area(context, pp->current_padding, pp);
1418 if (r < 0)
1419 return r;
1420 }
1421
1422 found = true;
1423 break;
1424 }
1425 }
1426
1427 /* If we have no matching definition, create a new one. */
1428 if (!found) {
1429 _cleanup_(partition_freep) Partition *np = NULL;
1430
1431 np = partition_new();
1432 if (!np)
1433 return log_oom();
1434
1435 np->current_uuid = id;
1436 np->type_uuid = ptid;
1437 np->current_size = sz;
1438 np->offset = start;
1439 np->partno = partno;
1440 np->current_label = TAKE_PTR(label_copy);
1441
1442 np->current_partition = p;
1443 fdisk_ref_partition(p);
1444
1445 r = determine_current_padding(c, t, p, &np->current_padding);
1446 if (r < 0)
1447 return r;
1448
1449 if (np->current_padding > 0) {
1450 r = context_add_free_area(context, np->current_padding, np);
1451 if (r < 0)
1452 return r;
1453 }
1454
1455 LIST_INSERT_AFTER(partitions, context->partitions, last, TAKE_PTR(np));
1456 context->n_partitions++;
1457 }
1458 }
1459
1460 add_initial_free_area:
1461 nsectors = fdisk_get_nsectors(c);
1462 assert(nsectors <= UINT64_MAX/512);
1463 nsectors *= 512;
1464
1465 first_lba = fdisk_get_first_lba(c);
1466 assert(first_lba <= UINT64_MAX/512);
1467 first_lba *= 512;
1468
1469 last_lba = fdisk_get_last_lba(c);
1470 assert(last_lba < UINT64_MAX);
1471 last_lba++;
1472 assert(last_lba <= UINT64_MAX/512);
1473 last_lba *= 512;
1474
1475 assert(last_lba >= first_lba);
1476
1477 if (left_boundary == UINT64_MAX) {
1478 /* No partitions at all? Then the whole disk is up for grabs. */
1479
1480 first_lba = round_up_size(first_lba, 4096);
1481 last_lba = round_down_size(last_lba, 4096);
1482
1483 if (last_lba > first_lba) {
1484 r = context_add_free_area(context, last_lba - first_lba, NULL);
1485 if (r < 0)
1486 return r;
1487 }
1488 } else {
1489 /* Add space left of first partition */
1490 assert(left_boundary >= first_lba);
1491
1492 first_lba = round_up_size(first_lba, 4096);
1493 left_boundary = round_down_size(left_boundary, 4096);
1494 last_lba = round_down_size(last_lba, 4096);
1495
1496 if (left_boundary > first_lba) {
1497 r = context_add_free_area(context, left_boundary - first_lba, NULL);
1498 if (r < 0)
1499 return r;
1500 }
1501 }
1502
1503 context->start = first_lba;
1504 context->end = last_lba;
1505 context->total = nsectors;
1506 context->fdisk_context = TAKE_PTR(c);
1507
1508 return from_scratch;
1509 }
1510
1511 static void context_unload_partition_table(Context *context) {
1512 Partition *p, *next;
1513
1514 assert(context);
1515
1516 LIST_FOREACH_SAFE(partitions, p, next, context->partitions) {
1517
1518 /* Entirely remove partitions that have no configuration */
1519 if (PARTITION_IS_FOREIGN(p)) {
1520 partition_unlink_and_free(context, p);
1521 continue;
1522 }
1523
1524 /* Otherwise drop all data we read off the block device and everything we might have
1525 * calculated based on it */
1526
1527 p->dropped = false;
1528 p->current_size = UINT64_MAX;
1529 p->new_size = UINT64_MAX;
1530 p->current_padding = UINT64_MAX;
1531 p->new_padding = UINT64_MAX;
1532 p->partno = UINT64_MAX;
1533 p->offset = UINT64_MAX;
1534
1535 if (p->current_partition) {
1536 fdisk_unref_partition(p->current_partition);
1537 p->current_partition = NULL;
1538 }
1539
1540 if (p->new_partition) {
1541 fdisk_unref_partition(p->new_partition);
1542 p->new_partition = NULL;
1543 }
1544
1545 p->padding_area = NULL;
1546 p->allocated_to_area = NULL;
1547
1548 p->current_uuid = p->new_uuid = SD_ID128_NULL;
1549 }
1550
1551 context->start = UINT64_MAX;
1552 context->end = UINT64_MAX;
1553 context->total = UINT64_MAX;
1554
1555 if (context->fdisk_context) {
1556 fdisk_unref_context(context->fdisk_context);
1557 context->fdisk_context = NULL;
1558 }
1559
1560 context_free_free_areas(context);
1561 }
1562
1563 static int format_size_change(uint64_t from, uint64_t to, char **ret) {
1564 char format_buffer1[FORMAT_BYTES_MAX], format_buffer2[FORMAT_BYTES_MAX], *buf;
1565
1566 if (from != UINT64_MAX)
1567 format_bytes(format_buffer1, sizeof(format_buffer1), from);
1568 if (to != UINT64_MAX)
1569 format_bytes(format_buffer2, sizeof(format_buffer2), to);
1570
1571 if (from != UINT64_MAX) {
1572 if (from == to || to == UINT64_MAX)
1573 buf = strdup(format_buffer1);
1574 else
1575 buf = strjoin(format_buffer1, " ", special_glyph(SPECIAL_GLYPH_ARROW), " ", format_buffer2);
1576 } else if (to != UINT64_MAX)
1577 buf = strjoin(special_glyph(SPECIAL_GLYPH_ARROW), " ", format_buffer2);
1578 else {
1579 *ret = NULL;
1580 return 0;
1581 }
1582
1583 if (!buf)
1584 return log_oom();
1585
1586 *ret = TAKE_PTR(buf);
1587 return 1;
1588 }
1589
1590 static const char *partition_label(const Partition *p) {
1591 assert(p);
1592
1593 if (p->new_label)
1594 return p->new_label;
1595
1596 if (p->current_label)
1597 return p->current_label;
1598
1599 return gpt_partition_type_uuid_to_string(p->type_uuid);
1600 }
1601
1602 static int context_dump_partitions(Context *context, const char *node) {
1603 _cleanup_(table_unrefp) Table *t = NULL;
1604 uint64_t sum_padding = 0, sum_size = 0;
1605 Partition *p;
1606 int r;
1607
1608 t = table_new("type", "label", "uuid", "file", "node", "offset", "raw size", "size", "raw padding", "padding");
1609 if (!t)
1610 return log_oom();
1611
1612 if (!DEBUG_LOGGING)
1613 (void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4, (size_t) 7, (size_t) 9, (size_t) -1);
1614
1615 (void) table_set_align_percent(t, table_get_cell(t, 0, 4), 100);
1616 (void) table_set_align_percent(t, table_get_cell(t, 0, 5), 100);
1617
1618 LIST_FOREACH(partitions, p, context->partitions) {
1619 _cleanup_free_ char *size_change = NULL, *padding_change = NULL, *partname = NULL;
1620 char uuid_buffer[ID128_UUID_STRING_MAX];
1621 const char *label;
1622
1623 if (p->dropped)
1624 continue;
1625
1626 label = partition_label(p);
1627 partname = p->partno != UINT64_MAX ? fdisk_partname(node, p->partno+1) : NULL;
1628
1629 r = format_size_change(p->current_size, p->new_size, &size_change);
1630 if (r < 0)
1631 return r;
1632
1633 r = format_size_change(p->current_padding, p->new_padding, &padding_change);
1634 if (r < 0)
1635 return r;
1636
1637 if (p->new_size != UINT64_MAX)
1638 sum_size += p->new_size;
1639 if (p->new_padding != UINT64_MAX)
1640 sum_padding += p->new_padding;
1641
1642 r = table_add_many(
1643 t,
1644 TABLE_STRING, gpt_partition_type_uuid_to_string_harder(p->type_uuid, uuid_buffer),
1645 TABLE_STRING, label ?: "-", TABLE_SET_COLOR, label ? NULL : ansi_grey(),
1646 TABLE_UUID, sd_id128_is_null(p->new_uuid) ? p->current_uuid : p->new_uuid,
1647 TABLE_STRING, p->definition_path ? basename(p->definition_path) : "-", TABLE_SET_COLOR, p->definition_path ? NULL : ansi_grey(),
1648 TABLE_STRING, partname ?: "no", TABLE_SET_COLOR, partname ? NULL : ansi_highlight(),
1649 TABLE_UINT64, p->offset,
1650 TABLE_UINT64, p->new_size,
1651 TABLE_STRING, size_change, TABLE_SET_COLOR, !p->partitions_next && sum_size > 0 ? ansi_underline() : NULL,
1652 TABLE_UINT64, p->new_padding,
1653 TABLE_STRING, padding_change, TABLE_SET_COLOR, !p->partitions_next && sum_padding > 0 ? ansi_underline() : NULL);
1654 if (r < 0)
1655 return log_error_errno(r, "Failed to add row to table: %m");
1656 }
1657
1658 if (sum_padding > 0 || sum_size > 0) {
1659 char s[FORMAT_BYTES_MAX];
1660 const char *a, *b;
1661
1662 a = strjoina(special_glyph(SPECIAL_GLYPH_SIGMA), " = ", format_bytes(s, sizeof(s), sum_size));
1663 b = strjoina(special_glyph(SPECIAL_GLYPH_SIGMA), " = ", format_bytes(s, sizeof(s), sum_padding));
1664
1665 r = table_add_many(
1666 t,
1667 TABLE_EMPTY,
1668 TABLE_EMPTY,
1669 TABLE_EMPTY,
1670 TABLE_EMPTY,
1671 TABLE_EMPTY,
1672 TABLE_EMPTY,
1673 TABLE_EMPTY,
1674 TABLE_STRING, a,
1675 TABLE_EMPTY,
1676 TABLE_STRING, b);
1677 if (r < 0)
1678 return log_error_errno(r, "Failed to add row to table: %m");
1679 }
1680
1681 r = table_print(t, stdout);
1682 if (r < 0)
1683 return log_error_errno(r, "Failed to dump table: %m");
1684
1685 return 0;
1686 }
1687
1688 static void context_bar_char_process_partition(
1689 Context *context,
1690 Partition *bar[],
1691 size_t n,
1692 Partition *p,
1693 size_t *ret_start) {
1694
1695 uint64_t from, to, total;
1696 size_t x, y;
1697
1698 assert(context);
1699 assert(bar);
1700 assert(n > 0);
1701 assert(p);
1702
1703 if (p->dropped)
1704 return;
1705
1706 assert(p->offset != UINT64_MAX);
1707 assert(p->new_size != UINT64_MAX);
1708
1709 from = p->offset;
1710 to = from + p->new_size;
1711
1712 assert(context->end >= context->start);
1713 total = context->end - context->start;
1714
1715 assert(from >= context->start);
1716 assert(from <= context->end);
1717 x = (from - context->start) * n / total;
1718
1719 assert(to >= context->start);
1720 assert(to <= context->end);
1721 y = (to - context->start) * n / total;
1722
1723 assert(x <= y);
1724 assert(y <= n);
1725
1726 for (size_t i = x; i < y; i++)
1727 bar[i] = p;
1728
1729 *ret_start = x;
1730 }
1731
1732 static int partition_hint(const Partition *p, const char *node, char **ret) {
1733 _cleanup_free_ char *buf = NULL;
1734 char ids[ID128_UUID_STRING_MAX];
1735 const char *label;
1736 sd_id128_t id;
1737
1738 /* Tries really hard to find a suitable description for this partition */
1739
1740 if (p->definition_path) {
1741 buf = strdup(basename(p->definition_path));
1742 goto done;
1743 }
1744
1745 label = partition_label(p);
1746 if (!isempty(label)) {
1747 buf = strdup(label);
1748 goto done;
1749 }
1750
1751 if (p->partno != UINT64_MAX) {
1752 buf = fdisk_partname(node, p->partno+1);
1753 goto done;
1754 }
1755
1756 if (!sd_id128_is_null(p->new_uuid))
1757 id = p->new_uuid;
1758 else if (!sd_id128_is_null(p->current_uuid))
1759 id = p->current_uuid;
1760 else
1761 id = p->type_uuid;
1762
1763 buf = strdup(id128_to_uuid_string(id, ids));
1764
1765 done:
1766 if (!buf)
1767 return -ENOMEM;
1768
1769 *ret = TAKE_PTR(buf);
1770 return 0;
1771 }
1772
1773 static int context_dump_partition_bar(Context *context, const char *node) {
1774 _cleanup_free_ Partition **bar = NULL;
1775 _cleanup_free_ size_t *start_array = NULL;
1776 Partition *p, *last = NULL;
1777 bool z = false;
1778 size_t c, j = 0;
1779
1780 assert_se((c = columns()) >= 2);
1781 c -= 2; /* We do not use the leftmost and rightmost character cell */
1782
1783 bar = new0(Partition*, c);
1784 if (!bar)
1785 return log_oom();
1786
1787 start_array = new(size_t, context->n_partitions);
1788 if (!start_array)
1789 return log_oom();
1790
1791 LIST_FOREACH(partitions, p, context->partitions)
1792 context_bar_char_process_partition(context, bar, c, p, start_array + j++);
1793
1794 putc(' ', stdout);
1795
1796 for (size_t i = 0; i < c; i++) {
1797 if (bar[i]) {
1798 if (last != bar[i])
1799 z = !z;
1800
1801 fputs(z ? ansi_green() : ansi_yellow(), stdout);
1802 fputs(special_glyph(SPECIAL_GLYPH_DARK_SHADE), stdout);
1803 } else {
1804 fputs(ansi_normal(), stdout);
1805 fputs(special_glyph(SPECIAL_GLYPH_LIGHT_SHADE), stdout);
1806 }
1807
1808 last = bar[i];
1809 }
1810
1811 fputs(ansi_normal(), stdout);
1812 putc('\n', stdout);
1813
1814 for (size_t i = 0; i < context->n_partitions; i++) {
1815 _cleanup_free_ char **line = NULL;
1816
1817 line = new0(char*, c);
1818 if (!line)
1819 return log_oom();
1820
1821 j = 0;
1822 LIST_FOREACH(partitions, p, context->partitions) {
1823 _cleanup_free_ char *d = NULL;
1824 j++;
1825
1826 if (i < context->n_partitions - j) {
1827
1828 if (line[start_array[j-1]]) {
1829 const char *e;
1830
1831 /* Upgrade final corner to the right with a branch to the right */
1832 e = startswith(line[start_array[j-1]], special_glyph(SPECIAL_GLYPH_TREE_RIGHT));
1833 if (e) {
1834 d = strjoin(special_glyph(SPECIAL_GLYPH_TREE_BRANCH), e);
1835 if (!d)
1836 return log_oom();
1837 }
1838 }
1839
1840 if (!d) {
1841 d = strdup(special_glyph(SPECIAL_GLYPH_TREE_VERTICAL));
1842 if (!d)
1843 return log_oom();
1844 }
1845
1846 } else if (i == context->n_partitions - j) {
1847 _cleanup_free_ char *hint = NULL;
1848
1849 (void) partition_hint(p, node, &hint);
1850
1851 if (streq_ptr(line[start_array[j-1]], special_glyph(SPECIAL_GLYPH_TREE_VERTICAL)))
1852 d = strjoin(special_glyph(SPECIAL_GLYPH_TREE_BRANCH), " ", strna(hint));
1853 else
1854 d = strjoin(special_glyph(SPECIAL_GLYPH_TREE_RIGHT), " ", strna(hint));
1855
1856 if (!d)
1857 return log_oom();
1858 }
1859
1860 if (d)
1861 free_and_replace(line[start_array[j-1]], d);
1862 }
1863
1864 putc(' ', stdout);
1865
1866 j = 0;
1867 while (j < c) {
1868 if (line[j]) {
1869 fputs(line[j], stdout);
1870 j += utf8_console_width(line[j]);
1871 } else {
1872 putc(' ', stdout);
1873 j++;
1874 }
1875 }
1876
1877 putc('\n', stdout);
1878
1879 for (j = 0; j < c; j++)
1880 free(line[j]);
1881 }
1882
1883 return 0;
1884 }
1885
1886 static bool context_changed(const Context *context) {
1887 Partition *p;
1888
1889 LIST_FOREACH(partitions, p, context->partitions) {
1890 if (p->dropped)
1891 continue;
1892
1893 if (p->allocated_to_area)
1894 return true;
1895
1896 if (p->new_size != p->current_size)
1897 return true;
1898 }
1899
1900 return false;
1901 }
1902
1903 static int context_wipe_partition(Context *context, Partition *p) {
1904 _cleanup_(blkid_free_probep) blkid_probe probe = NULL;
1905 int r;
1906
1907 assert(context);
1908 assert(p);
1909 assert(!PARTITION_EXISTS(p)); /* Safety check: never wipe existing partitions */
1910
1911 probe = blkid_new_probe();
1912 if (!probe)
1913 return log_oom();
1914
1915 assert(p->offset != UINT64_MAX);
1916 assert(p->new_size != UINT64_MAX);
1917
1918 errno = 0;
1919 r = blkid_probe_set_device(probe, fdisk_get_devfd(context->fdisk_context), p->offset, p->new_size);
1920 if (r < 0)
1921 return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to allocate device probe for partition %" PRIu64 ".", p->partno);
1922
1923 errno = 0;
1924 if (blkid_probe_enable_superblocks(probe, true) < 0 ||
1925 blkid_probe_set_superblocks_flags(probe, BLKID_SUBLKS_MAGIC|BLKID_SUBLKS_BADCSUM) < 0 ||
1926 blkid_probe_enable_partitions(probe, true) < 0 ||
1927 blkid_probe_set_partitions_flags(probe, BLKID_PARTS_MAGIC) < 0)
1928 return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to enable superblock and partition probing for partition %" PRIu64 ".", p->partno);
1929
1930 for (;;) {
1931 errno = 0;
1932 r = blkid_do_probe(probe);
1933 if (r < 0)
1934 return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe for file systems.");
1935 if (r > 0)
1936 break;
1937
1938 errno = 0;
1939 if (blkid_do_wipe(probe, false) < 0)
1940 return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to wipe file system signature.");
1941 }
1942
1943 log_info("Successfully wiped file system signatures from partition %" PRIu64 ".", p->partno);
1944 return 0;
1945 }
1946
1947 static int context_discard_range(Context *context, uint64_t offset, uint64_t size) {
1948 struct stat st;
1949 int fd;
1950
1951 assert(context);
1952 assert(offset != UINT64_MAX);
1953 assert(size != UINT64_MAX);
1954
1955 if (size <= 0)
1956 return 0;
1957
1958 assert_se((fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
1959
1960 if (fstat(fd, &st) < 0)
1961 return -errno;
1962
1963 if (S_ISREG(st.st_mode)) {
1964 if (fallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, offset, size) < 0) {
1965 if (ERRNO_IS_NOT_SUPPORTED(errno))
1966 return -EOPNOTSUPP;
1967
1968 return -errno;
1969 }
1970
1971 return 1;
1972 }
1973
1974 if (S_ISBLK(st.st_mode)) {
1975 uint64_t range[2], end;
1976
1977 range[0] = round_up_size(offset, 512);
1978
1979 end = offset + size;
1980 if (end <= range[0])
1981 return 0;
1982
1983 range[1] = round_down_size(end - range[0], 512);
1984 if (range[1] <= 0)
1985 return 0;
1986
1987 if (ioctl(fd, BLKDISCARD, range) < 0) {
1988 if (ERRNO_IS_NOT_SUPPORTED(errno))
1989 return -EOPNOTSUPP;
1990
1991 return -errno;
1992 }
1993
1994 return 1;
1995 }
1996
1997 return -EOPNOTSUPP;
1998 }
1999
2000 static int context_discard_partition(Context *context, Partition *p) {
2001 int r;
2002
2003 assert(context);
2004 assert(p);
2005
2006 assert(p->offset != UINT64_MAX);
2007 assert(p->new_size != UINT64_MAX);
2008 assert(!PARTITION_EXISTS(p)); /* Safety check: never discard existing partitions */
2009
2010 if (!arg_discard)
2011 return 0;
2012
2013 r = context_discard_range(context, p->offset, p->new_size);
2014 if (r == -EOPNOTSUPP) {
2015 log_info("Storage does not support discarding, not discarding data in new partition %" PRIu64 ".", p->partno);
2016 return 0;
2017 }
2018 if (r == 0) {
2019 log_info("Partition %" PRIu64 " too short for discard, skipping.", p->partno);
2020 return 0;
2021 }
2022 if (r < 0)
2023 return log_error_errno(r, "Failed to discard data for new partition %" PRIu64 ".", p->partno);
2024
2025 log_info("Successfully discarded data from partition %" PRIu64 ".", p->partno);
2026 return 1;
2027 }
2028
2029 static int context_discard_gap_after(Context *context, Partition *p) {
2030 uint64_t gap, next = UINT64_MAX;
2031 Partition *q;
2032 int r;
2033
2034 assert(context);
2035 assert(!p || (p->offset != UINT64_MAX && p->new_size != UINT64_MAX));
2036
2037 if (p)
2038 gap = p->offset + p->new_size;
2039 else
2040 gap = context->start;
2041
2042 LIST_FOREACH(partitions, q, context->partitions) {
2043 if (q->dropped)
2044 continue;
2045
2046 assert(q->offset != UINT64_MAX);
2047 assert(q->new_size != UINT64_MAX);
2048
2049 if (q->offset < gap)
2050 continue;
2051
2052 if (next == UINT64_MAX || q->offset < next)
2053 next = q->offset;
2054 }
2055
2056 if (next == UINT64_MAX) {
2057 next = context->end;
2058 if (gap > next)
2059 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Partition end beyond disk end.");
2060 }
2061
2062 assert(next >= gap);
2063 r = context_discard_range(context, gap, next - gap);
2064 if (r == -EOPNOTSUPP) {
2065 if (p)
2066 log_info("Storage does not support discarding, not discarding gap after partition %" PRIu64 ".", p->partno);
2067 else
2068 log_info("Storage does not support discarding, not discarding gap at beginning of disk.");
2069 return 0;
2070 }
2071 if (r == 0) /* Too short */
2072 return 0;
2073 if (r < 0) {
2074 if (p)
2075 return log_error_errno(r, "Failed to discard gap after partition %" PRIu64 ".", p->partno);
2076 else
2077 return log_error_errno(r, "Failed to discard gap at beginning of disk.");
2078 }
2079
2080 if (p)
2081 log_info("Successfully discarded gap after partition %" PRIu64 ".", p->partno);
2082 else
2083 log_info("Successfully discarded gap at beginning of disk.");
2084
2085 return 0;
2086 }
2087
2088 static int context_wipe_and_discard(Context *context, bool from_scratch) {
2089 Partition *p;
2090 int r;
2091
2092 assert(context);
2093
2094 /* Wipe and discard the contents of all partitions we are about to create. We skip the discarding if
2095 * we were supposed to start from scratch anyway, as in that case we just discard the whole block
2096 * device in one go early on. */
2097
2098 LIST_FOREACH(partitions, p, context->partitions) {
2099
2100 if (!p->allocated_to_area)
2101 continue;
2102
2103 if (!from_scratch) {
2104 r = context_discard_partition(context, p);
2105 if (r < 0)
2106 return r;
2107 }
2108
2109 r = context_wipe_partition(context, p);
2110 if (r < 0)
2111 return r;
2112
2113 if (!from_scratch) {
2114 r = context_discard_gap_after(context, p);
2115 if (r < 0)
2116 return r;
2117 }
2118 }
2119
2120 if (!from_scratch) {
2121 r = context_discard_gap_after(context, NULL);
2122 if (r < 0)
2123 return r;
2124 }
2125
2126 return 0;
2127 }
2128
2129 static int partition_acquire_uuid(Context *context, Partition *p, sd_id128_t *ret) {
2130 struct {
2131 sd_id128_t type_uuid;
2132 uint64_t counter;
2133 } _packed_ plaintext = {};
2134 union {
2135 unsigned char md[SHA256_DIGEST_LENGTH];
2136 sd_id128_t id;
2137 } result;
2138
2139 uint64_t k = 0;
2140 Partition *q;
2141 int r;
2142
2143 assert(context);
2144 assert(p);
2145 assert(ret);
2146
2147 /* Calculate a good UUID for the indicated partition. We want a certain degree of reproducibility,
2148 * hence we won't generate the UUIDs randomly. Instead we use a cryptographic hash (precisely:
2149 * HMAC-SHA256) to derive them from a single seed. The seed is generally the machine ID of the
2150 * installation we are processing, but if random behaviour is desired can be random, too. We use the
2151 * seed value as key for the HMAC (since the machine ID is something we generally don't want to leak)
2152 * and the partition type as plaintext. The partition type is suffixed with a counter (only for the
2153 * second and later partition of the same type) if we have more than one partition of the same
2154 * time. Or in other words:
2155 *
2156 * With:
2157 * SEED := /etc/machine-id
2158 *
2159 * If first partition instance of type TYPE_UUID:
2160 * PARTITION_UUID := HMAC-SHA256(SEED, TYPE_UUID)
2161 *
2162 * For all later partition instances of type TYPE_UUID with INSTANCE being the LE64 encoded instance number:
2163 * PARTITION_UUID := HMAC-SHA256(SEED, TYPE_UUID || INSTANCE)
2164 */
2165
2166 LIST_FOREACH(partitions, q, context->partitions) {
2167 if (p == q)
2168 break;
2169
2170 if (!sd_id128_equal(p->type_uuid, q->type_uuid))
2171 continue;
2172
2173 k++;
2174 }
2175
2176 plaintext.type_uuid = p->type_uuid;
2177 plaintext.counter = htole64(k);
2178
2179 if (!HMAC(EVP_sha256(),
2180 &context->seed, sizeof(context->seed),
2181 (const unsigned char*) &plaintext, k == 0 ? sizeof(sd_id128_t) : sizeof(plaintext),
2182 result.md, NULL))
2183 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "SHA256 calculation failed.");
2184
2185 /* Take the first half, mark it as v4 UUID */
2186 assert_cc(sizeof(result.md) == sizeof(result.id) * 2);
2187 result.id = id128_make_v4_uuid(result.id);
2188
2189 /* Ensure this partition UUID is actually unique, and there's no remaining partition from an earlier run? */
2190 LIST_FOREACH(partitions, q, context->partitions) {
2191 if (p == q)
2192 continue;
2193
2194 if (sd_id128_equal(q->current_uuid, result.id) ||
2195 sd_id128_equal(q->new_uuid, result.id)) {
2196 log_warning("Partition UUID calculated from seed for partition %" PRIu64 " exists already, reverting to randomized UUID.", p->partno);
2197
2198 r = sd_id128_randomize(&result.id);
2199 if (r < 0)
2200 return log_error_errno(r, "Failed to generate randomized UUID: %m");
2201
2202 break;
2203 }
2204 }
2205
2206 *ret = result.id;
2207 return 0;
2208 }
2209
2210 static int partition_acquire_label(Context *context, Partition *p, char **ret) {
2211 _cleanup_free_ char *label = NULL;
2212 const char *prefix;
2213 unsigned k = 1;
2214
2215 assert(context);
2216 assert(p);
2217 assert(ret);
2218
2219 prefix = gpt_partition_type_uuid_to_string(p->type_uuid);
2220 if (!prefix)
2221 prefix = "linux";
2222
2223 for (;;) {
2224 const char *ll = label ?: prefix;
2225 bool retry = false;
2226 Partition *q;
2227
2228 LIST_FOREACH(partitions, q, context->partitions) {
2229 if (p == q)
2230 break;
2231
2232 if (streq_ptr(ll, q->current_label) ||
2233 streq_ptr(ll, q->new_label)) {
2234 retry = true;
2235 break;
2236 }
2237 }
2238
2239 if (!retry)
2240 break;
2241
2242 label = mfree(label);
2243
2244
2245 if (asprintf(&label, "%s-%u", prefix, ++k) < 0)
2246 return log_oom();
2247 }
2248
2249 if (!label) {
2250 label = strdup(prefix);
2251 if (!label)
2252 return log_oom();
2253 }
2254
2255 *ret = TAKE_PTR(label);
2256 return 0;
2257 }
2258
2259 static int context_acquire_partition_uuids_and_labels(Context *context) {
2260 Partition *p;
2261 int r;
2262
2263 assert(context);
2264
2265 LIST_FOREACH(partitions, p, context->partitions) {
2266 /* Never touch foreign partitions */
2267 if (PARTITION_IS_FOREIGN(p)) {
2268 p->new_uuid = p->current_uuid;
2269
2270 if (p->current_label) {
2271 free(p->new_label);
2272 p->new_label = strdup(p->current_label);
2273 if (!p->new_label)
2274 return log_oom();
2275 }
2276
2277 continue;
2278 }
2279
2280 if (!sd_id128_is_null(p->current_uuid))
2281 p->new_uuid = p->current_uuid; /* Never change initialized UUIDs */
2282 else if (sd_id128_is_null(p->new_uuid)) {
2283 /* Not explicitly set by user! */
2284 r = partition_acquire_uuid(context, p, &p->new_uuid);
2285 if (r < 0)
2286 return r;
2287 }
2288
2289 if (!isempty(p->current_label)) {
2290 free(p->new_label);
2291 p->new_label = strdup(p->current_label); /* never change initialized labels */
2292 if (!p->new_label)
2293 return log_oom();
2294 } else if (!p->new_label) {
2295 /* Not explicitly set by user! */
2296
2297 r = partition_acquire_label(context, p, &p->new_label);
2298 if (r < 0)
2299 return r;
2300 }
2301 }
2302
2303 return 0;
2304 }
2305
2306 static int device_kernel_partitions_supported(int fd) {
2307 struct loop_info64 info;
2308 struct stat st;
2309
2310 assert(fd >= 0);
2311
2312 if (fstat(fd, &st) < 0)
2313 return log_error_errno(fd, "Failed to fstat() image file: %m");
2314 if (!S_ISBLK(st.st_mode))
2315 return -ENOTBLK; /* we do not log in this one special case about errors */
2316
2317 if (ioctl(fd, LOOP_GET_STATUS64, &info) < 0) {
2318
2319 if (ERRNO_IS_NOT_SUPPORTED(errno) || errno == EINVAL)
2320 return true; /* not a loopback device, let's assume partition are supported */
2321
2322 return log_error_errno(fd, "Failed to issue LOOP_GET_STATUS64 on block device: %m");
2323 }
2324
2325 #if HAVE_VALGRIND_MEMCHECK_H
2326 /* Valgrind currently doesn't know LOOP_GET_STATUS64. Remove this once it does */
2327 VALGRIND_MAKE_MEM_DEFINED(&info, sizeof(info));
2328 #endif
2329
2330 return FLAGS_SET(info.lo_flags, LO_FLAGS_PARTSCAN);
2331 }
2332
2333 static int context_write_partition_table(
2334 Context *context,
2335 const char *node,
2336 bool from_scratch) {
2337
2338 _cleanup_(fdisk_unref_tablep) struct fdisk_table *original_table = NULL;
2339 int capable, r;
2340 Partition *p;
2341
2342 assert(context);
2343
2344 if (arg_pretty > 0 ||
2345 (arg_pretty < 0 && isatty(STDOUT_FILENO) > 0)) {
2346
2347 if (context->n_partitions == 0)
2348 puts("Empty partition table.");
2349 else
2350 (void) context_dump_partitions(context, node);
2351
2352 putc('\n', stdout);
2353
2354 (void) context_dump_partition_bar(context, node);
2355 putc('\n', stdout);
2356 fflush(stdout);
2357 }
2358
2359 if (!from_scratch && !context_changed(context)) {
2360 log_info("No changes.");
2361 return 0;
2362 }
2363
2364 if (arg_dry_run) {
2365 log_notice("Refusing to repartition, please re-run with --dry-run=no.");
2366 return 0;
2367 }
2368
2369 log_info("Applying changes.");
2370
2371 if (from_scratch) {
2372 r = context_discard_range(context, 0, context->total);
2373 if (r == -EOPNOTSUPP)
2374 log_info("Storage does not support discarding, not discarding entire block device data.");
2375 else if (r < 0)
2376 return log_error_errno(r, "Failed to discard entire block device: %m");
2377 else if (r > 0)
2378 log_info("Discarded entire block device.");
2379 }
2380
2381 r = fdisk_get_partitions(context->fdisk_context, &original_table);
2382 if (r < 0)
2383 return log_error_errno(r, "Failed to acquire partition table: %m");
2384
2385 /* Wipe fs signatures and discard sectors where the new partitions are going to be placed and in the
2386 * gaps between partitions, just to be sure. */
2387 r = context_wipe_and_discard(context, from_scratch);
2388 if (r < 0)
2389 return r;
2390
2391 LIST_FOREACH(partitions, p, context->partitions) {
2392 if (p->dropped)
2393 continue;
2394
2395 assert(p->new_size != UINT64_MAX);
2396 assert(p->offset != UINT64_MAX);
2397 assert(p->partno != UINT64_MAX);
2398
2399 if (PARTITION_EXISTS(p)) {
2400 bool changed = false;
2401
2402 assert(p->current_partition);
2403
2404 if (p->new_size != p->current_size) {
2405 assert(p->new_size >= p->current_size);
2406 assert(p->new_size % 512 == 0);
2407
2408 r = fdisk_partition_size_explicit(p->current_partition, true);
2409 if (r < 0)
2410 return log_error_errno(r, "Failed to enable explicit sizing: %m");
2411
2412 r = fdisk_partition_set_size(p->current_partition, p->new_size / 512);
2413 if (r < 0)
2414 return log_error_errno(r, "Failed to grow partition: %m");
2415
2416 log_info("Growing existing partition %" PRIu64 ".", p->partno);
2417 changed = true;
2418 }
2419
2420 if (!sd_id128_equal(p->new_uuid, p->current_uuid)) {
2421 char buf[ID128_UUID_STRING_MAX];
2422
2423 assert(!sd_id128_is_null(p->new_uuid));
2424
2425 r = fdisk_partition_set_uuid(p->current_partition, id128_to_uuid_string(p->new_uuid, buf));
2426 if (r < 0)
2427 return log_error_errno(r, "Failed to set partition UUID: %m");
2428
2429 log_info("Initializing UUID of existing partition %" PRIu64 ".", p->partno);
2430 changed = true;
2431 }
2432
2433 if (!streq_ptr(p->new_label, p->current_label)) {
2434 assert(!isempty(p->new_label));
2435
2436 r = fdisk_partition_set_name(p->current_partition, p->new_label);
2437 if (r < 0)
2438 return log_error_errno(r, "Failed to set partition label: %m");
2439
2440 log_info("Setting partition label of existing partition %" PRIu64 ".", p->partno);
2441 changed = true;
2442 }
2443
2444 if (changed) {
2445 assert(!PARTITION_IS_FOREIGN(p)); /* never touch foreign partitions */
2446
2447 r = fdisk_set_partition(context->fdisk_context, p->partno, p->current_partition);
2448 if (r < 0)
2449 return log_error_errno(r, "Failed to update partition: %m");
2450 }
2451 } else {
2452 _cleanup_(fdisk_unref_partitionp) struct fdisk_partition *q = NULL;
2453 _cleanup_(fdisk_unref_parttypep) struct fdisk_parttype *t = NULL;
2454 char ids[ID128_UUID_STRING_MAX];
2455
2456 assert(!p->new_partition);
2457 assert(p->offset % 512 == 0);
2458 assert(p->new_size % 512 == 0);
2459 assert(!sd_id128_is_null(p->new_uuid));
2460 assert(!isempty(p->new_label));
2461
2462 t = fdisk_new_parttype();
2463 if (!t)
2464 return log_oom();
2465
2466 r = fdisk_parttype_set_typestr(t, id128_to_uuid_string(p->type_uuid, ids));
2467 if (r < 0)
2468 return log_error_errno(r, "Failed to initialize partition type: %m");
2469
2470 q = fdisk_new_partition();
2471 if (!q)
2472 return log_oom();
2473
2474 r = fdisk_partition_set_type(q, t);
2475 if (r < 0)
2476 return log_error_errno(r, "Failed to set partition type: %m");
2477
2478 r = fdisk_partition_size_explicit(q, true);
2479 if (r < 0)
2480 return log_error_errno(r, "Failed to enable explicit sizing: %m");
2481
2482 r = fdisk_partition_set_start(q, p->offset / 512);
2483 if (r < 0)
2484 return log_error_errno(r, "Failed to position partition: %m");
2485
2486 r = fdisk_partition_set_size(q, p->new_size / 512);
2487 if (r < 0)
2488 return log_error_errno(r, "Failed to grow partition: %m");
2489
2490 r = fdisk_partition_set_partno(q, p->partno);
2491 if (r < 0)
2492 return log_error_errno(r, "Failed to set partition number: %m");
2493
2494 r = fdisk_partition_set_uuid(q, id128_to_uuid_string(p->new_uuid, ids));
2495 if (r < 0)
2496 return log_error_errno(r, "Failed to set partition UUID: %m");
2497
2498 r = fdisk_partition_set_name(q, p->new_label);
2499 if (r < 0)
2500 return log_error_errno(r, "Failed to set partition label: %m");
2501
2502 log_info("Creating new partition %" PRIu64 ".", p->partno);
2503
2504 r = fdisk_add_partition(context->fdisk_context, q, NULL);
2505 if (r < 0)
2506 return log_error_errno(r, "Failed to add partition: %m");
2507
2508 assert(!p->new_partition);
2509 p->new_partition = TAKE_PTR(q);
2510 }
2511 }
2512
2513 log_info("Writing new partition table.");
2514
2515 r = fdisk_write_disklabel(context->fdisk_context);
2516 if (r < 0)
2517 return log_error_errno(r, "Failed to write partition table: %m");
2518
2519 capable = device_kernel_partitions_supported(fdisk_get_devfd(context->fdisk_context));
2520 if (capable == -ENOTBLK)
2521 log_debug("Not telling kernel to reread partition table, since we are not operating on a block device.");
2522 else if (capable < 0)
2523 return capable;
2524 else if (capable > 0) {
2525 log_info("Telling kernel to reread partition table.");
2526
2527 if (from_scratch)
2528 r = fdisk_reread_partition_table(context->fdisk_context);
2529 else
2530 r = fdisk_reread_changes(context->fdisk_context, original_table);
2531 if (r < 0)
2532 return log_error_errno(r, "Failed to reread partition table: %m");
2533 } else
2534 log_notice("Not telling kernel to reread partition table, because selected image does not support kernel partition block devices.");
2535
2536 log_info("All done.");
2537
2538 return 0;
2539 }
2540
2541 static int context_read_seed(Context *context, const char *root) {
2542 int r;
2543
2544 assert(context);
2545
2546 if (!sd_id128_is_null(context->seed))
2547 return 0;
2548
2549 if (!arg_randomize) {
2550 _cleanup_close_ int fd = -1;
2551
2552 fd = chase_symlinks_and_open("/etc/machine-id", root, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC, NULL);
2553 if (fd == -ENOENT)
2554 log_info("No machine ID set, using randomized partition UUIDs.");
2555 else if (fd < 0)
2556 return log_error_errno(fd, "Failed to determine machine ID of image: %m");
2557 else {
2558 r = id128_read_fd(fd, ID128_PLAIN, &context->seed);
2559 if (r == -ENOMEDIUM)
2560 log_info("No machine ID set, using randomized partition UUIDs.");
2561 else if (r < 0)
2562 return log_error_errno(r, "Failed to parse machine ID of image: %m");
2563
2564 return 0;
2565 }
2566 }
2567
2568 r = sd_id128_randomize(&context->seed);
2569 if (r < 0)
2570 return log_error_errno(r, "Failed to generate randomized seed: %m");
2571
2572 return 0;
2573 }
2574
2575 static int context_factory_reset(Context *context, bool from_scratch) {
2576 Partition *p;
2577 size_t n = 0;
2578 int r;
2579
2580 assert(context);
2581
2582 if (arg_factory_reset <= 0)
2583 return 0;
2584
2585 if (from_scratch) /* Nothing to reset if we start from scratch */
2586 return 0;
2587
2588 if (arg_dry_run) {
2589 log_notice("Refusing to factory reset, please re-run with --dry-run=no.");
2590 return 0;
2591 }
2592
2593 log_info("Applying factory reset.");
2594
2595 LIST_FOREACH(partitions, p, context->partitions) {
2596
2597 if (!p->factory_reset || !PARTITION_EXISTS(p))
2598 continue;
2599
2600 assert(p->partno != UINT64_MAX);
2601
2602 log_info("Removing partition %" PRIu64 " for factory reset.", p->partno);
2603
2604 r = fdisk_delete_partition(context->fdisk_context, p->partno);
2605 if (r < 0)
2606 return log_error_errno(r, "Failed to remove partition %" PRIu64 ": %m", p->partno);
2607
2608 n++;
2609 }
2610
2611 if (n == 0) {
2612 log_info("Factory reset requested, but no partitions to delete found.");
2613 return 0;
2614 }
2615
2616 r = fdisk_write_disklabel(context->fdisk_context);
2617 if (r < 0)
2618 return log_error_errno(r, "Failed to write disk label: %m");
2619
2620 log_info("Successfully deleted %zu partitions.", n);
2621 return 1;
2622 }
2623
2624 static int context_can_factory_reset(Context *context) {
2625 Partition *p;
2626
2627 assert(context);
2628
2629 LIST_FOREACH(partitions, p, context->partitions)
2630 if (p->factory_reset && PARTITION_EXISTS(p))
2631 return true;
2632
2633 return false;
2634 }
2635
2636 static int help(void) {
2637 _cleanup_free_ char *link = NULL;
2638 int r;
2639
2640 r = terminal_urlify_man("systemd-repart", "1", &link);
2641 if (r < 0)
2642 return log_oom();
2643
2644 printf("%s [OPTIONS...] [DEVICE]\n"
2645 "\n%sGrow and add partitions to partition table.%s\n\n"
2646 " -h --help Show this help\n"
2647 " --version Show package version\n"
2648 " --dry-run=BOOL Whether to run dry-run operation\n"
2649 " --empty=MODE One of refuse, allow, require, force, create; controls\n"
2650 " how to handle empty disks lacking partition tables\n"
2651 " --discard=BOOL Whether to discard backing blocks for new partitions\n"
2652 " --pretty=BOOL Whether to show pretty summary before executing operation\n"
2653 " --factory-reset=BOOL Whether to remove data partitions before recreating\n"
2654 " them\n"
2655 " --can-factory-reset Test whether factory reset is defined\n"
2656 " --root=PATH Operate relative to root path\n"
2657 " --definitions=DIR Find partitions in specified directory\n"
2658 " --seed=UUID 128bit seed UUID to derive all UUIDs from\n"
2659 " --size=BYTES Grow loopback file to specified size\n"
2660 "\nSee the %s for details.\n"
2661 , program_invocation_short_name
2662 , ansi_highlight(), ansi_normal()
2663 , link
2664 );
2665
2666 return 0;
2667 }
2668
2669 static int parse_argv(int argc, char *argv[]) {
2670
2671 enum {
2672 ARG_VERSION = 0x100,
2673 ARG_DRY_RUN,
2674 ARG_EMPTY,
2675 ARG_DISCARD,
2676 ARG_FACTORY_RESET,
2677 ARG_CAN_FACTORY_RESET,
2678 ARG_ROOT,
2679 ARG_SEED,
2680 ARG_PRETTY,
2681 ARG_DEFINITIONS,
2682 ARG_SIZE,
2683 };
2684
2685 static const struct option options[] = {
2686 { "help", no_argument, NULL, 'h' },
2687 { "version", no_argument, NULL, ARG_VERSION },
2688 { "dry-run", required_argument, NULL, ARG_DRY_RUN },
2689 { "empty", required_argument, NULL, ARG_EMPTY },
2690 { "discard", required_argument, NULL, ARG_DISCARD },
2691 { "factory-reset", required_argument, NULL, ARG_FACTORY_RESET },
2692 { "can-factory-reset", no_argument, NULL, ARG_CAN_FACTORY_RESET },
2693 { "root", required_argument, NULL, ARG_ROOT },
2694 { "seed", required_argument, NULL, ARG_SEED },
2695 { "pretty", required_argument, NULL, ARG_PRETTY },
2696 { "definitions", required_argument, NULL, ARG_DEFINITIONS },
2697 { "size", required_argument, NULL, ARG_SIZE },
2698 {}
2699 };
2700
2701 int c, r, dry_run = -1;
2702
2703 assert(argc >= 0);
2704 assert(argv);
2705
2706 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
2707
2708 switch (c) {
2709
2710 case 'h':
2711 return help();
2712
2713 case ARG_VERSION:
2714 return version();
2715
2716 case ARG_DRY_RUN:
2717 r = parse_boolean(optarg);
2718 if (r < 0)
2719 return log_error_errno(r, "Failed to parse --dry-run= parameter: %s", optarg);
2720
2721 dry_run = r;
2722 break;
2723
2724 case ARG_EMPTY:
2725 if (isempty(optarg) || streq(optarg, "refuse"))
2726 arg_empty = EMPTY_REFUSE;
2727 else if (streq(optarg, "allow"))
2728 arg_empty = EMPTY_ALLOW;
2729 else if (streq(optarg, "require"))
2730 arg_empty = EMPTY_REQUIRE;
2731 else if (streq(optarg, "force"))
2732 arg_empty = EMPTY_FORCE;
2733 else if (streq(optarg, "create")) {
2734 arg_empty = EMPTY_CREATE;
2735
2736 if (dry_run < 0)
2737 dry_run = false; /* Imply --dry-run=no if we create the loopback file
2738 * anew. After all we cannot really break anyone's
2739 * partition tables that way. */
2740 } else
2741 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2742 "Failed to parse --empty= parameter: %s", optarg);
2743 break;
2744
2745 case ARG_DISCARD:
2746 r = parse_boolean(optarg);
2747 if (r < 0)
2748 return log_error_errno(r, "Failed to parse --discard= parameter: %s", optarg);
2749
2750 arg_discard = r;
2751 break;
2752
2753 case ARG_FACTORY_RESET:
2754 r = parse_boolean(optarg);
2755 if (r < 0)
2756 return log_error_errno(r, "Failed to parse --factory-reset= parameter: %s", optarg);
2757
2758 arg_factory_reset = r;
2759 break;
2760
2761 case ARG_CAN_FACTORY_RESET:
2762 arg_can_factory_reset = true;
2763 break;
2764
2765 case ARG_ROOT:
2766 r = parse_path_argument_and_warn(optarg, false, &arg_root);
2767 if (r < 0)
2768 return r;
2769 break;
2770
2771 case ARG_SEED:
2772 if (isempty(optarg)) {
2773 arg_seed = SD_ID128_NULL;
2774 arg_randomize = false;
2775 } else if (streq(optarg, "random"))
2776 arg_randomize = true;
2777 else {
2778 r = sd_id128_from_string(optarg, &arg_seed);
2779 if (r < 0)
2780 return log_error_errno(r, "Failed to parse seed: %s", optarg);
2781
2782 arg_randomize = false;
2783 }
2784
2785 break;
2786
2787 case ARG_PRETTY:
2788 r = parse_boolean(optarg);
2789 if (r < 0)
2790 return log_error_errno(r, "Failed to parse --pretty= parameter: %s", optarg);
2791
2792 arg_pretty = r;
2793 break;
2794
2795 case ARG_DEFINITIONS:
2796 r = parse_path_argument_and_warn(optarg, false, &arg_definitions);
2797 if (r < 0)
2798 return r;
2799 break;
2800
2801 case ARG_SIZE: {
2802 uint64_t parsed, rounded;
2803
2804 r = parse_size(optarg, 1024, &parsed);
2805 if (r < 0)
2806 return log_error_errno(r, "Failed to parse --size= parameter: %s", optarg);
2807
2808 rounded = round_up_size(parsed, 4096);
2809 if (rounded == 0)
2810 return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Specified image size too small, refusing.");
2811 if (rounded == UINT64_MAX)
2812 return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Specified image size too large, refusing.");
2813
2814 if (rounded != parsed)
2815 log_warning("Specified size is not a multiple of 4096, rounding up automatically. (%" PRIu64 " → %" PRIu64 ")",
2816 parsed, rounded);
2817
2818 arg_size = rounded;
2819 break;
2820 }
2821
2822 case '?':
2823 return -EINVAL;
2824
2825 default:
2826 assert_not_reached("Unhandled option");
2827 }
2828
2829 if (argc - optind > 1)
2830 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2831 "Expected at most one argument, the path to the block device.");
2832
2833 if (arg_factory_reset > 0 && IN_SET(arg_empty, EMPTY_FORCE, EMPTY_REQUIRE, EMPTY_CREATE))
2834 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2835 "Combination of --factory-reset=yes and --empty=force/--empty=require/--empty=create is invalid.");
2836
2837 if (arg_can_factory_reset)
2838 arg_dry_run = true; /* When --can-factory-reset is specified we don't make changes, hence
2839 * non-dry-run mode makes no sense. Thus, imply dry run mode so that we
2840 * open things strictly read-only. */
2841 else if (dry_run >= 0)
2842 arg_dry_run = dry_run;
2843
2844 if (arg_empty == EMPTY_CREATE && arg_size == UINT64_MAX)
2845 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2846 "If --empty=create is specified, --size= must be specified, too.");
2847
2848 arg_node = argc > optind ? argv[optind] : NULL;
2849
2850 if (IN_SET(arg_empty, EMPTY_FORCE, EMPTY_REQUIRE, EMPTY_CREATE) && !arg_node)
2851 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2852 "A path to a device node or loopback file must be specified when --empty=force, --empty=require or --empty=create are used.");
2853
2854 return 1;
2855 }
2856
2857 static int parse_proc_cmdline_factory_reset(void) {
2858 bool b;
2859 int r;
2860
2861 if (arg_factory_reset >= 0) /* Never override what is specified on the process command line */
2862 return 0;
2863
2864 if (!in_initrd()) /* Never honour kernel command line factory reset request outside of the initrd */
2865 return 0;
2866
2867 r = proc_cmdline_get_bool("systemd.factory_reset", &b);
2868 if (r < 0)
2869 return log_error_errno(r, "Failed to parse systemd.factory_reset kernel command line argument: %m");
2870 if (r > 0) {
2871 arg_factory_reset = b;
2872
2873 if (b)
2874 log_notice("Honouring factory reset requested via kernel command line.");
2875 }
2876
2877 return 0;
2878 }
2879
2880 static int parse_efi_variable_factory_reset(void) {
2881 _cleanup_free_ char *value = NULL;
2882 int r;
2883
2884 if (arg_factory_reset >= 0) /* Never override what is specified on the process command line */
2885 return 0;
2886
2887 if (!in_initrd()) /* Never honour EFI variable factory reset request outside of the initrd */
2888 return 0;
2889
2890 r = efi_get_variable_string(EFI_VENDOR_SYSTEMD, "FactoryReset", &value);
2891 if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r))
2892 return 0;
2893 if (r < 0)
2894 return log_error_errno(r, "Failed to read EFI variable FactoryReset: %m");
2895
2896 r = parse_boolean(value);
2897 if (r < 0)
2898 return log_error_errno(r, "Failed to parse EFI variable FactoryReset: %m");
2899
2900 arg_factory_reset = r;
2901 if (r)
2902 log_notice("Honouring factory reset requested via EFI variable FactoryReset: %m");
2903
2904 return 0;
2905 }
2906
2907 static int remove_efi_variable_factory_reset(void) {
2908 int r;
2909
2910 r = efi_set_variable(EFI_VENDOR_SYSTEMD, "FactoryReset", NULL, 0);
2911 if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r))
2912 return 0;
2913 if (r < 0)
2914 return log_error_errno(r, "Failed to remove EFI variable FactoryReset: %m");
2915
2916 log_info("Successfully unset EFI variable FactoryReset.");
2917 return 0;
2918 }
2919
2920 static int acquire_root_devno(const char *p, int mode, char **ret, int *ret_fd) {
2921 _cleanup_close_ int fd = -1;
2922 struct stat st;
2923 dev_t devno, fd_devno = (mode_t) -1;
2924 int r;
2925
2926 assert(p);
2927 assert(ret);
2928 assert(ret_fd);
2929
2930 fd = open(p, mode);
2931 if (fd < 0)
2932 return -errno;
2933
2934 if (fstat(fd, &st) < 0)
2935 return -errno;
2936
2937 if (S_ISREG(st.st_mode)) {
2938 char *s;
2939
2940 s = strdup(p);
2941 if (!s)
2942 return log_oom();
2943
2944 *ret = s;
2945 *ret_fd = TAKE_FD(fd);
2946
2947 return 0;
2948 }
2949
2950 if (S_ISBLK(st.st_mode))
2951 fd_devno = devno = st.st_rdev;
2952 else if (S_ISDIR(st.st_mode)) {
2953
2954 devno = st.st_dev;
2955 if (major(devno) == 0) {
2956 r = btrfs_get_block_device_fd(fd, &devno);
2957 if (r == -ENOTTY) /* not btrfs */
2958 return -ENODEV;
2959 if (r < 0)
2960 return r;
2961 }
2962 } else
2963 return -ENOTBLK;
2964
2965 /* From dm-crypt to backing partition */
2966 r = block_get_originating(devno, &devno);
2967 if (r < 0)
2968 log_debug_errno(r, "Failed to find underlying block device for '%s', ignoring: %m", p);
2969
2970 /* From partition to whole disk containing it */
2971 r = block_get_whole_disk(devno, &devno);
2972 if (r < 0)
2973 log_debug_errno(r, "Failed to find whole disk block device for '%s', ignoring: %m", p);
2974
2975 r = device_path_make_canonical(S_IFBLK, devno, ret);
2976 if (r < 0)
2977 return log_debug_errno(r, "Failed to determine canonical path for '%s': %m", p);
2978
2979 /* Only if we still lock at the same block device we can reuse the fd. Otherwise return an
2980 * invalidated fd. */
2981 *ret_fd = fd_devno != (mode_t) -1 && fd_devno == devno ? TAKE_FD(fd) : -1;
2982 return 0;
2983 }
2984
2985 static int find_root(char **ret, int *ret_fd) {
2986 const char *t;
2987 int r;
2988
2989 assert(ret);
2990 assert(ret_fd);
2991
2992 if (arg_node) {
2993 if (arg_empty == EMPTY_CREATE) {
2994 _cleanup_close_ int fd = -1;
2995 _cleanup_free_ char *s = NULL;
2996
2997 s = strdup(arg_node);
2998 if (!s)
2999 return log_oom();
3000
3001 fd = open(arg_node, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOFOLLOW, 0777);
3002 if (fd < 0)
3003 return log_error_errno(errno, "Failed to create '%s': %m", arg_node);
3004
3005 *ret = TAKE_PTR(s);
3006 *ret_fd = TAKE_FD(fd);
3007 return 0;
3008 }
3009
3010 r = acquire_root_devno(arg_node, O_RDONLY|O_CLOEXEC, ret, ret_fd);
3011 if (r < 0)
3012 return log_error_errno(r, "Failed to determine backing device of %s: %m", arg_node);
3013
3014 return 0;
3015 }
3016
3017 assert(IN_SET(arg_empty, EMPTY_REFUSE, EMPTY_ALLOW));
3018
3019 /* Let's search for the root device. We look for two cases here: first in /, and then in /usr. The
3020 * latter we check for cases where / is a tmpfs and only /usr is an actual persistent block device
3021 * (think: volatile setups) */
3022
3023 FOREACH_STRING(t, "/", "/usr") {
3024 _cleanup_free_ char *j = NULL;
3025 const char *p;
3026
3027 if (in_initrd()) {
3028 j = path_join("/sysroot", t);
3029 if (!j)
3030 return log_oom();
3031
3032 p = j;
3033 } else
3034 p = t;
3035
3036 r = acquire_root_devno(p, O_RDONLY|O_DIRECTORY|O_CLOEXEC, ret, ret_fd);
3037 if (r < 0) {
3038 if (r != -ENODEV)
3039 return log_error_errno(r, "Failed to determine backing device of %s: %m", p);
3040 } else
3041 return 0;
3042 }
3043
3044 return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "Failed to discover root block device.");
3045 }
3046
3047 static int resize_backing_fd(const char *node, int *fd) {
3048 char buf1[FORMAT_BYTES_MAX], buf2[FORMAT_BYTES_MAX];
3049 _cleanup_close_ int writable_fd = -1;
3050 struct stat st;
3051 int r;
3052
3053 assert(node);
3054 assert(fd);
3055
3056 if (arg_size == UINT64_MAX) /* Nothing to do */
3057 return 0;
3058
3059 if (*fd < 0) {
3060 /* Open the file if we haven't opened it yet. Note that we open it read-only here, just to
3061 * keep a reference to the file we can pass around. */
3062 *fd = open(node, O_RDONLY|O_CLOEXEC);
3063 if (*fd < 0)
3064 return log_error_errno(errno, "Failed to open '%s' in order to adjust size: %m", node);
3065 }
3066
3067 if (fstat(*fd, &st) < 0)
3068 return log_error_errno(errno, "Failed to stat '%s': %m", node);
3069
3070 r = stat_verify_regular(&st);
3071 if (r < 0)
3072 return log_error_errno(r, "Specified path '%s' is not a regular file, cannot resize: %m", node);
3073
3074 assert_se(format_bytes(buf1, sizeof(buf1), st.st_size));
3075 assert_se(format_bytes(buf2, sizeof(buf2), arg_size));
3076
3077 if ((uint64_t) st.st_size >= arg_size) {
3078 log_info("File '%s' already is of requested size or larger, not growing. (%s >= %s)", node, buf1, buf2);
3079 return 0;
3080 }
3081
3082 /* The file descriptor is read-only. In order to grow the file we need to have a writable fd. We
3083 * reopen the file for that temporarily. We keep the writable fd only open for this operation though,
3084 * as fdisk can't accept it anyway. */
3085
3086 writable_fd = fd_reopen(*fd, O_WRONLY|O_CLOEXEC);
3087 if (writable_fd < 0)
3088 return log_error_errno(writable_fd, "Failed to reopen backing file '%s' writable: %m", node);
3089
3090 if (!arg_discard) {
3091 if (fallocate(writable_fd, 0, 0, arg_size) < 0) {
3092 if (!ERRNO_IS_NOT_SUPPORTED(errno))
3093 return log_error_errno(errno, "Failed to grow '%s' from %s to %s by allocation: %m",
3094 node, buf1, buf2);
3095
3096 /* Fallback to truncation, if fallocate() is not supported. */
3097 log_debug("Backing file system does not support fallocate(), falling back to ftruncate().");
3098 } else {
3099 if (st.st_size == 0) /* Likely regular file just created by us */
3100 log_info("Allocated %s for '%s'.", buf2, node);
3101 else
3102 log_info("File '%s' grown from %s to %s by allocation.", node, buf1, buf2);
3103
3104 return 1;
3105 }
3106 }
3107
3108 if (ftruncate(writable_fd, arg_size) < 0)
3109 return log_error_errno(errno, "Failed to grow '%s' from %s to %s by truncation: %m",
3110 node, buf1, buf2);
3111
3112 if (st.st_size == 0) /* Likely regular file just created by us */
3113 log_info("Sized '%s' to %s.", node, buf2);
3114 else
3115 log_info("File '%s' grown from %s to %s by truncation.", node, buf1, buf2);
3116
3117 return 1;
3118 }
3119
3120 static int run(int argc, char *argv[]) {
3121 _cleanup_(context_freep) Context* context = NULL;
3122 _cleanup_free_ char *node = NULL;
3123 _cleanup_close_ int backing_fd = -1;
3124 bool from_scratch;
3125 int r;
3126
3127 log_show_color(true);
3128 log_parse_environment();
3129 log_open();
3130
3131 if (in_initrd()) {
3132 /* Default to operation on /sysroot when invoked in the initrd! */
3133 arg_root = strdup("/sysroot");
3134 if (!arg_root)
3135 return log_oom();
3136 }
3137
3138 r = parse_argv(argc, argv);
3139 if (r <= 0)
3140 return r;
3141
3142 r = parse_proc_cmdline_factory_reset();
3143 if (r < 0)
3144 return r;
3145
3146 r = parse_efi_variable_factory_reset();
3147 if (r < 0)
3148 return r;
3149
3150 context = context_new(arg_seed);
3151 if (!context)
3152 return log_oom();
3153
3154 r = context_read_definitions(context, arg_definitions, arg_root);
3155 if (r < 0)
3156 return r;
3157
3158 if (context->n_partitions <= 0 && arg_empty == EMPTY_REFUSE) {
3159 log_info("Didn't find any partition definition files, nothing to do.");
3160 return 0;
3161 }
3162
3163 r = find_root(&node, &backing_fd);
3164 if (r < 0)
3165 return r;
3166
3167 if (arg_size != UINT64_MAX) {
3168 r = resize_backing_fd(node, &backing_fd);
3169 if (r < 0)
3170 return r;
3171 }
3172
3173 r = context_load_partition_table(context, node, &backing_fd);
3174 if (r == -EHWPOISON)
3175 return 77; /* Special return value which means "Not GPT, so not doing anything". This isn't
3176 * really an error when called at boot. */
3177 if (r < 0)
3178 return r;
3179 from_scratch = r > 0; /* Starting from scratch */
3180
3181 if (arg_can_factory_reset) {
3182 r = context_can_factory_reset(context);
3183 if (r < 0)
3184 return r;
3185 if (r == 0)
3186 return EXIT_FAILURE;
3187
3188 return 0;
3189 }
3190
3191 r = context_factory_reset(context, from_scratch);
3192 if (r < 0)
3193 return r;
3194 if (r > 0) {
3195 /* We actually did a factory reset! */
3196 r = remove_efi_variable_factory_reset();
3197 if (r < 0)
3198 return r;
3199
3200 /* Reload the reduced partition table */
3201 context_unload_partition_table(context);
3202 r = context_load_partition_table(context, node, &backing_fd);
3203 if (r < 0)
3204 return r;
3205 }
3206
3207 #if 0
3208 (void) context_dump_partitions(context, node);
3209 putchar('\n');
3210 #endif
3211
3212 r = context_read_seed(context, arg_root);
3213 if (r < 0)
3214 return r;
3215
3216 /* First try to fit new partitions in, dropping by priority until it fits */
3217 for (;;) {
3218 if (context_allocate_partitions(context))
3219 break; /* Success! */
3220
3221 if (!context_drop_one_priority(context))
3222 return log_error_errno(SYNTHETIC_ERRNO(ENOSPC),
3223 "Can't fit requested partitions into free space, refusing.");
3224 }
3225
3226 /* Now assign free space according to the weight logic */
3227 r = context_grow_partitions(context);
3228 if (r < 0)
3229 return r;
3230
3231 /* Now calculate where each partition gets placed */
3232 context_place_partitions(context);
3233
3234 /* Make sure each partition has a unique UUID and unique label */
3235 r = context_acquire_partition_uuids_and_labels(context);
3236 if (r < 0)
3237 return r;
3238
3239 r = context_write_partition_table(context, node, from_scratch);
3240 if (r < 0)
3241 return r;
3242
3243 return 0;
3244 }
3245
3246 DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);