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>
30 #include "blkid-util.h"
31 #include "btrfs-util.h"
32 #include "dirent-util.h"
36 #include "fstab-util.h"
37 #include "generator.h"
41 #include "mount-util.h"
42 #include "parse-util.h"
43 #include "path-util.h"
44 #include "proc-cmdline.h"
46 #include "stat-util.h"
47 #include "string-util.h"
48 #include "udev-util.h"
49 #include "unit-name.h"
53 static const char *arg_dest
= "/tmp";
54 static bool arg_enabled
= true;
55 static bool arg_root_enabled
= true;
56 static bool arg_root_rw
= false;
58 static int add_cryptsetup(const char *id
, const char *what
, bool rw
, char **device
) {
59 _cleanup_free_
char *e
= NULL
, *n
= NULL
, *p
= NULL
, *d
= NULL
, *to
= NULL
;
60 _cleanup_fclose_
FILE *f
= NULL
;
68 r
= unit_name_from_path(what
, ".device", &d
);
70 return log_error_errno(r
, "Failed to generate unit name: %m");
72 e
= unit_name_escape(id
);
76 r
= unit_name_build("systemd-cryptsetup", e
, ".service", &n
);
78 return log_error_errno(r
, "Failed to generate unit name: %m");
80 p
= strjoin(arg_dest
, "/", n
, NULL
);
86 return log_error_errno(errno
, "Failed to create unit file %s: %m", p
);
89 "# Automatically generated by systemd-gpt-auto-generator\n\n"
91 "Description=Cryptography Setup for %%I\n"
92 "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
93 "DefaultDependencies=no\n"
94 "Conflicts=umount.target\n"
95 "BindsTo=dev-mapper-%%i.device %s\n"
96 "Before=umount.target cryptsetup.target\n"
98 "IgnoreOnIsolate=true\n"
101 "RemainAfterExit=yes\n"
102 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
103 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH
" attach '%s' '%s' '' '%s'\n"
104 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH
" detach '%s'\n",
106 id
, what
, rw
? "" : "read-only",
109 r
= fflush_and_check(f
);
111 return log_error_errno(r
, "Failed to write file %s: %m", p
);
113 from
= strjoina("../", n
);
115 to
= strjoin(arg_dest
, "/", d
, ".wants/", n
, NULL
);
119 mkdir_parents_label(to
, 0755);
120 if (symlink(from
, to
) < 0)
121 return log_error_errno(errno
, "Failed to create symlink %s: %m", to
);
124 to
= strjoin(arg_dest
, "/cryptsetup.target.requires/", n
, NULL
);
128 mkdir_parents_label(to
, 0755);
129 if (symlink(from
, to
) < 0)
130 return log_error_errno(errno
, "Failed to create symlink %s: %m", to
);
133 to
= strjoin(arg_dest
, "/dev-mapper-", e
, ".device.requires/", n
, NULL
);
137 mkdir_parents_label(to
, 0755);
138 if (symlink(from
, to
) < 0)
139 return log_error_errno(errno
, "Failed to create symlink %s: %m", to
);
142 p
= strjoin(arg_dest
, "/dev-mapper-", e
, ".device.d/50-job-timeout-sec-0.conf", NULL
);
146 mkdir_parents_label(p
, 0755);
147 r
= write_string_file(p
,
148 "# Automatically generated by systemd-gpt-auto-generator\n\n"
151 WRITE_STRING_FILE_CREATE
); /* the binary handles timeouts anyway */
153 return log_error_errno(r
, "Failed to write device drop-in: %m");
155 ret
= strappend("/dev/mapper/", id
);
163 static int add_mount(
170 const char *description
,
173 _cleanup_free_
char *unit
= NULL
, *lnk
= NULL
, *crypto_what
= NULL
, *p
= NULL
;
174 _cleanup_fclose_
FILE *f
= NULL
;
182 log_debug("Adding %s: %s %s", where
, what
, strna(fstype
));
184 if (streq_ptr(fstype
, "crypto_LUKS")) {
186 r
= add_cryptsetup(id
, what
, rw
, &crypto_what
);
194 r
= unit_name_from_path(where
, ".mount", &unit
);
196 return log_error_errno(r
, "Failed to generate unit name: %m");
198 p
= strjoin(arg_dest
, "/", unit
, NULL
);
204 return log_error_errno(errno
, "Failed to create unit file %s: %m", unit
);
207 "# Automatically generated by systemd-gpt-auto-generator\n\n"
210 "Documentation=man:systemd-gpt-auto-generator(8)\n",
214 fprintf(f
, "Before=%s\n", post
);
216 r
= generator_write_fsck_deps(f
, arg_dest
, what
, where
, fstype
);
228 fprintf(f
, "Type=%s\n", fstype
);
231 fprintf(f
, "Options=%s,%s\n", options
, rw
? "rw" : "ro");
233 fprintf(f
, "Options=%s\n", rw
? "rw" : "ro");
235 r
= fflush_and_check(f
);
237 return log_error_errno(r
, "Failed to write unit file %s: %m", p
);
240 lnk
= strjoin(arg_dest
, "/", post
, ".requires/", unit
, NULL
);
244 mkdir_parents_label(lnk
, 0755);
245 if (symlink(p
, lnk
) < 0)
246 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
252 static bool path_is_busy(const char *where
) {
255 /* already a mountpoint; generators run during reload */
256 r
= path_is_mount_point(where
, AT_SYMLINK_FOLLOW
);
260 /* the directory might not exist on a stateless system */
267 /* not a mountpoint but it contains files */
268 if (dir_is_empty(where
) <= 0)
274 static int probe_and_add_mount(
279 const char *description
,
282 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
283 const char *fstype
= NULL
;
291 if (path_is_busy(where
)) {
292 log_debug("%s already populated, ignoring.", where
);
296 /* Let's check the partition type here, so that we know
297 * whether to do LUKS magic. */
300 b
= blkid_new_probe_from_filename(what
);
304 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 log_error_errno(errno
, "Failed to allocate prober: %m");
508 blkid_probe_enable_partitions(b
, 1);
509 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
512 r
= blkid_do_safeprobe(b
);
513 if (r
== -2 || r
== 1) /* no result or uncertain */
516 return log_error_errno(errno
?: EIO
, "Failed to probe %s: %m", what
);
518 (void) blkid_probe_lookup_value(b
, "TYPE", &fstype
, NULL
);
519 if (!streq(fstype
, "vfat")) {
520 log_debug("Partition for /boot is not a FAT filesystem, ignoring.");
524 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_UUID", &uuid
, NULL
);
526 log_debug_errno(r
, "Partition for /boot does not have a UUID, ignoring. %m");
530 if (sd_id128_from_string(uuid
, &type_id
) < 0) {
531 log_debug("Partition for /boot does not have a valid UUID, ignoring.");
535 if (!sd_id128_equal(type_id
, id
)) {
536 log_debug("Partition for /boot does not appear to be the partition we are booted from.");
540 r
= add_automount("boot",
546 "EFI System Partition Automount",
552 static int add_boot(const char *what
) {
557 static int enumerate_partitions(dev_t devnum
) {
559 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
560 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
561 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
562 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
563 _cleanup_free_
char *boot
= NULL
, *home
= NULL
, *srv
= NULL
;
564 struct udev_list_entry
*first
, *item
;
565 struct udev_device
*parent
= NULL
;
566 const char *name
, *node
, *pttype
, *devtype
;
567 int boot_nr
= -1, home_nr
= -1, srv_nr
= -1;
568 bool home_rw
= true, srv_rw
= true;
577 d
= udev_device_new_from_devnum(udev
, 'b', devnum
);
581 name
= udev_device_get_devnode(d
);
583 name
= udev_device_get_syspath(d
);
585 log_debug("Device %u:%u does not have a name, ignoring.",
586 major(devnum
), minor(devnum
));
590 parent
= udev_device_get_parent(d
);
592 log_debug("%s: not a partitioned device, ignoring.", name
);
596 /* Does it have a devtype? */
597 devtype
= udev_device_get_devtype(parent
);
599 log_debug("%s: parent doesn't have a device type, ignoring.", name
);
603 /* Is this a disk or a partition? We only care for disks... */
604 if (!streq(devtype
, "disk")) {
605 log_debug("%s: parent isn't a raw disk, ignoring.", name
);
609 /* Does it have a device node? */
610 node
= udev_device_get_devnode(parent
);
612 log_debug("%s: parent device does not have device node, ignoring.", name
);
616 log_debug("%s: root device %s.", name
, node
);
618 pn
= udev_device_get_devnum(parent
);
623 b
= blkid_new_probe_from_filename(node
);
628 return log_error_errno(errno
, "%s: failed to allocate prober: %m", node
);
631 blkid_probe_enable_partitions(b
, 1);
632 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
635 r
= blkid_do_safeprobe(b
);
637 return 0; /* no results */
639 log_warning("%s: probe gave ambiguous results, ignoring", node
);
642 return log_error_errno(errno
?: EIO
, "%s: failed to probe: %m", node
);
645 r
= blkid_probe_lookup_value(b
, "PTTYPE", &pttype
, NULL
);
647 return log_error_errno(errno
?: EIO
,
648 "%s: failed to determine partition table type: %m", node
);
650 /* We only do this all for GPT... */
651 if (!streq_ptr(pttype
, "gpt")) {
652 log_debug("%s: not a GPT partition table, ignoring.", node
);
657 pl
= blkid_probe_get_partitions(b
);
662 return log_error_errno(errno
, "%s: failed to list partitions: %m", node
);
665 e
= udev_enumerate_new(udev
);
669 r
= udev_enumerate_add_match_parent(e
, parent
);
673 r
= udev_enumerate_add_match_subsystem(e
, "block");
677 r
= udev_enumerate_scan_devices(e
);
679 return log_error_errno(r
, "%s: failed to enumerate partitions: %m", node
);
681 first
= udev_enumerate_get_list_entry(e
);
682 udev_list_entry_foreach(item
, first
) {
683 _cleanup_udev_device_unref_
struct udev_device
*q
;
684 unsigned long long flags
;
685 const char *stype
, *subnode
;
691 q
= udev_device_new_from_syspath(udev
, udev_list_entry_get_name(item
));
695 qn
= udev_device_get_devnum(q
);
705 subnode
= udev_device_get_devnode(q
);
709 pp
= blkid_partlist_devno_to_partition(pl
, qn
);
713 nr
= blkid_partition_get_partno(pp
);
717 stype
= blkid_partition_get_type_string(pp
);
721 if (sd_id128_from_string(stype
, &type_id
) < 0)
724 flags
= blkid_partition_get_flags(pp
);
726 if (sd_id128_equal(type_id
, GPT_SWAP
)) {
728 if (flags
& GPT_FLAG_NO_AUTO
)
731 if (flags
& GPT_FLAG_READ_ONLY
) {
732 log_debug("%s marked as read-only swap partition, which is bogus. Ignoring.", subnode
);
736 k
= add_swap(subnode
);
740 } else if (sd_id128_equal(type_id
, GPT_ESP
)) {
742 /* We only care for the first /boot partition */
743 if (boot
&& nr
>= boot_nr
)
746 /* Note that we do not honour the "no-auto"
747 * flag for the ESP, as it is often unset, to
748 * hide it from Windows. */
752 r
= free_and_strdup(&boot
, subnode
);
756 } else if (sd_id128_equal(type_id
, GPT_HOME
)) {
758 if (flags
& GPT_FLAG_NO_AUTO
)
761 /* We only care for the first /home partition */
762 if (home
&& nr
>= home_nr
)
766 home_rw
= !(flags
& GPT_FLAG_READ_ONLY
),
768 r
= free_and_strdup(&home
, subnode
);
772 } else if (sd_id128_equal(type_id
, GPT_SRV
)) {
774 if (flags
& GPT_FLAG_NO_AUTO
)
777 /* We only care for the first /srv partition */
778 if (srv
&& nr
>= srv_nr
)
782 srv_rw
= !(flags
& GPT_FLAG_READ_ONLY
),
784 r
= free_and_strdup(&srv
, subnode
);
797 k
= probe_and_add_mount("home", home
, "/home", home_rw
, "Home Partition", SPECIAL_LOCAL_FS_TARGET
);
803 k
= probe_and_add_mount("srv", srv
, "/srv", srv_rw
, "Server Data Partition", SPECIAL_LOCAL_FS_TARGET
);
811 static int get_block_device(const char *path
, dev_t
*dev
) {
818 /* Get's the block device directly backing a file system. If
819 * the block device is encrypted, returns the device mapper
822 if (lstat(path
, &st
))
825 if (major(st
.st_dev
) != 0) {
830 if (statfs(path
, &sfs
) < 0)
833 if (F_TYPE_EQUAL(sfs
.f_type
, BTRFS_SUPER_MAGIC
))
834 return btrfs_get_block_device(path
, dev
);
839 static int get_block_device_harder(const char *path
, dev_t
*dev
) {
840 _cleanup_closedir_
DIR *d
= NULL
;
841 _cleanup_free_
char *p
= NULL
, *t
= NULL
;
842 struct dirent
*de
, *found
= NULL
;
851 /* Gets the backing block device for a file system, and
852 * handles LUKS encrypted file systems, looking for its
853 * immediate parent, if there is one. */
855 r
= get_block_device(path
, &dt
);
859 if (asprintf(&p
, "/sys/dev/block/%u:%u/slaves", major(dt
), minor(dt
)) < 0)
870 FOREACH_DIRENT_ALL(de
, d
, return -errno
) {
872 if (STR_IN_SET(de
->d_name
, ".", ".."))
875 if (!IN_SET(de
->d_type
, DT_LNK
, DT_UNKNOWN
))
878 if (found
) /* Don't try to support multiple backing block devices */
887 q
= strjoina(p
, "/", found
->d_name
, "/dev");
889 r
= read_one_line_file(q
, &t
);
895 if (sscanf(t
, "%u:%u", &maj
, &min
) != 2)
901 *dev
= makedev(maj
, min
);
909 static int parse_proc_cmdline_item(const char *key
, const char *value
) {
914 if (STR_IN_SET(key
, "systemd.gpt_auto", "rd.systemd.gpt_auto") && value
) {
916 r
= parse_boolean(value
);
918 log_warning("Failed to parse gpt-auto switch \"%s\". Ignoring.", value
);
922 } else if (streq(key
, "root") && value
) {
924 /* Disable root disk logic if there's a root= value
925 * specified (unless it happens to be "gpt-auto") */
927 arg_root_enabled
= streq(value
, "gpt-auto");
929 } else if (streq(key
, "rw") && !value
)
931 else if (streq(key
, "ro") && !value
)
937 static int add_root_mount(void) {
942 if (!is_efi_boot()) {
943 log_debug("Not a EFI boot, not creating root mount.");
947 r
= efi_loader_get_device_part_uuid(NULL
);
949 log_debug("EFI loader partition unknown, exiting.");
952 return log_error_errno(r
, "Failed to read ESP partition UUID: %m");
954 /* OK, we have an ESP partition, this is fantastic, so let's
955 * wait for a root device to show up. A udev rule will create
956 * the link for us under the right name. */
960 "/dev/gpt-auto-root",
961 in_initrd() ? "/sysroot" : "/",
966 in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET
: SPECIAL_LOCAL_FS_TARGET
);
972 static int add_mounts(void) {
976 r
= get_block_device_harder("/", &devno
);
978 return log_error_errno(r
, "Failed to determine block device of root file system: %m");
980 r
= get_block_device_harder("/usr", &devno
);
982 return log_error_errno(r
, "Failed to determine block device of /usr file system: %m");
984 log_debug("Neither root nor /usr file system are on a (single) block device.");
989 return enumerate_partitions(devno
);
992 int main(int argc
, char *argv
[]) {
995 if (argc
> 1 && argc
!= 4) {
996 log_error("This program takes three or no arguments.");
1003 log_set_target(LOG_TARGET_SAFE
);
1004 log_parse_environment();
1009 if (detect_container() > 0) {
1010 log_debug("In a container, exiting.");
1011 return EXIT_SUCCESS
;
1014 r
= parse_proc_cmdline(parse_proc_cmdline_item
);
1016 log_warning_errno(r
, "Failed to parse kernel command line, ignoring: %m");
1019 log_debug("Disabled, exiting.");
1020 return EXIT_SUCCESS
;
1023 if (arg_root_enabled
)
1024 r
= add_root_mount();
1034 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;