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"
147 "After=systemd-readahead-collect.service systemd-readahead-replay.service\n\n"
150 "RemainAfterExit=yes\n"
151 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
152 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '' '%s'\n"
153 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
155 id, what, rw ? "" : "read-only",
160 log_error("Failed to write file %s: %m", p);
164 from = strappenda("../", n);
166 to = strjoin(arg_dest, "/", d, ".wants/", n, NULL);
170 mkdir_parents_label(to, 0755);
171 if (symlink(from, to) < 0) {
172 log_error("Failed to create symlink %s: %m", to);
177 to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
181 mkdir_parents_label(to, 0755);
182 if (symlink(from, to) < 0) {
183 log_error("Failed to create symlink %s: %m", to);
188 to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
192 mkdir_parents_label(to, 0755);
193 if (symlink(from, to) < 0) {
194 log_error("Failed to create symlink %s: %m", to);
199 p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf", NULL);
203 mkdir_parents_label(p, 0755);
204 r = write_string_file(p,
205 "# Automatically generated by systemd-gpt-auto-generator\n\n"
207 "JobTimeoutSec=0\n"); /* the binary handles timeouts anyway */
209 log_error("Failed to write device drop-in: %s", strerror(-r));
213 ret = strappend("/dev/mapper/", id);
221 static int add_mount(
227 const char *description,
230 _cleanup_free_ char *unit = NULL, *lnk = NULL, *crypto_what = NULL, *p = NULL;
231 _cleanup_fclose_ FILE *f = NULL;
239 log_debug("Adding %s: %s %s", where, what, strna(fstype));
241 if (streq_ptr(fstype, "crypto_LUKS")) {
243 r = add_cryptsetup(id, what, rw, &crypto_what);
251 unit = unit_name_from_path(where, ".mount");
255 p = strjoin(arg_dest, "/", unit, NULL);
261 log_error("Failed to create unit file %s: %m", unit);
266 "# Automatically generated by systemd-gpt-auto-generator\n\n"
269 "Documentation=man:systemd-gpt-auto-generator(8)\n",
273 fprintf(f, "Before=%s\n", post);
275 r = generator_write_fsck_deps(f, arg_dest, what, where, fstype);
287 fprintf(f, "Type=%s\n", fstype);
289 fprintf(f, "Options=%s\n", rw ? "rw" : "ro");
293 log_error("Failed to write unit file %s: %m", p);
298 lnk = strjoin(arg_dest, "/", post, ".requires/", unit, NULL);
302 mkdir_parents_label(lnk, 0755);
303 if (symlink(p, lnk) < 0) {
304 log_error("Failed to create symlink %s: %m", lnk);
312 static int probe_and_add_mount(
317 const char *description,
320 _cleanup_blkid_free_probe_ blkid_probe b = NULL;
329 if (path_is_mount_point(where, true) <= 0 &&
330 dir_is_empty(where) <= 0) {
331 log_debug("%s already populated, ignoring.", where);
335 /* Let's check the partition type here, so that we know
336 * whether to do LUKS magic. */
339 b = blkid_new_probe_from_filename(what);
343 log_error("Failed to allocate prober: %m");
347 blkid_probe_enable_superblocks(b, 1);
348 blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
351 r = blkid_do_safeprobe(b);
352 if (r == -2 || r == 1) /* no result or uncertain */
357 log_error("Failed to probe %s: %m", what);
361 blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
373 static int enumerate_partitions(dev_t devnum) {
375 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
376 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
377 _cleanup_blkid_free_probe_ blkid_probe b = NULL;
378 _cleanup_udev_unref_ struct udev *udev = NULL;
379 _cleanup_free_ char *home = NULL, *srv = NULL;
380 struct udev_list_entry *first, *item;
381 struct udev_device *parent = NULL;
382 const char *node, *pttype, *devtype;
383 int home_nr = -1, srv_nr = -1;
384 bool home_rw = true, srv_rw = true;
393 d = udev_device_new_from_devnum(udev, 'b', devnum);
397 parent = udev_device_get_parent(d);
399 log_debug("Not a partitioned device, ignoring.");
403 /* Does it have a devtype? */
404 devtype = udev_device_get_devtype(parent);
406 log_debug("Parent doesn't have a device type, ignoring.");
410 /* Is this a disk or a partition? We only care for disks... */
411 if (!streq(devtype, "disk")) {
412 log_debug("Parent isn't a raw disk, ignoring.");
416 /* Does it have a device node? */
417 node = udev_device_get_devnode(parent);
419 log_debug("Parent device does not have device node, ignoring.");
423 log_debug("Root device %s.", node);
425 pn = udev_device_get_devnum(parent);
430 b = blkid_new_probe_from_filename(node);
435 log_error("Failed allocate prober: %m");
439 blkid_probe_enable_superblocks(b, 1);
440 blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
441 blkid_probe_enable_partitions(b, 1);
442 blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
445 r = blkid_do_safeprobe(b);
446 if (r == -2 || r == 1) /* no result or uncertain */
451 log_error("Failed to probe %s: %m", node);
456 r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
460 log_error("Failed to determine partition table type of %s: %m", node);
464 /* We only do this all for GPT... */
465 if (!streq_ptr(pttype, "gpt")) {
466 log_debug("Not a GPT partition table, ignoring.");
471 pl = blkid_probe_get_partitions(b);
476 log_error("Failed to list partitions of %s: %m", node);
480 e = udev_enumerate_new(udev);
484 r = udev_enumerate_add_match_parent(e, parent);
488 r = udev_enumerate_add_match_subsystem(e, "block");
492 r = udev_enumerate_scan_devices(e);
494 log_error("Failed to enumerate partitions on %s: %s", node, strerror(-r));
498 first = udev_enumerate_get_list_entry(e);
499 udev_list_entry_foreach(item, first) {
500 _cleanup_udev_device_unref_ struct udev_device *q;
501 const char *stype, *subnode;
506 unsigned long long flags;
508 q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
512 qn = udev_device_get_devnum(q);
522 subnode = udev_device_get_devnode(q);
526 pp = blkid_partlist_devno_to_partition(pl, qn);
530 flags = blkid_partition_get_flags(pp);
532 /* Ignore partitions that are not marked for automatic
533 * mounting on discovery */
534 if (flags & GPT_FLAG_NO_AUTO)
537 nr = blkid_partition_get_partno(pp);
541 stype = blkid_partition_get_type_string(pp);
545 if (sd_id128_from_string(stype, &type_id) < 0)
548 if (sd_id128_equal(type_id, GPT_SWAP)) {
550 if (flags & GPT_FLAG_READ_ONLY) {
551 log_debug("%s marked as read-only swap partition, which is bogus, ignoring.", subnode);
555 k = add_swap(subnode);
559 } else if (sd_id128_equal(type_id, GPT_HOME)) {
561 /* We only care for the first /home partition */
562 if (home && nr >= home_nr)
566 home_rw = !(flags & GPT_FLAG_READ_ONLY),
569 home = strdup(subnode);
573 } else if (sd_id128_equal(type_id, GPT_SRV)) {
575 /* We only care for the first /srv partition */
576 if (srv && nr >= srv_nr)
580 srv_rw = !(flags & GPT_FLAG_READ_ONLY),
590 k = probe_and_add_mount("home", home, "/home", home_rw, "Home Partition", SPECIAL_LOCAL_FS_TARGET);
596 k = probe_and_add_mount("srv", srv, "/srv", srv_rw, "Server Data Partition", SPECIAL_LOCAL_FS_TARGET);
604 static int get_btrfs_block_device(const char *path, dev_t *dev) {
605 struct btrfs_ioctl_fs_info_args fsi = {};
606 _cleanup_close_ int fd = -1;
612 fd = open(path, O_DIRECTORY|O_CLOEXEC);
616 if (ioctl(fd, BTRFS_IOC_FS_INFO, &fsi) < 0)
619 /* We won't do this for btrfs RAID */
620 if (fsi.num_devices != 1)
623 for (id = 1; id <= fsi.max_id; id++) {
624 struct btrfs_ioctl_dev_info_args di = {
629 if (ioctl(fd, BTRFS_IOC_DEV_INFO, &di) < 0) {
636 if (stat((char*) di.path, &st) < 0)
639 if (!S_ISBLK(st.st_mode))
642 if (major(st.st_rdev) == 0)
652 static int get_block_device(const char *path, dev_t *dev) {
659 if (lstat(path, &st))
662 if (major(st.st_dev) != 0) {
667 if (statfs(path, &sfs) < 0)
670 if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
671 return get_btrfs_block_device(path, dev);
676 static int parse_proc_cmdline_item(const char *key, const char *value) {
681 if (STR_IN_SET(key, "systemd.gpt_auto", "rd.systemd.gpt_auto") && value) {
683 r = parse_boolean(value);
685 log_warning("Failed to parse gpt-auto switch %s. Ignoring.", value);
689 } else if (streq(key, "root") && value) {
691 /* Disable root disk logic if there's a root= value
692 * specified (unless it happens to be "gpt-auto") */
694 arg_root_enabled = streq(value, "gpt-auto");
696 } else if (streq(key, "rw") && !value)
698 else if (streq(key, "ro") && !value)
700 else if (startswith(key, "systemd.gpt-auto.") || startswith(key, "rd.systemd.gpt-auto."))
701 log_warning("Unknown kernel switch %s. Ignoring.", key);
706 static int add_root_mount(void) {
711 if (!is_efi_boot()) {
712 log_debug("Not a EFI boot, not creating root mount.");
716 r = efi_loader_get_device_part_uuid(NULL);
718 log_debug("EFI loader partition unknown, exiting.");
721 log_error("Failed to read ESP partition UUID: %s", strerror(-r));
725 /* OK, we have an ESP partition, this is fantastic, so let's
726 * wait for a root device to show up. A udev rule will create
727 * the link for us under the right name. */
731 "/dev/gpt-auto-root",
732 in_initrd() ? "/sysroot" : "/",
736 in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET);
742 static int add_mounts(void) {
746 r = get_block_device("/", &devno);
748 log_error("Failed to determine block device of root file system: %s", strerror(-r));
751 log_debug("Root file system not on a (single) block device.");
755 return enumerate_partitions(devno);
758 int main(int argc, char *argv[]) {
761 if (argc > 1 && argc != 4) {
762 log_error("This program takes three or no arguments.");
769 log_set_target(LOG_TARGET_SAFE);
770 log_parse_environment();
775 if (detect_container(NULL) > 0) {
776 log_debug("In a container, exiting.");
780 if (parse_proc_cmdline(parse_proc_cmdline_item) < 0)
784 log_debug("Disabled, exiting.");
788 if (arg_root_enabled)
789 r = add_root_mount();
799 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;