cryptsetup-generator.c revision 608d41f355d580a6f73e76b298bfc1b4e3155b80
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2010 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
25300b5a1fcf54674a69d0f4ab08925be00b0227Lennart Poetteringstatic bool arg_enabled = true;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poetteringstatic bool arg_read_crypttab = true;
ebeccf9eecf5939a2ef772c3160e89efcad96194Lennart Poetteringstatic bool has_option(const char *haystack, const char *needle) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering const char *f = haystack;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (f[l] != 0 && f[l] != ',') {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char _cleanup_free_ *p = NULL, *n = NULL, *d = NULL, *u = NULL, *from = NULL, *to = NULL, *e = NULL;
1ddb263d21099ae42195c2bc382bdf72a7f24f82Lennart Poettering n = unit_name_from_path_instance("systemd-cryptsetup", name, ".service");
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering log_error("Failed to create unit file %s: %m", p);
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering "# Automatically generated by systemd-cryptsetup-generator\n\n"
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering "Description=Cryptography Setup for %%I\n"
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering "Documentation=man:systemd-cryptsetup@.service(8) man:crypttab(5)\n"
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering "SourcePath=/etc/crypttab\n"
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering "Conflicts=umount.target\n"
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering "DefaultDependencies=no\n"
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering "BindsTo=%s dev-mapper-%%i.device\n"
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering "After=systemd-readahead-collect.service systemd-readahead-replay.service %s\n"
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering "Before=umount.target\n",
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering "Before=cryptsetup.target\n");
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering if (password && (streq(password, "/dev/urandom") ||
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering fputs("After=systemd-random-seed-load.service\n", f);
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering "\n[Service]\n"
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering "Type=oneshot\n"
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering "RemainAfterExit=yes\n"
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering "TimeoutSec=0\n" /* the binary handles timeouts anyway */
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n"
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering name, u, strempty(password), strempty(options),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n",
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering "ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to write file %s: %m", p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering to = strjoin(arg_dest, "/", d, ".wants/", n, NULL);
b9a8d250810d4803bc9bf6b36932b528cb991d1eLennart Poettering log_error("Failed to create symlink '%s' to '%s': %m", from, to);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering to = strjoin(arg_dest, "/cryptsetup.target.wants/", n, NULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to create symlink '%s' to '%s': %m", from, to);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering log_error("Failed to create symlink '%s' to '%s': %m", from, to);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic int parse_proc_cmdline(char ***arg_proc_cmdline_disks) {
ebeccf9eecf5939a2ef772c3160e89efcad96194Lennart Poettering r = read_one_line_file("/proc/cmdline", &line);
ebeccf9eecf5939a2ef772c3160e89efcad96194Lennart Poettering log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_warning("Failed to parse luks switch %s. Ignoring.", word + 5);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering } else if (startswith(word, "rd.luks=")) {
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt log_warning("Failed to parse luks switch %s. Ignoring.", word + 8);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering } else if (startswith(word, "luks.crypttab=")) {
11b90e69e5620c2483b019340eff121d504db115Lennart Poettering log_warning("Failed to parse luks crypttab switch %s. Ignoring.", word + 14);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt } else if (startswith(word, "rd.luks.crypttab=")) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_warning("Failed to parse luks crypttab switch %s. Ignoring.", word + 17);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering } else if (startswith(word, "luks.uuid=")) {
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt t = strv_append(*arg_proc_cmdline_disks, word + 10);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else if (startswith(word, "rd.luks.uuid=")) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering t = strv_append(*arg_proc_cmdline_disks, word + 13);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt (in_initrd() && startswith(word, "rd.luks."))) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Unknown kernel switch %s. Ignoring.", word);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unsigned n = 0;
49f3fffd94591bdf2bd6c2233a9300daeab79566Lennart Poettering char _cleanup_strv_free_ **arg_proc_cmdline_disks_done = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char _cleanup_strv_free_ **arg_proc_cmdline_disks = NULL;
49f3fffd94591bdf2bd6c2233a9300daeab79566Lennart Poettering log_error("This program takes three or no arguments.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (parse_proc_cmdline(&arg_proc_cmdline_disks) < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to open /etc/crypttab: %m");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering } else for (;;) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char _cleanup_free_ *name = NULL, *device = NULL, *password = NULL, *options = NULL;
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering if (*l == '#' || *l == 0)
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering k = sscanf(l, "%ms %ms %ms %ms", &name, &device, &password, &options);
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering log_error("Failed to parse /etc/crypttab:%u, ignoring.", n);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering If luks UUIDs are specified on the kernel command line, use them as a filter
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for /etc/crypttab and only generate units for those.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering STRV_FOREACH(i, arg_proc_cmdline_disks) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char _cleanup_free_ *proc_device = NULL, *proc_name = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *p = *i;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (streq(proc_device, device) || streq(proc_name, name)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (create_disk(name, device, password, options) < 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering t = strv_append(arg_proc_cmdline_disks_done, p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (create_disk(name, device, password, options) < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering STRV_FOREACH(i, arg_proc_cmdline_disks) {
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek Generate units for those UUIDs, which were specified
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering on the kernel command line and not yet written.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char _cleanup_free_ *name = NULL, *device = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *p = *i;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (strv_contains(arg_proc_cmdline_disks_done, p))
return log_oom();
r = EXIT_FAILURE;