gpt-auto-generator.c revision 458a2f85e8ae08c534bf8d030fbeeb791893422b
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;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic bool arg_root_enabled = true;
4b1b14a6a6acb1640596d5e9542829d32989d385Lennart Poetteringstatic bool arg_root_rw = false;
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;
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek _cleanup_fclose_ FILE *f = NULL;
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek r = unit_name_from_path(what, ".device", &d);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to generate unit name: %m");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = unit_name_build("systemd-cryptsetup", e, ".service", &n);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to generate unit name: %m");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno, "Failed to create unit file %s: %m", p);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek "# Automatically generated by systemd-gpt-auto-generator\n\n"
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek "Description=Cryptography Setup for %%I\n"
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek "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"
091526ab20485492124852dcf629787f35816df8Zbigniew Jędrzejewski-Szmek "IgnoreOnIsolate=true\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Type=oneshot\n"
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek "RemainAfterExit=yes\n"
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek "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 return log_error_errno(r, "Failed to write file %s: %m", p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering to = strjoin(arg_dest, "/", d, ".wants/", n, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno, "Failed to create symlink %s: %m", to);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno, "Failed to create symlink %s: %m", to);
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno, "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",
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering WRITE_STRING_FILE_CREATE); /* the binary handles timeouts anyway */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(r, "Failed to write device drop-in: %m");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *post) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_free_ char *unit = NULL, *lnk = NULL, *crypto_what = NULL, *p = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_debug("Adding %s: %s %s", where, what, strna(fstype));
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = add_cryptsetup(id, what, rw, &crypto_what);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = unit_name_from_path(where, ".mount", &unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(r, "Failed to generate unit name: %m");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno, "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,%s\n", options, rw ? "rw" : "ro");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fprintf(f, "Options=%s\n", rw ? "rw" : "ro");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(r, "Failed to write unit file %s: %m", p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering lnk = strjoin(arg_dest, "/", post, ".requires/", unit, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic bool path_is_busy(const char *where) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering /* already a mountpoint; generators run during reload */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = path_is_mount_point(where, AT_SYMLINK_FOLLOW);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering /* the directory might not exist on a stateless system */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering /* not a mountpoint but it contains files */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *post) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_blkid_free_probe_ blkid_probe b = NULL;
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_errno(errno, "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 return log_error_errno(errno ?: EIO, "Failed to probe %s: %m", what);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering /* add_mount is OK with fstype being NULL. */
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = unit_name_from_path(path, ".swap", &name);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(r, "Failed to generate unit name: %m");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering unit = strjoin(arg_dest, "/", name, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Description=Swap Partition\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Documentation=man:systemd-gpt-auto-generator(8)\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(r, "Failed to write unit file %s: %m", unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_free_ char *unit = NULL, *lnk = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = unit_name_from_path(where, ".automount", &unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(r, "Failed to generate unit name: %m");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
c51cf05646a11c65daf65c1123c77efb068f4f7bZbigniew Jędrzejewski-Szmek "Description=%s\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Documentation=man:systemd-gpt-auto-generator(8)\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "[Automount]\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "TimeoutIdleSec=%lld\n",
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering (unsigned long long)timeout / USEC_PER_SEC);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering return log_error_errno(r, "Failed to write unit file %s: %m", p);
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek lnk = strjoin(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".wants/", unit, NULL);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering _cleanup_blkid_free_probe_ blkid_probe b = NULL;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering log_debug("Not an EFI boot, ignoring /boot.");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_debug("In a container, ignoring /boot.");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_debug("/boot already populated, ignoring.");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = efi_loader_get_device_part_uuid(&id);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_debug("EFI loader partition unknown.");
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek log_error_errno(r, "Failed to read ESP partition UUID: %m");
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek b = blkid_new_probe_from_filename(what);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering log_error_errno(errno, "Failed to allocate prober: %m");
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering 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 return log_error_errno(errno ?: EIO, "Failed to probe %s: %m", what);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering log_debug("Partition for /boot is not a FAT filesystem, ignoring.");
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &uuid, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_debug_errno(r, "Partition for /boot does not have a UUID, ignoring. %m");
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (sd_id128_from_string(uuid, &type_id) < 0) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_debug("Partition for /boot does not have a valid UUID, ignoring.");
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering log_debug("Partition for /boot does not appear to be the partition we are booted from.");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "EFI System Partition Automount",
if (!udev)
return log_oom();
return log_oom();
if (!name)
if (!name) {
if (!parent) {
if (!devtype) {
if (!node) {
errno = 0;
if (errno == 0)
return log_oom();
errno = 0;
r = blkid_do_safeprobe(b);
errno = 0;
errno = 0;
if (!pl) {
if (errno == 0)
return log_oom();
return log_oom();
return log_oom();
return log_oom();
r = udev_enumerate_scan_devices(e);
int nr;
if (!subnode)
if (!pp)
if (nr < 0)
if (!stype)
unsigned long long flags;
return log_oom();
unsigned long long flags;
return log_oom();
unsigned long long flags;
return log_oom();
if (boot) {
if (home) {
if (srv) {
k = probe_and_add_mount("srv", srv, "/srv", srv_rw, "Server Data Partition", SPECIAL_LOCAL_FS_TARGET);
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,
NULL,
static int add_mounts(void) {
return EXIT_FAILURE;
log_open();
return EXIT_SUCCESS;
if (!arg_enabled) {
return EXIT_SUCCESS;
if (arg_root_enabled)
r = add_root_mount();
if (!in_initrd()) {
k = add_mounts();