gpt-auto-generator.c revision 458a2f85e8ae08c534bf8d030fbeeb791893422b
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering/***
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering This file is part of systemd.
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering Copyright 2013 Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart 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
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
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 Poettering***/
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include <unistd.h>
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include <stdlib.h>
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include <sys/statfs.h>
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include <blkid/blkid.h>
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "sd-id128.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "libudev.h"
4b357e15876b730343db08719c877fdb45b6ad42Michael Marineau#include "path-util.h"
4b357e15876b730343db08719c877fdb45b6ad42Michael Marineau#include "util.h"
4b357e15876b730343db08719c877fdb45b6ad42Michael Marineau#include "mkdir.h"
4b357e15876b730343db08719c877fdb45b6ad42Michael Marineau#include "missing.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "udev-util.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "special.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "unit-name.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "virt.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "generator.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "gpt.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "fileio.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "efivars.h"
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek#include "blkid-util.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "btrfs-util.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic const char *arg_dest = "/tmp";
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic bool arg_enabled = true;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic bool arg_root_enabled = true;
4b1b14a6a6acb1640596d5e9542829d32989d385Lennart Poetteringstatic bool arg_root_rw = false;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
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;
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek char *from, *ret;
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek int r;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering assert(id);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek assert(what);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek assert(device);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek r = unit_name_from_path(what, ".device", &d);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek if (r < 0)
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to generate unit name: %m");
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek e = unit_name_escape(id);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!e)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = unit_name_build("systemd-cryptsetup", e, ".service", &n);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (r < 0)
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to generate unit name: %m");
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering p = strjoin(arg_dest, "/", n, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!p)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering f = fopen(p, "wxe");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!f)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno, "Failed to create unit file %s: %m", p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek fprintf(f,
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek "# Automatically generated by systemd-gpt-auto-generator\n\n"
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek "[Unit]\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"
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek "After=%s\n"
091526ab20485492124852dcf629787f35816df8Zbigniew Jędrzejewski-Szmek "IgnoreOnIsolate=true\n"
091526ab20485492124852dcf629787f35816df8Zbigniew Jędrzejewski-Szmek "[Service]\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 d, d,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering id, what, rw ? "" : "read-only",
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek id);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = fflush_and_check(f);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (r < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(r, "Failed to write file %s: %m", p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering from = strjoina("../", n);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering to = strjoin(arg_dest, "/", d, ".wants/", n, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!to)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek mkdir_parents_label(to, 0755);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (symlink(from, to) < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno, "Failed to create symlink %s: %m", to);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering free(to);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!to)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering mkdir_parents_label(to, 0755);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (symlink(from, to) < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno, "Failed to create symlink %s: %m", to);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering free(to);
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek if (!to)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek mkdir_parents_label(to, 0755);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (symlink(from, to) < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno, "Failed to create symlink %s: %m", to);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering free(p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf", NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!p)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering mkdir_parents_label(p, 0755);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = write_string_file(p,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "[Unit]\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "JobTimeoutSec=0\n",
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering WRITE_STRING_FILE_CREATE); /* the binary handles timeouts anyway */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (r < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(r, "Failed to write device drop-in: %m");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering ret = strappend("/dev/mapper/", id);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!ret)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering *device = ret;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering}
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int add_mount(
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *id,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *what,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *where,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *fstype,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering bool rw,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *options,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *description,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *post) {
ee530d8b73246f29781bd54a707ca75c7ef5a6cbLennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_free_ char *unit = NULL, *lnk = NULL, *crypto_what = NULL, *p = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering int r;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering assert(id);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering assert(what);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering assert(where);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering assert(description);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_debug("Adding %s: %s %s", where, what, strna(fstype));
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (streq_ptr(fstype, "crypto_LUKS")) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = add_cryptsetup(id, what, rw, &crypto_what);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (r < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return r;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering what = crypto_what;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fstype = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = unit_name_from_path(where, ".mount", &unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (r < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(r, "Failed to generate unit name: %m");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering p = strjoin(arg_dest, "/", unit, NULL);
4b1b14a6a6acb1640596d5e9542829d32989d385Lennart Poettering if (!p)
4b1b14a6a6acb1640596d5e9542829d32989d385Lennart Poettering return log_oom();
4b1b14a6a6acb1640596d5e9542829d32989d385Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering f = fopen(p, "wxe");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!f)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fprintf(f,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "[Unit]\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Description=%s\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Documentation=man:systemd-gpt-auto-generator(8)\n",
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering description);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (post)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fprintf(f, "Before=%s\n", post);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = generator_write_fsck_deps(f, arg_dest, what, where, fstype);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (r < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return r;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fprintf(f,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "[Mount]\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "What=%s\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Where=%s\n",
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering what, where);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (fstype)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fprintf(f, "Type=%s\n", fstype);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (options)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fprintf(f, "Options=%s,%s\n", options, rw ? "rw" : "ro");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering else
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fprintf(f, "Options=%s\n", rw ? "rw" : "ro");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = fflush_and_check(f);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (r < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(r, "Failed to write unit file %s: %m", p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (post) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering lnk = strjoin(arg_dest, "/", post, ".requires/", unit, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!lnk)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering mkdir_parents_label(lnk, 0755);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (symlink(p, lnk) < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering}
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic bool path_is_busy(const char *where) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering int r;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering /* already a mountpoint; generators run during reload */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = path_is_mount_point(where, AT_SYMLINK_FOLLOW);
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek if (r > 0)
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek return false;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering /* the directory might not exist on a stateless system */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (r == -ENOENT)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return false;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (r < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return true;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering /* not a mountpoint but it contains files */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (dir_is_empty(where) <= 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return true;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return false;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering}
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int probe_and_add_mount(
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *id,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *what,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *where,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering bool rw,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *description,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *post) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_blkid_free_probe_ blkid_probe b = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *fstype = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering int r;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
d98cc1c019651b895464161072894a02cc43daabZbigniew Jędrzejewski-Szmek assert(id);
d98cc1c019651b895464161072894a02cc43daabZbigniew Jędrzejewski-Szmek assert(what);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering assert(where);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering assert(description);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (path_is_busy(where)) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_debug("%s already populated, ignoring.", where);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering /* Let's check the partition type here, so that we know
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering * whether to do LUKS magic. */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering errno = 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering b = blkid_new_probe_from_filename(what);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!b) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (errno == 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error_errno(errno, "Failed to allocate prober: %m");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return -errno;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering blkid_probe_enable_superblocks(b, 1);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering errno = 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = blkid_do_safeprobe(b);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (r == -2 || r == 1) /* no result or uncertain */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering else if (r != 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno ?: EIO, "Failed to probe %s: %m", what);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering /* add_mount is OK with fstype being NULL. */
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return add_mount(
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering id,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering what,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering where,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fstype,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering rw,
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek NULL,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering description,
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek post);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering}
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int add_swap(const char *path) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering int r;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering assert(path);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_debug("Adding swap: %s", path);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = unit_name_from_path(path, ".swap", &name);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (r < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(r, "Failed to generate unit name: %m");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering unit = strjoin(arg_dest, "/", name, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!unit)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering f = fopen(unit, "wxe");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!f)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fprintf(f,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "[Unit]\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Description=Swap Partition\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Documentation=man:systemd-gpt-auto-generator(8)\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "[Swap]\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "What=%s\n",
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering path);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = fflush_and_check(f);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (r < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(r, "Failed to write unit file %s: %m", unit);
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!lnk)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering mkdir_parents_label(lnk, 0755);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (symlink(unit, lnk) < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering}
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#ifdef ENABLE_EFI
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int add_automount(
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *id,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *what,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *where,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *fstype,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering bool rw,
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek const char *options,
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek const char *description,
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek usec_t timeout) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_free_ char *unit = NULL, *lnk = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_free_ char *opt, *p = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering int r;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering assert(id);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering assert(where);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering assert(description);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (options)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering opt = strjoin(options, ",noauto", NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering else
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering opt = strdup("noauto");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!opt)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = add_mount(id,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering what,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering where,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fstype,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering rw,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering opt,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering description,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (r < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return r;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = unit_name_from_path(where, ".automount", &unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (r < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(r, "Failed to generate unit name: %m");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering p = strjoin(arg_dest, "/", unit, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!p)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering f = fopen(p, "wxe");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!f)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fprintf(f,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "[Unit]\n"
c51cf05646a11c65daf65c1123c77efb068f4f7bZbigniew Jędrzejewski-Szmek "Description=%s\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Documentation=man:systemd-gpt-auto-generator(8)\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "[Automount]\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Where=%s\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "TimeoutIdleSec=%lld\n",
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering description,
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering where,
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering (unsigned long long)timeout / USEC_PER_SEC);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering r = fflush_and_check(f);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (r < 0)
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering return log_error_errno(r, "Failed to write unit file %s: %m", p);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek lnk = strjoin(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".wants/", unit, NULL);
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek if (!lnk)
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering return log_oom();
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering mkdir_parents_label(lnk, 0755);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (symlink(p, lnk) < 0)
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering return 0;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering}
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poetteringstatic int add_boot(const char *what) {
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering _cleanup_blkid_free_probe_ blkid_probe b = NULL;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering const char *fstype = NULL, *uuid = NULL;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering sd_id128_t id, type_id;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering int r;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering assert(what);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek if (!is_efi_boot()) {
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering log_debug("Not an EFI boot, ignoring /boot.");
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering return 0;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering }
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (in_initrd()) {
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering log_debug("In initrd, ignoring /boot.");
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering return 0;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (detect_container(NULL) > 0) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_debug("In a container, ignoring /boot.");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering }
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (path_is_busy("/boot")) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_debug("/boot already populated, ignoring.");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = efi_loader_get_device_part_uuid(&id);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (r == -ENOENT) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_debug("EFI loader partition unknown.");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (r < 0) {
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek log_error_errno(r, "Failed to read ESP partition UUID: %m");
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek return r;
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek }
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek errno = 0;
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek b = blkid_new_probe_from_filename(what);
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek if (!b) {
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (errno == 0)
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering return log_oom();
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering log_error_errno(errno, "Failed to allocate prober: %m");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return -errno;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering blkid_probe_enable_partitions(b, 1);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering errno = 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = blkid_do_safeprobe(b);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (r == -2 || r == 1) /* no result or uncertain */
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering return 0;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering else if (r != 0)
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering return log_error_errno(errno ?: EIO, "Failed to probe %s: %m", what);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (!streq(fstype, "vfat")) {
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering log_debug("Partition for /boot is not a FAT filesystem, ignoring.");
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering return 0;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering }
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &uuid, NULL);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (r != 0) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_debug_errno(r, "Partition for /boot does not have a UUID, ignoring. %m");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
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 return 0;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!sd_id128_equal(type_id, id)) {
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering log_debug("Partition for /boot does not appear to be the partition we are booted from.");
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering return 0;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering r = add_automount("boot",
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering what,
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering "/boot",
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "vfat",
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "EFI System Partition Automount",
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering false,
"umask=0077",
120 * USEC_PER_SEC);
return r;
}
#else
static int add_boot(const char *what) {
return 0;
}
#endif
static int enumerate_partitions(dev_t devnum) {
_cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
_cleanup_udev_device_unref_ struct udev_device *d = NULL;
_cleanup_blkid_free_probe_ blkid_probe b = NULL;
_cleanup_udev_unref_ struct udev *udev = NULL;
_cleanup_free_ char *boot = NULL, *home = NULL, *srv = NULL;
struct udev_list_entry *first, *item;
struct udev_device *parent = NULL;
const char *name, *node, *pttype, *devtype;
int boot_nr = -1, home_nr = -1, srv_nr = -1;
bool home_rw = true, srv_rw = true;
blkid_partlist pl;
int r, k;
dev_t pn;
udev = udev_new();
if (!udev)
return log_oom();
d = udev_device_new_from_devnum(udev, 'b', devnum);
if (!d)
return log_oom();
name = udev_device_get_devnode(d);
if (!name)
name = udev_device_get_syspath(d);
if (!name) {
log_debug("Device %u:%u does not have a name, ignoring.",
major(devnum), minor(devnum));
return 0;
}
parent = udev_device_get_parent(d);
if (!parent) {
log_debug("%s: not a partitioned device, ignoring.", name);
return 0;
}
/* Does it have a devtype? */
devtype = udev_device_get_devtype(parent);
if (!devtype) {
log_debug("%s: parent doesn't have a device type, ignoring.", name);
return 0;
}
/* Is this a disk or a partition? We only care for disks... */
if (!streq(devtype, "disk")) {
log_debug("%s: parent isn't a raw disk, ignoring.", name);
return 0;
}
/* Does it have a device node? */
node = udev_device_get_devnode(parent);
if (!node) {
log_debug("%s: parent device does not have device node, ignoring.", name);
return 0;
}
log_debug("%s: root device %s.", name, node);
pn = udev_device_get_devnum(parent);
if (major(pn) == 0)
return 0;
errno = 0;
b = blkid_new_probe_from_filename(node);
if (!b) {
if (errno == 0)
return log_oom();
return log_error_errno(errno, "%s: failed to allocate prober: %m", node);
}
blkid_probe_enable_partitions(b, 1);
blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
errno = 0;
r = blkid_do_safeprobe(b);
if (r == 1)
return 0; /* no results */
else if (r == -2) {
log_warning("%s: probe gave ambiguous results, ignoring", node);
return 0;
} else if (r != 0)
return log_error_errno(errno ?: EIO, "%s: failed to probe: %m", node);
errno = 0;
r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
if (r != 0)
return log_error_errno(errno ?: EIO,
"%s: failed to determine partition table type: %m", node);
/* We only do this all for GPT... */
if (!streq_ptr(pttype, "gpt")) {
log_debug("%s: not a GPT partition table, ignoring.", node);
return 0;
}
errno = 0;
pl = blkid_probe_get_partitions(b);
if (!pl) {
if (errno == 0)
return log_oom();
return log_error_errno(errno, "%s: failed to list partitions: %m", node);
}
e = udev_enumerate_new(udev);
if (!e)
return log_oom();
r = udev_enumerate_add_match_parent(e, parent);
if (r < 0)
return log_oom();
r = udev_enumerate_add_match_subsystem(e, "block");
if (r < 0)
return log_oom();
r = udev_enumerate_scan_devices(e);
if (r < 0)
return log_error_errno(r, "%s: failed to enumerate partitions: %m", node);
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
_cleanup_udev_device_unref_ struct udev_device *q;
const char *stype, *subnode;
sd_id128_t type_id;
blkid_partition pp;
dev_t qn;
int nr;
q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
if (!q)
continue;
qn = udev_device_get_devnum(q);
if (major(qn) == 0)
continue;
if (qn == devnum)
continue;
if (qn == pn)
continue;
subnode = udev_device_get_devnode(q);
if (!subnode)
continue;
pp = blkid_partlist_devno_to_partition(pl, qn);
if (!pp)
continue;
nr = blkid_partition_get_partno(pp);
if (nr < 0)
continue;
stype = blkid_partition_get_type_string(pp);
if (!stype)
continue;
if (sd_id128_from_string(stype, &type_id) < 0)
continue;
if (sd_id128_equal(type_id, GPT_SWAP)) {
unsigned long long flags;
flags = blkid_partition_get_flags(pp);
if (flags & GPT_FLAG_NO_AUTO)
continue;
if (flags & GPT_FLAG_READ_ONLY) {
log_debug("%s marked as read-only swap partition, which is bogus. Ignoring.", subnode);
continue;
}
k = add_swap(subnode);
if (k < 0)
r = k;
} else if (sd_id128_equal(type_id, GPT_ESP)) {
/* We only care for the first /boot partition */
if (boot && nr >= boot_nr)
continue;
boot_nr = nr;
r = free_and_strdup(&boot, subnode);
if (r < 0)
return log_oom();
} else if (sd_id128_equal(type_id, GPT_HOME)) {
unsigned long long flags;
flags = blkid_partition_get_flags(pp);
if (flags & GPT_FLAG_NO_AUTO)
continue;
/* We only care for the first /home partition */
if (home && nr >= home_nr)
continue;
home_nr = nr;
home_rw = !(flags & GPT_FLAG_READ_ONLY),
r = free_and_strdup(&home, subnode);
if (r < 0)
return log_oom();
} else if (sd_id128_equal(type_id, GPT_SRV)) {
unsigned long long flags;
flags = blkid_partition_get_flags(pp);
if (flags & GPT_FLAG_NO_AUTO)
continue;
/* We only care for the first /srv partition */
if (srv && nr >= srv_nr)
continue;
srv_nr = nr;
srv_rw = !(flags & GPT_FLAG_READ_ONLY),
r = free_and_strdup(&srv, subnode);
if (r < 0)
return log_oom();
}
}
if (boot) {
k = add_boot(boot);
if (k < 0)
r = k;
}
if (home) {
k = probe_and_add_mount("home", home, "/home", home_rw, "Home Partition", SPECIAL_LOCAL_FS_TARGET);
if (k < 0)
r = k;
}
if (srv) {
k = probe_and_add_mount("srv", srv, "/srv", srv_rw, "Server Data Partition", SPECIAL_LOCAL_FS_TARGET);
if (k < 0)
r = k;
}
return r;
}
static int get_block_device(const char *path, dev_t *dev) {
struct stat st;
struct statfs sfs;
assert(path);
assert(dev);
if (lstat(path, &st))
return -errno;
if (major(st.st_dev) != 0) {
*dev = st.st_dev;
return 1;
}
if (statfs(path, &sfs) < 0)
return -errno;
if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
return btrfs_get_block_device(path, dev);
return 0;
}
static int parse_proc_cmdline_item(const char *key, const char *value) {
int r;
assert(key);
if (STR_IN_SET(key, "systemd.gpt_auto", "rd.systemd.gpt_auto") && value) {
r = parse_boolean(value);
if (r < 0)
log_warning("Failed to parse gpt-auto switch \"%s\". Ignoring.", value);
else
arg_enabled = r;
} else if (streq(key, "root") && value) {
/* Disable root disk logic if there's a root= value
* specified (unless it happens to be "gpt-auto") */
arg_root_enabled = streq(value, "gpt-auto");
} else if (streq(key, "rw") && !value)
arg_root_rw = true;
else if (streq(key, "ro") && !value)
arg_root_rw = false;
return 0;
}
static int add_root_mount(void) {
#ifdef ENABLE_EFI
int r;
if (!is_efi_boot()) {
log_debug("Not a EFI boot, not creating root mount.");
return 0;
}
r = efi_loader_get_device_part_uuid(NULL);
if (r == -ENOENT) {
log_debug("EFI loader partition unknown, exiting.");
return 0;
} else if (r < 0)
return log_error_errno(r, "Failed to read ESP partition UUID: %m");
/* OK, we have an ESP partition, this is fantastic, so let's
* wait for a root device to show up. A udev rule will create
* the link for us under the right name. */
return add_mount(
"root",
"/dev/gpt-auto-root",
in_initrd() ? "/sysroot" : "/",
NULL,
arg_root_rw,
NULL,
"Root Partition",
in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET);
#else
return 0;
#endif
}
static int add_mounts(void) {
dev_t devno;
int r;
r = get_block_device("/", &devno);
if (r < 0)
return log_error_errno(r, "Failed to determine block device of root file system: %m");
else if (r == 0) {
r = get_block_device("/usr", &devno);
if (r < 0)
return log_error_errno(r, "Failed to determine block device of /usr file system: %m");
else if (r == 0) {
log_debug("Neither root nor /usr file system are on a (single) block device.");
return 0;
}
}
return enumerate_partitions(devno);
}
int main(int argc, char *argv[]) {
int r = 0;
if (argc > 1 && argc != 4) {
log_error("This program takes three or no arguments.");
return EXIT_FAILURE;
}
if (argc > 1)
arg_dest = argv[3];
log_set_target(LOG_TARGET_SAFE);
log_parse_environment();
log_open();
umask(0022);
if (detect_container(NULL) > 0) {
log_debug("In a container, exiting.");
return EXIT_SUCCESS;
}
r = parse_proc_cmdline(parse_proc_cmdline_item);
if (r < 0)
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
if (!arg_enabled) {
log_debug("Disabled, exiting.");
return EXIT_SUCCESS;
}
if (arg_root_enabled)
r = add_root_mount();
if (!in_initrd()) {
int k;
k = add_mounts();
if (k < 0)
r = k;
}
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}