cryptsetup-generator.c revision 4469ff4adebbed4778e7fe767f0165776c1ba62a
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering/***
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering This file is part of systemd.
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering Copyright 2010 Lennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering systemd is free software; you can redistribute it and/or modify it
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering under the terms of the GNU Lesser General Public License as published by
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering (at your option) any later version.
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering systemd is distributed in the hope that it will be useful, but
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering Lesser General Public License for more details.
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering You should have received a copy of the GNU Lesser General Public License
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering***/
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering#include <string.h>
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering#include <errno.h>
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering#include <unistd.h>
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering#include "log.h"
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering#include "util.h"
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering#include "unit-name.h"
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering#include "mkdir.h"
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering#include "virt.h"
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering#include "strv.h"
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering#include "fileio.h"
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poetteringstatic const char *arg_dest = "/tmp";
31885cd5e38ec9807a6a7ab32660cf8c2fcf48f7Zbigniew Jędrzejewski-Szmekstatic bool arg_enabled = true;
b68fa010f72599e6da5822feda5ae3a47a4e63d8Simon Peetersstatic bool arg_read_crypttab = true;
b68fa010f72599e6da5822feda5ae3a47a4e63d8Simon Peeters
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poetteringstatic bool has_option(const char *haystack, const char *needle) {
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering const char *f = haystack;
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering size_t l;
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering assert(needle);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering if (!haystack)
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering return false;
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering l = strlen(needle);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering while ((f = strstr(f, needle))) {
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering if (f > haystack && f[-1] != ',') {
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering f++;
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering continue;
5841bd803f1b651c0d70c6ae114630723a76d1daZbigniew Jędrzejewski-Szmek }
5841bd803f1b651c0d70c6ae114630723a76d1daZbigniew Jędrzejewski-Szmek
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering if (f[l] != 0 && f[l] != ',') {
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering f++;
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering continue;
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering }
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering return true;
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering }
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering return false;
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering}
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poetteringstatic int create_disk(
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering const char *name,
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering const char *device,
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering const char *password,
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering const char *options) {
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering _cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *from = NULL, *to = NULL, *e = NULL;
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering _cleanup_fclose_ FILE *f = NULL;
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering bool noauto, nofail, tmp, swap;
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering assert(name);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering assert(device);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering noauto = has_option(options, "noauto");
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering nofail = has_option(options, "nofail");
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering tmp = has_option(options, "tmp");
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering swap = has_option(options, "swap");
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering if (tmp && swap) {
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering log_error("Device '%s' cannot be both 'tmp' and 'swap'. Ignoring.", name);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering return -EINVAL;
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering }
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering n = unit_name_from_path_instance("systemd-cryptsetup", name, ".service");
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering if (!n)
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering return log_oom();
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering p = strjoin(arg_dest, "/", n, NULL);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering if (!p)
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering return log_oom();
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering u = fstab_node_to_udev_node(device);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering if (!u)
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering return log_oom();
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering d = unit_name_from_path(u, ".device");
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering if (!d)
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering return log_oom();
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering f = fopen(p, "wxe");
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering if (!f) {
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering log_error("Failed to create unit file %s: %m", p);
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering return -errno;
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering }
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering fputs(
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering "# Automatically generated by systemd-cryptsetup-generator\n\n"
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering "[Unit]\n"
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering "Description=Cryptography Setup for %I\n"
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering "Documentation=man:systemd-cryptsetup@.service(8) man:crypttab(5)\n"
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering "SourcePath=/etc/crypttab\n"
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering "Conflicts=umount.target\n"
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering "DefaultDependencies=no\n"
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering "BindsTo=dev-mapper-%i.device\n"
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering "IgnoreOnIsolate=true\n"
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering "After=systemd-readahead-collect.service systemd-readahead-replay.service\n",
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering f);
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering if (!nofail)
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering fprintf(f,
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering "Before=cryptsetup.target\n");
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering if (password) {
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering if (streq(password, "/dev/urandom") ||
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering streq(password, "/dev/random") ||
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering streq(password, "/dev/hw_random"))
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering fputs("After=systemd-random-seed.service\n", f);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering else if (!streq(password, "-") &&
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering !streq(password, "none"))
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering fprintf(f,
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering "RequiresMountsFor=%s\n",
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering password);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering }
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering if (is_device_path(u))
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering fprintf(f,
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering "BindsTo=%s\n"
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering "After=%s\n"
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering "Before=umount.target\n",
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering d, d);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering else
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering fprintf(f,
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering "RequiresMountsFor=%s\n",
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering u);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering fprintf(f,
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering "\n[Service]\n"
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering "Type=oneshot\n"
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering "RemainAfterExit=yes\n"
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering "TimeoutSec=0\n" /* the binary handles timeouts anyway */
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n"
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering name, u, strempty(password), strempty(options),
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering name);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering if (tmp)
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering fprintf(f,
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering "ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n",
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering name);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering if (swap)
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering fprintf(f,
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering "ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n",
df758e98754016119a9c8d49213a636a80ffab22Kay Sievers name);
df758e98754016119a9c8d49213a636a80ffab22Kay Sievers
df758e98754016119a9c8d49213a636a80ffab22Kay Sievers fflush(f);
df758e98754016119a9c8d49213a636a80ffab22Kay Sievers
ccd06097c79218f7d5ea4c21721bbcbc7c467dcaZbigniew Jędrzejewski-Szmek if (ferror(f)) {
df758e98754016119a9c8d49213a636a80ffab22Kay Sievers log_error("Failed to write file %s: %m", p);
df758e98754016119a9c8d49213a636a80ffab22Kay Sievers return -errno;
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering }
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering
ccd06097c79218f7d5ea4c21721bbcbc7c467dcaZbigniew Jędrzejewski-Szmek if (asprintf(&from, "../%s", n) < 0)
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering return log_oom();
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering if (!noauto) {
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering to = strjoin(arg_dest, "/", d, ".wants/", n, NULL);
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering if (!to)
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering return log_oom();
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering mkdir_parents_label(to, 0755);
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering if (symlink(from, to) < 0) {
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering log_error("Failed to create symlink %s: %m", to);
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering return -errno;
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering }
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering free(to);
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering if (!nofail)
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering else
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering to = strjoin(arg_dest, "/cryptsetup.target.wants/", n, NULL);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering if (!to)
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering return log_oom();
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering mkdir_parents_label(to, 0755);
6301a98cdf26dc073f5317506c806bfa69f74cc8Lennart Poettering if (symlink(from, to) < 0) {
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering log_error("Failed to create symlink %s: %m", to);
b6e8f1f03dc8b7579f8c6b00372f136d74c45232Harald Hoyer return -errno;
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering }
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering }
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering e = unit_name_escape(name);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering if (!e)
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering return log_oom();
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering free(to);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering if (!to)
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering return log_oom();
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering mkdir_parents_label(to, 0755);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering if (symlink(from, to) < 0) {
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering log_error("Failed to create symlink %s: %m", to);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering return -errno;
3d141780b8d509e4a6c3083de207cd84cbce187bLennart Poettering }
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering if (!noauto && !nofail) {
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering int r;
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering free(p);
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf", NULL);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering if (!p)
return log_oom();
mkdir_parents_label(p, 0755);
r = write_string_file(p,
"# Automatically generated by systemd-cryptsetup-generator\n\n"
"[Unit]\n"
"JobTimeoutSec=0\n"); /* the binary handles timeouts anyway */
if (r)
return r;
}
return 0;
}
static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char ***arg_proc_cmdline_options, char **arg_proc_cmdline_keyfile) {
_cleanup_free_ char *line = NULL;
char *w = NULL, *state = NULL;
int r;
size_t l;
if (detect_container(NULL) > 0)
return 0;
r = read_one_line_file("/proc/cmdline", &line);
if (r < 0) {
log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
return 0;
}
FOREACH_WORD_QUOTED(w, l, line, state) {
_cleanup_free_ char *word = NULL;
word = strndup(w, l);
if (!word)
return log_oom();
if (startswith(word, "luks=")) {
r = parse_boolean(word + 5);
if (r < 0)
log_warning("Failed to parse luks switch %s. Ignoring.", word + 5);
else
arg_enabled = r;
} else if (startswith(word, "rd.luks=")) {
if (in_initrd()) {
r = parse_boolean(word + 8);
if (r < 0)
log_warning("Failed to parse luks switch %s. Ignoring.", word + 8);
else
arg_enabled = r;
}
} else if (startswith(word, "luks.crypttab=")) {
r = parse_boolean(word + 14);
if (r < 0)
log_warning("Failed to parse luks crypttab switch %s. Ignoring.", word + 14);
else
arg_read_crypttab = r;
} else if (startswith(word, "rd.luks.crypttab=")) {
if (in_initrd()) {
r = parse_boolean(word + 17);
if (r < 0)
log_warning("Failed to parse luks crypttab switch %s. Ignoring.", word + 17);
else
arg_read_crypttab = r;
}
} else if (startswith(word, "luks.uuid=")) {
if (strv_extend(arg_proc_cmdline_disks, word + 10) < 0)
return log_oom();
} else if (startswith(word, "rd.luks.uuid=")) {
if (in_initrd()) {
if (strv_extend(arg_proc_cmdline_disks, word + 13) < 0)
return log_oom();
}
} else if (startswith(word, "luks.options=")) {
if (strv_extend(arg_proc_cmdline_options, word + 13) < 0)
return log_oom();
} else if (startswith(word, "rd.luks.options=")) {
if (in_initrd()) {
if (strv_extend(arg_proc_cmdline_options, word + 16) < 0)
return log_oom();
}
} else if (startswith(word, "luks.key=")) {
if (*arg_proc_cmdline_keyfile)
free(*arg_proc_cmdline_keyfile);
*arg_proc_cmdline_keyfile = strdup(word + 9);
if (!*arg_proc_cmdline_keyfile)
return log_oom();
} else if (startswith(word, "rd.luks.key=")) {
if (in_initrd()) {
if (*arg_proc_cmdline_keyfile)
free(*arg_proc_cmdline_keyfile);
*arg_proc_cmdline_keyfile = strdup(word + 12);
if (!*arg_proc_cmdline_keyfile)
return log_oom();
}
} else if (startswith(word, "luks.") ||
(in_initrd() && startswith(word, "rd.luks."))) {
log_warning("Unknown kernel switch %s. Ignoring.", word);
}
}
strv_uniq(*arg_proc_cmdline_disks);
return 0;
}
int main(int argc, char *argv[]) {
_cleanup_strv_free_ char **arg_proc_cmdline_disks_done = NULL;
_cleanup_strv_free_ char **arg_proc_cmdline_disks = NULL;
_cleanup_strv_free_ char **arg_proc_cmdline_options = NULL;
_cleanup_free_ char *arg_proc_cmdline_keyfile = NULL;
_cleanup_fclose_ FILE *f = NULL;
unsigned n = 0;
int r = EXIT_SUCCESS;
char **i;
if (argc > 1 && argc != 4) {
log_error("This program takes three or no arguments.");
return EXIT_FAILURE;
}
if (argc > 1)
arg_dest = argv[1];
log_set_target(LOG_TARGET_SAFE);
log_parse_environment();
log_open();
umask(0022);
if (parse_proc_cmdline(&arg_proc_cmdline_disks, &arg_proc_cmdline_options, &arg_proc_cmdline_keyfile) < 0)
return EXIT_FAILURE;
if (!arg_enabled)
return EXIT_SUCCESS;
if (arg_read_crypttab) {
struct stat st;
f = fopen("/etc/crypttab", "re");
if (!f) {
if (errno == ENOENT)
r = EXIT_SUCCESS;
else {
r = EXIT_FAILURE;
log_error("Failed to open /etc/crypttab: %m");
}
goto next;
}
if (fstat(fileno(f), &st) < 0) {
log_error("Failed to stat /etc/crypttab: %m");
r = EXIT_FAILURE;
goto next;
}
/* If we readd support for specifying passphrases
* directly in crypttabe we should upgrade the warning
* below, though possibly only if a passphrase is
* specified directly. */
if (st.st_mode & 0005)
log_debug("/etc/crypttab is world-readable. This is usually not a good idea.");
for (;;) {
char line[LINE_MAX], *l;
_cleanup_free_ char *name = NULL, *device = NULL, *password = NULL, *options = NULL;
int k;
if (!fgets(line, sizeof(line), f))
break;
n++;
l = strstrip(line);
if (*l == '#' || *l == 0)
continue;
k = sscanf(l, "%ms %ms %ms %ms", &name, &device, &password, &options);
if (k < 2 || k > 4) {
log_error("Failed to parse /etc/crypttab:%u, ignoring.", n);
r = EXIT_FAILURE;
continue;
}
if (arg_proc_cmdline_options) {
/*
If options are specified on the kernel commandline, let them override
the ones from crypttab.
*/
STRV_FOREACH(i, arg_proc_cmdline_options) {
_cleanup_free_ char *proc_uuid = NULL, *proc_options = NULL;
const char *p = *i;
k = sscanf(p, "%m[0-9a-fA-F-]=%ms", &proc_uuid, &proc_options);
if (k == 2 && streq(proc_uuid, device + 5)) {
if (options)
free(options);
options = strdup(p);
if (!proc_options)
return log_oom();
}
}
}
if (arg_proc_cmdline_disks) {
/*
If luks UUIDs are specified on the kernel command line, use them as a filter
for /etc/crypttab and only generate units for those.
*/
STRV_FOREACH(i, arg_proc_cmdline_disks) {
_cleanup_free_ char *proc_device = NULL, *proc_name = NULL;
const char *p = *i;
if (startswith(p, "luks-"))
p += 5;
proc_name = strappend("luks-", p);
proc_device = strappend("UUID=", p);
if (!proc_name || !proc_device)
return log_oom();
if (streq(proc_device, device) || streq(proc_name, name)) {
if (create_disk(name, device, password, options) < 0)
r = EXIT_FAILURE;
if (strv_extend(&arg_proc_cmdline_disks_done, p) < 0)
return log_oom();
}
}
} else {
if (create_disk(name, device, password, options) < 0)
r = EXIT_FAILURE;
}
}
}
next:
STRV_FOREACH(i, arg_proc_cmdline_disks) {
/*
Generate units for those UUIDs, which were specified
on the kernel command line and not yet written.
*/
_cleanup_free_ char *name = NULL, *device = NULL, *options = NULL;
const char *p = *i;
if (startswith(p, "luks-"))
p += 5;
if (strv_contains(arg_proc_cmdline_disks_done, p))
continue;
name = strappend("luks-", p);
device = strappend("UUID=", p);
if (!name || !device)
return log_oom();
if (arg_proc_cmdline_options) {
/*
If options are specified on the kernel commandline, use them.
*/
char **j;
STRV_FOREACH(j, arg_proc_cmdline_options) {
_cleanup_free_ char *proc_uuid = NULL, *proc_options = NULL;
const char *s = *j;
int k;
k = sscanf(s, "%m[0-9a-fA-F-]=%ms", &proc_uuid, &proc_options);
if (k == 2) {
if (streq(proc_uuid, device + 5)) {
if (options)
free(options);
options = strdup(proc_options);
if (!options)
return log_oom();
}
} else if (!options) {
/*
Fall back to options without a specified UUID
*/
options = strdup(s);
if (!options)
return log_oom();
}
}
}
if (!options) {
options = strdup("timeout=0");
if (!options)
return log_oom();
}
if (create_disk(name, device, arg_proc_cmdline_keyfile, options) < 0)
r = EXIT_FAILURE;
}
return r;
}