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 if (!(n = unit_name_build_escape("cryptsetup", name, ".service"))) {
81 log_error("Failed to allocate unit name.");
85 if (asprintf(&p, "%s/%s", arg_dest, n) < 0) {
87 log_error("Failed to allocate unit file name.");
91 if (!(u = fstab_node_to_udev_node(device))) {
93 log_error("Failed to allocate device node.");
97 if (!(d = unit_name_from_path(u, ".device"))) {
99 log_error("Failed to allocate device name.");
103 if (!(f = fopen(p, "wxe"))) {
105 log_error("Failed to create unit file: %m");
111 "Description=Cryptography Setup for %%I\n"
112 "Conflicts=umount.target\n"
113 "DefaultDependencies=no\n"
114 "BindTo=%s dev-mapper-%%i.device\n"
115 "After=systemd-readahead-collect.service systemd-readahead-replay.service %s\n"
116 "Before=umount.target\n",
121 "Before=cryptsetup.target\n");
123 if (password && (streq(password, "/dev/urandom") ||
124 streq(password, "/dev/random") ||
125 streq(password, "/dev/hw_random")))
127 "After=systemd-random-seed-load.service\n");
130 "Before=local-fs.target\n");
135 "RemainAfterExit=yes\n"
136 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
137 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n"
138 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
139 name, u, strempty(password), strempty(options),
142 if (has_option(options, "tmp"))
144 "ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n",
147 if (has_option(options, "swap"))
149 "ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n",
156 log_error("Failed to write file: %m");
160 if (asprintf(&from, "../%s", n) < 0) {
167 if (asprintf(&to, "%s/%s.wants/%s", arg_dest, d, n) < 0) {
172 mkdir_parents(to, 0755);
174 if (symlink(from, to) < 0) {
175 log_error("Failed to create symlink '%s' to '%s': %m", from, to);
184 asprintf(&to, "%s/cryptsetup.target.requires/%s", arg_dest, n);
186 asprintf(&to, "%s/cryptsetup.target.wants/%s", arg_dest, n);
193 mkdir_parents(to, 0755);
195 if (symlink(from, to) < 0) {
196 log_error("Failed to create symlink '%s' to '%s': %m", from, to);
205 e = unit_name_escape(name);
206 if (asprintf(&to, "%s/dev-mapper-%s.device.requires/%s", arg_dest, e, n) < 0) {
211 mkdir_parents(to, 0755);
213 if (symlink(from, to) < 0) {
214 log_error("Failed to create symlink '%s' to '%s': %m", from, to);
236 int main(int argc, char *argv[]) {
238 int r = EXIT_SUCCESS;
242 log_error("This program takes one or no arguments.");
249 log_set_target(LOG_TARGET_AUTO);
250 log_parse_environment();
255 if (!(f = fopen("/etc/crypttab", "re"))) {
261 log_error("Failed to open /etc/crypttab: %m");
268 char line[LINE_MAX], *l;
269 char *name = NULL, *device = NULL, *password = NULL, *options = NULL;
272 if (!(fgets(line, sizeof(line), f)))
278 if (*l == '#' || *l == 0)
281 if ((k = sscanf(l, "%ms %ms %ms %ms", &name, &device, &password, &options)) < 2 || k > 4) {
282 log_error("Failed to parse /etc/crypttab:%u, ignoring.", n);
287 if (create_disk(name, device, password, options) < 0)