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 "blkid-util.h"
42 #include "btrfs-util.h"
44 static const char *arg_dest
= "/tmp";
45 static bool arg_enabled
= true;
46 static bool arg_root_enabled
= true;
47 static bool arg_root_rw
= false;
49 static int add_cryptsetup(const char *id
, const char *what
, bool rw
, char **device
) {
50 _cleanup_free_
char *e
= NULL
, *n
= NULL
, *p
= NULL
, *d
= NULL
, *to
= NULL
;
51 _cleanup_fclose_
FILE *f
= NULL
;
59 r
= unit_name_from_path(what
, ".device", &d
);
61 return log_error_errno(r
, "Failed to generate unit name: %m");
63 e
= unit_name_escape(id
);
67 r
= unit_name_build("systemd-cryptsetup", e
, ".service", &n
);
69 return log_error_errno(r
, "Failed to generate unit name: %m");
71 p
= strjoin(arg_dest
, "/", n
, NULL
);
77 return log_error_errno(errno
, "Failed to create unit file %s: %m", p
);
80 "# Automatically generated by systemd-gpt-auto-generator\n\n"
82 "Description=Cryptography Setup for %%I\n"
83 "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
84 "DefaultDependencies=no\n"
85 "Conflicts=umount.target\n"
86 "BindsTo=dev-mapper-%%i.device %s\n"
87 "Before=umount.target cryptsetup.target\n"
89 "IgnoreOnIsolate=true\n"
92 "RemainAfterExit=yes\n"
93 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
94 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH
" attach '%s' '%s' '' '%s'\n"
95 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH
" detach '%s'\n",
97 id
, what
, rw
? "" : "read-only",
100 r
= fflush_and_check(f
);
102 return log_error_errno(r
, "Failed to write file %s: %m", p
);
104 from
= strjoina("../", n
);
106 to
= strjoin(arg_dest
, "/", d
, ".wants/", n
, NULL
);
110 mkdir_parents_label(to
, 0755);
111 if (symlink(from
, to
) < 0)
112 return log_error_errno(errno
, "Failed to create symlink %s: %m", to
);
115 to
= strjoin(arg_dest
, "/cryptsetup.target.requires/", 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
, "/dev-mapper-", e
, ".device.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 p
= strjoin(arg_dest
, "/dev-mapper-", e
, ".device.d/50-job-timeout-sec-0.conf", NULL
);
137 mkdir_parents_label(p
, 0755);
138 r
= write_string_file(p
,
139 "# Automatically generated by systemd-gpt-auto-generator\n\n"
142 WRITE_STRING_FILE_CREATE
); /* the binary handles timeouts anyway */
144 return log_error_errno(r
, "Failed to write device drop-in: %m");
146 ret
= strappend("/dev/mapper/", id
);
154 static int add_mount(
161 const char *description
,
164 _cleanup_free_
char *unit
= NULL
, *lnk
= NULL
, *crypto_what
= NULL
, *p
= NULL
;
165 _cleanup_fclose_
FILE *f
= NULL
;
173 log_debug("Adding %s: %s %s", where
, what
, strna(fstype
));
175 if (streq_ptr(fstype
, "crypto_LUKS")) {
177 r
= add_cryptsetup(id
, what
, rw
, &crypto_what
);
185 r
= unit_name_from_path(where
, ".mount", &unit
);
187 return log_error_errno(r
, "Failed to generate unit name: %m");
189 p
= strjoin(arg_dest
, "/", unit
, NULL
);
195 return log_error_errno(errno
, "Failed to create unit file %s: %m", unit
);
198 "# Automatically generated by systemd-gpt-auto-generator\n\n"
201 "Documentation=man:systemd-gpt-auto-generator(8)\n",
205 fprintf(f
, "Before=%s\n", post
);
207 r
= generator_write_fsck_deps(f
, arg_dest
, what
, where
, fstype
);
219 fprintf(f
, "Type=%s\n", fstype
);
222 fprintf(f
, "Options=%s,%s\n", options
, rw
? "rw" : "ro");
224 fprintf(f
, "Options=%s\n", rw
? "rw" : "ro");
226 r
= fflush_and_check(f
);
228 return log_error_errno(r
, "Failed to write unit file %s: %m", p
);
231 lnk
= strjoin(arg_dest
, "/", post
, ".requires/", unit
, NULL
);
235 mkdir_parents_label(lnk
, 0755);
236 if (symlink(p
, lnk
) < 0)
237 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
243 static bool path_is_busy(const char *where
) {
246 /* already a mountpoint; generators run during reload */
247 r
= path_is_mount_point(where
, AT_SYMLINK_FOLLOW
);
251 /* the directory might not exist on a stateless system */
258 /* not a mountpoint but it contains files */
259 if (dir_is_empty(where
) <= 0)
265 static int probe_and_add_mount(
270 const char *description
,
273 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
274 const char *fstype
= NULL
;
282 if (path_is_busy(where
)) {
283 log_debug("%s already populated, ignoring.", where
);
287 /* Let's check the partition type here, so that we know
288 * whether to do LUKS magic. */
291 b
= blkid_new_probe_from_filename(what
);
295 log_error_errno(errno
, "Failed to allocate prober: %m");
299 blkid_probe_enable_superblocks(b
, 1);
300 blkid_probe_set_superblocks_flags(b
, BLKID_SUBLKS_TYPE
);
303 r
= blkid_do_safeprobe(b
);
304 if (r
== -2 || r
== 1) /* no result or uncertain */
307 return log_error_errno(errno
?: EIO
, "Failed to probe %s: %m", what
);
309 /* add_mount is OK with fstype being NULL. */
310 (void) blkid_probe_lookup_value(b
, "TYPE", &fstype
, NULL
);
323 static int add_swap(const char *path
) {
324 _cleanup_free_
char *name
= NULL
, *unit
= NULL
, *lnk
= NULL
;
325 _cleanup_fclose_
FILE *f
= NULL
;
330 log_debug("Adding swap: %s", path
);
332 r
= unit_name_from_path(path
, ".swap", &name
);
334 return log_error_errno(r
, "Failed to generate unit name: %m");
336 unit
= strjoin(arg_dest
, "/", name
, NULL
);
340 f
= fopen(unit
, "wxe");
342 return log_error_errno(errno
, "Failed to create unit file %s: %m", unit
);
345 "# Automatically generated by systemd-gpt-auto-generator\n\n"
347 "Description=Swap Partition\n"
348 "Documentation=man:systemd-gpt-auto-generator(8)\n\n"
353 r
= fflush_and_check(f
);
355 return log_error_errno(r
, "Failed to write unit file %s: %m", unit
);
357 lnk
= strjoin(arg_dest
, "/" SPECIAL_SWAP_TARGET
".wants/", name
, NULL
);
361 mkdir_parents_label(lnk
, 0755);
362 if (symlink(unit
, lnk
) < 0)
363 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
369 static int add_automount(
376 const char *description
,
379 _cleanup_free_
char *unit
= NULL
, *lnk
= NULL
;
380 _cleanup_free_
char *opt
, *p
= NULL
;
381 _cleanup_fclose_
FILE *f
= NULL
;
389 opt
= strjoin(options
, ",noauto", NULL
);
391 opt
= strdup("noauto");
406 r
= unit_name_from_path(where
, ".automount", &unit
);
408 return log_error_errno(r
, "Failed to generate unit name: %m");
410 p
= strjoin(arg_dest
, "/", unit
, NULL
);
416 return log_error_errno(errno
, "Failed to create unit file %s: %m", unit
);
419 "# Automatically generated by systemd-gpt-auto-generator\n\n"
422 "Documentation=man:systemd-gpt-auto-generator(8)\n"
425 "TimeoutIdleSec=%lld\n",
428 (unsigned long long)timeout
/ USEC_PER_SEC
);
430 r
= fflush_and_check(f
);
432 return log_error_errno(r
, "Failed to write unit file %s: %m", p
);
434 lnk
= strjoin(arg_dest
, "/" SPECIAL_LOCAL_FS_TARGET
".wants/", unit
, NULL
);
437 mkdir_parents_label(lnk
, 0755);
439 if (symlink(p
, lnk
) < 0)
440 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
445 static int add_boot(const char *what
) {
446 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
447 const char *fstype
= NULL
, *uuid
= NULL
;
448 sd_id128_t id
, type_id
;
453 if (!is_efi_boot()) {
454 log_debug("Not an EFI boot, ignoring /boot.");
459 log_debug("In initrd, ignoring /boot.");
463 if (detect_container() > 0) {
464 log_debug("In a container, ignoring /boot.");
468 if (path_is_busy("/boot")) {
469 log_debug("/boot already populated, ignoring.");
473 r
= efi_loader_get_device_part_uuid(&id
);
475 log_debug("EFI loader partition unknown.");
480 log_error_errno(r
, "Failed to read ESP partition UUID: %m");
485 b
= blkid_new_probe_from_filename(what
);
489 log_error_errno(errno
, "Failed to allocate prober: %m");
493 blkid_probe_enable_partitions(b
, 1);
494 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
497 r
= blkid_do_safeprobe(b
);
498 if (r
== -2 || r
== 1) /* no result or uncertain */
501 return log_error_errno(errno
?: EIO
, "Failed to probe %s: %m", what
);
503 (void) blkid_probe_lookup_value(b
, "TYPE", &fstype
, NULL
);
504 if (!streq(fstype
, "vfat")) {
505 log_debug("Partition for /boot is not a FAT filesystem, ignoring.");
509 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_UUID", &uuid
, NULL
);
511 log_debug_errno(r
, "Partition for /boot does not have a UUID, ignoring. %m");
515 if (sd_id128_from_string(uuid
, &type_id
) < 0) {
516 log_debug("Partition for /boot does not have a valid UUID, ignoring.");
520 if (!sd_id128_equal(type_id
, id
)) {
521 log_debug("Partition for /boot does not appear to be the partition we are booted from.");
525 r
= add_automount("boot",
529 "EFI System Partition Automount",
537 static int add_boot(const char *what
) {
542 static int enumerate_partitions(dev_t devnum
) {
544 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
545 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
546 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
547 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
548 _cleanup_free_
char *boot
= NULL
, *home
= NULL
, *srv
= NULL
;
549 struct udev_list_entry
*first
, *item
;
550 struct udev_device
*parent
= NULL
;
551 const char *name
, *node
, *pttype
, *devtype
;
552 int boot_nr
= -1, home_nr
= -1, srv_nr
= -1;
553 bool home_rw
= true, srv_rw
= true;
562 d
= udev_device_new_from_devnum(udev
, 'b', devnum
);
566 name
= udev_device_get_devnode(d
);
568 name
= udev_device_get_syspath(d
);
570 log_debug("Device %u:%u does not have a name, ignoring.",
571 major(devnum
), minor(devnum
));
575 parent
= udev_device_get_parent(d
);
577 log_debug("%s: not a partitioned device, ignoring.", name
);
581 /* Does it have a devtype? */
582 devtype
= udev_device_get_devtype(parent
);
584 log_debug("%s: parent doesn't have a device type, ignoring.", name
);
588 /* Is this a disk or a partition? We only care for disks... */
589 if (!streq(devtype
, "disk")) {
590 log_debug("%s: parent isn't a raw disk, ignoring.", name
);
594 /* Does it have a device node? */
595 node
= udev_device_get_devnode(parent
);
597 log_debug("%s: parent device does not have device node, ignoring.", name
);
601 log_debug("%s: root device %s.", name
, node
);
603 pn
= udev_device_get_devnum(parent
);
608 b
= blkid_new_probe_from_filename(node
);
613 return log_error_errno(errno
, "%s: failed to allocate prober: %m", node
);
616 blkid_probe_enable_partitions(b
, 1);
617 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
620 r
= blkid_do_safeprobe(b
);
622 return 0; /* no results */
624 log_warning("%s: probe gave ambiguous results, ignoring", node
);
627 return log_error_errno(errno
?: EIO
, "%s: failed to probe: %m", node
);
630 r
= blkid_probe_lookup_value(b
, "PTTYPE", &pttype
, NULL
);
632 return log_error_errno(errno
?: EIO
,
633 "%s: failed to determine partition table type: %m", node
);
635 /* We only do this all for GPT... */
636 if (!streq_ptr(pttype
, "gpt")) {
637 log_debug("%s: not a GPT partition table, ignoring.", node
);
642 pl
= blkid_probe_get_partitions(b
);
647 return log_error_errno(errno
, "%s: failed to list partitions: %m", node
);
650 e
= udev_enumerate_new(udev
);
654 r
= udev_enumerate_add_match_parent(e
, parent
);
658 r
= udev_enumerate_add_match_subsystem(e
, "block");
662 r
= udev_enumerate_scan_devices(e
);
664 return log_error_errno(r
, "%s: failed to enumerate partitions: %m", node
);
666 first
= udev_enumerate_get_list_entry(e
);
667 udev_list_entry_foreach(item
, first
) {
668 _cleanup_udev_device_unref_
struct udev_device
*q
;
669 unsigned long long flags
;
670 const char *stype
, *subnode
;
676 q
= udev_device_new_from_syspath(udev
, udev_list_entry_get_name(item
));
680 qn
= udev_device_get_devnum(q
);
690 subnode
= udev_device_get_devnode(q
);
694 pp
= blkid_partlist_devno_to_partition(pl
, qn
);
698 nr
= blkid_partition_get_partno(pp
);
702 stype
= blkid_partition_get_type_string(pp
);
706 if (sd_id128_from_string(stype
, &type_id
) < 0)
709 flags
= blkid_partition_get_flags(pp
);
711 if (sd_id128_equal(type_id
, GPT_SWAP
)) {
713 if (flags
& GPT_FLAG_NO_AUTO
)
716 if (flags
& GPT_FLAG_READ_ONLY
) {
717 log_debug("%s marked as read-only swap partition, which is bogus. Ignoring.", subnode
);
721 k
= add_swap(subnode
);
725 } else if (sd_id128_equal(type_id
, GPT_ESP
)) {
727 /* We only care for the first /boot partition */
728 if (boot
&& nr
>= boot_nr
)
731 /* Note that we do not honour the "no-auto"
732 * flag for the ESP, as it is often unset, to
733 * hide it from Windows. */
737 r
= free_and_strdup(&boot
, subnode
);
741 } else if (sd_id128_equal(type_id
, GPT_HOME
)) {
743 if (flags
& GPT_FLAG_NO_AUTO
)
746 /* We only care for the first /home partition */
747 if (home
&& nr
>= home_nr
)
751 home_rw
= !(flags
& GPT_FLAG_READ_ONLY
),
753 r
= free_and_strdup(&home
, subnode
);
757 } else if (sd_id128_equal(type_id
, GPT_SRV
)) {
759 if (flags
& GPT_FLAG_NO_AUTO
)
762 /* We only care for the first /srv partition */
763 if (srv
&& nr
>= srv_nr
)
767 srv_rw
= !(flags
& GPT_FLAG_READ_ONLY
),
769 r
= free_and_strdup(&srv
, subnode
);
782 k
= probe_and_add_mount("home", home
, "/home", home_rw
, "Home Partition", SPECIAL_LOCAL_FS_TARGET
);
788 k
= probe_and_add_mount("srv", srv
, "/srv", srv_rw
, "Server Data Partition", SPECIAL_LOCAL_FS_TARGET
);
796 static int get_block_device(const char *path
, dev_t
*dev
) {
803 /* Get's the block device directly backing a file system. If
804 * the block device is encrypted, returns the device mapper
807 if (lstat(path
, &st
))
810 if (major(st
.st_dev
) != 0) {
815 if (statfs(path
, &sfs
) < 0)
818 if (F_TYPE_EQUAL(sfs
.f_type
, BTRFS_SUPER_MAGIC
))
819 return btrfs_get_block_device(path
, dev
);
824 static int get_block_device_harder(const char *path
, dev_t
*dev
) {
825 _cleanup_closedir_
DIR *d
= NULL
;
826 _cleanup_free_
char *p
= NULL
, *t
= NULL
;
827 struct dirent
*de
, *found
= NULL
;
836 /* Gets the backing block device for a file system, and
837 * handles LUKS encrypted file systems, looking for its
838 * immediate parent, if there is one. */
840 r
= get_block_device(path
, &dt
);
844 if (asprintf(&p
, "/sys/dev/block/%u:%u/slaves", major(dt
), minor(dt
)) < 0)
855 FOREACH_DIRENT_ALL(de
, d
, return -errno
) {
857 if (STR_IN_SET(de
->d_name
, ".", ".."))
860 if (!IN_SET(de
->d_type
, DT_LNK
, DT_UNKNOWN
))
863 if (found
) /* Don't try to support multiple backing block devices */
873 q
= strjoina(p
, "/", found
->d_name
, "/dev");
875 r
= read_one_line_file(q
, &t
);
881 if (sscanf(t
, "%u:%u", &maj
, &min
) != 2)
887 *dev
= makedev(maj
, min
);
895 static int parse_proc_cmdline_item(const char *key
, const char *value
) {
900 if (STR_IN_SET(key
, "systemd.gpt_auto", "rd.systemd.gpt_auto") && value
) {
902 r
= parse_boolean(value
);
904 log_warning("Failed to parse gpt-auto switch \"%s\". Ignoring.", value
);
908 } else if (streq(key
, "root") && value
) {
910 /* Disable root disk logic if there's a root= value
911 * specified (unless it happens to be "gpt-auto") */
913 arg_root_enabled
= streq(value
, "gpt-auto");
915 } else if (streq(key
, "rw") && !value
)
917 else if (streq(key
, "ro") && !value
)
923 static int add_root_mount(void) {
928 if (!is_efi_boot()) {
929 log_debug("Not a EFI boot, not creating root mount.");
933 r
= efi_loader_get_device_part_uuid(NULL
);
935 log_debug("EFI loader partition unknown, exiting.");
938 return log_error_errno(r
, "Failed to read ESP partition UUID: %m");
940 /* OK, we have an ESP partition, this is fantastic, so let's
941 * wait for a root device to show up. A udev rule will create
942 * the link for us under the right name. */
946 "/dev/gpt-auto-root",
947 in_initrd() ? "/sysroot" : "/",
952 in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET
: SPECIAL_LOCAL_FS_TARGET
);
958 static int add_mounts(void) {
962 r
= get_block_device_harder("/", &devno
);
964 return log_error_errno(r
, "Failed to determine block device of root file system: %m");
966 r
= get_block_device_harder("/usr", &devno
);
968 return log_error_errno(r
, "Failed to determine block device of /usr file system: %m");
970 log_debug("Neither root nor /usr file system are on a (single) block device.");
975 return enumerate_partitions(devno
);
978 int main(int argc
, char *argv
[]) {
981 if (argc
> 1 && argc
!= 4) {
982 log_error("This program takes three or no arguments.");
989 log_set_target(LOG_TARGET_SAFE
);
990 log_parse_environment();
995 if (detect_container() > 0) {
996 log_debug("In a container, exiting.");
1000 r
= parse_proc_cmdline(parse_proc_cmdline_item
);
1002 log_warning_errno(r
, "Failed to parse kernel command line, ignoring: %m");
1005 log_debug("Disabled, exiting.");
1006 return EXIT_SUCCESS
;
1009 if (arg_root_enabled
)
1010 r
= add_root_mount();
1020 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;