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/>.
22 #include <blkid/blkid.h>
24 #include <sys/statfs.h>
30 #include "alloc-util.h"
31 #include "blkid-util.h"
32 #include "btrfs-util.h"
33 #include "dirent-util.h"
37 #include "fstab-util.h"
38 #include "generator.h"
42 #include "mount-util.h"
43 #include "parse-util.h"
44 #include "path-util.h"
45 #include "proc-cmdline.h"
47 #include "stat-util.h"
48 #include "string-util.h"
49 #include "udev-util.h"
50 #include "unit-name.h"
54 static const char *arg_dest
= "/tmp";
55 static bool arg_enabled
= true;
56 static bool arg_root_enabled
= true;
57 static bool arg_root_rw
= false;
59 static int add_cryptsetup(const char *id
, const char *what
, bool rw
, char **device
) {
60 _cleanup_free_
char *e
= NULL
, *n
= NULL
, *p
= NULL
, *d
= NULL
, *to
= NULL
;
61 _cleanup_fclose_
FILE *f
= NULL
;
69 r
= unit_name_from_path(what
, ".device", &d
);
71 return log_error_errno(r
, "Failed to generate unit name: %m");
73 e
= unit_name_escape(id
);
77 r
= unit_name_build("systemd-cryptsetup", e
, ".service", &n
);
79 return log_error_errno(r
, "Failed to generate unit name: %m");
81 p
= strjoin(arg_dest
, "/", n
, NULL
);
87 return log_error_errno(errno
, "Failed to create unit file %s: %m", p
);
90 "# Automatically generated by systemd-gpt-auto-generator\n\n"
92 "Description=Cryptography Setup for %%I\n"
93 "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
94 "DefaultDependencies=no\n"
95 "Conflicts=umount.target\n"
96 "BindsTo=dev-mapper-%%i.device %s\n"
97 "Before=umount.target cryptsetup.target\n"
99 "IgnoreOnIsolate=true\n"
102 "RemainAfterExit=yes\n"
103 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
104 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH
" attach '%s' '%s' '' '%s'\n"
105 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH
" detach '%s'\n",
107 id
, what
, rw
? "" : "read-only",
110 r
= fflush_and_check(f
);
112 return log_error_errno(r
, "Failed to write file %s: %m", p
);
114 from
= strjoina("../", n
);
116 to
= strjoin(arg_dest
, "/", d
, ".wants/", n
, NULL
);
120 mkdir_parents_label(to
, 0755);
121 if (symlink(from
, to
) < 0)
122 return log_error_errno(errno
, "Failed to create symlink %s: %m", to
);
125 to
= strjoin(arg_dest
, "/cryptsetup.target.requires/", n
, NULL
);
129 mkdir_parents_label(to
, 0755);
130 if (symlink(from
, to
) < 0)
131 return log_error_errno(errno
, "Failed to create symlink %s: %m", to
);
134 to
= strjoin(arg_dest
, "/dev-mapper-", e
, ".device.requires/", n
, NULL
);
138 mkdir_parents_label(to
, 0755);
139 if (symlink(from
, to
) < 0)
140 return log_error_errno(errno
, "Failed to create symlink %s: %m", to
);
143 p
= strjoin(arg_dest
, "/dev-mapper-", e
, ".device.d/50-job-timeout-sec-0.conf", NULL
);
147 mkdir_parents_label(p
, 0755);
148 r
= write_string_file(p
,
149 "# Automatically generated by systemd-gpt-auto-generator\n\n"
152 WRITE_STRING_FILE_CREATE
); /* the binary handles timeouts anyway */
154 return log_error_errno(r
, "Failed to write device drop-in: %m");
156 ret
= strappend("/dev/mapper/", id
);
164 static int add_mount(
171 const char *description
,
174 _cleanup_free_
char *unit
= NULL
, *lnk
= NULL
, *crypto_what
= NULL
, *p
= NULL
;
175 _cleanup_fclose_
FILE *f
= NULL
;
183 log_debug("Adding %s: %s %s", where
, what
, strna(fstype
));
185 if (streq_ptr(fstype
, "crypto_LUKS")) {
187 r
= add_cryptsetup(id
, what
, rw
, &crypto_what
);
195 r
= unit_name_from_path(where
, ".mount", &unit
);
197 return log_error_errno(r
, "Failed to generate unit name: %m");
199 p
= strjoin(arg_dest
, "/", unit
, NULL
);
205 return log_error_errno(errno
, "Failed to create unit file %s: %m", unit
);
208 "# Automatically generated by systemd-gpt-auto-generator\n\n"
211 "Documentation=man:systemd-gpt-auto-generator(8)\n",
215 fprintf(f
, "Before=%s\n", post
);
217 r
= generator_write_fsck_deps(f
, arg_dest
, what
, where
, fstype
);
229 fprintf(f
, "Type=%s\n", fstype
);
232 fprintf(f
, "Options=%s,%s\n", options
, rw
? "rw" : "ro");
234 fprintf(f
, "Options=%s\n", rw
? "rw" : "ro");
236 r
= fflush_and_check(f
);
238 return log_error_errno(r
, "Failed to write unit file %s: %m", p
);
241 lnk
= strjoin(arg_dest
, "/", post
, ".requires/", unit
, NULL
);
245 mkdir_parents_label(lnk
, 0755);
246 if (symlink(p
, lnk
) < 0)
247 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
253 static bool path_is_busy(const char *where
) {
256 /* already a mountpoint; generators run during reload */
257 r
= path_is_mount_point(where
, AT_SYMLINK_FOLLOW
);
261 /* the directory might not exist on a stateless system */
268 /* not a mountpoint but it contains files */
269 if (dir_is_empty(where
) <= 0)
275 static int probe_and_add_mount(
280 const char *description
,
283 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
284 const char *fstype
= NULL
;
292 if (path_is_busy(where
)) {
293 log_debug("%s already populated, ignoring.", where
);
297 /* Let's check the partition type here, so that we know
298 * whether to do LUKS magic. */
301 b
= blkid_new_probe_from_filename(what
);
305 return log_error_errno(errno
, "Failed to allocate prober: %m");
308 blkid_probe_enable_superblocks(b
, 1);
309 blkid_probe_set_superblocks_flags(b
, BLKID_SUBLKS_TYPE
);
312 r
= blkid_do_safeprobe(b
);
313 if (r
== -2 || r
== 1) /* no result or uncertain */
316 return log_error_errno(errno
?: EIO
, "Failed to probe %s: %m", what
);
318 /* add_mount is OK with fstype being NULL. */
319 (void) blkid_probe_lookup_value(b
, "TYPE", &fstype
, NULL
);
332 static int add_swap(const char *path
) {
333 _cleanup_free_
char *name
= NULL
, *unit
= NULL
, *lnk
= NULL
;
334 _cleanup_fclose_
FILE *f
= NULL
;
339 log_debug("Adding swap: %s", path
);
341 r
= unit_name_from_path(path
, ".swap", &name
);
343 return log_error_errno(r
, "Failed to generate unit name: %m");
345 unit
= strjoin(arg_dest
, "/", name
, NULL
);
349 f
= fopen(unit
, "wxe");
351 return log_error_errno(errno
, "Failed to create unit file %s: %m", unit
);
354 "# Automatically generated by systemd-gpt-auto-generator\n\n"
356 "Description=Swap Partition\n"
357 "Documentation=man:systemd-gpt-auto-generator(8)\n\n"
362 r
= fflush_and_check(f
);
364 return log_error_errno(r
, "Failed to write unit file %s: %m", unit
);
366 lnk
= strjoin(arg_dest
, "/" SPECIAL_SWAP_TARGET
".wants/", name
, NULL
);
370 mkdir_parents_label(lnk
, 0755);
371 if (symlink(unit
, lnk
) < 0)
372 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
378 static int add_automount(
385 const char *description
,
388 _cleanup_free_
char *unit
= NULL
, *lnk
= NULL
;
389 _cleanup_free_
char *opt
, *p
= NULL
;
390 _cleanup_fclose_
FILE *f
= NULL
;
398 opt
= strjoin(options
, ",noauto", NULL
);
400 opt
= strdup("noauto");
415 r
= unit_name_from_path(where
, ".automount", &unit
);
417 return log_error_errno(r
, "Failed to generate unit name: %m");
419 p
= strjoin(arg_dest
, "/", unit
, NULL
);
425 return log_error_errno(errno
, "Failed to create unit file %s: %m", unit
);
428 "# Automatically generated by systemd-gpt-auto-generator\n\n"
431 "Documentation=man:systemd-gpt-auto-generator(8)\n"
434 "TimeoutIdleSec=%lld\n",
437 (unsigned long long)timeout
/ USEC_PER_SEC
);
439 r
= fflush_and_check(f
);
441 return log_error_errno(r
, "Failed to write unit file %s: %m", p
);
443 lnk
= strjoin(arg_dest
, "/" SPECIAL_LOCAL_FS_TARGET
".wants/", unit
, NULL
);
446 mkdir_parents_label(lnk
, 0755);
448 if (symlink(p
, lnk
) < 0)
449 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
454 static int add_boot(const char *what
) {
455 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
456 const char *fstype
= NULL
, *uuid
= NULL
;
457 sd_id128_t id
, type_id
;
462 if (!is_efi_boot()) {
463 log_debug("Not an EFI boot, ignoring /boot.");
468 log_debug("In initrd, ignoring /boot.");
472 if (detect_container() > 0) {
473 log_debug("In a container, ignoring /boot.");
477 /* We create an .automount which is not overridden by the .mount from the fstab generator. */
478 if (fstab_is_mount_point("/boot")) {
479 log_debug("/boot specified in fstab, ignoring.");
483 if (path_is_busy("/boot")) {
484 log_debug("/boot already populated, ignoring.");
488 r
= efi_loader_get_device_part_uuid(&id
);
490 log_debug("EFI loader partition unknown.");
495 log_error_errno(r
, "Failed to read ESP partition UUID: %m");
500 b
= blkid_new_probe_from_filename(what
);
504 return log_error_errno(errno
, "Failed to allocate prober: %m");
507 blkid_probe_enable_partitions(b
, 1);
508 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
511 r
= blkid_do_safeprobe(b
);
512 if (r
== -2 || r
== 1) /* no result or uncertain */
515 return log_error_errno(errno
?: EIO
, "Failed to probe %s: %m", what
);
517 (void) blkid_probe_lookup_value(b
, "TYPE", &fstype
, NULL
);
518 if (!streq(fstype
, "vfat")) {
519 log_debug("Partition for /boot is not a FAT filesystem, ignoring.");
523 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_UUID", &uuid
, NULL
);
525 log_debug_errno(r
, "Partition for /boot does not have a UUID, ignoring. %m");
529 if (sd_id128_from_string(uuid
, &type_id
) < 0) {
530 log_debug("Partition for /boot does not have a valid UUID, ignoring.");
534 if (!sd_id128_equal(type_id
, id
)) {
535 log_debug("Partition for /boot does not appear to be the partition we are booted from.");
539 r
= add_automount("boot",
545 "EFI System Partition Automount",
551 static int add_boot(const char *what
) {
556 static int enumerate_partitions(dev_t devnum
) {
558 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
559 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
560 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
561 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
562 _cleanup_free_
char *boot
= NULL
, *home
= NULL
, *srv
= NULL
;
563 struct udev_list_entry
*first
, *item
;
564 struct udev_device
*parent
= NULL
;
565 const char *name
, *node
, *pttype
, *devtype
;
566 int boot_nr
= -1, home_nr
= -1, srv_nr
= -1;
567 bool home_rw
= true, srv_rw
= true;
576 d
= udev_device_new_from_devnum(udev
, 'b', devnum
);
580 name
= udev_device_get_devnode(d
);
582 name
= udev_device_get_syspath(d
);
584 log_debug("Device %u:%u does not have a name, ignoring.",
585 major(devnum
), minor(devnum
));
589 parent
= udev_device_get_parent(d
);
591 log_debug("%s: not a partitioned device, ignoring.", name
);
595 /* Does it have a devtype? */
596 devtype
= udev_device_get_devtype(parent
);
598 log_debug("%s: parent doesn't have a device type, ignoring.", name
);
602 /* Is this a disk or a partition? We only care for disks... */
603 if (!streq(devtype
, "disk")) {
604 log_debug("%s: parent isn't a raw disk, ignoring.", name
);
608 /* Does it have a device node? */
609 node
= udev_device_get_devnode(parent
);
611 log_debug("%s: parent device does not have device node, ignoring.", name
);
615 log_debug("%s: root device %s.", name
, node
);
617 pn
= udev_device_get_devnum(parent
);
622 b
= blkid_new_probe_from_filename(node
);
627 return log_error_errno(errno
, "%s: failed to allocate prober: %m", node
);
630 blkid_probe_enable_partitions(b
, 1);
631 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
634 r
= blkid_do_safeprobe(b
);
636 return 0; /* no results */
638 log_warning("%s: probe gave ambiguous results, ignoring.", node
);
641 return log_error_errno(errno
?: EIO
, "%s: failed to probe: %m", node
);
644 r
= blkid_probe_lookup_value(b
, "PTTYPE", &pttype
, NULL
);
647 return 0; /* No partition table found. */
649 return log_error_errno(errno
, "%s: failed to determine partition table type: %m", node
);
652 /* We only do this all for GPT... */
653 if (!streq_ptr(pttype
, "gpt")) {
654 log_debug("%s: not a GPT partition table, ignoring.", node
);
659 pl
= blkid_probe_get_partitions(b
);
664 return log_error_errno(errno
, "%s: failed to list partitions: %m", node
);
667 e
= udev_enumerate_new(udev
);
671 r
= udev_enumerate_add_match_parent(e
, parent
);
675 r
= udev_enumerate_add_match_subsystem(e
, "block");
679 r
= udev_enumerate_scan_devices(e
);
681 return log_error_errno(r
, "%s: failed to enumerate partitions: %m", node
);
683 first
= udev_enumerate_get_list_entry(e
);
684 udev_list_entry_foreach(item
, first
) {
685 _cleanup_udev_device_unref_
struct udev_device
*q
;
686 unsigned long long flags
;
687 const char *stype
, *subnode
;
693 q
= udev_device_new_from_syspath(udev
, udev_list_entry_get_name(item
));
697 qn
= udev_device_get_devnum(q
);
707 subnode
= udev_device_get_devnode(q
);
711 pp
= blkid_partlist_devno_to_partition(pl
, qn
);
715 nr
= blkid_partition_get_partno(pp
);
719 stype
= blkid_partition_get_type_string(pp
);
723 if (sd_id128_from_string(stype
, &type_id
) < 0)
726 flags
= blkid_partition_get_flags(pp
);
728 if (sd_id128_equal(type_id
, GPT_SWAP
)) {
730 if (flags
& GPT_FLAG_NO_AUTO
)
733 if (flags
& GPT_FLAG_READ_ONLY
) {
734 log_debug("%s marked as read-only swap partition, which is bogus. Ignoring.", subnode
);
738 k
= add_swap(subnode
);
742 } else if (sd_id128_equal(type_id
, GPT_ESP
)) {
744 /* We only care for the first /boot partition */
745 if (boot
&& nr
>= boot_nr
)
748 /* Note that we do not honour the "no-auto"
749 * flag for the ESP, as it is often unset, to
750 * hide it from Windows. */
754 r
= free_and_strdup(&boot
, subnode
);
758 } else if (sd_id128_equal(type_id
, GPT_HOME
)) {
760 if (flags
& GPT_FLAG_NO_AUTO
)
763 /* We only care for the first /home partition */
764 if (home
&& nr
>= home_nr
)
768 home_rw
= !(flags
& GPT_FLAG_READ_ONLY
),
770 r
= free_and_strdup(&home
, subnode
);
774 } else if (sd_id128_equal(type_id
, GPT_SRV
)) {
776 if (flags
& GPT_FLAG_NO_AUTO
)
779 /* We only care for the first /srv partition */
780 if (srv
&& nr
>= srv_nr
)
784 srv_rw
= !(flags
& GPT_FLAG_READ_ONLY
),
786 r
= free_and_strdup(&srv
, subnode
);
799 k
= probe_and_add_mount("home", home
, "/home", home_rw
, "Home Partition", SPECIAL_LOCAL_FS_TARGET
);
805 k
= probe_and_add_mount("srv", srv
, "/srv", srv_rw
, "Server Data Partition", SPECIAL_LOCAL_FS_TARGET
);
813 static int get_block_device(const char *path
, dev_t
*dev
) {
820 /* Get's the block device directly backing a file system. If
821 * the block device is encrypted, returns the device mapper
824 if (lstat(path
, &st
))
827 if (major(st
.st_dev
) != 0) {
832 if (statfs(path
, &sfs
) < 0)
835 if (F_TYPE_EQUAL(sfs
.f_type
, BTRFS_SUPER_MAGIC
))
836 return btrfs_get_block_device(path
, dev
);
841 static int get_block_device_harder(const char *path
, dev_t
*dev
) {
842 _cleanup_closedir_
DIR *d
= NULL
;
843 _cleanup_free_
char *p
= NULL
, *t
= NULL
;
844 struct dirent
*de
, *found
= NULL
;
853 /* Gets the backing block device for a file system, and
854 * handles LUKS encrypted file systems, looking for its
855 * immediate parent, if there is one. */
857 r
= get_block_device(path
, &dt
);
861 if (asprintf(&p
, "/sys/dev/block/%u:%u/slaves", major(dt
), minor(dt
)) < 0)
872 FOREACH_DIRENT_ALL(de
, d
, return -errno
) {
874 if (STR_IN_SET(de
->d_name
, ".", ".."))
877 if (!IN_SET(de
->d_type
, DT_LNK
, DT_UNKNOWN
))
880 if (found
) /* Don't try to support multiple backing block devices */
889 q
= strjoina(p
, "/", found
->d_name
, "/dev");
891 r
= read_one_line_file(q
, &t
);
897 if (sscanf(t
, "%u:%u", &maj
, &min
) != 2)
903 *dev
= makedev(maj
, min
);
911 static int parse_proc_cmdline_item(const char *key
, const char *value
) {
916 if (STR_IN_SET(key
, "systemd.gpt_auto", "rd.systemd.gpt_auto") && value
) {
918 r
= parse_boolean(value
);
920 log_warning("Failed to parse gpt-auto switch \"%s\". Ignoring.", value
);
924 } else if (streq(key
, "root") && value
) {
926 /* Disable root disk logic if there's a root= value
927 * specified (unless it happens to be "gpt-auto") */
929 arg_root_enabled
= streq(value
, "gpt-auto");
931 } else if (streq(key
, "rw") && !value
)
933 else if (streq(key
, "ro") && !value
)
939 static int add_root_mount(void) {
944 if (!is_efi_boot()) {
945 log_debug("Not a EFI boot, not creating root mount.");
949 r
= efi_loader_get_device_part_uuid(NULL
);
951 log_debug("EFI loader partition unknown, exiting.");
954 return log_error_errno(r
, "Failed to read ESP partition UUID: %m");
956 /* OK, we have an ESP partition, this is fantastic, so let's
957 * wait for a root device to show up. A udev rule will create
958 * the link for us under the right name. */
962 "/dev/gpt-auto-root",
963 in_initrd() ? "/sysroot" : "/",
968 in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET
: SPECIAL_LOCAL_FS_TARGET
);
974 static int add_mounts(void) {
978 r
= get_block_device_harder("/", &devno
);
980 return log_error_errno(r
, "Failed to determine block device of root file system: %m");
982 r
= get_block_device_harder("/usr", &devno
);
984 return log_error_errno(r
, "Failed to determine block device of /usr file system: %m");
986 log_debug("Neither root nor /usr file system are on a (single) block device.");
991 return enumerate_partitions(devno
);
994 int main(int argc
, char *argv
[]) {
997 if (argc
> 1 && argc
!= 4) {
998 log_error("This program takes three or no arguments.");
1005 log_set_target(LOG_TARGET_SAFE
);
1006 log_parse_environment();
1011 if (detect_container() > 0) {
1012 log_debug("In a container, exiting.");
1013 return EXIT_SUCCESS
;
1016 r
= parse_proc_cmdline(parse_proc_cmdline_item
);
1018 log_warning_errno(r
, "Failed to parse kernel command line, ignoring: %m");
1021 log_debug("Disabled, exiting.");
1022 return EXIT_SUCCESS
;
1025 if (arg_root_enabled
)
1026 r
= add_root_mount();
1036 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;