1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
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.
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.
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/>.
25 #include <sys/ioctl.h>
26 #include <sys/statfs.h>
27 #include <blkid/blkid.h>
31 #include "path-util.h"
35 #include "udev-util.h"
37 #include "unit-name.h"
39 #include "generator.h"
43 #include "blkid-util.h"
44 #include "btrfs-util.h"
46 static const char *arg_dest = "/tmp";
47 static bool arg_enabled = true;
48 static bool arg_root_enabled = true;
49 static bool arg_root_rw = false;
51 static int add_swap(const char *path) {
52 _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
53 _cleanup_fclose_ FILE *f = NULL;
57 log_debug("Adding swap: %s", path);
59 name = unit_name_from_path(path, ".swap");
63 unit = strjoin(arg_dest, "/", name, NULL);
67 f = fopen(unit, "wxe");
69 return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
72 "# Automatically generated by systemd-gpt-auto-generator\n\n"
74 "Description=Swap Partition\n"
75 "Documentation=man:systemd-gpt-auto-generator(8)\n\n"
82 return log_error_errno(errno, "Failed to write unit file %s: %m", unit);
84 lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
88 mkdir_parents_label(lnk, 0755);
89 if (symlink(unit, lnk) < 0)
90 return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
95 static int add_cryptsetup(const char *id, const char *what, bool rw, char **device) {
96 _cleanup_free_ char *e = NULL, *n = NULL, *p = NULL, *d = NULL, *to = NULL;
97 _cleanup_fclose_ FILE *f = NULL;
105 d = unit_name_from_path(what, ".device");
109 e = unit_name_escape(id);
113 n = unit_name_build("systemd-cryptsetup", e, ".service");
117 p = strjoin(arg_dest, "/", n, NULL);
123 return log_error_errno(errno, "Failed to create unit file %s: %m", p);
126 "# Automatically generated by systemd-gpt-auto-generator\n\n"
128 "Description=Cryptography Setup for %%I\n"
129 "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
130 "DefaultDependencies=no\n"
131 "Conflicts=umount.target\n"
132 "BindsTo=dev-mapper-%%i.device %s\n"
133 "Before=umount.target cryptsetup.target\n"
135 "IgnoreOnIsolate=true\n"
138 "RemainAfterExit=yes\n"
139 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
140 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '' '%s'\n"
141 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
143 id, what, rw ? "" : "read-only",
148 return log_error_errno(errno, "Failed to write file %s: %m", p);
150 from = strappenda("../", n);
152 to = strjoin(arg_dest, "/", d, ".wants/", n, NULL);
156 mkdir_parents_label(to, 0755);
157 if (symlink(from, to) < 0)
158 return log_error_errno(errno, "Failed to create symlink %s: %m", to);
161 to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
165 mkdir_parents_label(to, 0755);
166 if (symlink(from, to) < 0)
167 return log_error_errno(errno, "Failed to create symlink %s: %m", to);
170 to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
174 mkdir_parents_label(to, 0755);
175 if (symlink(from, to) < 0)
176 return log_error_errno(errno, "Failed to create symlink %s: %m", to);
179 p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf", NULL);
183 mkdir_parents_label(p, 0755);
184 r = write_string_file(p,
185 "# Automatically generated by systemd-gpt-auto-generator\n\n"
187 "JobTimeoutSec=0\n"); /* the binary handles timeouts anyway */
189 return log_error_errno(r, "Failed to write device drop-in: %m");
191 ret = strappend("/dev/mapper/", id);
199 static int add_mount(
205 const char *description,
208 _cleanup_free_ char *unit = NULL, *lnk = NULL, *crypto_what = NULL, *p = NULL;
209 _cleanup_fclose_ FILE *f = NULL;
217 log_debug("Adding %s: %s %s", where, what, strna(fstype));
219 if (streq_ptr(fstype, "crypto_LUKS")) {
221 r = add_cryptsetup(id, what, rw, &crypto_what);
229 unit = unit_name_from_path(where, ".mount");
233 p = strjoin(arg_dest, "/", unit, NULL);
239 return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
242 "# Automatically generated by systemd-gpt-auto-generator\n\n"
245 "Documentation=man:systemd-gpt-auto-generator(8)\n",
249 fprintf(f, "Before=%s\n", post);
251 r = generator_write_fsck_deps(f, arg_dest, what, where, fstype);
263 fprintf(f, "Type=%s\n", fstype);
265 fprintf(f, "Options=%s\n", rw ? "rw" : "ro");
269 return log_error_errno(errno, "Failed to write unit file %s: %m", p);
272 lnk = strjoin(arg_dest, "/", post, ".requires/", unit, NULL);
276 mkdir_parents_label(lnk, 0755);
277 if (symlink(p, lnk) < 0)
278 return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
284 static int probe_and_add_mount(
289 const char *description,
292 _cleanup_blkid_free_probe_ blkid_probe b = NULL;
301 if (path_is_mount_point(where, true) <= 0 &&
302 dir_is_empty(where) <= 0) {
303 log_debug("%s already populated, ignoring.", where);
307 /* Let's check the partition type here, so that we know
308 * whether to do LUKS magic. */
311 b = blkid_new_probe_from_filename(what);
315 log_error_errno(errno, "Failed to allocate prober: %m");
319 blkid_probe_enable_superblocks(b, 1);
320 blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
323 r = blkid_do_safeprobe(b);
324 if (r == -2 || r == 1) /* no result or uncertain */
329 log_error_errno(errno, "Failed to probe %s: %m", what);
333 blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
345 static int enumerate_partitions(dev_t devnum) {
347 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
348 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
349 _cleanup_blkid_free_probe_ blkid_probe b = NULL;
350 _cleanup_udev_unref_ struct udev *udev = NULL;
351 _cleanup_free_ char *home = NULL, *srv = NULL;
352 struct udev_list_entry *first, *item;
353 struct udev_device *parent = NULL;
354 const char *node, *pttype, *devtype;
355 int home_nr = -1, srv_nr = -1;
356 bool home_rw = true, srv_rw = true;
365 d = udev_device_new_from_devnum(udev, 'b', devnum);
369 parent = udev_device_get_parent(d);
371 log_debug("Not a partitioned device, ignoring.");
375 /* Does it have a devtype? */
376 devtype = udev_device_get_devtype(parent);
378 log_debug("Parent doesn't have a device type, ignoring.");
382 /* Is this a disk or a partition? We only care for disks... */
383 if (!streq(devtype, "disk")) {
384 log_debug("Parent isn't a raw disk, ignoring.");
388 /* Does it have a device node? */
389 node = udev_device_get_devnode(parent);
391 log_debug("Parent device does not have device node, ignoring.");
395 log_debug("Root device %s.", node);
397 pn = udev_device_get_devnum(parent);
402 b = blkid_new_probe_from_filename(node);
407 log_error_errno(errno, "Failed allocate prober: %m");
411 blkid_probe_enable_partitions(b, 1);
412 blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
415 r = blkid_do_safeprobe(b);
416 if (r == -2 || r == 1) /* no result or uncertain */
421 log_error_errno(errno, "Failed to probe %s: %m", node);
426 r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
430 log_error_errno(errno, "Failed to determine partition table type of %s: %m", node);
434 /* We only do this all for GPT... */
435 if (!streq_ptr(pttype, "gpt")) {
436 log_debug("Not a GPT partition table, ignoring.");
441 pl = blkid_probe_get_partitions(b);
446 log_error_errno(errno, "Failed to list partitions of %s: %m", node);
450 e = udev_enumerate_new(udev);
454 r = udev_enumerate_add_match_parent(e, parent);
458 r = udev_enumerate_add_match_subsystem(e, "block");
462 r = udev_enumerate_scan_devices(e);
464 return log_error_errno(r, "Failed to enumerate partitions on %s: %m", node);
466 first = udev_enumerate_get_list_entry(e);
467 udev_list_entry_foreach(item, first) {
468 _cleanup_udev_device_unref_ struct udev_device *q;
469 const char *stype, *subnode;
474 unsigned long long flags;
476 q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
480 qn = udev_device_get_devnum(q);
490 subnode = udev_device_get_devnode(q);
494 pp = blkid_partlist_devno_to_partition(pl, qn);
498 flags = blkid_partition_get_flags(pp);
500 /* Ignore partitions that are not marked for automatic
501 * mounting on discovery */
502 if (flags & GPT_FLAG_NO_AUTO)
505 nr = blkid_partition_get_partno(pp);
509 stype = blkid_partition_get_type_string(pp);
513 if (sd_id128_from_string(stype, &type_id) < 0)
516 if (sd_id128_equal(type_id, GPT_SWAP)) {
518 if (flags & GPT_FLAG_READ_ONLY) {
519 log_debug("%s marked as read-only swap partition, which is bogus, ignoring.", subnode);
523 k = add_swap(subnode);
527 } else if (sd_id128_equal(type_id, GPT_HOME)) {
529 /* We only care for the first /home partition */
530 if (home && nr >= home_nr)
534 home_rw = !(flags & GPT_FLAG_READ_ONLY),
537 home = strdup(subnode);
541 } else if (sd_id128_equal(type_id, GPT_SRV)) {
543 /* We only care for the first /srv partition */
544 if (srv && nr >= srv_nr)
548 srv_rw = !(flags & GPT_FLAG_READ_ONLY),
558 k = probe_and_add_mount("home", home, "/home", home_rw, "Home Partition", SPECIAL_LOCAL_FS_TARGET);
564 k = probe_and_add_mount("srv", srv, "/srv", srv_rw, "Server Data Partition", SPECIAL_LOCAL_FS_TARGET);
572 static int get_block_device(const char *path, dev_t *dev) {
579 if (lstat(path, &st))
582 if (major(st.st_dev) != 0) {
587 if (statfs(path, &sfs) < 0)
590 if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
591 return btrfs_get_block_device(path, dev);
596 static int parse_proc_cmdline_item(const char *key, const char *value) {
601 if (STR_IN_SET(key, "systemd.gpt_auto", "rd.systemd.gpt_auto") && value) {
603 r = parse_boolean(value);
605 log_warning("Failed to parse gpt-auto switch %s. Ignoring.", value);
609 } else if (streq(key, "root") && value) {
611 /* Disable root disk logic if there's a root= value
612 * specified (unless it happens to be "gpt-auto") */
614 arg_root_enabled = streq(value, "gpt-auto");
616 } else if (streq(key, "rw") && !value)
618 else if (streq(key, "ro") && !value)
624 static int add_root_mount(void) {
629 if (!is_efi_boot()) {
630 log_debug("Not a EFI boot, not creating root mount.");
634 r = efi_loader_get_device_part_uuid(NULL);
636 log_debug("EFI loader partition unknown, exiting.");
639 return log_error_errno(r, "Failed to read ESP partition UUID: %m");
641 /* OK, we have an ESP partition, this is fantastic, so let's
642 * wait for a root device to show up. A udev rule will create
643 * the link for us under the right name. */
647 "/dev/gpt-auto-root",
648 in_initrd() ? "/sysroot" : "/",
652 in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET);
658 static int add_mounts(void) {
662 r = get_block_device("/", &devno);
664 return log_error_errno(r, "Failed to determine block device of root file system: %m");
666 log_debug("Root file system not on a (single) block device.");
670 return enumerate_partitions(devno);
673 int main(int argc, char *argv[]) {
676 if (argc > 1 && argc != 4) {
677 log_error("This program takes three or no arguments.");
684 log_set_target(LOG_TARGET_SAFE);
685 log_parse_environment();
690 if (detect_container(NULL) > 0) {
691 log_debug("In a container, exiting.");
695 r = parse_proc_cmdline(parse_proc_cmdline_item);
697 log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
700 log_debug("Disabled, exiting.");
704 if (arg_root_enabled)
705 r = add_root_mount();
715 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;