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>
29 #ifdef HAVE_LINUX_BTRFS_H
30 #include <linux/btrfs.h>
35 #include "path-util.h"
39 #include "udev-util.h"
41 #include "unit-name.h"
43 #include "generator.h"
47 #include "blkid-util.h"
49 static const char *arg_dest = "/tmp";
50 static bool arg_enabled = true;
51 static bool arg_root_enabled = true;
52 static bool arg_root_rw = false;
54 static int add_swap(const char *path) {
55 _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
56 _cleanup_fclose_ FILE *f = NULL;
60 log_debug("Adding swap: %s", path);
62 name = unit_name_from_path(path, ".swap");
66 unit = strjoin(arg_dest, "/", name, NULL);
70 f = fopen(unit, "wxe");
72 log_error("Failed to create unit file %s: %m", unit);
77 "# Automatically generated by systemd-gpt-auto-generator\n\n"
79 "Description=Swap Partition\n"
80 "Documentation=man:systemd-gpt-auto-generator(8)\n\n"
87 log_error("Failed to write unit file %s: %m", unit);
91 lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
95 mkdir_parents_label(lnk, 0755);
96 if (symlink(unit, lnk) < 0) {
97 log_error("Failed to create symlink %s: %m", lnk);
104 static int add_cryptsetup(const char *id, const char *what, bool rw, char **device) {
105 _cleanup_free_ char *e = NULL, *n = NULL, *p = NULL, *d = NULL, *to = NULL;
106 _cleanup_fclose_ FILE *f = NULL;
114 d = unit_name_from_path(what, ".device");
118 e = unit_name_escape(id);
122 n = unit_name_build("systemd-cryptsetup", e, ".service");
126 p = strjoin(arg_dest, "/", n, NULL);
132 log_error("Failed to create unit file %s: %m", p);
137 "# Automatically generated by systemd-gpt-auto-generator\n\n"
139 "Description=Cryptography Setup for %%I\n"
140 "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
141 "DefaultDependencies=no\n"
142 "Conflicts=umount.target\n"
143 "BindsTo=dev-mapper-%%i.device %s\n"
144 "Before=umount.target cryptsetup.target\n"
146 "IgnoreOnIsolate=true\n"
149 "RemainAfterExit=yes\n"
150 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
151 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '' '%s'\n"
152 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
154 id, what, rw ? "" : "read-only",
159 log_error("Failed to write file %s: %m", p);
163 from = strappenda("../", n);
165 to = strjoin(arg_dest, "/", d, ".wants/", n, NULL);
169 mkdir_parents_label(to, 0755);
170 if (symlink(from, to) < 0) {
171 log_error("Failed to create symlink %s: %m", to);
176 to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
180 mkdir_parents_label(to, 0755);
181 if (symlink(from, to) < 0) {
182 log_error("Failed to create symlink %s: %m", to);
187 to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
191 mkdir_parents_label(to, 0755);
192 if (symlink(from, to) < 0) {
193 log_error("Failed to create symlink %s: %m", to);
198 p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf", NULL);
202 mkdir_parents_label(p, 0755);
203 r = write_string_file(p,
204 "# Automatically generated by systemd-gpt-auto-generator\n\n"
206 "JobTimeoutSec=0\n"); /* the binary handles timeouts anyway */
208 log_error("Failed to write device drop-in: %s", strerror(-r));
212 ret = strappend("/dev/mapper/", id);
220 static int add_mount(
226 const char *description,
229 _cleanup_free_ char *unit = NULL, *lnk = NULL, *crypto_what = NULL, *p = NULL;
230 _cleanup_fclose_ FILE *f = NULL;
238 log_debug("Adding %s: %s %s", where, what, strna(fstype));
240 if (streq_ptr(fstype, "crypto_LUKS")) {
242 r = add_cryptsetup(id, what, rw, &crypto_what);
250 unit = unit_name_from_path(where, ".mount");
254 p = strjoin(arg_dest, "/", unit, NULL);
260 log_error("Failed to create unit file %s: %m", unit);
265 "# Automatically generated by systemd-gpt-auto-generator\n\n"
268 "Documentation=man:systemd-gpt-auto-generator(8)\n",
272 fprintf(f, "Before=%s\n", post);
274 r = generator_write_fsck_deps(f, arg_dest, what, where, fstype);
286 fprintf(f, "Type=%s\n", fstype);
288 fprintf(f, "Options=%s\n", rw ? "rw" : "ro");
292 log_error("Failed to write unit file %s: %m", p);
297 lnk = strjoin(arg_dest, "/", post, ".requires/", unit, NULL);
301 mkdir_parents_label(lnk, 0755);
302 if (symlink(p, lnk) < 0) {
303 log_error("Failed to create symlink %s: %m", lnk);
311 static int probe_and_add_mount(
316 const char *description,
319 _cleanup_blkid_free_probe_ blkid_probe b = NULL;
328 if (path_is_mount_point(where, true) <= 0 &&
329 dir_is_empty(where) <= 0) {
330 log_debug("%s already populated, ignoring.", where);
334 /* Let's check the partition type here, so that we know
335 * whether to do LUKS magic. */
338 b = blkid_new_probe_from_filename(what);
342 log_error("Failed to allocate prober: %m");
346 blkid_probe_enable_superblocks(b, 1);
347 blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
350 r = blkid_do_safeprobe(b);
351 if (r == -2 || r == 1) /* no result or uncertain */
356 log_error("Failed to probe %s: %m", what);
360 blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
372 static int enumerate_partitions(dev_t devnum) {
374 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
375 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
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;
379 struct udev_list_entry *first, *item;
380 struct udev_device *parent = NULL;
381 const char *node, *pttype, *devtype;
382 int home_nr = -1, srv_nr = -1;
383 bool home_rw = true, srv_rw = true;
392 d = udev_device_new_from_devnum(udev, 'b', devnum);
396 parent = udev_device_get_parent(d);
398 log_debug("Not a partitioned device, ignoring.");
402 /* Does it have a devtype? */
403 devtype = udev_device_get_devtype(parent);
405 log_debug("Parent doesn't have a device type, ignoring.");
409 /* Is this a disk or a partition? We only care for disks... */
410 if (!streq(devtype, "disk")) {
411 log_debug("Parent isn't a raw disk, ignoring.");
415 /* Does it have a device node? */
416 node = udev_device_get_devnode(parent);
418 log_debug("Parent device does not have device node, ignoring.");
422 log_debug("Root device %s.", node);
424 pn = udev_device_get_devnum(parent);
429 b = blkid_new_probe_from_filename(node);
434 log_error("Failed allocate prober: %m");
438 blkid_probe_enable_partitions(b, 1);
439 blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
442 r = blkid_do_safeprobe(b);
443 if (r == -2 || r == 1) /* no result or uncertain */
448 log_error("Failed to probe %s: %m", node);
453 r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
457 log_error("Failed to determine partition table type of %s: %m", node);
461 /* We only do this all for GPT... */
462 if (!streq_ptr(pttype, "gpt")) {
463 log_debug("Not a GPT partition table, ignoring.");
468 pl = blkid_probe_get_partitions(b);
473 log_error("Failed to list partitions of %s: %m", node);
477 e = udev_enumerate_new(udev);
481 r = udev_enumerate_add_match_parent(e, parent);
485 r = udev_enumerate_add_match_subsystem(e, "block");
489 r = udev_enumerate_scan_devices(e);
491 log_error("Failed to enumerate partitions on %s: %s", node, strerror(-r));
495 first = udev_enumerate_get_list_entry(e);
496 udev_list_entry_foreach(item, first) {
497 _cleanup_udev_device_unref_ struct udev_device *q;
498 const char *stype, *subnode;
503 unsigned long long flags;
505 q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
509 qn = udev_device_get_devnum(q);
519 subnode = udev_device_get_devnode(q);
523 pp = blkid_partlist_devno_to_partition(pl, qn);
527 flags = blkid_partition_get_flags(pp);
529 /* Ignore partitions that are not marked for automatic
530 * mounting on discovery */
531 if (flags & GPT_FLAG_NO_AUTO)
534 nr = blkid_partition_get_partno(pp);
538 stype = blkid_partition_get_type_string(pp);
542 if (sd_id128_from_string(stype, &type_id) < 0)
545 if (sd_id128_equal(type_id, GPT_SWAP)) {
547 if (flags & GPT_FLAG_READ_ONLY) {
548 log_debug("%s marked as read-only swap partition, which is bogus, ignoring.", subnode);
552 k = add_swap(subnode);
556 } else if (sd_id128_equal(type_id, GPT_HOME)) {
558 /* We only care for the first /home partition */
559 if (home && nr >= home_nr)
563 home_rw = !(flags & GPT_FLAG_READ_ONLY),
566 home = strdup(subnode);
570 } else if (sd_id128_equal(type_id, GPT_SRV)) {
572 /* We only care for the first /srv partition */
573 if (srv && nr >= srv_nr)
577 srv_rw = !(flags & GPT_FLAG_READ_ONLY),
587 k = probe_and_add_mount("home", home, "/home", home_rw, "Home Partition", SPECIAL_LOCAL_FS_TARGET);
593 k = probe_and_add_mount("srv", srv, "/srv", srv_rw, "Server Data Partition", SPECIAL_LOCAL_FS_TARGET);
601 static int get_btrfs_block_device(const char *path, dev_t *dev) {
602 struct btrfs_ioctl_fs_info_args fsi = {};
603 _cleanup_close_ int fd = -1;
609 fd = open(path, O_DIRECTORY|O_CLOEXEC);
613 if (ioctl(fd, BTRFS_IOC_FS_INFO, &fsi) < 0)
616 /* We won't do this for btrfs RAID */
617 if (fsi.num_devices != 1)
620 for (id = 1; id <= fsi.max_id; id++) {
621 struct btrfs_ioctl_dev_info_args di = {
626 if (ioctl(fd, BTRFS_IOC_DEV_INFO, &di) < 0) {
633 if (stat((char*) di.path, &st) < 0)
636 if (!S_ISBLK(st.st_mode))
639 if (major(st.st_rdev) == 0)
649 static int get_block_device(const char *path, dev_t *dev) {
656 if (lstat(path, &st))
659 if (major(st.st_dev) != 0) {
664 if (statfs(path, &sfs) < 0)
667 if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
668 return get_btrfs_block_device(path, dev);
673 static int parse_proc_cmdline_item(const char *key, const char *value) {
678 if (STR_IN_SET(key, "systemd.gpt_auto", "rd.systemd.gpt_auto") && value) {
680 r = parse_boolean(value);
682 log_warning("Failed to parse gpt-auto switch %s. Ignoring.", value);
686 } else if (streq(key, "root") && value) {
688 /* Disable root disk logic if there's a root= value
689 * specified (unless it happens to be "gpt-auto") */
691 arg_root_enabled = streq(value, "gpt-auto");
693 } else if (streq(key, "rw") && !value)
695 else if (streq(key, "ro") && !value)
701 static int add_root_mount(void) {
706 if (!is_efi_boot()) {
707 log_debug("Not a EFI boot, not creating root mount.");
711 r = efi_loader_get_device_part_uuid(NULL);
713 log_debug("EFI loader partition unknown, exiting.");
716 log_error("Failed to read ESP partition UUID: %s", strerror(-r));
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. */
726 "/dev/gpt-auto-root",
727 in_initrd() ? "/sysroot" : "/",
731 in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET);
737 static int add_mounts(void) {
741 r = get_block_device("/", &devno);
743 log_error("Failed to determine block device of root file system: %s", strerror(-r));
746 log_debug("Root file system not on a (single) block device.");
750 return enumerate_partitions(devno);
753 int main(int argc, char *argv[]) {
756 if (argc > 1 && argc != 4) {
757 log_error("This program takes three or no arguments.");
764 log_set_target(LOG_TARGET_SAFE);
765 log_parse_environment();
770 if (detect_container(NULL) > 0) {
771 log_debug("In a container, exiting.");
775 if (parse_proc_cmdline(parse_proc_cmdline_item) < 0)
779 log_debug("Disabled, exiting.");
783 if (arg_root_enabled)
784 r = add_root_mount();
794 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;