]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/gpt-auto-generator/gpt-auto-generator.c
treewide: use log_*_errno whenever %m is in the format string
[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) {
56f64d95 72 log_error_errno(errno, "Failed to create unit file %s: %m", unit);
1a14a53c
LP
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)) {
56f64d95 87 log_error_errno(errno, "Failed to write unit file %s: %m", unit);
1a14a53c
LP
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) {
56f64d95 97 log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
1a14a53c
LP
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) {
56f64d95 132 log_error_errno(errno, "Failed to create unit file %s: %m", p);
1af72119
LP
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)) {
56f64d95 159 log_error_errno(errno, "Failed to write file %s: %m", p);
1af72119
LP
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) {
56f64d95 171 log_error_errno(errno, "Failed to create symlink %s: %m", to);
1af72119
LP
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) {
56f64d95 182 log_error_errno(errno, "Failed to create symlink %s: %m", to);
1af72119
LP
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) {
56f64d95 193 log_error_errno(errno, "Failed to create symlink %s: %m", to);
1af72119
LP
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 */
23bbb0de
MS
207 if (r < 0)
208 return log_error_errno(r, "Failed to write device drop-in: %m");
1af72119
LP
209
210 ret = strappend("/dev/mapper/", id);
211 if (!ret)
212 return log_oom();
213
214 *device = ret;
215 return 0;
216}
217
73b80ec2
LP
218static int add_mount(
219 const char *id,
220 const char *what,
221 const char *where,
222 const char *fstype,
cca1dfdd 223 bool rw,
73b80ec2
LP
224 const char *description,
225 const char *post) {
226
1af72119 227 _cleanup_free_ char *unit = NULL, *lnk = NULL, *crypto_what = NULL, *p = NULL;
1a14a53c 228 _cleanup_fclose_ FILE *f = NULL;
e48fdd84 229 int r;
1a14a53c 230
1af72119
LP
231 assert(id);
232 assert(what);
233 assert(where);
1af72119
LP
234 assert(description);
235
73b80ec2 236 log_debug("Adding %s: %s %s", where, what, strna(fstype));
1a14a53c 237
73b80ec2 238 if (streq_ptr(fstype, "crypto_LUKS")) {
1af72119 239
cca1dfdd 240 r = add_cryptsetup(id, what, rw, &crypto_what);
1af72119
LP
241 if (r < 0)
242 return r;
243
244 what = crypto_what;
245 fstype = NULL;
246 }
247
e48fdd84 248 unit = unit_name_from_path(where, ".mount");
1a14a53c
LP
249 if (!unit)
250 return log_oom();
251
e48fdd84
LP
252 p = strjoin(arg_dest, "/", unit, NULL);
253 if (!p)
254 return log_oom();
255
256 f = fopen(p, "wxe");
1a14a53c 257 if (!f) {
56f64d95 258 log_error_errno(errno, "Failed to create unit file %s: %m", unit);
1a14a53c
LP
259 return -errno;
260 }
261
262 fprintf(f,
263 "# Automatically generated by systemd-gpt-auto-generator\n\n"
264 "[Unit]\n"
c3834f9b
LP
265 "Description=%s\n"
266 "Documentation=man:systemd-gpt-auto-generator(8)\n",
e48fdd84
LP
267 description);
268
73b80ec2
LP
269 if (post)
270 fprintf(f, "Before=%s\n", post);
271
e48fdd84
LP
272 r = generator_write_fsck_deps(f, arg_dest, what, where, fstype);
273 if (r < 0)
274 return r;
275
276 fprintf(f,
277 "\n"
1a14a53c
LP
278 "[Mount]\n"
279 "What=%s\n"
1af72119
LP
280 "Where=%s\n",
281 what, where);
282
73b80ec2
LP
283 if (fstype)
284 fprintf(f, "Type=%s\n", fstype);
285
cca1dfdd 286 fprintf(f, "Options=%s\n", rw ? "rw" : "ro");
1a14a53c
LP
287
288 fflush(f);
289 if (ferror(f)) {
56f64d95 290 log_error_errno(errno, "Failed to write unit file %s: %m", p);
1a14a53c
LP
291 return -errno;
292 }
293
73b80ec2
LP
294 if (post) {
295 lnk = strjoin(arg_dest, "/", post, ".requires/", unit, NULL);
296 if (!lnk)
297 return log_oom();
1a14a53c 298
73b80ec2
LP
299 mkdir_parents_label(lnk, 0755);
300 if (symlink(p, lnk) < 0) {
56f64d95 301 log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
73b80ec2
LP
302 return -errno;
303 }
1a14a53c
LP
304 }
305
306 return 0;
307}
308
61331eab
LP
309static int probe_and_add_mount(
310 const char *id,
311 const char *what,
312 const char *where,
cca1dfdd 313 bool rw,
61331eab
LP
314 const char *description,
315 const char *post) {
316
317 _cleanup_blkid_free_probe_ blkid_probe b = NULL;
318 const char *fstype;
319 int r;
320
321 assert(id);
322 assert(what);
323 assert(where);
324 assert(description);
325
326 if (path_is_mount_point(where, true) <= 0 &&
327 dir_is_empty(where) <= 0) {
328 log_debug("%s already populated, ignoring.", where);
329 return 0;
330 }
331
332 /* Let's check the partition type here, so that we know
333 * whether to do LUKS magic. */
334
335 errno = 0;
336 b = blkid_new_probe_from_filename(what);
337 if (!b) {
338 if (errno == 0)
339 return log_oom();
56f64d95 340 log_error_errno(errno, "Failed to allocate prober: %m");
61331eab
LP
341 return -errno;
342 }
343
344 blkid_probe_enable_superblocks(b, 1);
345 blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
346
347 errno = 0;
348 r = blkid_do_safeprobe(b);
349 if (r == -2 || r == 1) /* no result or uncertain */
350 return 0;
351 else if (r != 0) {
352 if (errno == 0)
353 errno = EIO;
56f64d95 354 log_error_errno(errno, "Failed to probe %s: %m", what);
61331eab
LP
355 return -errno;
356 }
357
358 blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
359
360 return add_mount(
361 id,
362 what,
363 where,
364 fstype,
cca1dfdd 365 rw,
61331eab
LP
366 description,
367 post);
368}
369
370static int enumerate_partitions(dev_t devnum) {
371
1ca208fb
ZJS
372 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
373 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
61331eab
LP
374 _cleanup_blkid_free_probe_ blkid_probe b = NULL;
375 _cleanup_udev_unref_ struct udev *udev = NULL;
376 _cleanup_free_ char *home = NULL, *srv = NULL;
1a14a53c 377 struct udev_list_entry *first, *item;
e48fdd84 378 struct udev_device *parent = NULL;
61331eab
LP
379 const char *node, *pttype, *devtype;
380 int home_nr = -1, srv_nr = -1;
cca1dfdd 381 bool home_rw = true, srv_rw = true;
61331eab 382 blkid_partlist pl;
73b80ec2 383 int r, k;
61331eab 384 dev_t pn;
1a14a53c 385
61331eab
LP
386 udev = udev_new();
387 if (!udev)
b47d419c 388 return log_oom();
1a14a53c 389
61331eab 390 d = udev_device_new_from_devnum(udev, 'b', devnum);
1ca208fb
ZJS
391 if (!d)
392 return log_oom();
1a14a53c
LP
393
394 parent = udev_device_get_parent(d);
fa041593
LP
395 if (!parent) {
396 log_debug("Not a partitioned device, ignoring.");
9c4495ca 397 return 0;
fa041593 398 }
1a14a53c 399
61331eab
LP
400 /* Does it have a devtype? */
401 devtype = udev_device_get_devtype(parent);
fa041593
LP
402 if (!devtype) {
403 log_debug("Parent doesn't have a device type, ignoring.");
61331eab 404 return 0;
fa041593 405 }
61331eab
LP
406
407 /* Is this a disk or a partition? We only care for disks... */
fa041593
LP
408 if (!streq(devtype, "disk")) {
409 log_debug("Parent isn't a raw disk, ignoring.");
61331eab 410 return 0;
fa041593 411 }
61331eab
LP
412
413 /* Does it have a device node? */
414 node = udev_device_get_devnode(parent);
fa041593
LP
415 if (!node) {
416 log_debug("Parent device does not have device node, ignoring.");
61331eab 417 return 0;
fa041593 418 }
61331eab
LP
419
420 log_debug("Root device %s.", node);
421
422 pn = udev_device_get_devnum(parent);
423 if (major(pn) == 0)
424 return 0;
425
426 errno = 0;
427 b = blkid_new_probe_from_filename(node);
428 if (!b) {
429 if (errno == 0)
430 return log_oom();
431
56f64d95 432 log_error_errno(errno, "Failed allocate prober: %m");
61331eab
LP
433 return -errno;
434 }
435
61331eab
LP
436 blkid_probe_enable_partitions(b, 1);
437 blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
438
439 errno = 0;
440 r = blkid_do_safeprobe(b);
441 if (r == -2 || r == 1) /* no result or uncertain */
442 return 0;
443 else if (r != 0) {
444 if (errno == 0)
445 errno = EIO;
56f64d95 446 log_error_errno(errno, "Failed to probe %s: %m", node);
61331eab
LP
447 return -errno;
448 }
449
450 errno = 0;
451 r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
452 if (r != 0) {
453 if (errno == 0)
454 errno = EIO;
56f64d95 455 log_error_errno(errno, "Failed to determine partition table type of %s: %m", node);
61331eab
LP
456 return -errno;
457 }
458
459 /* We only do this all for GPT... */
fa041593
LP
460 if (!streq_ptr(pttype, "gpt")) {
461 log_debug("Not a GPT partition table, ignoring.");
61331eab 462 return 0;
fa041593 463 }
61331eab
LP
464
465 errno = 0;
466 pl = blkid_probe_get_partitions(b);
467 if (!pl) {
468 if (errno == 0)
469 return log_oom();
470
56f64d95 471 log_error_errno(errno, "Failed to list partitions of %s: %m", node);
61331eab
LP
472 return -errno;
473 }
474
475 e = udev_enumerate_new(udev);
476 if (!e)
477 return log_oom();
478
1a14a53c 479 r = udev_enumerate_add_match_parent(e, parent);
1ca208fb
ZJS
480 if (r < 0)
481 return log_oom();
1a14a53c
LP
482
483 r = udev_enumerate_add_match_subsystem(e, "block");
1ca208fb
ZJS
484 if (r < 0)
485 return log_oom();
1a14a53c
LP
486
487 r = udev_enumerate_scan_devices(e);
23bbb0de
MS
488 if (r < 0)
489 return log_error_errno(r, "Failed to enumerate partitions on %s: %m", node);
1a14a53c
LP
490
491 first = udev_enumerate_get_list_entry(e);
492 udev_list_entry_foreach(item, first) {
e48fdd84 493 _cleanup_udev_device_unref_ struct udev_device *q;
61331eab 494 const char *stype, *subnode;
1a14a53c 495 sd_id128_t type_id;
61331eab
LP
496 blkid_partition pp;
497 dev_t qn;
498 int nr;
cca1dfdd 499 unsigned long long flags;
1a14a53c
LP
500
501 q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
1ca208fb 502 if (!q)
61331eab 503 continue;
1a14a53c 504
61331eab
LP
505 qn = udev_device_get_devnum(q);
506 if (major(qn) == 0)
1ca208fb 507 continue;
1a14a53c 508
61331eab 509 if (qn == devnum)
1ca208fb 510 continue;
1a14a53c 511
61331eab
LP
512 if (qn == pn)
513 continue;
1a14a53c 514
61331eab
LP
515 subnode = udev_device_get_devnode(q);
516 if (!subnode)
517 continue;
73b80ec2 518
61331eab
LP
519 pp = blkid_partlist_devno_to_partition(pl, qn);
520 if (!pp)
73b80ec2 521 continue;
61331eab 522
cca1dfdd
LP
523 flags = blkid_partition_get_flags(pp);
524
525 /* Ignore partitions that are not marked for automatic
526 * mounting on discovery */
527 if (flags & GPT_FLAG_NO_AUTO)
528 continue;
529
61331eab
LP
530 nr = blkid_partition_get_partno(pp);
531 if (nr < 0)
532 continue;
533
534 stype = blkid_partition_get_type_string(pp);
535 if (!stype)
536 continue;
537
538 if (sd_id128_from_string(stype, &type_id) < 0)
1ca208fb 539 continue;
1a14a53c 540
73b80ec2
LP
541 if (sd_id128_equal(type_id, GPT_SWAP)) {
542
cca1dfdd
LP
543 if (flags & GPT_FLAG_READ_ONLY) {
544 log_debug("%s marked as read-only swap partition, which is bogus, ignoring.", subnode);
545 continue;
546 }
547
61331eab 548 k = add_swap(subnode);
73b80ec2
LP
549 if (k < 0)
550 r = k;
e48fdd84 551
73b80ec2 552 } else if (sd_id128_equal(type_id, GPT_HOME)) {
e48fdd84
LP
553
554 /* We only care for the first /home partition */
555 if (home && nr >= home_nr)
556 continue;
557
558 home_nr = nr;
cca1dfdd 559 home_rw = !(flags & GPT_FLAG_READ_ONLY),
e48fdd84
LP
560
561 free(home);
61331eab 562 home = strdup(subnode);
e48fdd84
LP
563 if (!home)
564 return log_oom();
565
e48fdd84
LP
566 } else if (sd_id128_equal(type_id, GPT_SRV)) {
567
568 /* We only care for the first /srv partition */
569 if (srv && nr >= srv_nr)
570 continue;
571
572 srv_nr = nr;
cca1dfdd 573 srv_rw = !(flags & GPT_FLAG_READ_ONLY),
e48fdd84
LP
574
575 free(srv);
576 srv = strdup(node);
577 if (!srv)
578 return log_oom();
1a14a53c 579 }
1a14a53c
LP
580 }
581
61331eab 582 if (home) {
cca1dfdd 583 k = probe_and_add_mount("home", home, "/home", home_rw, "Home Partition", SPECIAL_LOCAL_FS_TARGET);
73b80ec2
LP
584 if (k < 0)
585 r = k;
586 }
e48fdd84 587
61331eab 588 if (srv) {
cca1dfdd 589 k = probe_and_add_mount("srv", srv, "/srv", srv_rw, "Server Data Partition", SPECIAL_LOCAL_FS_TARGET);
73b80ec2
LP
590 if (k < 0)
591 r = k;
592 }
1a14a53c 593
1a14a53c
LP
594 return r;
595}
596
597static int get_btrfs_block_device(const char *path, dev_t *dev) {
b47d419c 598 struct btrfs_ioctl_fs_info_args fsi = {};
1a14a53c
LP
599 _cleanup_close_ int fd = -1;
600 uint64_t id;
601
602 assert(path);
603 assert(dev);
604
605 fd = open(path, O_DIRECTORY|O_CLOEXEC);
606 if (fd < 0)
607 return -errno;
608
1a14a53c
LP
609 if (ioctl(fd, BTRFS_IOC_FS_INFO, &fsi) < 0)
610 return -errno;
611
612 /* We won't do this for btrfs RAID */
613 if (fsi.num_devices != 1)
614 return 0;
615
616 for (id = 1; id <= fsi.max_id; id++) {
b47d419c
ZJS
617 struct btrfs_ioctl_dev_info_args di = {
618 .devid = id,
619 };
1a14a53c
LP
620 struct stat st;
621
1a14a53c
LP
622 if (ioctl(fd, BTRFS_IOC_DEV_INFO, &di) < 0) {
623 if (errno == ENODEV)
624 continue;
625
626 return -errno;
627 }
628
629 if (stat((char*) di.path, &st) < 0)
630 return -errno;
631
632 if (!S_ISBLK(st.st_mode))
633 return -ENODEV;
634
635 if (major(st.st_rdev) == 0)
636 return -ENODEV;
637
638 *dev = st.st_rdev;
639 return 1;
640 }
641
642 return -ENODEV;
643}
644
645static int get_block_device(const char *path, dev_t *dev) {
646 struct stat st;
647 struct statfs sfs;
648
649 assert(path);
650 assert(dev);
651
e48fdd84 652 if (lstat(path, &st))
1a14a53c
LP
653 return -errno;
654
655 if (major(st.st_dev) != 0) {
656 *dev = st.st_dev;
657 return 1;
658 }
659
e48fdd84 660 if (statfs(path, &sfs) < 0)
1a14a53c
LP
661 return -errno;
662
c51cf056 663 if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
1a14a53c
LP
664 return get_btrfs_block_device(path, dev);
665
666 return 0;
667}
668
73b80ec2
LP
669static int parse_proc_cmdline_item(const char *key, const char *value) {
670 int r;
1a14a53c 671
73b80ec2 672 assert(key);
1a14a53c 673
73b80ec2 674 if (STR_IN_SET(key, "systemd.gpt_auto", "rd.systemd.gpt_auto") && value) {
1a14a53c 675
73b80ec2
LP
676 r = parse_boolean(value);
677 if (r < 0)
678 log_warning("Failed to parse gpt-auto switch %s. Ignoring.", value);
8086ffac
ZJS
679 else
680 arg_enabled = r;
1a14a53c 681
73b80ec2
LP
682 } else if (streq(key, "root") && value) {
683
684 /* Disable root disk logic if there's a root= value
685 * specified (unless it happens to be "gpt-auto") */
686
687 arg_root_enabled = streq(value, "gpt-auto");
688
689 } else if (streq(key, "rw") && !value)
690 arg_root_rw = true;
691 else if (streq(key, "ro") && !value)
692 arg_root_rw = false;
73b80ec2
LP
693
694 return 0;
695}
696
697static int add_root_mount(void) {
698
699#ifdef ENABLE_EFI
700 int r;
701
702 if (!is_efi_boot()) {
703 log_debug("Not a EFI boot, not creating root mount.");
704 return 0;
9a5cb137
ZJS
705 }
706
73b80ec2
LP
707 r = efi_loader_get_device_part_uuid(NULL);
708 if (r == -ENOENT) {
709 log_debug("EFI loader partition unknown, exiting.");
710 return 0;
23bbb0de
MS
711 } else if (r < 0)
712 return log_error_errno(r, "Failed to read ESP partition UUID: %m");
1a14a53c 713
73b80ec2
LP
714 /* OK, we have an ESP partition, this is fantastic, so let's
715 * wait for a root device to show up. A udev rule will create
716 * the link for us under the right name. */
717
718 return add_mount(
719 "root",
98b2f766 720 "/dev/gpt-auto-root",
73b80ec2
LP
721 in_initrd() ? "/sysroot" : "/",
722 NULL,
cca1dfdd 723 arg_root_rw,
73b80ec2
LP
724 "Root Partition",
725 in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET);
726#else
727 return 0;
728#endif
729}
730
731static int add_mounts(void) {
73b80ec2
LP
732 dev_t devno;
733 int r;
734
3db604b9 735 r = get_block_device("/", &devno);
23bbb0de
MS
736 if (r < 0)
737 return log_error_errno(r, "Failed to determine block device of root file system: %m");
738 else if (r == 0) {
1a14a53c 739 log_debug("Root file system not on a (single) block device.");
73b80ec2 740 return 0;
3db604b9
LP
741 }
742
61331eab 743 return enumerate_partitions(devno);
73b80ec2
LP
744}
745
746int main(int argc, char *argv[]) {
747 int r = 0;
748
749 if (argc > 1 && argc != 4) {
750 log_error("This program takes three or no arguments.");
751 return EXIT_FAILURE;
752 }
753
754 if (argc > 1)
755 arg_dest = argv[3];
756
757 log_set_target(LOG_TARGET_SAFE);
758 log_parse_environment();
759 log_open();
760
761 umask(0022);
762
763 if (detect_container(NULL) > 0) {
764 log_debug("In a container, exiting.");
e48fdd84 765 return EXIT_SUCCESS;
1a14a53c 766 }
3db604b9 767
b5884878
LP
768 r = parse_proc_cmdline(parse_proc_cmdline_item);
769 if (r < 0)
da927ba9 770 log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
1a14a53c 771
73b80ec2
LP
772 if (!arg_enabled) {
773 log_debug("Disabled, exiting.");
774 return EXIT_SUCCESS;
775 }
776
777 if (arg_root_enabled)
778 r = add_root_mount();
779
780 if (!in_initrd()) {
781 int k;
782
783 k = add_mounts();
784 if (k < 0)
785 r = k;
786 }
787
788 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1a14a53c 789}