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/>.
24 #include <sys/statfs.h>
25 #include <blkid/blkid.h>
29 #include "path-util.h"
33 #include "udev-util.h"
35 #include "unit-name.h"
37 #include "generator.h"
41 #include "fstab-util.h"
42 #include "blkid-util.h"
43 #include "btrfs-util.h"
45 static const char *arg_dest
= "/tmp";
46 static bool arg_enabled
= true;
47 static bool arg_root_enabled
= true;
48 static bool arg_root_rw
= false;
50 static int add_cryptsetup(const char *id
, const char *what
, bool rw
, char **device
) {
51 _cleanup_free_
char *e
= NULL
, *n
= NULL
, *p
= NULL
, *d
= NULL
, *to
= NULL
;
52 _cleanup_fclose_
FILE *f
= NULL
;
60 r
= unit_name_from_path(what
, ".device", &d
);
62 return log_error_errno(r
, "Failed to generate unit name: %m");
64 e
= unit_name_escape(id
);
68 r
= unit_name_build("systemd-cryptsetup", e
, ".service", &n
);
70 return log_error_errno(r
, "Failed to generate unit name: %m");
72 p
= strjoin(arg_dest
, "/", n
, NULL
);
78 return log_error_errno(errno
, "Failed to create unit file %s: %m", p
);
81 "# Automatically generated by systemd-gpt-auto-generator\n\n"
83 "Description=Cryptography Setup for %%I\n"
84 "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
85 "DefaultDependencies=no\n"
86 "Conflicts=umount.target\n"
87 "BindsTo=dev-mapper-%%i.device %s\n"
88 "Before=umount.target cryptsetup.target\n"
90 "IgnoreOnIsolate=true\n"
93 "RemainAfterExit=yes\n"
94 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
95 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH
" attach '%s' '%s' '' '%s'\n"
96 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH
" detach '%s'\n",
98 id
, what
, rw
? "" : "read-only",
101 r
= fflush_and_check(f
);
103 return log_error_errno(r
, "Failed to write file %s: %m", p
);
105 from
= strjoina("../", n
);
107 to
= strjoin(arg_dest
, "/", d
, ".wants/", n
, NULL
);
111 mkdir_parents_label(to
, 0755);
112 if (symlink(from
, to
) < 0)
113 return log_error_errno(errno
, "Failed to create symlink %s: %m", to
);
116 to
= strjoin(arg_dest
, "/cryptsetup.target.requires/", 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
, "/dev-mapper-", e
, ".device.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 p
= strjoin(arg_dest
, "/dev-mapper-", e
, ".device.d/50-job-timeout-sec-0.conf", NULL
);
138 mkdir_parents_label(p
, 0755);
139 r
= write_string_file(p
,
140 "# Automatically generated by systemd-gpt-auto-generator\n\n"
143 WRITE_STRING_FILE_CREATE
); /* the binary handles timeouts anyway */
145 return log_error_errno(r
, "Failed to write device drop-in: %m");
147 ret
= strappend("/dev/mapper/", id
);
155 static int add_mount(
162 const char *description
,
165 _cleanup_free_
char *unit
= NULL
, *lnk
= NULL
, *crypto_what
= NULL
, *p
= NULL
;
166 _cleanup_fclose_
FILE *f
= NULL
;
174 log_debug("Adding %s: %s %s", where
, what
, strna(fstype
));
176 if (streq_ptr(fstype
, "crypto_LUKS")) {
178 r
= add_cryptsetup(id
, what
, rw
, &crypto_what
);
186 r
= unit_name_from_path(where
, ".mount", &unit
);
188 return log_error_errno(r
, "Failed to generate unit name: %m");
190 p
= strjoin(arg_dest
, "/", unit
, NULL
);
196 return log_error_errno(errno
, "Failed to create unit file %s: %m", unit
);
199 "# Automatically generated by systemd-gpt-auto-generator\n\n"
202 "Documentation=man:systemd-gpt-auto-generator(8)\n",
206 fprintf(f
, "Before=%s\n", post
);
208 r
= generator_write_fsck_deps(f
, arg_dest
, what
, where
, fstype
);
220 fprintf(f
, "Type=%s\n", fstype
);
223 fprintf(f
, "Options=%s,%s\n", options
, rw
? "rw" : "ro");
225 fprintf(f
, "Options=%s\n", rw
? "rw" : "ro");
227 r
= fflush_and_check(f
);
229 return log_error_errno(r
, "Failed to write unit file %s: %m", p
);
232 lnk
= strjoin(arg_dest
, "/", post
, ".requires/", unit
, NULL
);
236 mkdir_parents_label(lnk
, 0755);
237 if (symlink(p
, lnk
) < 0)
238 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
244 static bool path_is_busy(const char *where
) {
247 /* already a mountpoint; generators run during reload */
248 r
= path_is_mount_point(where
, AT_SYMLINK_FOLLOW
);
252 /* the directory might not exist on a stateless system */
259 /* not a mountpoint but it contains files */
260 if (dir_is_empty(where
) <= 0)
266 static int probe_and_add_mount(
271 const char *description
,
274 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
275 const char *fstype
= NULL
;
283 if (path_is_busy(where
)) {
284 log_debug("%s already populated, ignoring.", where
);
288 /* Let's check the partition type here, so that we know
289 * whether to do LUKS magic. */
292 b
= blkid_new_probe_from_filename(what
);
296 log_error_errno(errno
, "Failed to allocate prober: %m");
300 blkid_probe_enable_superblocks(b
, 1);
301 blkid_probe_set_superblocks_flags(b
, BLKID_SUBLKS_TYPE
);
304 r
= blkid_do_safeprobe(b
);
305 if (r
== -2 || r
== 1) /* no result or uncertain */
308 return log_error_errno(errno
?: EIO
, "Failed to probe %s: %m", what
);
310 /* add_mount is OK with fstype being NULL. */
311 (void) blkid_probe_lookup_value(b
, "TYPE", &fstype
, NULL
);
324 static int add_swap(const char *path
) {
325 _cleanup_free_
char *name
= NULL
, *unit
= NULL
, *lnk
= NULL
;
326 _cleanup_fclose_
FILE *f
= NULL
;
331 log_debug("Adding swap: %s", path
);
333 r
= unit_name_from_path(path
, ".swap", &name
);
335 return log_error_errno(r
, "Failed to generate unit name: %m");
337 unit
= strjoin(arg_dest
, "/", name
, NULL
);
341 f
= fopen(unit
, "wxe");
343 return log_error_errno(errno
, "Failed to create unit file %s: %m", unit
);
346 "# Automatically generated by systemd-gpt-auto-generator\n\n"
348 "Description=Swap Partition\n"
349 "Documentation=man:systemd-gpt-auto-generator(8)\n\n"
354 r
= fflush_and_check(f
);
356 return log_error_errno(r
, "Failed to write unit file %s: %m", unit
);
358 lnk
= strjoin(arg_dest
, "/" SPECIAL_SWAP_TARGET
".wants/", name
, NULL
);
362 mkdir_parents_label(lnk
, 0755);
363 if (symlink(unit
, lnk
) < 0)
364 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
370 static int add_automount(
377 const char *description
,
380 _cleanup_free_
char *unit
= NULL
, *lnk
= NULL
;
381 _cleanup_free_
char *opt
, *p
= NULL
;
382 _cleanup_fclose_
FILE *f
= NULL
;
390 opt
= strjoin(options
, ",noauto", NULL
);
392 opt
= strdup("noauto");
407 r
= unit_name_from_path(where
, ".automount", &unit
);
409 return log_error_errno(r
, "Failed to generate unit name: %m");
411 p
= strjoin(arg_dest
, "/", unit
, NULL
);
417 return log_error_errno(errno
, "Failed to create unit file %s: %m", unit
);
420 "# Automatically generated by systemd-gpt-auto-generator\n\n"
423 "Documentation=man:systemd-gpt-auto-generator(8)\n"
426 "TimeoutIdleSec=%lld\n",
429 (unsigned long long)timeout
/ USEC_PER_SEC
);
431 r
= fflush_and_check(f
);
433 return log_error_errno(r
, "Failed to write unit file %s: %m", p
);
435 lnk
= strjoin(arg_dest
, "/" SPECIAL_LOCAL_FS_TARGET
".wants/", unit
, NULL
);
438 mkdir_parents_label(lnk
, 0755);
440 if (symlink(p
, lnk
) < 0)
441 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
446 static int add_boot(const char *what
) {
447 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
448 const char *fstype
= NULL
, *uuid
= NULL
;
449 sd_id128_t id
, type_id
;
454 if (!is_efi_boot()) {
455 log_debug("Not an EFI boot, ignoring /boot.");
460 log_debug("In initrd, ignoring /boot.");
464 if (detect_container() > 0) {
465 log_debug("In a container, ignoring /boot.");
469 /* We create an .automount which is not overridden by the .mount from the fstab generator. */
470 if (fstab_is_mount_point("/boot")) {
471 log_debug("/boot specified in fstab, ignoring.");
475 if (path_is_busy("/boot")) {
476 log_debug("/boot already populated, ignoring.");
480 r
= efi_loader_get_device_part_uuid(&id
);
482 log_debug("EFI loader partition unknown.");
487 log_error_errno(r
, "Failed to read ESP partition UUID: %m");
492 b
= blkid_new_probe_from_filename(what
);
496 log_error_errno(errno
, "Failed to allocate prober: %m");
500 blkid_probe_enable_partitions(b
, 1);
501 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
504 r
= blkid_do_safeprobe(b
);
505 if (r
== -2 || r
== 1) /* no result or uncertain */
508 return log_error_errno(errno
?: EIO
, "Failed to probe %s: %m", what
);
510 (void) blkid_probe_lookup_value(b
, "TYPE", &fstype
, NULL
);
511 if (!streq(fstype
, "vfat")) {
512 log_debug("Partition for /boot is not a FAT filesystem, ignoring.");
516 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_UUID", &uuid
, NULL
);
518 log_debug_errno(r
, "Partition for /boot does not have a UUID, ignoring. %m");
522 if (sd_id128_from_string(uuid
, &type_id
) < 0) {
523 log_debug("Partition for /boot does not have a valid UUID, ignoring.");
527 if (!sd_id128_equal(type_id
, id
)) {
528 log_debug("Partition for /boot does not appear to be the partition we are booted from.");
532 r
= add_automount("boot",
538 "EFI System Partition Automount",
544 static int add_boot(const char *what
) {
549 static int enumerate_partitions(dev_t devnum
) {
551 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
552 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
553 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
554 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
555 _cleanup_free_
char *boot
= NULL
, *home
= NULL
, *srv
= NULL
;
556 struct udev_list_entry
*first
, *item
;
557 struct udev_device
*parent
= NULL
;
558 const char *name
, *node
, *pttype
, *devtype
;
559 int boot_nr
= -1, home_nr
= -1, srv_nr
= -1;
560 bool home_rw
= true, srv_rw
= true;
569 d
= udev_device_new_from_devnum(udev
, 'b', devnum
);
573 name
= udev_device_get_devnode(d
);
575 name
= udev_device_get_syspath(d
);
577 log_debug("Device %u:%u does not have a name, ignoring.",
578 major(devnum
), minor(devnum
));
582 parent
= udev_device_get_parent(d
);
584 log_debug("%s: not a partitioned device, ignoring.", name
);
588 /* Does it have a devtype? */
589 devtype
= udev_device_get_devtype(parent
);
591 log_debug("%s: parent doesn't have a device type, ignoring.", name
);
595 /* Is this a disk or a partition? We only care for disks... */
596 if (!streq(devtype
, "disk")) {
597 log_debug("%s: parent isn't a raw disk, ignoring.", name
);
601 /* Does it have a device node? */
602 node
= udev_device_get_devnode(parent
);
604 log_debug("%s: parent device does not have device node, ignoring.", name
);
608 log_debug("%s: root device %s.", name
, node
);
610 pn
= udev_device_get_devnum(parent
);
615 b
= blkid_new_probe_from_filename(node
);
620 return log_error_errno(errno
, "%s: failed to allocate prober: %m", node
);
623 blkid_probe_enable_partitions(b
, 1);
624 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
627 r
= blkid_do_safeprobe(b
);
629 return 0; /* no results */
631 log_warning("%s: probe gave ambiguous results, ignoring", node
);
634 return log_error_errno(errno
?: EIO
, "%s: failed to probe: %m", node
);
637 r
= blkid_probe_lookup_value(b
, "PTTYPE", &pttype
, NULL
);
639 return log_error_errno(errno
?: EIO
,
640 "%s: failed to determine partition table type: %m", node
);
642 /* We only do this all for GPT... */
643 if (!streq_ptr(pttype
, "gpt")) {
644 log_debug("%s: not a GPT partition table, ignoring.", node
);
649 pl
= blkid_probe_get_partitions(b
);
654 return log_error_errno(errno
, "%s: failed to list partitions: %m", node
);
657 e
= udev_enumerate_new(udev
);
661 r
= udev_enumerate_add_match_parent(e
, parent
);
665 r
= udev_enumerate_add_match_subsystem(e
, "block");
669 r
= udev_enumerate_scan_devices(e
);
671 return log_error_errno(r
, "%s: failed to enumerate partitions: %m", node
);
673 first
= udev_enumerate_get_list_entry(e
);
674 udev_list_entry_foreach(item
, first
) {
675 _cleanup_udev_device_unref_
struct udev_device
*q
;
676 unsigned long long flags
;
677 const char *stype
, *subnode
;
683 q
= udev_device_new_from_syspath(udev
, udev_list_entry_get_name(item
));
687 qn
= udev_device_get_devnum(q
);
697 subnode
= udev_device_get_devnode(q
);
701 pp
= blkid_partlist_devno_to_partition(pl
, qn
);
705 nr
= blkid_partition_get_partno(pp
);
709 stype
= blkid_partition_get_type_string(pp
);
713 if (sd_id128_from_string(stype
, &type_id
) < 0)
716 flags
= blkid_partition_get_flags(pp
);
718 if (sd_id128_equal(type_id
, GPT_SWAP
)) {
720 if (flags
& GPT_FLAG_NO_AUTO
)
723 if (flags
& GPT_FLAG_READ_ONLY
) {
724 log_debug("%s marked as read-only swap partition, which is bogus. Ignoring.", subnode
);
728 k
= add_swap(subnode
);
732 } else if (sd_id128_equal(type_id
, GPT_ESP
)) {
734 /* We only care for the first /boot partition */
735 if (boot
&& nr
>= boot_nr
)
738 /* Note that we do not honour the "no-auto"
739 * flag for the ESP, as it is often unset, to
740 * hide it from Windows. */
744 r
= free_and_strdup(&boot
, subnode
);
748 } else if (sd_id128_equal(type_id
, GPT_HOME
)) {
750 if (flags
& GPT_FLAG_NO_AUTO
)
753 /* We only care for the first /home partition */
754 if (home
&& nr
>= home_nr
)
758 home_rw
= !(flags
& GPT_FLAG_READ_ONLY
),
760 r
= free_and_strdup(&home
, subnode
);
764 } else if (sd_id128_equal(type_id
, GPT_SRV
)) {
766 if (flags
& GPT_FLAG_NO_AUTO
)
769 /* We only care for the first /srv partition */
770 if (srv
&& nr
>= srv_nr
)
774 srv_rw
= !(flags
& GPT_FLAG_READ_ONLY
),
776 r
= free_and_strdup(&srv
, subnode
);
789 k
= probe_and_add_mount("home", home
, "/home", home_rw
, "Home Partition", SPECIAL_LOCAL_FS_TARGET
);
795 k
= probe_and_add_mount("srv", srv
, "/srv", srv_rw
, "Server Data Partition", SPECIAL_LOCAL_FS_TARGET
);
803 static int get_block_device(const char *path
, dev_t
*dev
) {
810 /* Get's the block device directly backing a file system. If
811 * the block device is encrypted, returns the device mapper
814 if (lstat(path
, &st
))
817 if (major(st
.st_dev
) != 0) {
822 if (statfs(path
, &sfs
) < 0)
825 if (F_TYPE_EQUAL(sfs
.f_type
, BTRFS_SUPER_MAGIC
))
826 return btrfs_get_block_device(path
, dev
);
831 static int get_block_device_harder(const char *path
, dev_t
*dev
) {
832 _cleanup_closedir_
DIR *d
= NULL
;
833 _cleanup_free_
char *p
= NULL
, *t
= NULL
;
834 struct dirent
*de
, *found
= NULL
;
843 /* Gets the backing block device for a file system, and
844 * handles LUKS encrypted file systems, looking for its
845 * immediate parent, if there is one. */
847 r
= get_block_device(path
, &dt
);
851 if (asprintf(&p
, "/sys/dev/block/%u:%u/slaves", major(dt
), minor(dt
)) < 0)
862 FOREACH_DIRENT_ALL(de
, d
, return -errno
) {
864 if (STR_IN_SET(de
->d_name
, ".", ".."))
867 if (!IN_SET(de
->d_type
, DT_LNK
, DT_UNKNOWN
))
870 if (found
) /* Don't try to support multiple backing block devices */
879 q
= strjoina(p
, "/", found
->d_name
, "/dev");
881 r
= read_one_line_file(q
, &t
);
887 if (sscanf(t
, "%u:%u", &maj
, &min
) != 2)
893 *dev
= makedev(maj
, min
);
901 static int parse_proc_cmdline_item(const char *key
, const char *value
) {
906 if (STR_IN_SET(key
, "systemd.gpt_auto", "rd.systemd.gpt_auto") && value
) {
908 r
= parse_boolean(value
);
910 log_warning("Failed to parse gpt-auto switch \"%s\". Ignoring.", value
);
914 } else if (streq(key
, "root") && value
) {
916 /* Disable root disk logic if there's a root= value
917 * specified (unless it happens to be "gpt-auto") */
919 arg_root_enabled
= streq(value
, "gpt-auto");
921 } else if (streq(key
, "rw") && !value
)
923 else if (streq(key
, "ro") && !value
)
929 static int add_root_mount(void) {
934 if (!is_efi_boot()) {
935 log_debug("Not a EFI boot, not creating root mount.");
939 r
= efi_loader_get_device_part_uuid(NULL
);
941 log_debug("EFI loader partition unknown, exiting.");
944 return log_error_errno(r
, "Failed to read ESP partition UUID: %m");
946 /* OK, we have an ESP partition, this is fantastic, so let's
947 * wait for a root device to show up. A udev rule will create
948 * the link for us under the right name. */
952 "/dev/gpt-auto-root",
953 in_initrd() ? "/sysroot" : "/",
958 in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET
: SPECIAL_LOCAL_FS_TARGET
);
964 static int add_mounts(void) {
968 r
= get_block_device_harder("/", &devno
);
970 return log_error_errno(r
, "Failed to determine block device of root file system: %m");
972 r
= get_block_device_harder("/usr", &devno
);
974 return log_error_errno(r
, "Failed to determine block device of /usr file system: %m");
976 log_debug("Neither root nor /usr file system are on a (single) block device.");
981 return enumerate_partitions(devno
);
984 int main(int argc
, char *argv
[]) {
987 if (argc
> 1 && argc
!= 4) {
988 log_error("This program takes three or no arguments.");
995 log_set_target(LOG_TARGET_SAFE
);
996 log_parse_environment();
1001 if (detect_container() > 0) {
1002 log_debug("In a container, exiting.");
1003 return EXIT_SUCCESS
;
1006 r
= parse_proc_cmdline(parse_proc_cmdline_item
);
1008 log_warning_errno(r
, "Failed to parse kernel command line, ignoring: %m");
1011 log_debug("Disabled, exiting.");
1012 return EXIT_SUCCESS
;
1015 if (arg_root_enabled
)
1016 r
= add_root_mount();
1026 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;