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