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"
48 static const char *arg_dest = "/tmp";
49 static bool arg_enabled = true;
50 static bool arg_root_enabled = true;
51 static bool arg_root_rw = false;
53 DEFINE_TRIVIAL_CLEANUP_FUNC(blkid_probe, blkid_free_probe);
54 #define _cleanup_blkid_freep_probe_ _cleanup_(blkid_free_probep)
56 static int verify_gpt_partition(const char *node, sd_id128_t *type, unsigned *nr, char **fstype) {
57 _cleanup_blkid_freep_probe_ blkid_probe b = NULL;
62 b = blkid_new_probe_from_filename(node);
64 return errno != 0 ? -errno : -ENOMEM;
66 blkid_probe_enable_superblocks(b, 1);
67 blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
68 blkid_probe_enable_partitions(b, 1);
69 blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
72 r = blkid_do_safeprobe(b);
73 if (r == -2 || r == 1) /* no result or uncertain */
76 return errno ? -errno : -EIO;
79 r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL);
81 /* return 0 if we're not on GPT */
82 return errno ? -errno : 0;
84 if (strcmp(v, "gpt") != 0)
89 r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
91 return errno ? -errno : -EIO;
93 r = sd_id128_from_string(v, type);
100 r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL);
102 return errno ? -errno : -EIO;
104 r = safe_atou(v, nr);
112 r = blkid_probe_lookup_value(b, "TYPE", &v, NULL);
129 static int add_swap(const char *path, const char *fstype) {
130 _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
131 _cleanup_fclose_ FILE *f = NULL;
133 log_debug("Adding swap: %s %s", path, fstype);
135 name = unit_name_from_path(path, ".swap");
139 unit = strjoin(arg_dest, "/", name, NULL);
143 f = fopen(unit, "wxe");
145 log_error("Failed to create unit file %s: %m", unit);
150 "# Automatically generated by systemd-gpt-auto-generator\n\n"
152 "Description=Swap Partition\n"
153 "Documentation=man:systemd-gpt-auto-generator(8)\n\n"
160 log_error("Failed to write unit file %s: %m", unit);
164 lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
168 mkdir_parents_label(lnk, 0755);
169 if (symlink(unit, lnk) < 0) {
170 log_error("Failed to create symlink %s: %m", lnk);
177 static int add_cryptsetup(const char *id, const char *what, char **device) {
178 _cleanup_free_ char *e = NULL, *n = NULL, *p = NULL, *d = NULL, *to = NULL;
179 _cleanup_fclose_ FILE *f = NULL;
187 d = unit_name_from_path(what, ".device");
191 e = unit_name_escape(id);
195 n = unit_name_build("systemd-cryptsetup", e, ".service");
199 p = strjoin(arg_dest, "/", n, NULL);
205 log_error("Failed to create unit file %s: %m", p);
210 "# Automatically generated by systemd-gpt-auto-generator\n\n"
212 "Description=Cryptography Setup for %%I\n"
213 "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
214 "DefaultDependencies=no\n"
215 "Conflicts=umount.target\n"
216 "BindsTo=dev-mapper-%%i.device %s\n"
217 "Before=umount.target cryptsetup.target\n"
219 "IgnoreOnIsolate=true\n"
220 "After=systemd-readahead-collect.service systemd-readahead-replay.service\n\n"
223 "RemainAfterExit=yes\n"
224 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
225 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s'\n"
226 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
233 log_error("Failed to write file %s: %m", p);
237 from = strappenda("../", n);
239 to = strjoin(arg_dest, "/", d, ".wants/", n, NULL);
243 mkdir_parents_label(to, 0755);
244 if (symlink(from, to) < 0) {
245 log_error("Failed to create symlink %s: %m", to);
250 to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
254 mkdir_parents_label(to, 0755);
255 if (symlink(from, to) < 0) {
256 log_error("Failed to create symlink %s: %m", to);
261 to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
265 mkdir_parents_label(to, 0755);
266 if (symlink(from, to) < 0) {
267 log_error("Failed to create symlink %s: %m", to);
272 p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf", NULL);
276 mkdir_parents_label(p, 0755);
277 r = write_string_file(p,
278 "# Automatically generated by systemd-gpt-auto-generator\n\n"
280 "JobTimeoutSec=0\n"); /* the binary handles timeouts anyway */
282 log_error("Failed to write device drop-in: %s", strerror(-r));
286 ret = strappend("/dev/mapper/", id);
294 static int add_mount(
300 const char *description,
303 _cleanup_free_ char *unit = NULL, *lnk = NULL, *crypto_what = NULL, *p = NULL;
304 _cleanup_fclose_ FILE *f = NULL;
312 if (path_is_mount_point(where, true) <= 0 &&
313 dir_is_empty(where) <= 0) {
314 log_debug("%s already populated, ignoring.", where);
318 log_debug("Adding %s: %s %s", where, what, strna(fstype));
320 if (streq_ptr(fstype, "crypto_LUKS")) {
322 r = add_cryptsetup(id, what, &crypto_what);
330 unit = unit_name_from_path(where, ".mount");
334 p = strjoin(arg_dest, "/", unit, NULL);
340 log_error("Failed to create unit file %s: %m", unit);
345 "# Automatically generated by systemd-gpt-auto-generator\n\n"
348 "Documentation=man:systemd-gpt-auto-generator(8)\n",
352 fprintf(f, "Before=%s\n", post);
354 r = generator_write_fsck_deps(f, arg_dest, what, where, fstype);
366 fprintf(f, "Type=%s\n", fstype);
369 fprintf(f, "Options=%s\n", options);
373 log_error("Failed to write unit file %s: %m", p);
378 lnk = strjoin(arg_dest, "/", post, ".requires/", unit, NULL);
382 mkdir_parents_label(lnk, 0755);
383 if (symlink(p, lnk) < 0) {
384 log_error("Failed to create symlink %s: %m", lnk);
392 static int enumerate_partitions(struct udev *udev, dev_t dev) {
393 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
394 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
395 _cleanup_free_ char *home = NULL, *home_fstype = NULL, *srv = NULL, *srv_fstype = NULL;
396 unsigned home_nr = (unsigned) -1, srv_nr = (unsigned )-1;
397 struct udev_list_entry *first, *item;
398 struct udev_device *parent = NULL;
401 e = udev_enumerate_new(udev);
405 d = udev_device_new_from_devnum(udev, 'b', dev);
409 parent = udev_device_get_parent(d);
413 r = udev_enumerate_add_match_parent(e, parent);
417 r = udev_enumerate_add_match_subsystem(e, "block");
421 r = udev_enumerate_scan_devices(e);
423 log_error("Failed to enumerate partitions on /dev/block/%u:%u: %s", major(dev), minor(dev), strerror(-r));
429 first = udev_enumerate_get_list_entry(e);
430 udev_list_entry_foreach(item, first) {
431 _cleanup_udev_device_unref_ struct udev_device *q;
432 _cleanup_free_ char *fstype = NULL;
433 const char *node = NULL;
437 q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
441 if (udev_device_get_devnum(q) == udev_device_get_devnum(d))
444 if (udev_device_get_devnum(q) == udev_device_get_devnum(parent))
447 node = udev_device_get_devnode(q);
451 k = verify_gpt_partition(node, &type_id, &nr, &fstype);
453 /* skip child devices which are not detected properly */
457 log_error("Failed to verify GPT partition %s: %s", node, strerror(-k));
464 if (sd_id128_equal(type_id, GPT_SWAP)) {
466 k = add_swap(node, fstype);
470 } else if (sd_id128_equal(type_id, GPT_HOME)) {
472 /* We only care for the first /home partition */
473 if (home && nr >= home_nr)
484 home_fstype = fstype;
487 } else if (sd_id128_equal(type_id, GPT_SRV)) {
489 /* We only care for the first /srv partition */
490 if (srv && nr >= srv_nr)
506 if (home && home_fstype) {
507 k = add_mount("home", home, "/home", home_fstype, NULL, "Home Partition", SPECIAL_LOCAL_FS_TARGET);
512 if (srv && srv_fstype) {
513 k = add_mount("srv", srv, "/srv", srv_fstype, NULL, "Server Data Partition", SPECIAL_LOCAL_FS_TARGET);
521 static int get_btrfs_block_device(const char *path, dev_t *dev) {
522 struct btrfs_ioctl_fs_info_args fsi = {};
523 _cleanup_close_ int fd = -1;
529 fd = open(path, O_DIRECTORY|O_CLOEXEC);
533 if (ioctl(fd, BTRFS_IOC_FS_INFO, &fsi) < 0)
536 /* We won't do this for btrfs RAID */
537 if (fsi.num_devices != 1)
540 for (id = 1; id <= fsi.max_id; id++) {
541 struct btrfs_ioctl_dev_info_args di = {
546 if (ioctl(fd, BTRFS_IOC_DEV_INFO, &di) < 0) {
553 if (stat((char*) di.path, &st) < 0)
556 if (!S_ISBLK(st.st_mode))
559 if (major(st.st_rdev) == 0)
569 static int get_block_device(const char *path, dev_t *dev) {
576 if (lstat(path, &st))
579 if (major(st.st_dev) != 0) {
584 if (statfs(path, &sfs) < 0)
587 if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
588 return get_btrfs_block_device(path, dev);
593 static int devno_to_devnode(struct udev *udev, dev_t devno, char **ret) {
594 _cleanup_udev_device_unref_ struct udev_device *d;
598 d = udev_device_new_from_devnum(udev, 'b', devno);
602 t = udev_device_get_devnode(d);
614 static int parse_proc_cmdline_item(const char *key, const char *value) {
619 if (STR_IN_SET(key, "systemd.gpt_auto", "rd.systemd.gpt_auto") && value) {
621 r = parse_boolean(value);
623 log_warning("Failed to parse gpt-auto switch %s. Ignoring.", value);
627 } else if (streq(key, "root") && value) {
629 /* Disable root disk logic if there's a root= value
630 * specified (unless it happens to be "gpt-auto") */
632 arg_root_enabled = streq(value, "gpt-auto");
634 } else if (streq(key, "rw") && !value)
636 else if (streq(key, "ro") && !value)
638 else if (startswith(key, "systemd.gpt-auto.") || startswith(key, "rd.systemd.gpt-auto."))
639 log_warning("Unknown kernel switch %s. Ignoring.", key);
644 static int add_root_mount(void) {
649 if (!is_efi_boot()) {
650 log_debug("Not a EFI boot, not creating root mount.");
654 r = efi_loader_get_device_part_uuid(NULL);
656 log_debug("EFI loader partition unknown, exiting.");
659 log_error("Failed to read ESP partition UUID: %s", strerror(-r));
663 /* OK, we have an ESP partition, this is fantastic, so let's
664 * wait for a root device to show up. A udev rule will create
665 * the link for us under the right name. */
669 "/dev/disk/by-id/gpt-auto-root",
670 in_initrd() ? "/sysroot" : "/",
672 arg_root_rw ? "rw" : "ro",
674 in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET);
680 static int add_mounts(void) {
681 _cleanup_udev_unref_ struct udev *udev = NULL;
682 _cleanup_free_ char *node = NULL;
686 r = get_block_device("/", &devno);
688 log_error("Failed to determine block device of root file system: %s", strerror(-r));
691 log_debug("Root file system not on a (single) block device.");
699 r = devno_to_devnode(udev, devno, &node);
701 log_error("Failed to determine block device node from major/minor: %s", strerror(-r));
705 log_debug("Root device %s.", node);
707 r = verify_gpt_partition(node, NULL, NULL, NULL);
709 log_error("Failed to verify GPT partition %s: %s", node, strerror(-r));
713 log_debug("Not a GPT disk, exiting.");
717 return enumerate_partitions(udev, devno);
720 int main(int argc, char *argv[]) {
723 if (argc > 1 && argc != 4) {
724 log_error("This program takes three or no arguments.");
731 log_set_target(LOG_TARGET_SAFE);
732 log_parse_environment();
737 if (detect_container(NULL) > 0) {
738 log_debug("In a container, exiting.");
742 if (parse_proc_cmdline(parse_proc_cmdline_item) < 0)
746 log_debug("Disabled, exiting.");
750 if (arg_root_enabled)
751 r = add_root_mount();
761 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;