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"
35 #include "fstab-util.h"
36 #include "generator.h"
40 #include "path-util.h"
42 #include "string-util.h"
43 #include "udev-util.h"
44 #include "unit-name.h"
48 static const char *arg_dest
= "/tmp";
49 static bool arg_enabled
= true;
50 static bool arg_root_enabled
= true;
51 static bool arg_root_rw
= false;
53 static int add_cryptsetup(const char *id
, const char *what
, bool rw
, char **device
) {
54 _cleanup_free_
char *e
= NULL
, *n
= NULL
, *p
= NULL
, *d
= NULL
, *to
= NULL
;
55 _cleanup_fclose_
FILE *f
= NULL
;
63 r
= unit_name_from_path(what
, ".device", &d
);
65 return log_error_errno(r
, "Failed to generate unit name: %m");
67 e
= unit_name_escape(id
);
71 r
= unit_name_build("systemd-cryptsetup", e
, ".service", &n
);
73 return log_error_errno(r
, "Failed to generate unit name: %m");
75 p
= strjoin(arg_dest
, "/", n
, NULL
);
81 return log_error_errno(errno
, "Failed to create unit file %s: %m", p
);
84 "# Automatically generated by systemd-gpt-auto-generator\n\n"
86 "Description=Cryptography Setup for %%I\n"
87 "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
88 "DefaultDependencies=no\n"
89 "Conflicts=umount.target\n"
90 "BindsTo=dev-mapper-%%i.device %s\n"
91 "Before=umount.target cryptsetup.target\n"
93 "IgnoreOnIsolate=true\n"
96 "RemainAfterExit=yes\n"
97 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
98 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH
" attach '%s' '%s' '' '%s'\n"
99 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH
" detach '%s'\n",
101 id
, what
, rw
? "" : "read-only",
104 r
= fflush_and_check(f
);
106 return log_error_errno(r
, "Failed to write file %s: %m", p
);
108 from
= strjoina("../", n
);
110 to
= strjoin(arg_dest
, "/", d
, ".wants/", n
, NULL
);
114 mkdir_parents_label(to
, 0755);
115 if (symlink(from
, to
) < 0)
116 return log_error_errno(errno
, "Failed to create symlink %s: %m", to
);
119 to
= strjoin(arg_dest
, "/cryptsetup.target.requires/", n
, NULL
);
123 mkdir_parents_label(to
, 0755);
124 if (symlink(from
, to
) < 0)
125 return log_error_errno(errno
, "Failed to create symlink %s: %m", to
);
128 to
= strjoin(arg_dest
, "/dev-mapper-", e
, ".device.requires/", n
, NULL
);
132 mkdir_parents_label(to
, 0755);
133 if (symlink(from
, to
) < 0)
134 return log_error_errno(errno
, "Failed to create symlink %s: %m", to
);
137 p
= strjoin(arg_dest
, "/dev-mapper-", e
, ".device.d/50-job-timeout-sec-0.conf", NULL
);
141 mkdir_parents_label(p
, 0755);
142 r
= write_string_file(p
,
143 "# Automatically generated by systemd-gpt-auto-generator\n\n"
146 WRITE_STRING_FILE_CREATE
); /* the binary handles timeouts anyway */
148 return log_error_errno(r
, "Failed to write device drop-in: %m");
150 ret
= strappend("/dev/mapper/", id
);
158 static int add_mount(
165 const char *description
,
168 _cleanup_free_
char *unit
= NULL
, *lnk
= NULL
, *crypto_what
= NULL
, *p
= NULL
;
169 _cleanup_fclose_
FILE *f
= NULL
;
177 log_debug("Adding %s: %s %s", where
, what
, strna(fstype
));
179 if (streq_ptr(fstype
, "crypto_LUKS")) {
181 r
= add_cryptsetup(id
, what
, rw
, &crypto_what
);
189 r
= unit_name_from_path(where
, ".mount", &unit
);
191 return log_error_errno(r
, "Failed to generate unit name: %m");
193 p
= strjoin(arg_dest
, "/", unit
, NULL
);
199 return log_error_errno(errno
, "Failed to create unit file %s: %m", unit
);
202 "# Automatically generated by systemd-gpt-auto-generator\n\n"
205 "Documentation=man:systemd-gpt-auto-generator(8)\n",
209 fprintf(f
, "Before=%s\n", post
);
211 r
= generator_write_fsck_deps(f
, arg_dest
, what
, where
, fstype
);
223 fprintf(f
, "Type=%s\n", fstype
);
226 fprintf(f
, "Options=%s,%s\n", options
, rw
? "rw" : "ro");
228 fprintf(f
, "Options=%s\n", rw
? "rw" : "ro");
230 r
= fflush_and_check(f
);
232 return log_error_errno(r
, "Failed to write unit file %s: %m", p
);
235 lnk
= strjoin(arg_dest
, "/", post
, ".requires/", unit
, NULL
);
239 mkdir_parents_label(lnk
, 0755);
240 if (symlink(p
, lnk
) < 0)
241 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
247 static bool path_is_busy(const char *where
) {
250 /* already a mountpoint; generators run during reload */
251 r
= path_is_mount_point(where
, AT_SYMLINK_FOLLOW
);
255 /* the directory might not exist on a stateless system */
262 /* not a mountpoint but it contains files */
263 if (dir_is_empty(where
) <= 0)
269 static int probe_and_add_mount(
274 const char *description
,
277 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
278 const char *fstype
= NULL
;
286 if (path_is_busy(where
)) {
287 log_debug("%s already populated, ignoring.", where
);
291 /* Let's check the partition type here, so that we know
292 * whether to do LUKS magic. */
295 b
= blkid_new_probe_from_filename(what
);
299 log_error_errno(errno
, "Failed to allocate prober: %m");
303 blkid_probe_enable_superblocks(b
, 1);
304 blkid_probe_set_superblocks_flags(b
, BLKID_SUBLKS_TYPE
);
307 r
= blkid_do_safeprobe(b
);
308 if (r
== -2 || r
== 1) /* no result or uncertain */
311 return log_error_errno(errno
?: EIO
, "Failed to probe %s: %m", what
);
313 /* add_mount is OK with fstype being NULL. */
314 (void) blkid_probe_lookup_value(b
, "TYPE", &fstype
, NULL
);
327 static int add_swap(const char *path
) {
328 _cleanup_free_
char *name
= NULL
, *unit
= NULL
, *lnk
= NULL
;
329 _cleanup_fclose_
FILE *f
= NULL
;
334 log_debug("Adding swap: %s", path
);
336 r
= unit_name_from_path(path
, ".swap", &name
);
338 return log_error_errno(r
, "Failed to generate unit name: %m");
340 unit
= strjoin(arg_dest
, "/", name
, NULL
);
344 f
= fopen(unit
, "wxe");
346 return log_error_errno(errno
, "Failed to create unit file %s: %m", unit
);
349 "# Automatically generated by systemd-gpt-auto-generator\n\n"
351 "Description=Swap Partition\n"
352 "Documentation=man:systemd-gpt-auto-generator(8)\n\n"
357 r
= fflush_and_check(f
);
359 return log_error_errno(r
, "Failed to write unit file %s: %m", unit
);
361 lnk
= strjoin(arg_dest
, "/" SPECIAL_SWAP_TARGET
".wants/", name
, NULL
);
365 mkdir_parents_label(lnk
, 0755);
366 if (symlink(unit
, lnk
) < 0)
367 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
373 static int add_automount(
380 const char *description
,
383 _cleanup_free_
char *unit
= NULL
, *lnk
= NULL
;
384 _cleanup_free_
char *opt
, *p
= NULL
;
385 _cleanup_fclose_
FILE *f
= NULL
;
393 opt
= strjoin(options
, ",noauto", NULL
);
395 opt
= strdup("noauto");
410 r
= unit_name_from_path(where
, ".automount", &unit
);
412 return log_error_errno(r
, "Failed to generate unit name: %m");
414 p
= strjoin(arg_dest
, "/", unit
, NULL
);
420 return log_error_errno(errno
, "Failed to create unit file %s: %m", unit
);
423 "# Automatically generated by systemd-gpt-auto-generator\n\n"
426 "Documentation=man:systemd-gpt-auto-generator(8)\n"
429 "TimeoutIdleSec=%lld\n",
432 (unsigned long long)timeout
/ USEC_PER_SEC
);
434 r
= fflush_and_check(f
);
436 return log_error_errno(r
, "Failed to write unit file %s: %m", p
);
438 lnk
= strjoin(arg_dest
, "/" SPECIAL_LOCAL_FS_TARGET
".wants/", unit
, NULL
);
441 mkdir_parents_label(lnk
, 0755);
443 if (symlink(p
, lnk
) < 0)
444 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
449 static int add_boot(const char *what
) {
450 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
451 const char *fstype
= NULL
, *uuid
= NULL
;
452 sd_id128_t id
, type_id
;
457 if (!is_efi_boot()) {
458 log_debug("Not an EFI boot, ignoring /boot.");
463 log_debug("In initrd, ignoring /boot.");
467 if (detect_container() > 0) {
468 log_debug("In a container, ignoring /boot.");
472 /* We create an .automount which is not overridden by the .mount from the fstab generator. */
473 if (fstab_is_mount_point("/boot")) {
474 log_debug("/boot specified in fstab, ignoring.");
478 if (path_is_busy("/boot")) {
479 log_debug("/boot already populated, ignoring.");
483 r
= efi_loader_get_device_part_uuid(&id
);
485 log_debug("EFI loader partition unknown.");
490 log_error_errno(r
, "Failed to read ESP partition UUID: %m");
495 b
= blkid_new_probe_from_filename(what
);
499 log_error_errno(errno
, "Failed to allocate prober: %m");
503 blkid_probe_enable_partitions(b
, 1);
504 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
507 r
= blkid_do_safeprobe(b
);
508 if (r
== -2 || r
== 1) /* no result or uncertain */
511 return log_error_errno(errno
?: EIO
, "Failed to probe %s: %m", what
);
513 (void) blkid_probe_lookup_value(b
, "TYPE", &fstype
, NULL
);
514 if (!streq(fstype
, "vfat")) {
515 log_debug("Partition for /boot is not a FAT filesystem, ignoring.");
519 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_UUID", &uuid
, NULL
);
521 log_debug_errno(r
, "Partition for /boot does not have a UUID, ignoring. %m");
525 if (sd_id128_from_string(uuid
, &type_id
) < 0) {
526 log_debug("Partition for /boot does not have a valid UUID, ignoring.");
530 if (!sd_id128_equal(type_id
, id
)) {
531 log_debug("Partition for /boot does not appear to be the partition we are booted from.");
535 r
= add_automount("boot",
541 "EFI System Partition Automount",
547 static int add_boot(const char *what
) {
552 static int enumerate_partitions(dev_t devnum
) {
554 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
555 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
556 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
557 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
558 _cleanup_free_
char *boot
= NULL
, *home
= NULL
, *srv
= NULL
;
559 struct udev_list_entry
*first
, *item
;
560 struct udev_device
*parent
= NULL
;
561 const char *name
, *node
, *pttype
, *devtype
;
562 int boot_nr
= -1, home_nr
= -1, srv_nr
= -1;
563 bool home_rw
= true, srv_rw
= true;
572 d
= udev_device_new_from_devnum(udev
, 'b', devnum
);
576 name
= udev_device_get_devnode(d
);
578 name
= udev_device_get_syspath(d
);
580 log_debug("Device %u:%u does not have a name, ignoring.",
581 major(devnum
), minor(devnum
));
585 parent
= udev_device_get_parent(d
);
587 log_debug("%s: not a partitioned device, ignoring.", name
);
591 /* Does it have a devtype? */
592 devtype
= udev_device_get_devtype(parent
);
594 log_debug("%s: parent doesn't have a device type, ignoring.", name
);
598 /* Is this a disk or a partition? We only care for disks... */
599 if (!streq(devtype
, "disk")) {
600 log_debug("%s: parent isn't a raw disk, ignoring.", name
);
604 /* Does it have a device node? */
605 node
= udev_device_get_devnode(parent
);
607 log_debug("%s: parent device does not have device node, ignoring.", name
);
611 log_debug("%s: root device %s.", name
, node
);
613 pn
= udev_device_get_devnum(parent
);
618 b
= blkid_new_probe_from_filename(node
);
623 return log_error_errno(errno
, "%s: failed to allocate prober: %m", node
);
626 blkid_probe_enable_partitions(b
, 1);
627 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
630 r
= blkid_do_safeprobe(b
);
632 return 0; /* no results */
634 log_warning("%s: probe gave ambiguous results, ignoring", node
);
637 return log_error_errno(errno
?: EIO
, "%s: failed to probe: %m", node
);
640 r
= blkid_probe_lookup_value(b
, "PTTYPE", &pttype
, NULL
);
642 return log_error_errno(errno
?: EIO
,
643 "%s: failed to determine partition table type: %m", node
);
645 /* We only do this all for GPT... */
646 if (!streq_ptr(pttype
, "gpt")) {
647 log_debug("%s: not a GPT partition table, ignoring.", node
);
652 pl
= blkid_probe_get_partitions(b
);
657 return log_error_errno(errno
, "%s: failed to list partitions: %m", node
);
660 e
= udev_enumerate_new(udev
);
664 r
= udev_enumerate_add_match_parent(e
, parent
);
668 r
= udev_enumerate_add_match_subsystem(e
, "block");
672 r
= udev_enumerate_scan_devices(e
);
674 return log_error_errno(r
, "%s: failed to enumerate partitions: %m", node
);
676 first
= udev_enumerate_get_list_entry(e
);
677 udev_list_entry_foreach(item
, first
) {
678 _cleanup_udev_device_unref_
struct udev_device
*q
;
679 unsigned long long flags
;
680 const char *stype
, *subnode
;
686 q
= udev_device_new_from_syspath(udev
, udev_list_entry_get_name(item
));
690 qn
= udev_device_get_devnum(q
);
700 subnode
= udev_device_get_devnode(q
);
704 pp
= blkid_partlist_devno_to_partition(pl
, qn
);
708 nr
= blkid_partition_get_partno(pp
);
712 stype
= blkid_partition_get_type_string(pp
);
716 if (sd_id128_from_string(stype
, &type_id
) < 0)
719 flags
= blkid_partition_get_flags(pp
);
721 if (sd_id128_equal(type_id
, GPT_SWAP
)) {
723 if (flags
& GPT_FLAG_NO_AUTO
)
726 if (flags
& GPT_FLAG_READ_ONLY
) {
727 log_debug("%s marked as read-only swap partition, which is bogus. Ignoring.", subnode
);
731 k
= add_swap(subnode
);
735 } else if (sd_id128_equal(type_id
, GPT_ESP
)) {
737 /* We only care for the first /boot partition */
738 if (boot
&& nr
>= boot_nr
)
741 /* Note that we do not honour the "no-auto"
742 * flag for the ESP, as it is often unset, to
743 * hide it from Windows. */
747 r
= free_and_strdup(&boot
, subnode
);
751 } else if (sd_id128_equal(type_id
, GPT_HOME
)) {
753 if (flags
& GPT_FLAG_NO_AUTO
)
756 /* We only care for the first /home partition */
757 if (home
&& nr
>= home_nr
)
761 home_rw
= !(flags
& GPT_FLAG_READ_ONLY
),
763 r
= free_and_strdup(&home
, subnode
);
767 } else if (sd_id128_equal(type_id
, GPT_SRV
)) {
769 if (flags
& GPT_FLAG_NO_AUTO
)
772 /* We only care for the first /srv partition */
773 if (srv
&& nr
>= srv_nr
)
777 srv_rw
= !(flags
& GPT_FLAG_READ_ONLY
),
779 r
= free_and_strdup(&srv
, subnode
);
792 k
= probe_and_add_mount("home", home
, "/home", home_rw
, "Home Partition", SPECIAL_LOCAL_FS_TARGET
);
798 k
= probe_and_add_mount("srv", srv
, "/srv", srv_rw
, "Server Data Partition", SPECIAL_LOCAL_FS_TARGET
);
806 static int get_block_device(const char *path
, dev_t
*dev
) {
813 /* Get's the block device directly backing a file system. If
814 * the block device is encrypted, returns the device mapper
817 if (lstat(path
, &st
))
820 if (major(st
.st_dev
) != 0) {
825 if (statfs(path
, &sfs
) < 0)
828 if (F_TYPE_EQUAL(sfs
.f_type
, BTRFS_SUPER_MAGIC
))
829 return btrfs_get_block_device(path
, dev
);
834 static int get_block_device_harder(const char *path
, dev_t
*dev
) {
835 _cleanup_closedir_
DIR *d
= NULL
;
836 _cleanup_free_
char *p
= NULL
, *t
= NULL
;
837 struct dirent
*de
, *found
= NULL
;
846 /* Gets the backing block device for a file system, and
847 * handles LUKS encrypted file systems, looking for its
848 * immediate parent, if there is one. */
850 r
= get_block_device(path
, &dt
);
854 if (asprintf(&p
, "/sys/dev/block/%u:%u/slaves", major(dt
), minor(dt
)) < 0)
865 FOREACH_DIRENT_ALL(de
, d
, return -errno
) {
867 if (STR_IN_SET(de
->d_name
, ".", ".."))
870 if (!IN_SET(de
->d_type
, DT_LNK
, DT_UNKNOWN
))
873 if (found
) /* Don't try to support multiple backing block devices */
882 q
= strjoina(p
, "/", found
->d_name
, "/dev");
884 r
= read_one_line_file(q
, &t
);
890 if (sscanf(t
, "%u:%u", &maj
, &min
) != 2)
896 *dev
= makedev(maj
, min
);
904 static int parse_proc_cmdline_item(const char *key
, const char *value
) {
909 if (STR_IN_SET(key
, "systemd.gpt_auto", "rd.systemd.gpt_auto") && value
) {
911 r
= parse_boolean(value
);
913 log_warning("Failed to parse gpt-auto switch \"%s\". Ignoring.", value
);
917 } else if (streq(key
, "root") && value
) {
919 /* Disable root disk logic if there's a root= value
920 * specified (unless it happens to be "gpt-auto") */
922 arg_root_enabled
= streq(value
, "gpt-auto");
924 } else if (streq(key
, "rw") && !value
)
926 else if (streq(key
, "ro") && !value
)
932 static int add_root_mount(void) {
937 if (!is_efi_boot()) {
938 log_debug("Not a EFI boot, not creating root mount.");
942 r
= efi_loader_get_device_part_uuid(NULL
);
944 log_debug("EFI loader partition unknown, exiting.");
947 return log_error_errno(r
, "Failed to read ESP partition UUID: %m");
949 /* OK, we have an ESP partition, this is fantastic, so let's
950 * wait for a root device to show up. A udev rule will create
951 * the link for us under the right name. */
955 "/dev/gpt-auto-root",
956 in_initrd() ? "/sysroot" : "/",
961 in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET
: SPECIAL_LOCAL_FS_TARGET
);
967 static int add_mounts(void) {
971 r
= get_block_device_harder("/", &devno
);
973 return log_error_errno(r
, "Failed to determine block device of root file system: %m");
975 r
= get_block_device_harder("/usr", &devno
);
977 return log_error_errno(r
, "Failed to determine block device of /usr file system: %m");
979 log_debug("Neither root nor /usr file system are on a (single) block device.");
984 return enumerate_partitions(devno
);
987 int main(int argc
, char *argv
[]) {
990 if (argc
> 1 && argc
!= 4) {
991 log_error("This program takes three or no arguments.");
998 log_set_target(LOG_TARGET_SAFE
);
999 log_parse_environment();
1004 if (detect_container() > 0) {
1005 log_debug("In a container, exiting.");
1006 return EXIT_SUCCESS
;
1009 r
= parse_proc_cmdline(parse_proc_cmdline_item
);
1011 log_warning_errno(r
, "Failed to parse kernel command line, ignoring: %m");
1014 log_debug("Disabled, exiting.");
1015 return EXIT_SUCCESS
;
1018 if (arg_root_enabled
)
1019 r
= add_root_mount();
1029 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;