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