2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include <blkid/blkid.h>
22 #include <sys/statfs.h>
28 #include "alloc-util.h"
29 #include "blkid-util.h"
30 #include "btrfs-util.h"
31 #include "dirent-util.h"
35 #include "fstab-util.h"
36 #include "generator.h"
40 #include "mount-util.h"
41 #include "parse-util.h"
42 #include "path-util.h"
43 #include "proc-cmdline.h"
45 #include "stat-util.h"
46 #include "string-util.h"
47 #include "udev-util.h"
48 #include "unit-name.h"
52 static const char *arg_dest
= "/tmp";
53 static bool arg_enabled
= true;
54 static bool arg_root_enabled
= true;
55 static bool arg_root_rw
= false;
57 static int add_cryptsetup(const char *id
, const char *what
, bool rw
, char **device
) {
58 _cleanup_free_
char *e
= NULL
, *n
= NULL
, *p
= NULL
, *d
= NULL
, *to
= NULL
;
59 _cleanup_fclose_
FILE *f
= NULL
;
67 r
= unit_name_from_path(what
, ".device", &d
);
69 return log_error_errno(r
, "Failed to generate unit name: %m");
71 e
= unit_name_escape(id
);
75 r
= unit_name_build("systemd-cryptsetup", e
, ".service", &n
);
77 return log_error_errno(r
, "Failed to generate unit name: %m");
79 p
= strjoin(arg_dest
, "/", n
, NULL
);
85 return log_error_errno(errno
, "Failed to create unit file %s: %m", p
);
88 "# Automatically generated by systemd-gpt-auto-generator\n\n"
90 "Description=Cryptography Setup for %%I\n"
91 "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
92 "DefaultDependencies=no\n"
93 "Conflicts=umount.target\n"
94 "BindsTo=dev-mapper-%%i.device %s\n"
95 "Before=umount.target cryptsetup.target\n"
97 "IgnoreOnIsolate=true\n"
100 "RemainAfterExit=yes\n"
101 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
102 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH
" attach '%s' '%s' '' '%s'\n"
103 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH
" detach '%s'\n",
105 id
, what
, rw
? "" : "read-only",
108 r
= fflush_and_check(f
);
110 return log_error_errno(r
, "Failed to write file %s: %m", p
);
112 from
= strjoina("../", n
);
114 to
= strjoin(arg_dest
, "/", d
, ".wants/", n
, NULL
);
118 mkdir_parents_label(to
, 0755);
119 if (symlink(from
, to
) < 0)
120 return log_error_errno(errno
, "Failed to create symlink %s: %m", to
);
123 to
= strjoin(arg_dest
, "/cryptsetup.target.requires/", n
, NULL
);
127 mkdir_parents_label(to
, 0755);
128 if (symlink(from
, to
) < 0)
129 return log_error_errno(errno
, "Failed to create symlink %s: %m", to
);
132 to
= strjoin(arg_dest
, "/dev-mapper-", e
, ".device.requires/", n
, NULL
);
136 mkdir_parents_label(to
, 0755);
137 if (symlink(from
, to
) < 0)
138 return log_error_errno(errno
, "Failed to create symlink %s: %m", to
);
141 p
= strjoin(arg_dest
, "/dev-mapper-", e
, ".device.d/50-job-timeout-sec-0.conf", NULL
);
145 mkdir_parents_label(p
, 0755);
146 r
= write_string_file(p
,
147 "# Automatically generated by systemd-gpt-auto-generator\n\n"
150 WRITE_STRING_FILE_CREATE
); /* the binary handles timeouts anyway */
152 return log_error_errno(r
, "Failed to write device drop-in: %m");
154 ret
= strappend("/dev/mapper/", id
);
162 static int add_mount(
169 const char *description
,
172 _cleanup_free_
char *unit
= NULL
, *lnk
= NULL
, *crypto_what
= NULL
, *p
= NULL
;
173 _cleanup_fclose_
FILE *f
= NULL
;
181 log_debug("Adding %s: %s %s", where
, what
, strna(fstype
));
183 if (streq_ptr(fstype
, "crypto_LUKS")) {
185 r
= add_cryptsetup(id
, what
, rw
, &crypto_what
);
193 r
= unit_name_from_path(where
, ".mount", &unit
);
195 return log_error_errno(r
, "Failed to generate unit name: %m");
197 p
= strjoin(arg_dest
, "/", unit
, NULL
);
203 return log_error_errno(errno
, "Failed to create unit file %s: %m", unit
);
206 "# Automatically generated by systemd-gpt-auto-generator\n\n"
209 "Documentation=man:systemd-gpt-auto-generator(8)\n",
213 fprintf(f
, "Before=%s\n", post
);
215 r
= generator_write_fsck_deps(f
, arg_dest
, what
, where
, fstype
);
227 fprintf(f
, "Type=%s\n", fstype
);
230 fprintf(f
, "Options=%s,%s\n", options
, rw
? "rw" : "ro");
232 fprintf(f
, "Options=%s\n", rw
? "rw" : "ro");
234 r
= fflush_and_check(f
);
236 return log_error_errno(r
, "Failed to write unit file %s: %m", p
);
239 lnk
= strjoin(arg_dest
, "/", post
, ".requires/", unit
, NULL
);
243 mkdir_parents_label(lnk
, 0755);
244 if (symlink(p
, lnk
) < 0)
245 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
251 static bool path_is_busy(const char *where
) {
254 /* already a mountpoint; generators run during reload */
255 r
= path_is_mount_point(where
, AT_SYMLINK_FOLLOW
);
259 /* the directory might not exist on a stateless system */
266 /* not a mountpoint but it contains files */
267 if (dir_is_empty(where
) <= 0)
273 static int probe_and_add_mount(
278 const char *description
,
281 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
282 const char *fstype
= NULL
;
290 if (path_is_busy(where
)) {
291 log_debug("%s already populated, ignoring.", where
);
295 /* Let's check the partition type here, so that we know
296 * whether to do LUKS magic. */
299 b
= blkid_new_probe_from_filename(what
);
303 return log_error_errno(errno
, "Failed to allocate prober: %m");
306 blkid_probe_enable_superblocks(b
, 1);
307 blkid_probe_set_superblocks_flags(b
, BLKID_SUBLKS_TYPE
);
310 r
= blkid_do_safeprobe(b
);
311 if (r
== -2 || r
== 1) /* no result or uncertain */
314 return log_error_errno(errno
?: EIO
, "Failed to probe %s: %m", what
);
316 /* add_mount is OK with fstype being NULL. */
317 (void) blkid_probe_lookup_value(b
, "TYPE", &fstype
, NULL
);
330 static int add_swap(const char *path
) {
331 _cleanup_free_
char *name
= NULL
, *unit
= NULL
, *lnk
= NULL
;
332 _cleanup_fclose_
FILE *f
= NULL
;
337 log_debug("Adding swap: %s", path
);
339 r
= unit_name_from_path(path
, ".swap", &name
);
341 return log_error_errno(r
, "Failed to generate unit name: %m");
343 unit
= strjoin(arg_dest
, "/", name
, NULL
);
347 f
= fopen(unit
, "wxe");
349 return log_error_errno(errno
, "Failed to create unit file %s: %m", unit
);
352 "# Automatically generated by systemd-gpt-auto-generator\n\n"
354 "Description=Swap Partition\n"
355 "Documentation=man:systemd-gpt-auto-generator(8)\n\n"
360 r
= fflush_and_check(f
);
362 return log_error_errno(r
, "Failed to write unit file %s: %m", unit
);
364 lnk
= strjoin(arg_dest
, "/" SPECIAL_SWAP_TARGET
".wants/", name
, NULL
);
368 mkdir_parents_label(lnk
, 0755);
369 if (symlink(unit
, lnk
) < 0)
370 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
376 static int add_automount(
383 const char *description
,
386 _cleanup_free_
char *unit
= NULL
, *lnk
= NULL
;
387 _cleanup_free_
char *opt
, *p
= NULL
;
388 _cleanup_fclose_
FILE *f
= NULL
;
396 opt
= strjoin(options
, ",noauto", NULL
);
398 opt
= strdup("noauto");
413 r
= unit_name_from_path(where
, ".automount", &unit
);
415 return log_error_errno(r
, "Failed to generate unit name: %m");
417 p
= strjoin(arg_dest
, "/", unit
, NULL
);
423 return log_error_errno(errno
, "Failed to create unit file %s: %m", unit
);
426 "# Automatically generated by systemd-gpt-auto-generator\n\n"
429 "Documentation=man:systemd-gpt-auto-generator(8)\n"
432 "TimeoutIdleSec=%lld\n",
435 (unsigned long long)timeout
/ USEC_PER_SEC
);
437 r
= fflush_and_check(f
);
439 return log_error_errno(r
, "Failed to write unit file %s: %m", p
);
441 lnk
= strjoin(arg_dest
, "/" SPECIAL_LOCAL_FS_TARGET
".wants/", unit
, NULL
);
444 mkdir_parents_label(lnk
, 0755);
446 if (symlink(p
, lnk
) < 0)
447 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
452 static int add_boot(const char *what
) {
459 log_debug("In initrd, ignoring the ESP.");
463 if (detect_container() > 0) {
464 log_debug("In a container, ignoring the ESP.");
468 /* If /efi exists we'll use that. Otherwise we'll use /boot, as that's usually the better choice */
469 esp
= access("/efi/", F_OK
) >= 0 ? "/efi" : "/boot";
471 /* We create an .automount which is not overridden by the .mount from the fstab generator. */
472 if (fstab_is_mount_point(esp
)) {
473 log_debug("%s specified in fstab, ignoring.", esp
);
477 if (path_is_busy(esp
)) {
478 log_debug("%s already populated, ignoring.", esp
);
483 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
484 const char *fstype
= NULL
, *uuid_string
= NULL
;
485 sd_id128_t loader_uuid
, part_uuid
;
487 /* If this is an EFI boot, be extra careful, and only mount the ESP if it was the ESP used for booting. */
489 r
= efi_loader_get_device_part_uuid(&loader_uuid
);
491 log_debug("EFI loader partition unknown.");
495 return log_error_errno(r
, "Failed to read ESP partition UUID: %m");
498 b
= blkid_new_probe_from_filename(what
);
502 return log_error_errno(errno
, "Failed to allocate prober: %m");
505 blkid_probe_enable_partitions(b
, 1);
506 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
509 r
= blkid_do_safeprobe(b
);
510 if (r
== -2 || r
== 1) /* no result or uncertain */
513 return log_error_errno(errno
?: EIO
, "Failed to probe %s: %m", what
);
515 (void) blkid_probe_lookup_value(b
, "TYPE", &fstype
, NULL
);
516 if (!streq_ptr(fstype
, "vfat")) {
517 log_debug("Partition for %s is not a FAT filesystem, ignoring.", esp
);
522 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_UUID", &uuid_string
, NULL
);
524 log_debug_errno(errno
, "Partition for %s does not have a UUID, ignoring.", esp
);
528 if (sd_id128_from_string(uuid_string
, &part_uuid
) < 0) {
529 log_debug("Partition for %s does not have a valid UUID, ignoring.", esp
);
533 if (!sd_id128_equal(part_uuid
, loader_uuid
)) {
534 log_debug("Partition for %s does not appear to be the partition we are booted from.", esp
);
538 log_debug("Not an EFI boot, skipping ESP check.");
540 return add_automount("boot",
546 "EFI System Partition Automount",
550 static int add_boot(const char *what
) {
555 static int enumerate_partitions(dev_t devnum
) {
557 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
558 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
559 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
560 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
561 _cleanup_free_
char *boot
= NULL
, *home
= NULL
, *srv
= NULL
;
562 struct udev_list_entry
*first
, *item
;
563 struct udev_device
*parent
= NULL
;
564 const char *name
, *node
, *pttype
, *devtype
;
565 int boot_nr
= -1, home_nr
= -1, srv_nr
= -1;
566 bool home_rw
= true, srv_rw
= true;
575 d
= udev_device_new_from_devnum(udev
, 'b', devnum
);
579 name
= udev_device_get_devnode(d
);
581 name
= udev_device_get_syspath(d
);
583 log_debug("Device %u:%u does not have a name, ignoring.",
584 major(devnum
), minor(devnum
));
588 parent
= udev_device_get_parent(d
);
590 log_debug("%s: not a partitioned device, ignoring.", name
);
594 /* Does it have a devtype? */
595 devtype
= udev_device_get_devtype(parent
);
597 log_debug("%s: parent doesn't have a device type, ignoring.", name
);
601 /* Is this a disk or a partition? We only care for disks... */
602 if (!streq(devtype
, "disk")) {
603 log_debug("%s: parent isn't a raw disk, ignoring.", name
);
607 /* Does it have a device node? */
608 node
= udev_device_get_devnode(parent
);
610 log_debug("%s: parent device does not have device node, ignoring.", name
);
614 log_debug("%s: root device %s.", name
, node
);
616 pn
= udev_device_get_devnum(parent
);
621 b
= blkid_new_probe_from_filename(node
);
626 return log_error_errno(errno
, "%s: failed to allocate prober: %m", node
);
629 blkid_probe_enable_partitions(b
, 1);
630 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
633 r
= blkid_do_safeprobe(b
);
635 return 0; /* no results */
637 log_warning("%s: probe gave ambiguous results, ignoring.", node
);
640 return log_error_errno(errno
?: EIO
, "%s: failed to probe: %m", node
);
643 r
= blkid_probe_lookup_value(b
, "PTTYPE", &pttype
, NULL
);
646 return 0; /* No partition table found. */
648 return log_error_errno(errno
, "%s: failed to determine partition table type: %m", node
);
651 /* We only do this all for GPT... */
652 if (!streq_ptr(pttype
, "gpt")) {
653 log_debug("%s: not a GPT partition table, ignoring.", node
);
658 pl
= blkid_probe_get_partitions(b
);
663 return log_error_errno(errno
, "%s: failed to list partitions: %m", node
);
666 e
= udev_enumerate_new(udev
);
670 r
= udev_enumerate_add_match_parent(e
, parent
);
674 r
= udev_enumerate_add_match_subsystem(e
, "block");
678 r
= udev_enumerate_scan_devices(e
);
680 return log_error_errno(r
, "%s: failed to enumerate partitions: %m", node
);
682 first
= udev_enumerate_get_list_entry(e
);
683 udev_list_entry_foreach(item
, first
) {
684 _cleanup_udev_device_unref_
struct udev_device
*q
;
685 unsigned long long flags
;
686 const char *stype
, *subnode
;
692 q
= udev_device_new_from_syspath(udev
, udev_list_entry_get_name(item
));
696 qn
= udev_device_get_devnum(q
);
706 subnode
= udev_device_get_devnode(q
);
710 pp
= blkid_partlist_devno_to_partition(pl
, qn
);
714 nr
= blkid_partition_get_partno(pp
);
718 stype
= blkid_partition_get_type_string(pp
);
722 if (sd_id128_from_string(stype
, &type_id
) < 0)
725 flags
= blkid_partition_get_flags(pp
);
727 if (sd_id128_equal(type_id
, GPT_SWAP
)) {
729 if (flags
& GPT_FLAG_NO_AUTO
)
732 if (flags
& GPT_FLAG_READ_ONLY
) {
733 log_debug("%s marked as read-only swap partition, which is bogus. Ignoring.", subnode
);
737 k
= add_swap(subnode
);
741 } else if (sd_id128_equal(type_id
, GPT_ESP
)) {
743 /* We only care for the first /boot partition */
744 if (boot
&& nr
>= boot_nr
)
747 /* Note that we do not honour the "no-auto"
748 * flag for the ESP, as it is often unset, to
749 * hide it from Windows. */
753 r
= free_and_strdup(&boot
, subnode
);
757 } else if (sd_id128_equal(type_id
, GPT_HOME
)) {
759 if (flags
& GPT_FLAG_NO_AUTO
)
762 /* We only care for the first /home partition */
763 if (home
&& nr
>= home_nr
)
767 home_rw
= !(flags
& GPT_FLAG_READ_ONLY
),
769 r
= free_and_strdup(&home
, subnode
);
773 } else if (sd_id128_equal(type_id
, GPT_SRV
)) {
775 if (flags
& GPT_FLAG_NO_AUTO
)
778 /* We only care for the first /srv partition */
779 if (srv
&& nr
>= srv_nr
)
783 srv_rw
= !(flags
& GPT_FLAG_READ_ONLY
),
785 r
= free_and_strdup(&srv
, subnode
);
798 k
= probe_and_add_mount("home", home
, "/home", home_rw
, "Home Partition", SPECIAL_LOCAL_FS_TARGET
);
804 k
= probe_and_add_mount("srv", srv
, "/srv", srv_rw
, "Server Data Partition", SPECIAL_LOCAL_FS_TARGET
);
812 static int get_block_device(const char *path
, dev_t
*dev
) {
819 /* Get's the block device directly backing a file system. If
820 * the block device is encrypted, returns the device mapper
823 if (lstat(path
, &st
))
826 if (major(st
.st_dev
) != 0) {
831 if (statfs(path
, &sfs
) < 0)
834 if (F_TYPE_EQUAL(sfs
.f_type
, BTRFS_SUPER_MAGIC
))
835 return btrfs_get_block_device(path
, dev
);
840 static int get_block_device_harder(const char *path
, dev_t
*dev
) {
841 _cleanup_closedir_
DIR *d
= NULL
;
842 _cleanup_free_
char *p
= NULL
, *t
= NULL
;
843 struct dirent
*de
, *found
= NULL
;
852 /* Gets the backing block device for a file system, and
853 * handles LUKS encrypted file systems, looking for its
854 * immediate parent, if there is one. */
856 r
= get_block_device(path
, &dt
);
860 if (asprintf(&p
, "/sys/dev/block/%u:%u/slaves", major(dt
), minor(dt
)) < 0)
871 FOREACH_DIRENT_ALL(de
, d
, return -errno
) {
873 if (STR_IN_SET(de
->d_name
, ".", ".."))
876 if (!IN_SET(de
->d_type
, DT_LNK
, DT_UNKNOWN
))
879 if (found
) /* Don't try to support multiple backing block devices */
888 q
= strjoina(p
, "/", found
->d_name
, "/dev");
890 r
= read_one_line_file(q
, &t
);
896 if (sscanf(t
, "%u:%u", &maj
, &min
) != 2)
902 *dev
= makedev(maj
, min
);
910 static int parse_proc_cmdline_item(const char *key
, const char *value
, void *data
) {
915 if (STR_IN_SET(key
, "systemd.gpt_auto", "rd.systemd.gpt_auto") && value
) {
917 r
= parse_boolean(value
);
919 log_warning("Failed to parse gpt-auto switch \"%s\". Ignoring.", value
);
923 } else if (streq(key
, "root") && value
) {
925 /* Disable root disk logic if there's a root= value
926 * specified (unless it happens to be "gpt-auto") */
928 arg_root_enabled
= streq(value
, "gpt-auto");
930 } else if (streq(key
, "rw") && !value
)
932 else if (streq(key
, "ro") && !value
)
938 static int add_root_mount(void) {
943 if (!is_efi_boot()) {
944 log_debug("Not a EFI boot, not creating root mount.");
948 r
= efi_loader_get_device_part_uuid(NULL
);
950 log_debug("EFI loader partition unknown, exiting.");
953 return log_error_errno(r
, "Failed to read ESP partition UUID: %m");
955 /* OK, we have an ESP partition, this is fantastic, so let's
956 * wait for a root device to show up. A udev rule will create
957 * the link for us under the right name. */
960 r
= generator_write_initrd_root_device_deps(arg_dest
, "/dev/gpt-auto-root");
967 "/dev/gpt-auto-root",
968 in_initrd() ? "/sysroot" : "/",
973 in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET
: SPECIAL_LOCAL_FS_TARGET
);
979 static int add_mounts(void) {
983 r
= get_block_device_harder("/", &devno
);
985 return log_error_errno(r
, "Failed to determine block device of root file system: %m");
987 r
= get_block_device_harder("/usr", &devno
);
989 return log_error_errno(r
, "Failed to determine block device of /usr file system: %m");
991 log_debug("Neither root nor /usr file system are on a (single) block device.");
996 return enumerate_partitions(devno
);
999 int main(int argc
, char *argv
[]) {
1002 if (argc
> 1 && argc
!= 4) {
1003 log_error("This program takes three or no arguments.");
1004 return EXIT_FAILURE
;
1010 log_set_target(LOG_TARGET_SAFE
);
1011 log_parse_environment();
1016 if (detect_container() > 0) {
1017 log_debug("In a container, exiting.");
1018 return EXIT_SUCCESS
;
1021 r
= parse_proc_cmdline(parse_proc_cmdline_item
, NULL
, false);
1023 log_warning_errno(r
, "Failed to parse kernel command line, ignoring: %m");
1026 log_debug("Disabled, exiting.");
1027 return EXIT_SUCCESS
;
1030 if (arg_root_enabled
)
1031 r
= add_root_mount();
1041 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;