gpt-auto-generator.c revision cca1dfddd4ce4357113663532696488427cc54e4
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering This file is part of systemd.
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering Copyright 2013 Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering (at your option) any later version.
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering systemd is distributed in the hope that it will be useful, but
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering Lesser General Public License for more details.
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic bool arg_enabled = true;
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmekstatic bool arg_root_enabled = true;
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmekstatic bool arg_root_rw = false;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek _cleanup_fclose_ FILE *f = NULL;
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek log_debug("Adding swap: %s", path);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering name = unit_name_from_path(path, ".swap");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering unit = strjoin(arg_dest, "/", name, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to create unit file %s: %m", unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek "Description=Swap Partition\n"
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek "Documentation=man:systemd-gpt-auto-generator(8)\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to write unit file %s: %m", unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to create symlink %s: %m", lnk);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int add_cryptsetup(const char *id, const char *what, bool rw, char **device) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_free_ char *e = NULL, *n = NULL, *p = NULL, *d = NULL, *to = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering d = unit_name_from_path(what, ".device");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering n = unit_name_build("systemd-cryptsetup", e, ".service");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to create unit file %s: %m", p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Description=Cryptography Setup for %%I\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "DefaultDependencies=no\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Conflicts=umount.target\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "BindsTo=dev-mapper-%%i.device %s\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Before=umount.target cryptsetup.target\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "IgnoreOnIsolate=true\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "After=systemd-readahead-collect.service systemd-readahead-replay.service\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Type=oneshot\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "RemainAfterExit=yes\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "TimeoutSec=0\n" /* the binary handles timeouts anyway */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '' '%s'\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to write file %s: %m", p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering to = strjoin(arg_dest, "/", d, ".wants/", n, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to create symlink %s: %m", to);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to create symlink %s: %m", to);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to create symlink %s: %m", to);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf", NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "JobTimeoutSec=0\n"); /* the binary handles timeouts anyway */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to write device drop-in: %s", strerror(-r));
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *post) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_free_ char *unit = NULL, *lnk = NULL, *crypto_what = NULL, *p = NULL;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering log_debug("Adding %s: %s %s", where, what, strna(fstype));
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = add_cryptsetup(id, what, rw, &crypto_what);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering unit = unit_name_from_path(where, ".mount");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to create unit file %s: %m", unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Description=%s\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Documentation=man:systemd-gpt-auto-generator(8)\n",
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = generator_write_fsck_deps(f, arg_dest, what, where, fstype);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fprintf(f, "Options=%s\n", rw ? "rw" : "ro");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to write unit file %s: %m", p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering lnk = strjoin(arg_dest, "/", post, ".requires/", unit, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to create symlink %s: %m", lnk);
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek _cleanup_blkid_free_probe_ blkid_probe b = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (path_is_mount_point(where, true) <= 0 &&
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_debug("%s already populated, ignoring.", where);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering /* Let's check the partition type here, so that we know
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering * whether to do LUKS magic. */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to allocate prober: %m");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (r == -2 || r == 1) /* no result or uncertain */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering else if (r != 0) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to probe %s: %m", what);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int enumerate_partitions(dev_t devnum) {
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek _cleanup_udev_device_unref_ struct udev_device *d = NULL;
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek _cleanup_blkid_free_probe_ blkid_probe b = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_udev_unref_ struct udev *udev = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_free_ char *home = NULL, *srv = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering d = udev_device_new_from_devnum(udev, 'b', devnum);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering /* Does it have a devtype? */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering devtype = udev_device_get_devtype(parent);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering /* Is this a disk or a partition? We only care for disks... */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering /* Does it have a device node? */
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (r == -2 || r == 1) /* no result or uncertain */
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering else if (r != 0) {
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering log_error("Failed to probe %s: %m", node);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering log_error("Failed to determine partition table type of %s: %m", node);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering /* We only do this all for GPT... */
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering log_error("Failed to list partitions of %s: %m", node);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = udev_enumerate_add_match_parent(e, parent);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = udev_enumerate_add_match_subsystem(e, "block");
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek r = udev_enumerate_scan_devices(e);
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek log_error("Failed to enumerate partitions on %s: %s", node, strerror(-r));
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering first = udev_enumerate_get_list_entry(e);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_udev_device_unref_ struct udev_device *q;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering unsigned long long flags;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering pp = blkid_partlist_devno_to_partition(pl, qn);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering /* Ignore partitions that are not marked for automatic
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering * mounting on discovery */
if (!stype)
if (!home)
return log_oom();
if (!srv)
return log_oom();
if (home) {
if (srv) {
k = probe_and_add_mount("srv", srv, "/srv", srv_rw, "Server Data Partition", SPECIAL_LOCAL_FS_TARGET);
if (fd < 0)
return -errno;
return -errno;
return -errno;
return -errno;
return -ENODEV;
return -ENODEV;
return -ENODEV;
return -errno;
return -errno;
arg_enabled = r;
arg_root_rw = true;
arg_root_rw = false;
static int add_root_mount(void) {
#ifdef ENABLE_EFI
if (!is_efi_boot()) {
if (r == -ENOENT) {
return add_mount(
"/dev/gpt-auto-root",
NULL,
static int add_mounts(void) {
return EXIT_FAILURE;
log_open();
return EXIT_SUCCESS;
return EXIT_FAILURE;
if (!arg_enabled) {
return EXIT_SUCCESS;
if (arg_root_enabled)
r = add_root_mount();
if (!in_initrd()) {
k = add_mounts();