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