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