]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/gpt-auto-generator/gpt-auto-generator.c
log: add brief comment for log_set_open_when_needed() and log_set_always_reopen_console()
[thirdparty/systemd.git] / src / gpt-auto-generator / gpt-auto-generator.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
1a14a53c
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2013 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
6b5cf3ea 21#include <blkid.h>
1a14a53c 22#include <stdlib.h>
1a14a53c 23#include <sys/statfs.h>
cf0fbc49 24#include <unistd.h>
1a14a53c 25
b4bbcaa9 26#include "libudev.h"
07630cea
LP
27#include "sd-id128.h"
28
b5efdb8a 29#include "alloc-util.h"
07630cea 30#include "blkid-util.h"
18c528e9 31#include "blockdev-util.h"
07630cea 32#include "btrfs-util.h"
a0956174 33#include "dirent-util.h"
72e18a98 34#include "dissect-image.h"
07630cea 35#include "efivars.h"
3ffd4af2 36#include "fd-util.h"
07630cea
LP
37#include "fileio.h"
38#include "fstab-util.h"
39#include "generator.h"
40#include "gpt.h"
1a14a53c 41#include "missing.h"
07630cea 42#include "mkdir.h"
4349cd7c 43#include "mount-util.h"
6bedfcbb 44#include "parse-util.h"
07630cea 45#include "path-util.h"
4e731273 46#include "proc-cmdline.h"
1a14a53c 47#include "special.h"
98bad05e 48#include "specifier.h"
8fcde012 49#include "stat-util.h"
07630cea
LP
50#include "string-util.h"
51#include "udev-util.h"
1a14a53c 52#include "unit-name.h"
07630cea 53#include "util.h"
9a5cb137 54#include "virt.h"
1a14a53c 55
1a14a53c 56static const char *arg_dest = "/tmp";
73b80ec2
LP
57static bool arg_enabled = true;
58static bool arg_root_enabled = true;
59static bool arg_root_rw = false;
1a14a53c 60
01af8c01 61static int add_cryptsetup(const char *id, const char *what, bool rw, bool require, char **device) {
98bad05e 62 _cleanup_free_ char *e = NULL, *n = NULL, *p = NULL, *d = NULL, *id_escaped = NULL, *what_escaped = NULL;
1af72119 63 _cleanup_fclose_ FILE *f = NULL;
9cdcf368 64 char *ret;
1af72119
LP
65 int r;
66
67 assert(id);
68 assert(what);
1af72119 69
7410616c
LP
70 r = unit_name_from_path(what, ".device", &d);
71 if (r < 0)
72 return log_error_errno(r, "Failed to generate unit name: %m");
1af72119
LP
73
74 e = unit_name_escape(id);
75 if (!e)
76 return log_oom();
77
7410616c
LP
78 r = unit_name_build("systemd-cryptsetup", e, ".service", &n);
79 if (r < 0)
80 return log_error_errno(r, "Failed to generate unit name: %m");
1af72119 81
98bad05e
LP
82 id_escaped = specifier_escape(id);
83 if (!id_escaped)
84 return log_oom();
85
86 what_escaped = specifier_escape(what);
87 if (!what_escaped)
88 return log_oom();
89
605405c6 90 p = strjoin(arg_dest, "/", n);
821b2e79 91 if (!p)
1af72119
LP
92 return log_oom();
93
94 f = fopen(p, "wxe");
4a62c710
MS
95 if (!f)
96 return log_error_errno(errno, "Failed to create unit file %s: %m", p);
1af72119
LP
97
98 fprintf(f,
99 "# Automatically generated by systemd-gpt-auto-generator\n\n"
100 "[Unit]\n"
101 "Description=Cryptography Setup for %%I\n"
c3834f9b 102 "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
1af72119
LP
103 "DefaultDependencies=no\n"
104 "Conflicts=umount.target\n"
105 "BindsTo=dev-mapper-%%i.device %s\n"
106 "Before=umount.target cryptsetup.target\n"
107 "After=%s\n"
108 "IgnoreOnIsolate=true\n"
1af72119
LP
109 "[Service]\n"
110 "Type=oneshot\n"
111 "RemainAfterExit=yes\n"
112 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
0b1f68ac 113 "KeyringMode=shared\n" /* make sure we can share cached keys among instances */
cca1dfdd 114 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '' '%s'\n"
1af72119
LP
115 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
116 d, d,
98bad05e
LP
117 id_escaped, what_escaped, rw ? "" : "read-only",
118 id_escaped);
1af72119 119
dacd6cee
LP
120 r = fflush_and_check(f);
121 if (r < 0)
122 return log_error_errno(r, "Failed to write file %s: %m", p);
1af72119 123
9cdcf368
ZJS
124 r = generator_add_symlink(arg_dest, d, "wants", n);
125 if (r < 0)
126 return r;
1af72119 127
01af8c01 128 if (require) {
9cdcf368 129 const char *dmname;
1af72119 130
9cdcf368
ZJS
131 r = generator_add_symlink(arg_dest, "cryptsetup.target", "requires", n);
132 if (r < 0)
133 return r;
01af8c01 134
9cdcf368
ZJS
135 dmname = strjoina("dev-mapper-", e, ".device");
136 r = generator_add_symlink(arg_dest, dmname, "requires", n);
137 if (r < 0)
138 return r;
01af8c01 139 }
1af72119
LP
140
141 free(p);
605405c6 142 p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf");
1af72119
LP
143 if (!p)
144 return log_oom();
145
146 mkdir_parents_label(p, 0755);
147 r = write_string_file(p,
148 "# Automatically generated by systemd-gpt-auto-generator\n\n"
149 "[Unit]\n"
4c1fc3e4
DM
150 "JobTimeoutSec=0\n",
151 WRITE_STRING_FILE_CREATE); /* the binary handles timeouts anyway */
23bbb0de
MS
152 if (r < 0)
153 return log_error_errno(r, "Failed to write device drop-in: %m");
1af72119
LP
154
155 ret = strappend("/dev/mapper/", id);
156 if (!ret)
157 return log_oom();
158
01af8c01
LP
159 if (device)
160 *device = ret;
1af72119
LP
161 return 0;
162}
163
73b80ec2
LP
164static int add_mount(
165 const char *id,
166 const char *what,
167 const char *where,
168 const char *fstype,
cca1dfdd 169 bool rw,
59512f21 170 const char *options,
73b80ec2
LP
171 const char *description,
172 const char *post) {
173
9cdcf368 174 _cleanup_free_ char *unit = NULL, *crypto_what = NULL, *p = NULL;
1a14a53c 175 _cleanup_fclose_ FILE *f = NULL;
e48fdd84 176 int r;
1a14a53c 177
98bad05e
LP
178 /* Note that we don't apply specifier escaping on the input strings here, since we know they are not configured
179 * externally, but all originate from our own sources here, and hence we know they contain no % characters that
180 * could potentially be understood as specifiers. */
181
1af72119
LP
182 assert(id);
183 assert(what);
184 assert(where);
1af72119
LP
185 assert(description);
186
73b80ec2 187 log_debug("Adding %s: %s %s", where, what, strna(fstype));
1a14a53c 188
73b80ec2 189 if (streq_ptr(fstype, "crypto_LUKS")) {
1af72119 190
01af8c01 191 r = add_cryptsetup(id, what, rw, true, &crypto_what);
1af72119
LP
192 if (r < 0)
193 return r;
194
195 what = crypto_what;
196 fstype = NULL;
197 }
198
7410616c
LP
199 r = unit_name_from_path(where, ".mount", &unit);
200 if (r < 0)
201 return log_error_errno(r, "Failed to generate unit name: %m");
1a14a53c 202
605405c6 203 p = strjoin(arg_dest, "/", unit);
e48fdd84
LP
204 if (!p)
205 return log_oom();
206
207 f = fopen(p, "wxe");
4a62c710
MS
208 if (!f)
209 return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
1a14a53c
LP
210
211 fprintf(f,
212 "# Automatically generated by systemd-gpt-auto-generator\n\n"
213 "[Unit]\n"
c3834f9b
LP
214 "Description=%s\n"
215 "Documentation=man:systemd-gpt-auto-generator(8)\n",
e48fdd84
LP
216 description);
217
73b80ec2
LP
218 if (post)
219 fprintf(f, "Before=%s\n", post);
220
e48fdd84
LP
221 r = generator_write_fsck_deps(f, arg_dest, what, where, fstype);
222 if (r < 0)
223 return r;
224
225 fprintf(f,
226 "\n"
1a14a53c
LP
227 "[Mount]\n"
228 "What=%s\n"
1af72119
LP
229 "Where=%s\n",
230 what, where);
231
73b80ec2
LP
232 if (fstype)
233 fprintf(f, "Type=%s\n", fstype);
234
59512f21
KS
235 if (options)
236 fprintf(f, "Options=%s,%s\n", options, rw ? "rw" : "ro");
237 else
238 fprintf(f, "Options=%s\n", rw ? "rw" : "ro");
1a14a53c 239
dacd6cee
LP
240 r = fflush_and_check(f);
241 if (r < 0)
242 return log_error_errno(r, "Failed to write unit file %s: %m", p);
1a14a53c 243
9cdcf368
ZJS
244 if (post)
245 return generator_add_symlink(arg_dest, post, "requires", unit);
1a14a53c
LP
246 return 0;
247}
248
59512f21
KS
249static bool path_is_busy(const char *where) {
250 int r;
251
252 /* already a mountpoint; generators run during reload */
e1873695 253 r = path_is_mount_point(where, NULL, AT_SYMLINK_FOLLOW);
59512f21
KS
254 if (r > 0)
255 return false;
256
257 /* the directory might not exist on a stateless system */
258 if (r == -ENOENT)
259 return false;
260
261 if (r < 0)
262 return true;
263
264 /* not a mountpoint but it contains files */
265 if (dir_is_empty(where) <= 0)
266 return true;
267
268 return false;
269}
270
72e18a98
LP
271static int add_partition_mount(
272 DissectedPartition *p,
61331eab 273 const char *id,
61331eab 274 const char *where,
72e18a98 275 const char *description) {
61331eab 276
72e18a98 277 assert(p);
61331eab 278
59512f21 279 if (path_is_busy(where)) {
61331eab
LP
280 log_debug("%s already populated, ignoring.", where);
281 return 0;
282 }
283
61331eab
LP
284 return add_mount(
285 id,
72e18a98 286 p->node,
61331eab 287 where,
72e18a98
LP
288 p->fstype,
289 p->rw,
59512f21 290 NULL,
61331eab 291 description,
72e18a98 292 SPECIAL_LOCAL_FS_TARGET);
61331eab
LP
293}
294
59512f21 295static int add_swap(const char *path) {
9cdcf368 296 _cleanup_free_ char *name = NULL, *unit = NULL;
59512f21
KS
297 _cleanup_fclose_ FILE *f = NULL;
298 int r;
299
300 assert(path);
301
fc5bc384
FB
302 /* Disable the swap auto logic if at least one swap is defined in /etc/fstab, see #6192. */
303 r = fstab_has_fstype("swap");
304 if (r < 0)
305 return log_error_errno(r, "Failed to parse fstab: %m");
1a680ae3 306 if (r > 0) {
fc5bc384
FB
307 log_debug("swap specified in fstab, ignoring.");
308 return 0;
309 }
310
59512f21
KS
311 log_debug("Adding swap: %s", path);
312
313 r = unit_name_from_path(path, ".swap", &name);
314 if (r < 0)
315 return log_error_errno(r, "Failed to generate unit name: %m");
316
605405c6 317 unit = strjoin(arg_dest, "/", name);
59512f21
KS
318 if (!unit)
319 return log_oom();
320
321 f = fopen(unit, "wxe");
322 if (!f)
323 return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
324
325 fprintf(f,
326 "# Automatically generated by systemd-gpt-auto-generator\n\n"
327 "[Unit]\n"
328 "Description=Swap Partition\n"
329 "Documentation=man:systemd-gpt-auto-generator(8)\n\n"
330 "[Swap]\n"
331 "What=%s\n",
332 path);
333
dacd6cee
LP
334 r = fflush_and_check(f);
335 if (r < 0)
336 return log_error_errno(r, "Failed to write unit file %s: %m", unit);
59512f21 337
9cdcf368 338 return generator_add_symlink(arg_dest, SPECIAL_SWAP_TARGET, "wants", name);
59512f21
KS
339}
340
349cc4a5 341#if ENABLE_EFI
7a1494aa
TG
342static int add_automount(
343 const char *id,
344 const char *what,
345 const char *where,
346 const char *fstype,
347 bool rw,
348 const char *options,
349 const char *description,
350 usec_t timeout) {
351
9cdcf368 352 _cleanup_free_ char *unit = NULL;
7a1494aa
TG
353 _cleanup_free_ char *opt, *p = NULL;
354 _cleanup_fclose_ FILE *f = NULL;
355 int r;
356
357 assert(id);
358 assert(where);
359 assert(description);
360
361 if (options)
605405c6 362 opt = strjoin(options, ",noauto");
7a1494aa
TG
363 else
364 opt = strdup("noauto");
365 if (!opt)
366 return log_oom();
367
368 r = add_mount(id,
369 what,
370 where,
371 fstype,
372 rw,
373 opt,
374 description,
375 NULL);
376 if (r < 0)
377 return r;
378
379 r = unit_name_from_path(where, ".automount", &unit);
380 if (r < 0)
381 return log_error_errno(r, "Failed to generate unit name: %m");
382
605405c6 383 p = strjoin(arg_dest, "/", unit);
7a1494aa
TG
384 if (!p)
385 return log_oom();
386
387 f = fopen(p, "wxe");
388 if (!f)
389 return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
390
391 fprintf(f,
392 "# Automatically generated by systemd-gpt-auto-generator\n\n"
393 "[Unit]\n"
394 "Description=%s\n"
395 "Documentation=man:systemd-gpt-auto-generator(8)\n"
396 "[Automount]\n"
397 "Where=%s\n"
70887c5f 398 "TimeoutIdleSec="USEC_FMT"\n",
7a1494aa
TG
399 description,
400 where,
70887c5f 401 timeout / USEC_PER_SEC);
7a1494aa
TG
402
403 r = fflush_and_check(f);
404 if (r < 0)
405 return log_error_errno(r, "Failed to write unit file %s: %m", p);
406
9cdcf368 407 return generator_add_symlink(arg_dest, SPECIAL_LOCAL_FS_TARGET, "wants", unit);
7a1494aa
TG
408}
409
72e18a98 410static int add_esp(DissectedPartition *p) {
b52a109a 411 const char *esp;
59512f21
KS
412 int r;
413
72e18a98 414 assert(p);
59512f21 415
59512f21 416 if (in_initrd()) {
b52a109a 417 log_debug("In initrd, ignoring the ESP.");
59512f21
KS
418 return 0;
419 }
420
b52a109a
LP
421 /* If /efi exists we'll use that. Otherwise we'll use /boot, as that's usually the better choice */
422 esp = access("/efi/", F_OK) >= 0 ? "/efi" : "/boot";
59512f21 423
0b6b6787 424 /* We create an .automount which is not overridden by the .mount from the fstab generator. */
b9088048
FB
425 r = fstab_is_mount_point(esp);
426 if (r < 0)
427 return log_error_errno(r, "Failed to parse fstab: %m");
39b6a511 428 if (r > 0) {
b52a109a 429 log_debug("%s specified in fstab, ignoring.", esp);
59512f21
KS
430 return 0;
431 }
432
b52a109a
LP
433 if (path_is_busy(esp)) {
434 log_debug("%s already populated, ignoring.", esp);
59512f21
KS
435 return 0;
436 }
437
7ba25ab5 438 if (is_efi_boot()) {
72e18a98 439 sd_id128_t loader_uuid;
59512f21 440
7ba25ab5 441 /* If this is an EFI boot, be extra careful, and only mount the ESP if it was the ESP used for booting. */
59512f21 442
7ba25ab5
LP
443 r = efi_loader_get_device_part_uuid(&loader_uuid);
444 if (r == -ENOENT) {
445 log_debug("EFI loader partition unknown.");
446 return 0;
447 }
e28973ee
ZJS
448 if (r < 0)
449 return log_error_errno(r, "Failed to read ESP partition UUID: %m");
7ba25ab5 450
72e18a98 451 if (!sd_id128_equal(p->uuid, loader_uuid)) {
7ba25ab5
LP
452 log_debug("Partition for %s does not appear to be the partition we are booted from.", esp);
453 return 0;
454 }
455 } else
456 log_debug("Not an EFI boot, skipping ESP check.");
457
458 return add_automount("boot",
72e18a98
LP
459 p->node,
460 esp,
461 p->fstype,
462 true,
463 "umask=0077",
464 "EFI System Partition Automount",
465 120 * USEC_PER_SEC);
7a1494aa 466}
59512f21 467#else
d97beb0e 468static int add_esp(DissectedPartition *p) {
59512f21 469 return 0;
59512f21 470}
7a1494aa 471#endif
59512f21 472
72e18a98 473static int open_parent(dev_t devnum, int *ret) {
1ca208fb 474 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
61331eab 475 _cleanup_udev_unref_ struct udev *udev = NULL;
72e18a98
LP
476 const char *name, *devtype, *node;
477 struct udev_device *parent;
61331eab 478 dev_t pn;
72e18a98
LP
479 int fd;
480
481 assert(ret);
1a14a53c 482
61331eab
LP
483 udev = udev_new();
484 if (!udev)
b47d419c 485 return log_oom();
1a14a53c 486
61331eab 487 d = udev_device_new_from_devnum(udev, 'b', devnum);
1ca208fb
ZJS
488 if (!d)
489 return log_oom();
1a14a53c 490
d2a62382
ZJS
491 name = udev_device_get_devnode(d);
492 if (!name)
493 name = udev_device_get_syspath(d);
494 if (!name) {
72e18a98
LP
495 log_debug("Device %u:%u does not have a name, ignoring.", major(devnum), minor(devnum));
496 goto not_found;
d2a62382
ZJS
497 }
498
1a14a53c 499 parent = udev_device_get_parent(d);
fa041593 500 if (!parent) {
d2a62382 501 log_debug("%s: not a partitioned device, ignoring.", name);
72e18a98 502 goto not_found;
fa041593 503 }
1a14a53c 504
61331eab
LP
505 /* Does it have a devtype? */
506 devtype = udev_device_get_devtype(parent);
fa041593 507 if (!devtype) {
d2a62382 508 log_debug("%s: parent doesn't have a device type, ignoring.", name);
72e18a98 509 goto not_found;
fa041593 510 }
61331eab
LP
511
512 /* Is this a disk or a partition? We only care for disks... */
fa041593 513 if (!streq(devtype, "disk")) {
d2a62382 514 log_debug("%s: parent isn't a raw disk, ignoring.", name);
72e18a98 515 goto not_found;
fa041593 516 }
61331eab
LP
517
518 /* Does it have a device node? */
519 node = udev_device_get_devnode(parent);
fa041593 520 if (!node) {
d2a62382 521 log_debug("%s: parent device does not have device node, ignoring.", name);
72e18a98 522 goto not_found;
fa041593 523 }
61331eab 524
d2a62382 525 log_debug("%s: root device %s.", name, node);
61331eab
LP
526
527 pn = udev_device_get_devnum(parent);
72e18a98
LP
528 if (major(pn) == 0) {
529 log_debug("%s: parent device is not a proper block device, ignoring.", name);
530 goto not_found;
61331eab
LP
531 }
532
72e18a98
LP
533 fd = open(node, O_RDONLY|O_CLOEXEC|O_NOCTTY);
534 if (fd < 0)
535 return log_error_errno(errno, "Failed to open %s: %m", node);
61331eab 536
72e18a98
LP
537 *ret = fd;
538 return 1;
61331eab 539
72e18a98
LP
540not_found:
541 *ret = -1;
542 return 0;
543}
cb971249 544
72e18a98 545static int enumerate_partitions(dev_t devnum) {
61331eab 546
72e18a98
LP
547 _cleanup_close_ int fd = -1;
548 _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
549 int r, k;
61331eab 550
72e18a98
LP
551 r = open_parent(devnum, &fd);
552 if (r <= 0)
553 return r;
61331eab 554
72e18a98
LP
555 r = dissect_image(fd, NULL, 0, DISSECT_IMAGE_GPT_ONLY, &m);
556 if (r == -ENOPKG) {
557 log_debug_errno(r, "No suitable partition table found, ignoring.");
558 return 0;
61331eab 559 }
23bbb0de 560 if (r < 0)
72e18a98 561 return log_error_errno(r, "Failed to dissect: %m");
0238d4c6 562
72e18a98
LP
563 if (m->partitions[PARTITION_SWAP].found) {
564 k = add_swap(m->partitions[PARTITION_SWAP].node);
565 if (k < 0)
566 r = k;
1a14a53c
LP
567 }
568
72e18a98
LP
569 if (m->partitions[PARTITION_ESP].found) {
570 k = add_esp(m->partitions + PARTITION_ESP);
59512f21
KS
571 if (k < 0)
572 r = k;
573 }
574
72e18a98
LP
575 if (m->partitions[PARTITION_HOME].found) {
576 k = add_partition_mount(m->partitions + PARTITION_HOME, "home", "/home", "Home Partition");
73b80ec2
LP
577 if (k < 0)
578 r = k;
579 }
e48fdd84 580
72e18a98
LP
581 if (m->partitions[PARTITION_SRV].found) {
582 k = add_partition_mount(m->partitions + PARTITION_SRV, "srv", "/srv", "Server Data Partition");
73b80ec2
LP
583 if (k < 0)
584 r = k;
585 }
1a14a53c 586
1a14a53c
LP
587 return r;
588}
589
96287a49 590static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
73b80ec2 591 int r;
1a14a53c 592
73b80ec2 593 assert(key);
1a14a53c 594
1d84ad94 595 if (STR_IN_SET(key, "systemd.gpt_auto", "rd.systemd.gpt_auto")) {
1a14a53c 596
1d84ad94 597 r = value ? parse_boolean(value) : 1;
73b80ec2 598 if (r < 0)
d2a62382 599 log_warning("Failed to parse gpt-auto switch \"%s\". Ignoring.", value);
8086ffac
ZJS
600 else
601 arg_enabled = r;
1a14a53c 602
1d84ad94
LP
603 } else if (streq(key, "root")) {
604
605 if (proc_cmdline_value_missing(key, value))
606 return 0;
73b80ec2
LP
607
608 /* Disable root disk logic if there's a root= value
609 * specified (unless it happens to be "gpt-auto") */
610
611 arg_root_enabled = streq(value, "gpt-auto");
612
2f3dfc6f
LP
613 } else if (streq(key, "roothash")) {
614
615 if (proc_cmdline_value_missing(key, value))
616 return 0;
617
618 /* Disable root disk logic if there's roothash= defined (i.e. verity enabled) */
619
620 arg_root_enabled = false;
621
73b80ec2
LP
622 } else if (streq(key, "rw") && !value)
623 arg_root_rw = true;
624 else if (streq(key, "ro") && !value)
625 arg_root_rw = false;
73b80ec2
LP
626
627 return 0;
628}
629
349cc4a5 630#if ENABLE_EFI
01af8c01
LP
631static int add_root_cryptsetup(void) {
632
633 /* If a device /dev/gpt-auto-root-luks appears, then make it pull in systemd-cryptsetup-root.service, which
634 * sets it up, and causes /dev/gpt-auto-root to appear which is all we are looking for. */
635
636 return add_cryptsetup("root", "/dev/gpt-auto-root-luks", true, false, NULL);
637}
638#endif
639
73b80ec2
LP
640static int add_root_mount(void) {
641
349cc4a5 642#if ENABLE_EFI
73b80ec2
LP
643 int r;
644
645 if (!is_efi_boot()) {
646 log_debug("Not a EFI boot, not creating root mount.");
647 return 0;
9a5cb137
ZJS
648 }
649
73b80ec2
LP
650 r = efi_loader_get_device_part_uuid(NULL);
651 if (r == -ENOENT) {
652 log_debug("EFI loader partition unknown, exiting.");
653 return 0;
23bbb0de
MS
654 } else if (r < 0)
655 return log_error_errno(r, "Failed to read ESP partition UUID: %m");
1a14a53c 656
73b80ec2
LP
657 /* OK, we have an ESP partition, this is fantastic, so let's
658 * wait for a root device to show up. A udev rule will create
659 * the link for us under the right name. */
660
7163e1ca
DD
661 if (in_initrd()) {
662 r = generator_write_initrd_root_device_deps(arg_dest, "/dev/gpt-auto-root");
663 if (r < 0)
664 return 0;
01af8c01
LP
665
666 r = add_root_cryptsetup();
667 if (r < 0)
668 return r;
7163e1ca
DD
669 }
670
73b80ec2
LP
671 return add_mount(
672 "root",
98b2f766 673 "/dev/gpt-auto-root",
73b80ec2
LP
674 in_initrd() ? "/sysroot" : "/",
675 NULL,
cca1dfdd 676 arg_root_rw,
59512f21 677 NULL,
73b80ec2
LP
678 "Root Partition",
679 in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET);
680#else
681 return 0;
682#endif
683}
684
685static int add_mounts(void) {
73b80ec2
LP
686 dev_t devno;
687 int r;
688
c6ba0c18 689 r = get_block_device_harder("/", &devno);
23bbb0de
MS
690 if (r < 0)
691 return log_error_errno(r, "Failed to determine block device of root file system: %m");
57ab9f89 692 if (r == 0) {
c6ba0c18 693 r = get_block_device_harder("/usr", &devno);
eafe88e3
TH
694 if (r < 0)
695 return log_error_errno(r, "Failed to determine block device of /usr file system: %m");
57ab9f89 696 if (r == 0) {
eafe88e3
TH
697 log_debug("Neither root nor /usr file system are on a (single) block device.");
698 return 0;
699 }
3db604b9
LP
700 }
701
61331eab 702 return enumerate_partitions(devno);
73b80ec2
LP
703}
704
705int main(int argc, char *argv[]) {
8f50e86a 706 int r, k;
73b80ec2
LP
707
708 if (argc > 1 && argc != 4) {
709 log_error("This program takes three or no arguments.");
710 return EXIT_FAILURE;
711 }
712
713 if (argc > 1)
714 arg_dest = argv[3];
715
716 log_set_target(LOG_TARGET_SAFE);
717 log_parse_environment();
718 log_open();
719
720 umask(0022);
721
75f86906 722 if (detect_container() > 0) {
73b80ec2 723 log_debug("In a container, exiting.");
e48fdd84 724 return EXIT_SUCCESS;
1a14a53c 725 }
3db604b9 726
1d84ad94 727 r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0);
b5884878 728 if (r < 0)
da927ba9 729 log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
1a14a53c 730
73b80ec2
LP
731 if (!arg_enabled) {
732 log_debug("Disabled, exiting.");
733 return EXIT_SUCCESS;
734 }
735
736 if (arg_root_enabled)
737 r = add_root_mount();
8f50e86a
LP
738 else
739 r = 0;
73b80ec2
LP
740
741 if (!in_initrd()) {
73b80ec2
LP
742 k = add_mounts();
743 if (k < 0)
744 r = k;
745 }
746
747 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1a14a53c 748}