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