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"
45 #include "string-util.h"
46 #include "udev-util.h"
47 #include "unit-name.h"
51 static const char *arg_dest
= "/tmp";
52 static bool arg_enabled
= true;
53 static bool arg_root_enabled
= true;
54 static bool arg_root_rw
= false;
56 static int add_cryptsetup(const char *id
, const char *what
, bool rw
, char **device
) {
57 _cleanup_free_
char *e
= NULL
, *n
= NULL
, *p
= NULL
, *d
= NULL
, *to
= NULL
;
58 _cleanup_fclose_
FILE *f
= NULL
;
66 r
= unit_name_from_path(what
, ".device", &d
);
68 return log_error_errno(r
, "Failed to generate unit name: %m");
70 e
= unit_name_escape(id
);
74 r
= unit_name_build("systemd-cryptsetup", e
, ".service", &n
);
76 return log_error_errno(r
, "Failed to generate unit name: %m");
78 p
= strjoin(arg_dest
, "/", n
, NULL
);
84 return log_error_errno(errno
, "Failed to create unit file %s: %m", p
);
87 "# Automatically generated by systemd-gpt-auto-generator\n\n"
89 "Description=Cryptography Setup for %%I\n"
90 "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
91 "DefaultDependencies=no\n"
92 "Conflicts=umount.target\n"
93 "BindsTo=dev-mapper-%%i.device %s\n"
94 "Before=umount.target cryptsetup.target\n"
96 "IgnoreOnIsolate=true\n"
99 "RemainAfterExit=yes\n"
100 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
101 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH
" attach '%s' '%s' '' '%s'\n"
102 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH
" detach '%s'\n",
104 id
, what
, rw
? "" : "read-only",
107 r
= fflush_and_check(f
);
109 return log_error_errno(r
, "Failed to write file %s: %m", p
);
111 from
= strjoina("../", n
);
113 to
= strjoin(arg_dest
, "/", d
, ".wants/", n
, NULL
);
117 mkdir_parents_label(to
, 0755);
118 if (symlink(from
, to
) < 0)
119 return log_error_errno(errno
, "Failed to create symlink %s: %m", to
);
122 to
= strjoin(arg_dest
, "/cryptsetup.target.requires/", n
, NULL
);
126 mkdir_parents_label(to
, 0755);
127 if (symlink(from
, to
) < 0)
128 return log_error_errno(errno
, "Failed to create symlink %s: %m", to
);
131 to
= strjoin(arg_dest
, "/dev-mapper-", e
, ".device.requires/", n
, NULL
);
135 mkdir_parents_label(to
, 0755);
136 if (symlink(from
, to
) < 0)
137 return log_error_errno(errno
, "Failed to create symlink %s: %m", to
);
140 p
= strjoin(arg_dest
, "/dev-mapper-", e
, ".device.d/50-job-timeout-sec-0.conf", NULL
);
144 mkdir_parents_label(p
, 0755);
145 r
= write_string_file(p
,
146 "# Automatically generated by systemd-gpt-auto-generator\n\n"
149 WRITE_STRING_FILE_CREATE
); /* the binary handles timeouts anyway */
151 return log_error_errno(r
, "Failed to write device drop-in: %m");
153 ret
= strappend("/dev/mapper/", id
);
161 static int add_mount(
168 const char *description
,
171 _cleanup_free_
char *unit
= NULL
, *lnk
= NULL
, *crypto_what
= NULL
, *p
= NULL
;
172 _cleanup_fclose_
FILE *f
= NULL
;
180 log_debug("Adding %s: %s %s", where
, what
, strna(fstype
));
182 if (streq_ptr(fstype
, "crypto_LUKS")) {
184 r
= add_cryptsetup(id
, what
, rw
, &crypto_what
);
192 r
= unit_name_from_path(where
, ".mount", &unit
);
194 return log_error_errno(r
, "Failed to generate unit name: %m");
196 p
= strjoin(arg_dest
, "/", unit
, NULL
);
202 return log_error_errno(errno
, "Failed to create unit file %s: %m", unit
);
205 "# Automatically generated by systemd-gpt-auto-generator\n\n"
208 "Documentation=man:systemd-gpt-auto-generator(8)\n",
212 fprintf(f
, "Before=%s\n", post
);
214 r
= generator_write_fsck_deps(f
, arg_dest
, what
, where
, fstype
);
226 fprintf(f
, "Type=%s\n", fstype
);
229 fprintf(f
, "Options=%s,%s\n", options
, rw
? "rw" : "ro");
231 fprintf(f
, "Options=%s\n", rw
? "rw" : "ro");
233 r
= fflush_and_check(f
);
235 return log_error_errno(r
, "Failed to write unit file %s: %m", p
);
238 lnk
= strjoin(arg_dest
, "/", post
, ".requires/", unit
, NULL
);
242 mkdir_parents_label(lnk
, 0755);
243 if (symlink(p
, lnk
) < 0)
244 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
250 static bool path_is_busy(const char *where
) {
253 /* already a mountpoint; generators run during reload */
254 r
= path_is_mount_point(where
, AT_SYMLINK_FOLLOW
);
258 /* the directory might not exist on a stateless system */
265 /* not a mountpoint but it contains files */
266 if (dir_is_empty(where
) <= 0)
272 static int probe_and_add_mount(
277 const char *description
,
280 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
281 const char *fstype
= NULL
;
289 if (path_is_busy(where
)) {
290 log_debug("%s already populated, ignoring.", where
);
294 /* Let's check the partition type here, so that we know
295 * whether to do LUKS magic. */
298 b
= blkid_new_probe_from_filename(what
);
302 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
) {
453 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
454 const char *fstype
= NULL
, *uuid
= NULL
;
455 sd_id128_t id
, type_id
;
460 if (!is_efi_boot()) {
461 log_debug("Not an EFI boot, ignoring /boot.");
466 log_debug("In initrd, ignoring /boot.");
470 if (detect_container() > 0) {
471 log_debug("In a container, ignoring /boot.");
475 /* We create an .automount which is not overridden by the .mount from the fstab generator. */
476 if (fstab_is_mount_point("/boot")) {
477 log_debug("/boot specified in fstab, ignoring.");
481 if (path_is_busy("/boot")) {
482 log_debug("/boot already populated, ignoring.");
486 r
= efi_loader_get_device_part_uuid(&id
);
488 log_debug("EFI loader partition unknown.");
493 log_error_errno(r
, "Failed to read ESP partition UUID: %m");
498 b
= blkid_new_probe_from_filename(what
);
502 log_error_errno(errno
, "Failed to allocate prober: %m");
506 blkid_probe_enable_partitions(b
, 1);
507 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
510 r
= blkid_do_safeprobe(b
);
511 if (r
== -2 || r
== 1) /* no result or uncertain */
514 return log_error_errno(errno
?: EIO
, "Failed to probe %s: %m", what
);
516 (void) blkid_probe_lookup_value(b
, "TYPE", &fstype
, NULL
);
517 if (!streq(fstype
, "vfat")) {
518 log_debug("Partition for /boot is not a FAT filesystem, ignoring.");
522 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_UUID", &uuid
, NULL
);
524 log_debug_errno(r
, "Partition for /boot does not have a UUID, ignoring. %m");
528 if (sd_id128_from_string(uuid
, &type_id
) < 0) {
529 log_debug("Partition for /boot does not have a valid UUID, ignoring.");
533 if (!sd_id128_equal(type_id
, id
)) {
534 log_debug("Partition for /boot does not appear to be the partition we are booted from.");
538 r
= add_automount("boot",
544 "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
);
645 return log_error_errno(errno
?: EIO
,
646 "%s: failed to determine partition table type: %m", node
);
648 /* We only do this all for GPT... */
649 if (!streq_ptr(pttype
, "gpt")) {
650 log_debug("%s: not a GPT partition table, ignoring.", node
);
655 pl
= blkid_probe_get_partitions(b
);
660 return log_error_errno(errno
, "%s: failed to list partitions: %m", node
);
663 e
= udev_enumerate_new(udev
);
667 r
= udev_enumerate_add_match_parent(e
, parent
);
671 r
= udev_enumerate_add_match_subsystem(e
, "block");
675 r
= udev_enumerate_scan_devices(e
);
677 return log_error_errno(r
, "%s: failed to enumerate partitions: %m", node
);
679 first
= udev_enumerate_get_list_entry(e
);
680 udev_list_entry_foreach(item
, first
) {
681 _cleanup_udev_device_unref_
struct udev_device
*q
;
682 unsigned long long flags
;
683 const char *stype
, *subnode
;
689 q
= udev_device_new_from_syspath(udev
, udev_list_entry_get_name(item
));
693 qn
= udev_device_get_devnum(q
);
703 subnode
= udev_device_get_devnode(q
);
707 pp
= blkid_partlist_devno_to_partition(pl
, qn
);
711 nr
= blkid_partition_get_partno(pp
);
715 stype
= blkid_partition_get_type_string(pp
);
719 if (sd_id128_from_string(stype
, &type_id
) < 0)
722 flags
= blkid_partition_get_flags(pp
);
724 if (sd_id128_equal(type_id
, GPT_SWAP
)) {
726 if (flags
& GPT_FLAG_NO_AUTO
)
729 if (flags
& GPT_FLAG_READ_ONLY
) {
730 log_debug("%s marked as read-only swap partition, which is bogus. Ignoring.", subnode
);
734 k
= add_swap(subnode
);
738 } else if (sd_id128_equal(type_id
, GPT_ESP
)) {
740 /* We only care for the first /boot partition */
741 if (boot
&& nr
>= boot_nr
)
744 /* Note that we do not honour the "no-auto"
745 * flag for the ESP, as it is often unset, to
746 * hide it from Windows. */
750 r
= free_and_strdup(&boot
, subnode
);
754 } else if (sd_id128_equal(type_id
, GPT_HOME
)) {
756 if (flags
& GPT_FLAG_NO_AUTO
)
759 /* We only care for the first /home partition */
760 if (home
&& nr
>= home_nr
)
764 home_rw
= !(flags
& GPT_FLAG_READ_ONLY
),
766 r
= free_and_strdup(&home
, subnode
);
770 } else if (sd_id128_equal(type_id
, GPT_SRV
)) {
772 if (flags
& GPT_FLAG_NO_AUTO
)
775 /* We only care for the first /srv partition */
776 if (srv
&& nr
>= srv_nr
)
780 srv_rw
= !(flags
& GPT_FLAG_READ_ONLY
),
782 r
= free_and_strdup(&srv
, subnode
);
795 k
= probe_and_add_mount("home", home
, "/home", home_rw
, "Home Partition", SPECIAL_LOCAL_FS_TARGET
);
801 k
= probe_and_add_mount("srv", srv
, "/srv", srv_rw
, "Server Data Partition", SPECIAL_LOCAL_FS_TARGET
);
809 static int get_block_device(const char *path
, dev_t
*dev
) {
816 /* Get's the block device directly backing a file system. If
817 * the block device is encrypted, returns the device mapper
820 if (lstat(path
, &st
))
823 if (major(st
.st_dev
) != 0) {
828 if (statfs(path
, &sfs
) < 0)
831 if (F_TYPE_EQUAL(sfs
.f_type
, BTRFS_SUPER_MAGIC
))
832 return btrfs_get_block_device(path
, dev
);
837 static int get_block_device_harder(const char *path
, dev_t
*dev
) {
838 _cleanup_closedir_
DIR *d
= NULL
;
839 _cleanup_free_
char *p
= NULL
, *t
= NULL
;
840 struct dirent
*de
, *found
= NULL
;
849 /* Gets the backing block device for a file system, and
850 * handles LUKS encrypted file systems, looking for its
851 * immediate parent, if there is one. */
853 r
= get_block_device(path
, &dt
);
857 if (asprintf(&p
, "/sys/dev/block/%u:%u/slaves", major(dt
), minor(dt
)) < 0)
868 FOREACH_DIRENT_ALL(de
, d
, return -errno
) {
870 if (STR_IN_SET(de
->d_name
, ".", ".."))
873 if (!IN_SET(de
->d_type
, DT_LNK
, DT_UNKNOWN
))
876 if (found
) /* Don't try to support multiple backing block devices */
885 q
= strjoina(p
, "/", found
->d_name
, "/dev");
887 r
= read_one_line_file(q
, &t
);
893 if (sscanf(t
, "%u:%u", &maj
, &min
) != 2)
899 *dev
= makedev(maj
, min
);
907 static int parse_proc_cmdline_item(const char *key
, const char *value
) {
912 if (STR_IN_SET(key
, "systemd.gpt_auto", "rd.systemd.gpt_auto") && value
) {
914 r
= parse_boolean(value
);
916 log_warning("Failed to parse gpt-auto switch \"%s\". Ignoring.", value
);
920 } else if (streq(key
, "root") && value
) {
922 /* Disable root disk logic if there's a root= value
923 * specified (unless it happens to be "gpt-auto") */
925 arg_root_enabled
= streq(value
, "gpt-auto");
927 } else if (streq(key
, "rw") && !value
)
929 else if (streq(key
, "ro") && !value
)
935 static int add_root_mount(void) {
940 if (!is_efi_boot()) {
941 log_debug("Not a EFI boot, not creating root mount.");
945 r
= efi_loader_get_device_part_uuid(NULL
);
947 log_debug("EFI loader partition unknown, exiting.");
950 return log_error_errno(r
, "Failed to read ESP partition UUID: %m");
952 /* OK, we have an ESP partition, this is fantastic, so let's
953 * wait for a root device to show up. A udev rule will create
954 * the link for us under the right name. */
958 "/dev/gpt-auto-root",
959 in_initrd() ? "/sysroot" : "/",
964 in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET
: SPECIAL_LOCAL_FS_TARGET
);
970 static int add_mounts(void) {
974 r
= get_block_device_harder("/", &devno
);
976 return log_error_errno(r
, "Failed to determine block device of root file system: %m");
978 r
= get_block_device_harder("/usr", &devno
);
980 return log_error_errno(r
, "Failed to determine block device of /usr file system: %m");
982 log_debug("Neither root nor /usr file system are on a (single) block device.");
987 return enumerate_partitions(devno
);
990 int main(int argc
, char *argv
[]) {
993 if (argc
> 1 && argc
!= 4) {
994 log_error("This program takes three or no arguments.");
1001 log_set_target(LOG_TARGET_SAFE
);
1002 log_parse_environment();
1007 if (detect_container() > 0) {
1008 log_debug("In a container, exiting.");
1009 return EXIT_SUCCESS
;
1012 r
= parse_proc_cmdline(parse_proc_cmdline_item
);
1014 log_warning_errno(r
, "Failed to parse kernel command line, ignoring: %m");
1017 log_debug("Disabled, exiting.");
1018 return EXIT_SUCCESS
;
1021 if (arg_root_enabled
)
1022 r
= add_root_mount();
1032 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;