]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/gpt-auto-generator/gpt-auto-generator.c
util-lib: split string parsing related calls from util.[ch] into parse-util.[ch]
[thirdparty/systemd.git] / src / gpt-auto-generator / gpt-auto-generator.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <sys/statfs.h>
25 #include <blkid/blkid.h>
26
27 #include "libudev.h"
28 #include "sd-id128.h"
29
30 #include "blkid-util.h"
31 #include "btrfs-util.h"
32 #include "efivars.h"
33 #include "fd-util.h"
34 #include "fileio.h"
35 #include "fstab-util.h"
36 #include "generator.h"
37 #include "gpt.h"
38 #include "missing.h"
39 #include "mkdir.h"
40 #include "parse-util.h"
41 #include "path-util.h"
42 #include "special.h"
43 #include "string-util.h"
44 #include "udev-util.h"
45 #include "unit-name.h"
46 #include "util.h"
47 #include "virt.h"
48
49 static const char *arg_dest = "/tmp";
50 static bool arg_enabled = true;
51 static bool arg_root_enabled = true;
52 static bool arg_root_rw = false;
53
54 static int add_cryptsetup(const char *id, const char *what, bool rw, char **device) {
55 _cleanup_free_ char *e = NULL, *n = NULL, *p = NULL, *d = NULL, *to = NULL;
56 _cleanup_fclose_ FILE *f = NULL;
57 char *from, *ret;
58 int r;
59
60 assert(id);
61 assert(what);
62 assert(device);
63
64 r = unit_name_from_path(what, ".device", &d);
65 if (r < 0)
66 return log_error_errno(r, "Failed to generate unit name: %m");
67
68 e = unit_name_escape(id);
69 if (!e)
70 return log_oom();
71
72 r = unit_name_build("systemd-cryptsetup", e, ".service", &n);
73 if (r < 0)
74 return log_error_errno(r, "Failed to generate unit name: %m");
75
76 p = strjoin(arg_dest, "/", n, NULL);
77 if (!p)
78 return log_oom();
79
80 f = fopen(p, "wxe");
81 if (!f)
82 return log_error_errno(errno, "Failed to create unit file %s: %m", p);
83
84 fprintf(f,
85 "# Automatically generated by systemd-gpt-auto-generator\n\n"
86 "[Unit]\n"
87 "Description=Cryptography Setup for %%I\n"
88 "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
89 "DefaultDependencies=no\n"
90 "Conflicts=umount.target\n"
91 "BindsTo=dev-mapper-%%i.device %s\n"
92 "Before=umount.target cryptsetup.target\n"
93 "After=%s\n"
94 "IgnoreOnIsolate=true\n"
95 "[Service]\n"
96 "Type=oneshot\n"
97 "RemainAfterExit=yes\n"
98 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
99 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '' '%s'\n"
100 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
101 d, d,
102 id, what, rw ? "" : "read-only",
103 id);
104
105 r = fflush_and_check(f);
106 if (r < 0)
107 return log_error_errno(r, "Failed to write file %s: %m", p);
108
109 from = strjoina("../", n);
110
111 to = strjoin(arg_dest, "/", d, ".wants/", n, NULL);
112 if (!to)
113 return log_oom();
114
115 mkdir_parents_label(to, 0755);
116 if (symlink(from, to) < 0)
117 return log_error_errno(errno, "Failed to create symlink %s: %m", to);
118
119 free(to);
120 to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
121 if (!to)
122 return log_oom();
123
124 mkdir_parents_label(to, 0755);
125 if (symlink(from, to) < 0)
126 return log_error_errno(errno, "Failed to create symlink %s: %m", to);
127
128 free(to);
129 to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
130 if (!to)
131 return log_oom();
132
133 mkdir_parents_label(to, 0755);
134 if (symlink(from, to) < 0)
135 return log_error_errno(errno, "Failed to create symlink %s: %m", to);
136
137 free(p);
138 p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf", NULL);
139 if (!p)
140 return log_oom();
141
142 mkdir_parents_label(p, 0755);
143 r = write_string_file(p,
144 "# Automatically generated by systemd-gpt-auto-generator\n\n"
145 "[Unit]\n"
146 "JobTimeoutSec=0\n",
147 WRITE_STRING_FILE_CREATE); /* the binary handles timeouts anyway */
148 if (r < 0)
149 return log_error_errno(r, "Failed to write device drop-in: %m");
150
151 ret = strappend("/dev/mapper/", id);
152 if (!ret)
153 return log_oom();
154
155 *device = ret;
156 return 0;
157 }
158
159 static int add_mount(
160 const char *id,
161 const char *what,
162 const char *where,
163 const char *fstype,
164 bool rw,
165 const char *options,
166 const char *description,
167 const char *post) {
168
169 _cleanup_free_ char *unit = NULL, *lnk = NULL, *crypto_what = NULL, *p = NULL;
170 _cleanup_fclose_ FILE *f = NULL;
171 int r;
172
173 assert(id);
174 assert(what);
175 assert(where);
176 assert(description);
177
178 log_debug("Adding %s: %s %s", where, what, strna(fstype));
179
180 if (streq_ptr(fstype, "crypto_LUKS")) {
181
182 r = add_cryptsetup(id, what, rw, &crypto_what);
183 if (r < 0)
184 return r;
185
186 what = crypto_what;
187 fstype = NULL;
188 }
189
190 r = unit_name_from_path(where, ".mount", &unit);
191 if (r < 0)
192 return log_error_errno(r, "Failed to generate unit name: %m");
193
194 p = strjoin(arg_dest, "/", unit, NULL);
195 if (!p)
196 return log_oom();
197
198 f = fopen(p, "wxe");
199 if (!f)
200 return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
201
202 fprintf(f,
203 "# Automatically generated by systemd-gpt-auto-generator\n\n"
204 "[Unit]\n"
205 "Description=%s\n"
206 "Documentation=man:systemd-gpt-auto-generator(8)\n",
207 description);
208
209 if (post)
210 fprintf(f, "Before=%s\n", post);
211
212 r = generator_write_fsck_deps(f, arg_dest, what, where, fstype);
213 if (r < 0)
214 return r;
215
216 fprintf(f,
217 "\n"
218 "[Mount]\n"
219 "What=%s\n"
220 "Where=%s\n",
221 what, where);
222
223 if (fstype)
224 fprintf(f, "Type=%s\n", fstype);
225
226 if (options)
227 fprintf(f, "Options=%s,%s\n", options, rw ? "rw" : "ro");
228 else
229 fprintf(f, "Options=%s\n", rw ? "rw" : "ro");
230
231 r = fflush_and_check(f);
232 if (r < 0)
233 return log_error_errno(r, "Failed to write unit file %s: %m", p);
234
235 if (post) {
236 lnk = strjoin(arg_dest, "/", post, ".requires/", unit, NULL);
237 if (!lnk)
238 return log_oom();
239
240 mkdir_parents_label(lnk, 0755);
241 if (symlink(p, lnk) < 0)
242 return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
243 }
244
245 return 0;
246 }
247
248 static bool path_is_busy(const char *where) {
249 int r;
250
251 /* already a mountpoint; generators run during reload */
252 r = path_is_mount_point(where, AT_SYMLINK_FOLLOW);
253 if (r > 0)
254 return false;
255
256 /* the directory might not exist on a stateless system */
257 if (r == -ENOENT)
258 return false;
259
260 if (r < 0)
261 return true;
262
263 /* not a mountpoint but it contains files */
264 if (dir_is_empty(where) <= 0)
265 return true;
266
267 return false;
268 }
269
270 static int probe_and_add_mount(
271 const char *id,
272 const char *what,
273 const char *where,
274 bool rw,
275 const char *description,
276 const char *post) {
277
278 _cleanup_blkid_free_probe_ blkid_probe b = NULL;
279 const char *fstype = NULL;
280 int r;
281
282 assert(id);
283 assert(what);
284 assert(where);
285 assert(description);
286
287 if (path_is_busy(where)) {
288 log_debug("%s already populated, ignoring.", where);
289 return 0;
290 }
291
292 /* Let's check the partition type here, so that we know
293 * whether to do LUKS magic. */
294
295 errno = 0;
296 b = blkid_new_probe_from_filename(what);
297 if (!b) {
298 if (errno == 0)
299 return log_oom();
300 log_error_errno(errno, "Failed to allocate prober: %m");
301 return -errno;
302 }
303
304 blkid_probe_enable_superblocks(b, 1);
305 blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
306
307 errno = 0;
308 r = blkid_do_safeprobe(b);
309 if (r == -2 || r == 1) /* no result or uncertain */
310 return 0;
311 else if (r != 0)
312 return log_error_errno(errno ?: EIO, "Failed to probe %s: %m", what);
313
314 /* add_mount is OK with fstype being NULL. */
315 (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
316
317 return add_mount(
318 id,
319 what,
320 where,
321 fstype,
322 rw,
323 NULL,
324 description,
325 post);
326 }
327
328 static int add_swap(const char *path) {
329 _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
330 _cleanup_fclose_ FILE *f = NULL;
331 int r;
332
333 assert(path);
334
335 log_debug("Adding swap: %s", path);
336
337 r = unit_name_from_path(path, ".swap", &name);
338 if (r < 0)
339 return log_error_errno(r, "Failed to generate unit name: %m");
340
341 unit = strjoin(arg_dest, "/", name, NULL);
342 if (!unit)
343 return log_oom();
344
345 f = fopen(unit, "wxe");
346 if (!f)
347 return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
348
349 fprintf(f,
350 "# Automatically generated by systemd-gpt-auto-generator\n\n"
351 "[Unit]\n"
352 "Description=Swap Partition\n"
353 "Documentation=man:systemd-gpt-auto-generator(8)\n\n"
354 "[Swap]\n"
355 "What=%s\n",
356 path);
357
358 r = fflush_and_check(f);
359 if (r < 0)
360 return log_error_errno(r, "Failed to write unit file %s: %m", unit);
361
362 lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
363 if (!lnk)
364 return log_oom();
365
366 mkdir_parents_label(lnk, 0755);
367 if (symlink(unit, lnk) < 0)
368 return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
369
370 return 0;
371 }
372
373 #ifdef ENABLE_EFI
374 static int add_automount(
375 const char *id,
376 const char *what,
377 const char *where,
378 const char *fstype,
379 bool rw,
380 const char *options,
381 const char *description,
382 usec_t timeout) {
383
384 _cleanup_free_ char *unit = NULL, *lnk = NULL;
385 _cleanup_free_ char *opt, *p = NULL;
386 _cleanup_fclose_ FILE *f = NULL;
387 int r;
388
389 assert(id);
390 assert(where);
391 assert(description);
392
393 if (options)
394 opt = strjoin(options, ",noauto", NULL);
395 else
396 opt = strdup("noauto");
397 if (!opt)
398 return log_oom();
399
400 r = add_mount(id,
401 what,
402 where,
403 fstype,
404 rw,
405 opt,
406 description,
407 NULL);
408 if (r < 0)
409 return r;
410
411 r = unit_name_from_path(where, ".automount", &unit);
412 if (r < 0)
413 return log_error_errno(r, "Failed to generate unit name: %m");
414
415 p = strjoin(arg_dest, "/", unit, NULL);
416 if (!p)
417 return log_oom();
418
419 f = fopen(p, "wxe");
420 if (!f)
421 return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
422
423 fprintf(f,
424 "# Automatically generated by systemd-gpt-auto-generator\n\n"
425 "[Unit]\n"
426 "Description=%s\n"
427 "Documentation=man:systemd-gpt-auto-generator(8)\n"
428 "[Automount]\n"
429 "Where=%s\n"
430 "TimeoutIdleSec=%lld\n",
431 description,
432 where,
433 (unsigned long long)timeout / USEC_PER_SEC);
434
435 r = fflush_and_check(f);
436 if (r < 0)
437 return log_error_errno(r, "Failed to write unit file %s: %m", p);
438
439 lnk = strjoin(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".wants/", unit, NULL);
440 if (!lnk)
441 return log_oom();
442 mkdir_parents_label(lnk, 0755);
443
444 if (symlink(p, lnk) < 0)
445 return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
446
447 return 0;
448 }
449
450 static int add_boot(const char *what) {
451 _cleanup_blkid_free_probe_ blkid_probe b = NULL;
452 const char *fstype = NULL, *uuid = NULL;
453 sd_id128_t id, type_id;
454 int r;
455
456 assert(what);
457
458 if (!is_efi_boot()) {
459 log_debug("Not an EFI boot, ignoring /boot.");
460 return 0;
461 }
462
463 if (in_initrd()) {
464 log_debug("In initrd, ignoring /boot.");
465 return 0;
466 }
467
468 if (detect_container() > 0) {
469 log_debug("In a container, ignoring /boot.");
470 return 0;
471 }
472
473 /* We create an .automount which is not overridden by the .mount from the fstab generator. */
474 if (fstab_is_mount_point("/boot")) {
475 log_debug("/boot specified in fstab, ignoring.");
476 return 0;
477 }
478
479 if (path_is_busy("/boot")) {
480 log_debug("/boot already populated, ignoring.");
481 return 0;
482 }
483
484 r = efi_loader_get_device_part_uuid(&id);
485 if (r == -ENOENT) {
486 log_debug("EFI loader partition unknown.");
487 return 0;
488 }
489
490 if (r < 0) {
491 log_error_errno(r, "Failed to read ESP partition UUID: %m");
492 return r;
493 }
494
495 errno = 0;
496 b = blkid_new_probe_from_filename(what);
497 if (!b) {
498 if (errno == 0)
499 return log_oom();
500 log_error_errno(errno, "Failed to allocate prober: %m");
501 return -errno;
502 }
503
504 blkid_probe_enable_partitions(b, 1);
505 blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
506
507 errno = 0;
508 r = blkid_do_safeprobe(b);
509 if (r == -2 || r == 1) /* no result or uncertain */
510 return 0;
511 else if (r != 0)
512 return log_error_errno(errno ?: EIO, "Failed to probe %s: %m", what);
513
514 (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
515 if (!streq(fstype, "vfat")) {
516 log_debug("Partition for /boot is not a FAT filesystem, ignoring.");
517 return 0;
518 }
519
520 r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &uuid, NULL);
521 if (r != 0) {
522 log_debug_errno(r, "Partition for /boot does not have a UUID, ignoring. %m");
523 return 0;
524 }
525
526 if (sd_id128_from_string(uuid, &type_id) < 0) {
527 log_debug("Partition for /boot does not have a valid UUID, ignoring.");
528 return 0;
529 }
530
531 if (!sd_id128_equal(type_id, id)) {
532 log_debug("Partition for /boot does not appear to be the partition we are booted from.");
533 return 0;
534 }
535
536 r = add_automount("boot",
537 what,
538 "/boot",
539 "vfat",
540 true,
541 "umask=0077",
542 "EFI System Partition Automount",
543 120 * USEC_PER_SEC);
544
545 return r;
546 }
547 #else
548 static int add_boot(const char *what) {
549 return 0;
550 }
551 #endif
552
553 static int enumerate_partitions(dev_t devnum) {
554
555 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
556 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
557 _cleanup_blkid_free_probe_ blkid_probe b = NULL;
558 _cleanup_udev_unref_ struct udev *udev = NULL;
559 _cleanup_free_ char *boot = NULL, *home = NULL, *srv = NULL;
560 struct udev_list_entry *first, *item;
561 struct udev_device *parent = NULL;
562 const char *name, *node, *pttype, *devtype;
563 int boot_nr = -1, home_nr = -1, srv_nr = -1;
564 bool home_rw = true, srv_rw = true;
565 blkid_partlist pl;
566 int r, k;
567 dev_t pn;
568
569 udev = udev_new();
570 if (!udev)
571 return log_oom();
572
573 d = udev_device_new_from_devnum(udev, 'b', devnum);
574 if (!d)
575 return log_oom();
576
577 name = udev_device_get_devnode(d);
578 if (!name)
579 name = udev_device_get_syspath(d);
580 if (!name) {
581 log_debug("Device %u:%u does not have a name, ignoring.",
582 major(devnum), minor(devnum));
583 return 0;
584 }
585
586 parent = udev_device_get_parent(d);
587 if (!parent) {
588 log_debug("%s: not a partitioned device, ignoring.", name);
589 return 0;
590 }
591
592 /* Does it have a devtype? */
593 devtype = udev_device_get_devtype(parent);
594 if (!devtype) {
595 log_debug("%s: parent doesn't have a device type, ignoring.", name);
596 return 0;
597 }
598
599 /* Is this a disk or a partition? We only care for disks... */
600 if (!streq(devtype, "disk")) {
601 log_debug("%s: parent isn't a raw disk, ignoring.", name);
602 return 0;
603 }
604
605 /* Does it have a device node? */
606 node = udev_device_get_devnode(parent);
607 if (!node) {
608 log_debug("%s: parent device does not have device node, ignoring.", name);
609 return 0;
610 }
611
612 log_debug("%s: root device %s.", name, node);
613
614 pn = udev_device_get_devnum(parent);
615 if (major(pn) == 0)
616 return 0;
617
618 errno = 0;
619 b = blkid_new_probe_from_filename(node);
620 if (!b) {
621 if (errno == 0)
622 return log_oom();
623
624 return log_error_errno(errno, "%s: failed to allocate prober: %m", node);
625 }
626
627 blkid_probe_enable_partitions(b, 1);
628 blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
629
630 errno = 0;
631 r = blkid_do_safeprobe(b);
632 if (r == 1)
633 return 0; /* no results */
634 else if (r == -2) {
635 log_warning("%s: probe gave ambiguous results, ignoring", node);
636 return 0;
637 } else if (r != 0)
638 return log_error_errno(errno ?: EIO, "%s: failed to probe: %m", node);
639
640 errno = 0;
641 r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
642 if (r != 0)
643 return log_error_errno(errno ?: EIO,
644 "%s: failed to determine partition table type: %m", node);
645
646 /* We only do this all for GPT... */
647 if (!streq_ptr(pttype, "gpt")) {
648 log_debug("%s: not a GPT partition table, ignoring.", node);
649 return 0;
650 }
651
652 errno = 0;
653 pl = blkid_probe_get_partitions(b);
654 if (!pl) {
655 if (errno == 0)
656 return log_oom();
657
658 return log_error_errno(errno, "%s: failed to list partitions: %m", node);
659 }
660
661 e = udev_enumerate_new(udev);
662 if (!e)
663 return log_oom();
664
665 r = udev_enumerate_add_match_parent(e, parent);
666 if (r < 0)
667 return log_oom();
668
669 r = udev_enumerate_add_match_subsystem(e, "block");
670 if (r < 0)
671 return log_oom();
672
673 r = udev_enumerate_scan_devices(e);
674 if (r < 0)
675 return log_error_errno(r, "%s: failed to enumerate partitions: %m", node);
676
677 first = udev_enumerate_get_list_entry(e);
678 udev_list_entry_foreach(item, first) {
679 _cleanup_udev_device_unref_ struct udev_device *q;
680 unsigned long long flags;
681 const char *stype, *subnode;
682 sd_id128_t type_id;
683 blkid_partition pp;
684 dev_t qn;
685 int nr;
686
687 q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
688 if (!q)
689 continue;
690
691 qn = udev_device_get_devnum(q);
692 if (major(qn) == 0)
693 continue;
694
695 if (qn == devnum)
696 continue;
697
698 if (qn == pn)
699 continue;
700
701 subnode = udev_device_get_devnode(q);
702 if (!subnode)
703 continue;
704
705 pp = blkid_partlist_devno_to_partition(pl, qn);
706 if (!pp)
707 continue;
708
709 nr = blkid_partition_get_partno(pp);
710 if (nr < 0)
711 continue;
712
713 stype = blkid_partition_get_type_string(pp);
714 if (!stype)
715 continue;
716
717 if (sd_id128_from_string(stype, &type_id) < 0)
718 continue;
719
720 flags = blkid_partition_get_flags(pp);
721
722 if (sd_id128_equal(type_id, GPT_SWAP)) {
723
724 if (flags & GPT_FLAG_NO_AUTO)
725 continue;
726
727 if (flags & GPT_FLAG_READ_ONLY) {
728 log_debug("%s marked as read-only swap partition, which is bogus. Ignoring.", subnode);
729 continue;
730 }
731
732 k = add_swap(subnode);
733 if (k < 0)
734 r = k;
735
736 } else if (sd_id128_equal(type_id, GPT_ESP)) {
737
738 /* We only care for the first /boot partition */
739 if (boot && nr >= boot_nr)
740 continue;
741
742 /* Note that we do not honour the "no-auto"
743 * flag for the ESP, as it is often unset, to
744 * hide it from Windows. */
745
746 boot_nr = nr;
747
748 r = free_and_strdup(&boot, subnode);
749 if (r < 0)
750 return log_oom();
751
752 } else if (sd_id128_equal(type_id, GPT_HOME)) {
753
754 if (flags & GPT_FLAG_NO_AUTO)
755 continue;
756
757 /* We only care for the first /home partition */
758 if (home && nr >= home_nr)
759 continue;
760
761 home_nr = nr;
762 home_rw = !(flags & GPT_FLAG_READ_ONLY),
763
764 r = free_and_strdup(&home, subnode);
765 if (r < 0)
766 return log_oom();
767
768 } else if (sd_id128_equal(type_id, GPT_SRV)) {
769
770 if (flags & GPT_FLAG_NO_AUTO)
771 continue;
772
773 /* We only care for the first /srv partition */
774 if (srv && nr >= srv_nr)
775 continue;
776
777 srv_nr = nr;
778 srv_rw = !(flags & GPT_FLAG_READ_ONLY),
779
780 r = free_and_strdup(&srv, subnode);
781 if (r < 0)
782 return log_oom();
783 }
784 }
785
786 if (boot) {
787 k = add_boot(boot);
788 if (k < 0)
789 r = k;
790 }
791
792 if (home) {
793 k = probe_and_add_mount("home", home, "/home", home_rw, "Home Partition", SPECIAL_LOCAL_FS_TARGET);
794 if (k < 0)
795 r = k;
796 }
797
798 if (srv) {
799 k = probe_and_add_mount("srv", srv, "/srv", srv_rw, "Server Data Partition", SPECIAL_LOCAL_FS_TARGET);
800 if (k < 0)
801 r = k;
802 }
803
804 return r;
805 }
806
807 static int get_block_device(const char *path, dev_t *dev) {
808 struct stat st;
809 struct statfs sfs;
810
811 assert(path);
812 assert(dev);
813
814 /* Get's the block device directly backing a file system. If
815 * the block device is encrypted, returns the device mapper
816 * block device. */
817
818 if (lstat(path, &st))
819 return -errno;
820
821 if (major(st.st_dev) != 0) {
822 *dev = st.st_dev;
823 return 1;
824 }
825
826 if (statfs(path, &sfs) < 0)
827 return -errno;
828
829 if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
830 return btrfs_get_block_device(path, dev);
831
832 return 0;
833 }
834
835 static int get_block_device_harder(const char *path, dev_t *dev) {
836 _cleanup_closedir_ DIR *d = NULL;
837 _cleanup_free_ char *p = NULL, *t = NULL;
838 struct dirent *de, *found = NULL;
839 const char *q;
840 unsigned maj, min;
841 dev_t dt;
842 int r;
843
844 assert(path);
845 assert(dev);
846
847 /* Gets the backing block device for a file system, and
848 * handles LUKS encrypted file systems, looking for its
849 * immediate parent, if there is one. */
850
851 r = get_block_device(path, &dt);
852 if (r <= 0)
853 return r;
854
855 if (asprintf(&p, "/sys/dev/block/%u:%u/slaves", major(dt), minor(dt)) < 0)
856 return -ENOMEM;
857
858 d = opendir(p);
859 if (!d) {
860 if (errno == ENOENT)
861 goto fallback;
862
863 return -errno;
864 }
865
866 FOREACH_DIRENT_ALL(de, d, return -errno) {
867
868 if (STR_IN_SET(de->d_name, ".", ".."))
869 continue;
870
871 if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
872 continue;
873
874 if (found) /* Don't try to support multiple backing block devices */
875 goto fallback;
876
877 found = de;
878 }
879
880 if (!found)
881 goto fallback;
882
883 q = strjoina(p, "/", found->d_name, "/dev");
884
885 r = read_one_line_file(q, &t);
886 if (r == -ENOENT)
887 goto fallback;
888 if (r < 0)
889 return r;
890
891 if (sscanf(t, "%u:%u", &maj, &min) != 2)
892 return -EINVAL;
893
894 if (maj == 0)
895 goto fallback;
896
897 *dev = makedev(maj, min);
898 return 1;
899
900 fallback:
901 *dev = dt;
902 return 1;
903 }
904
905 static int parse_proc_cmdline_item(const char *key, const char *value) {
906 int r;
907
908 assert(key);
909
910 if (STR_IN_SET(key, "systemd.gpt_auto", "rd.systemd.gpt_auto") && value) {
911
912 r = parse_boolean(value);
913 if (r < 0)
914 log_warning("Failed to parse gpt-auto switch \"%s\". Ignoring.", value);
915 else
916 arg_enabled = r;
917
918 } else if (streq(key, "root") && value) {
919
920 /* Disable root disk logic if there's a root= value
921 * specified (unless it happens to be "gpt-auto") */
922
923 arg_root_enabled = streq(value, "gpt-auto");
924
925 } else if (streq(key, "rw") && !value)
926 arg_root_rw = true;
927 else if (streq(key, "ro") && !value)
928 arg_root_rw = false;
929
930 return 0;
931 }
932
933 static int add_root_mount(void) {
934
935 #ifdef ENABLE_EFI
936 int r;
937
938 if (!is_efi_boot()) {
939 log_debug("Not a EFI boot, not creating root mount.");
940 return 0;
941 }
942
943 r = efi_loader_get_device_part_uuid(NULL);
944 if (r == -ENOENT) {
945 log_debug("EFI loader partition unknown, exiting.");
946 return 0;
947 } else if (r < 0)
948 return log_error_errno(r, "Failed to read ESP partition UUID: %m");
949
950 /* OK, we have an ESP partition, this is fantastic, so let's
951 * wait for a root device to show up. A udev rule will create
952 * the link for us under the right name. */
953
954 return add_mount(
955 "root",
956 "/dev/gpt-auto-root",
957 in_initrd() ? "/sysroot" : "/",
958 NULL,
959 arg_root_rw,
960 NULL,
961 "Root Partition",
962 in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET);
963 #else
964 return 0;
965 #endif
966 }
967
968 static int add_mounts(void) {
969 dev_t devno;
970 int r;
971
972 r = get_block_device_harder("/", &devno);
973 if (r < 0)
974 return log_error_errno(r, "Failed to determine block device of root file system: %m");
975 else if (r == 0) {
976 r = get_block_device_harder("/usr", &devno);
977 if (r < 0)
978 return log_error_errno(r, "Failed to determine block device of /usr file system: %m");
979 else if (r == 0) {
980 log_debug("Neither root nor /usr file system are on a (single) block device.");
981 return 0;
982 }
983 }
984
985 return enumerate_partitions(devno);
986 }
987
988 int main(int argc, char *argv[]) {
989 int r = 0;
990
991 if (argc > 1 && argc != 4) {
992 log_error("This program takes three or no arguments.");
993 return EXIT_FAILURE;
994 }
995
996 if (argc > 1)
997 arg_dest = argv[3];
998
999 log_set_target(LOG_TARGET_SAFE);
1000 log_parse_environment();
1001 log_open();
1002
1003 umask(0022);
1004
1005 if (detect_container() > 0) {
1006 log_debug("In a container, exiting.");
1007 return EXIT_SUCCESS;
1008 }
1009
1010 r = parse_proc_cmdline(parse_proc_cmdline_item);
1011 if (r < 0)
1012 log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
1013
1014 if (!arg_enabled) {
1015 log_debug("Disabled, exiting.");
1016 return EXIT_SUCCESS;
1017 }
1018
1019 if (arg_root_enabled)
1020 r = add_root_mount();
1021
1022 if (!in_initrd()) {
1023 int k;
1024
1025 k = add_mounts();
1026 if (k < 0)
1027 r = k;
1028 }
1029
1030 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1031 }