gpt-auto-generator.c revision cca1dfddd4ce4357113663532696488427cc54e4
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 <fcntl.h>
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include <sys/ioctl.h>
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include <sys/statfs.h>
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include <blkid/blkid.h>
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
4b357e15876b730343db08719c877fdb45b6ad42Michael Marineau#ifdef HAVE_LINUX_BTRFS_H
4b357e15876b730343db08719c877fdb45b6ad42Michael Marineau#include <linux/btrfs.h>
4b357e15876b730343db08719c877fdb45b6ad42Michael Marineau#endif
4b357e15876b730343db08719c877fdb45b6ad42Michael Marineau
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "sd-id128.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "libudev.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "path-util.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "util.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "mkdir.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "missing.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "udev-util.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "special.h"
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek#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"
4b1b14a6a6acb1640596d5e9542829d32989d385Lennart Poettering#include "blkid-util.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic const char *arg_dest = "/tmp";
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic bool arg_enabled = true;
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmekstatic bool arg_root_enabled = true;
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmekstatic bool arg_root_rw = false;
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int add_swap(const char *path) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek _cleanup_fclose_ FILE *f = NULL;
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek assert(path);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek log_debug("Adding swap: %s", path);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering name = unit_name_from_path(path, ".swap");
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek if (!name)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering unit = strjoin(arg_dest, "/", name, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!unit)
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering return log_oom();
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek f = fopen(unit, "wxe");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!f) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to create unit file %s: %m", unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return -errno;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fprintf(f,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "[Unit]\n"
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek "Description=Swap Partition\n"
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek "Documentation=man:systemd-gpt-auto-generator(8)\n\n"
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek "[Swap]\n"
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek "What=%s\n",
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek path);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fflush(f);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (ferror(f)) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to write unit file %s: %m", unit);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek return -errno;
091526ab20485492124852dcf629787f35816df8Zbigniew Jędrzejewski-Szmek }
091526ab20485492124852dcf629787f35816df8Zbigniew Jędrzejewski-Szmek
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek if (!lnk)
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering mkdir_parents_label(lnk, 0755);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (symlink(unit, lnk) < 0) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to create symlink %s: %m", lnk);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek return -errno;
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering}
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;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering char *from, *ret;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering int r;
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek assert(id);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering assert(what);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering assert(device);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering d = unit_name_from_path(what, ".device");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!d)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering e = unit_name_escape(id);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!e)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering n = unit_name_build("systemd-cryptsetup", e, ".service");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!n)
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek return log_oom();
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering p = strjoin(arg_dest, "/", n, NULL);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek if (!n)
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering f = fopen(p, "wxe");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!f) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to create unit file %s: %m", p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return -errno;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fprintf(f,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "[Unit]\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 "After=%s\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "IgnoreOnIsolate=true\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "After=systemd-readahead-collect.service systemd-readahead-replay.service\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "[Service]\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 d, d,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering id, what, rw ? "" : "read-only",
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering id);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fflush(f);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (ferror(f)) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to write file %s: %m", p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return -errno;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
ee530d8b73246f29781bd54a707ca75c7ef5a6cbLennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering from = strappenda("../", n);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering to = strjoin(arg_dest, "/", d, ".wants/", 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 log_error("Failed to create symlink %s: %m", to);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return -errno;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
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 log_error("Failed to create symlink %s: %m", to);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return -errno;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering free(to);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!to)
4b1b14a6a6acb1640596d5e9542829d32989d385Lennart Poettering return log_oom();
4b1b14a6a6acb1640596d5e9542829d32989d385Lennart Poettering
4b1b14a6a6acb1640596d5e9542829d32989d385Lennart Poettering mkdir_parents_label(to, 0755);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (symlink(from, to) < 0) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to create symlink %s: %m", to);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return -errno;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
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"); /* the binary handles timeouts anyway */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (r < 0) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to write device drop-in: %s", strerror(-r));
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return r;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
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 *description,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *post) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart 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
3db604b907323b8df0fc810216f6112056d26a02Lennart 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;
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek fstype = NULL;
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering unit = unit_name_from_path(where, ".mount");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!unit)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
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 log_error("Failed to create unit file %s: %m", unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return -errno;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
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)
d98cc1c019651b895464161072894a02cc43daabZbigniew Jędrzejewski-Szmek return r;
d98cc1c019651b895464161072894a02cc43daabZbigniew Jędrzejewski-Szmek
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 fprintf(f, "Options=%s\n", rw ? "rw" : "ro");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fflush(f);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (ferror(f)) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to write unit file %s: %m", p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return -errno;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
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 log_error("Failed to create symlink %s: %m", lnk);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return -errno;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering}
3db604b907323b8df0fc810216f6112056d26a02Lennart 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,
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek const char *post) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek _cleanup_blkid_free_probe_ blkid_probe b = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *fstype;
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 if (path_is_mount_point(where, true) <= 0 &&
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering dir_is_empty(where) <= 0) {
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("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 if (errno == 0)
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek errno = EIO;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to probe %s: %m", what);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return -errno;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return add_mount(
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering id,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering what,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering where,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fstype,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering rw,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering description,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering post);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering}
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int enumerate_partitions(dev_t devnum) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
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 struct udev_list_entry *first, *item;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering struct udev_device *parent = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *node, *pttype, *devtype;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering int home_nr = -1, srv_nr = -1;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering bool home_rw = true, srv_rw = true;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering blkid_partlist pl;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering int r, k;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering dev_t pn;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering udev = udev_new();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!udev)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering d = udev_device_new_from_devnum(udev, 'b', devnum);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!d)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering parent = udev_device_get_parent(d);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!parent)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering /* Does it have a devtype? */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering devtype = udev_device_get_devtype(parent);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!devtype)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering /* Is this a disk or a partition? We only care for disks... */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!streq(devtype, "disk"))
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering /* Does it have a device node? */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering node = udev_device_get_devnode(parent);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!node)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_debug("Root device %s.", node);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering pn = udev_device_get_devnum(parent);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (major(pn) == 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
c51cf05646a11c65daf65c1123c77efb068f4f7bZbigniew Jędrzejewski-Szmek errno = 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering b = blkid_new_probe_from_filename(node);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!b) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (errno == 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering log_error("Failed allocate prober: %m");
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering return -errno;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering }
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering blkid_probe_enable_superblocks(b, 1);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering blkid_probe_enable_partitions(b, 1);
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering errno = 0;
3db604b907323b8df0fc810216f6112056d26a02Lennart 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 if (errno == 0)
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering errno = EIO;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering log_error("Failed to probe %s: %m", node);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering return -errno;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering }
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering errno = 0;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (r != 0) {
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (errno == 0)
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering errno = EIO;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering log_error("Failed to determine partition table type of %s: %m", node);
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek return -errno;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering }
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering /* We only do this all for GPT... */
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (!streq_ptr(pttype, "gpt"))
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering errno = 0;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering pl = blkid_probe_get_partitions(b);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!pl) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (errno == 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering log_error("Failed to list partitions of %s: %m", node);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering return -errno;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering e = udev_enumerate_new(udev);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (!e)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = udev_enumerate_add_match_parent(e, parent);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (r < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = udev_enumerate_add_match_subsystem(e, "block");
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (r < 0)
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek return log_oom();
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek r = udev_enumerate_scan_devices(e);
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek if (r < 0) {
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek log_error("Failed to enumerate partitions on %s: %s", node, strerror(-r));
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek return r;
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek }
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering first = udev_enumerate_get_list_entry(e);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering udev_list_entry_foreach(item, first) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_udev_device_unref_ struct udev_device *q;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering const char *stype, *subnode;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering sd_id128_t type_id;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering blkid_partition pp;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering dev_t qn;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering int nr;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering unsigned long long flags;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (!q)
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering continue;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering qn = udev_device_get_devnum(q);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (major(qn) == 0)
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering continue;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (qn == devnum)
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering continue;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (qn == pn)
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering continue;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering subnode = udev_device_get_devnode(q);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (!subnode)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering continue;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering pp = blkid_partlist_devno_to_partition(pl, qn);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering if (!pp)
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering continue;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering flags = blkid_partition_get_flags(pp);
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering /* Ignore partitions that are not marked for automatic
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering * mounting on discovery */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (flags & GPT_FLAG_NO_AUTO)
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering continue;
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering nr = blkid_partition_get_partno(pp);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (nr < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering continue;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
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)) {
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_HOME)) {
/* We only care for the first /home partition */
if (home && nr >= home_nr)
continue;
home_nr = nr;
home_rw = !(flags & GPT_FLAG_READ_ONLY),
free(home);
home = strdup(subnode);
if (!home)
return log_oom();
} else if (sd_id128_equal(type_id, GPT_SRV)) {
/* We only care for the first /srv partition */
if (srv && nr >= srv_nr)
continue;
srv_nr = nr;
srv_rw = !(flags & GPT_FLAG_READ_ONLY),
free(srv);
srv = strdup(node);
if (!srv)
return log_oom();
}
}
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_btrfs_block_device(const char *path, dev_t *dev) {
struct btrfs_ioctl_fs_info_args fsi = {};
_cleanup_close_ int fd = -1;
uint64_t id;
assert(path);
assert(dev);
fd = open(path, O_DIRECTORY|O_CLOEXEC);
if (fd < 0)
return -errno;
if (ioctl(fd, BTRFS_IOC_FS_INFO, &fsi) < 0)
return -errno;
/* We won't do this for btrfs RAID */
if (fsi.num_devices != 1)
return 0;
for (id = 1; id <= fsi.max_id; id++) {
struct btrfs_ioctl_dev_info_args di = {
.devid = id,
};
struct stat st;
if (ioctl(fd, BTRFS_IOC_DEV_INFO, &di) < 0) {
if (errno == ENODEV)
continue;
return -errno;
}
if (stat((char*) di.path, &st) < 0)
return -errno;
if (!S_ISBLK(st.st_mode))
return -ENODEV;
if (major(st.st_rdev) == 0)
return -ENODEV;
*dev = st.st_rdev;
return 1;
}
return -ENODEV;
}
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 get_btrfs_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);
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;
else if (startswith(key, "systemd.gpt-auto.") || startswith(key, "rd.systemd.gpt-auto."))
log_warning("Unknown kernel switch %s. Ignoring.", key);
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) {
log_error("Failed to read ESP partition UUID: %s", strerror(-r));
return r;
}
/* 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,
"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) {
log_error("Failed to determine block device of root file system: %s", strerror(-r));
return r;
} else if (r == 0) {
log_debug("Root file system not 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;
}
if (parse_proc_cmdline(parse_proc_cmdline_item) < 0)
return EXIT_FAILURE;
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;
}