1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include "unit-name.h"
31 const char *arg_dest = "/tmp";
33 static bool has_option(const char *haystack, const char *needle) {
34 const char *f = haystack;
44 while ((f = strstr(f, needle))) {
46 if (f > haystack && f[-1] != ',') {
51 if (f[l] != 0 && f[l] != ',') {
62 static int create_disk(
66 const char *options) {
68 char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *from = NULL, *to = NULL, *e = NULL;
76 noauto = has_option(options, "noauto");
77 nofail = has_option(options, "nofail");
79 n = unit_name_build_escape("cryptsetup", name, ".service");
82 log_error("Failed to allocate unit name.");
86 p = join(arg_dest, "/", n, NULL);
89 log_error("Failed to allocate unit file name.");
93 u = fstab_node_to_udev_node(device);
96 log_error("Failed to allocate device node.");
100 d = unit_name_from_path(u, ".device");
103 log_error("Failed to allocate device name.");
110 log_error("Failed to create unit file: %m");
115 "# Automatically generated by systemd-cryptsetup-generator\n\n"
117 "Description=Cryptography Setup for %%I\n"
118 "SourcePath=/etc/crypttab\n"
119 "Conflicts=umount.target\n"
120 "DefaultDependencies=no\n"
121 "BindTo=%s dev-mapper-%%i.device\n"
122 "After=systemd-readahead-collect.service systemd-readahead-replay.service %s\n"
123 "Before=umount.target\n",
128 "Before=cryptsetup.target\n");
130 if (password && (streq(password, "/dev/urandom") ||
131 streq(password, "/dev/random") ||
132 streq(password, "/dev/hw_random")))
133 fputs("After=systemd-random-seed-load.service\n", f);
135 fputs("Before=local-fs.target\n", f);
140 "RemainAfterExit=yes\n"
141 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
142 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n"
143 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
144 name, u, strempty(password), strempty(options),
147 if (has_option(options, "tmp"))
149 "ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n",
152 if (has_option(options, "swap"))
154 "ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n",
161 log_error("Failed to write file: %m");
165 if (asprintf(&from, "../%s", n) < 0) {
172 to = join(arg_dest, "/", d, ".wants/", n, NULL);
178 mkdir_parents(to, 0755);
179 if (symlink(from, to) < 0) {
180 log_error("Failed to create symlink '%s' to '%s': %m", from, to);
188 to = join(arg_dest, "/cryptsetup.target.requires/", n, NULL);
190 to = join(arg_dest, "/cryptsetup.target.wants/", n, NULL);
196 mkdir_parents(to, 0755);
197 if (symlink(from, to) < 0) {
198 log_error("Failed to create symlink '%s' to '%s': %m", from, to);
207 e = unit_name_escape(name);
208 to = join(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
214 mkdir_parents(to, 0755);
215 if (symlink(from, to) < 0) {
216 log_error("Failed to create symlink '%s' to '%s': %m", from, to);
238 int main(int argc, char *argv[]) {
240 int r = EXIT_SUCCESS;
243 if (argc > 1 && argc != 4) {
244 log_error("This program takes three or no arguments.");
251 log_set_target(LOG_TARGET_SAFE);
252 log_parse_environment();
257 f = fopen("/etc/crypttab", "re");
264 log_error("Failed to open /etc/crypttab: %m");
271 char line[LINE_MAX], *l;
272 char *name = NULL, *device = NULL, *password = NULL, *options = NULL;
275 if (!fgets(line, sizeof(line), f))
281 if (*l == '#' || *l == 0)
284 k = sscanf(l, "%ms %ms %ms %ms", &name, &device, &password, &options);
285 if (k < 2 || k > 4) {
286 log_error("Failed to parse /etc/crypttab:%u, ignoring.", n);
291 if (create_disk(name, device, password, options) < 0)