]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/cryptsetup/cryptsetup-generator.c
util: don't require libcap when building libsystemd-shared
[thirdparty/systemd.git] / src / cryptsetup / cryptsetup-generator.c
CommitLineData
e23a0ce8
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
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
e23a0ce8
LP
11 (at your option) any later version.
12
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
5430f7f2 16 Lesser General Public License for more details.
e23a0ce8 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
e23a0ce8
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <string.h>
23#include <errno.h>
24#include <unistd.h>
25
26#include "log.h"
27#include "util.h"
28#include "unit-name.h"
49e942b2 29#include "mkdir.h"
e23a0ce8
LP
30
31const char *arg_dest = "/tmp";
32
33static bool has_option(const char *haystack, const char *needle) {
34 const char *f = haystack;
35 size_t l;
36
f653f683
LP
37 assert(needle);
38
39 if (!haystack)
40 return false;
41
e23a0ce8
LP
42 l = strlen(needle);
43
44 while ((f = strstr(f, needle))) {
45
46 if (f > haystack && f[-1] != ',') {
47 f++;
48 continue;
49 }
50
aae5220d 51 if (f[l] != 0 && f[l] != ',') {
e23a0ce8
LP
52 f++;
53 continue;
54 }
55
56 return true;
57 }
58
59 return false;
60}
61
62static int create_disk(
63 const char *name,
64 const char *device,
65 const char *password,
66 const char *options) {
67
74715b82 68 char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *from = NULL, *to = NULL, *e = NULL;
e23a0ce8
LP
69 int r;
70 FILE *f = NULL;
155da457 71 bool noauto, nofail;
e23a0ce8
LP
72
73 assert(name);
74 assert(device);
75
155da457
LP
76 noauto = has_option(options, "noauto");
77 nofail = has_option(options, "nofail");
78
f7f21d33
LP
79 n = unit_name_build_escape("cryptsetup", name, ".service");
80 if (!n) {
e23a0ce8
LP
81 r = -ENOMEM;
82 log_error("Failed to allocate unit name.");
83 goto fail;
84 }
85
f7f21d33
LP
86 p = join(arg_dest, "/", n, NULL);
87 if (!p) {
e23a0ce8
LP
88 r = -ENOMEM;
89 log_error("Failed to allocate unit file name.");
90 goto fail;
91 }
92
f7f21d33
LP
93 u = fstab_node_to_udev_node(device);
94 if (!u) {
e23a0ce8
LP
95 r = -ENOMEM;
96 log_error("Failed to allocate device node.");
97 goto fail;
98 }
99
f7f21d33
LP
100 d = unit_name_from_path(u, ".device");
101 if (!d) {
e23a0ce8
LP
102 r = -ENOMEM;
103 log_error("Failed to allocate device name.");
104 goto fail;
105 }
106
f7f21d33
LP
107 f = fopen(p, "wxe");
108 if (!f) {
e23a0ce8
LP
109 r = -errno;
110 log_error("Failed to create unit file: %m");
111 goto fail;
112 }
113
114 fprintf(f,
6b1dc2bd 115 "# Automatically generated by systemd-cryptsetup-generator\n\n"
e23a0ce8 116 "[Unit]\n"
a4477e68 117 "Description=Cryptography Setup for %%I\n"
1b64d026 118 "SourcePath=/etc/crypttab\n"
155da457 119 "Conflicts=umount.target\n"
e23a0ce8 120 "DefaultDependencies=no\n"
49d50c55 121 "BindTo=%s dev-mapper-%%i.device\n"
e23a0ce8 122 "After=systemd-readahead-collect.service systemd-readahead-replay.service %s\n"
87e75fdd 123 "Before=umount.target\n",
e23a0ce8
LP
124 d, d);
125
155da457
LP
126 if (!nofail)
127 fprintf(f,
128 "Before=cryptsetup.target\n");
129
e23a0ce8
LP
130 if (password && (streq(password, "/dev/urandom") ||
131 streq(password, "/dev/random") ||
132 streq(password, "/dev/hw_random")))
1b64d026 133 fputs("After=systemd-random-seed-load.service\n", f);
87e75fdd 134 else
1b64d026 135 fputs("Before=local-fs.target\n", f);
e23a0ce8
LP
136
137 fprintf(f,
138 "\n[Service]\n"
139 "Type=oneshot\n"
140 "RemainAfterExit=yes\n"
90724929 141 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
260ab287 142 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n"
7f4e0805 143 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
e23a0ce8
LP
144 name, u, strempty(password), strempty(options),
145 name);
146
f653f683 147 if (has_option(options, "tmp"))
e23a0ce8 148 fprintf(f,
50109038 149 "ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n",
1d3399e6 150 name);
e23a0ce8 151
f653f683 152 if (has_option(options, "swap"))
e23a0ce8 153 fprintf(f,
50109038 154 "ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n",
1d3399e6 155 name);
e23a0ce8
LP
156
157 fflush(f);
158
159 if (ferror(f)) {
160 r = -errno;
161 log_error("Failed to write file: %m");
162 goto fail;
163 }
164
74715b82
LP
165 if (asprintf(&from, "../%s", n) < 0) {
166 r = -ENOMEM;
167 goto fail;
168 }
169
155da457 170 if (!noauto) {
e23a0ce8 171
f7f21d33
LP
172 to = join(arg_dest, "/", d, ".wants/", n, NULL);
173 if (!to) {
e23a0ce8
LP
174 r = -ENOMEM;
175 goto fail;
176 }
177
e23a0ce8 178 mkdir_parents(to, 0755);
e23a0ce8
LP
179 if (symlink(from, to) < 0) {
180 log_error("Failed to create symlink '%s' to '%s': %m", from, to);
181 r = -errno;
182 goto fail;
183 }
2f8cd170
LP
184
185 free(to);
2f8cd170 186
155da457 187 if (!nofail)
f7f21d33 188 to = join(arg_dest, "/cryptsetup.target.requires/", n, NULL);
155da457 189 else
f7f21d33 190 to = join(arg_dest, "/cryptsetup.target.wants/", n, NULL);
155da457
LP
191 if (!to) {
192 r = -ENOMEM;
193 goto fail;
194 }
2f8cd170 195
155da457 196 mkdir_parents(to, 0755);
155da457
LP
197 if (symlink(from, to) < 0) {
198 log_error("Failed to create symlink '%s' to '%s': %m", from, to);
199 r = -errno;
200 goto fail;
2f8cd170 201 }
e23a0ce8 202
f7f21d33
LP
203 free(to);
204 to = NULL;
205 }
74715b82
LP
206
207 e = unit_name_escape(name);
f7f21d33
LP
208 to = join(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
209 if (!to) {
74715b82
LP
210 r = -ENOMEM;
211 goto fail;
212 }
213
214 mkdir_parents(to, 0755);
74715b82
LP
215 if (symlink(from, to) < 0) {
216 log_error("Failed to create symlink '%s' to '%s': %m", from, to);
217 r = -errno;
218 goto fail;
219 }
220
e23a0ce8
LP
221 r = 0;
222
223fail:
224 free(p);
225 free(n);
226 free(d);
74715b82 227 free(e);
e23a0ce8
LP
228
229 free(from);
230 free(to);
231
232 if (f)
233 fclose(f);
234
235 return r;
236}
237
238int main(int argc, char *argv[]) {
239 FILE *f;
240 int r = EXIT_SUCCESS;
241 unsigned n = 0;
242
07719a21
LP
243 if (argc > 1 && argc != 4) {
244 log_error("This program takes three or no arguments.");
e23a0ce8
LP
245 return EXIT_FAILURE;
246 }
247
2a796654
LP
248 if (argc > 1)
249 arg_dest = argv[1];
e23a0ce8 250
a6903061 251 log_set_target(LOG_TARGET_SAFE);
e23a0ce8
LP
252 log_parse_environment();
253 log_open();
254
4c12626c
LP
255 umask(0022);
256
f7f21d33
LP
257 f = fopen("/etc/crypttab", "re");
258 if (!f) {
e23a0ce8
LP
259
260 if (errno == ENOENT)
261 r = EXIT_SUCCESS;
262 else {
263 r = EXIT_FAILURE;
264 log_error("Failed to open /etc/crypttab: %m");
265 }
266
267 goto finish;
268 }
269
270 for (;;) {
271 char line[LINE_MAX], *l;
272 char *name = NULL, *device = NULL, *password = NULL, *options = NULL;
273 int k;
274
f7f21d33 275 if (!fgets(line, sizeof(line), f))
e23a0ce8
LP
276 break;
277
278 n++;
279
280 l = strstrip(line);
281 if (*l == '#' || *l == 0)
282 continue;
283
f7f21d33
LP
284 k = sscanf(l, "%ms %ms %ms %ms", &name, &device, &password, &options);
285 if (k < 2 || k > 4) {
e23a0ce8
LP
286 log_error("Failed to parse /etc/crypttab:%u, ignoring.", n);
287 r = EXIT_FAILURE;
288 goto next;
289 }
290
291 if (create_disk(name, device, password, options) < 0)
292 r = EXIT_FAILURE;
293
294 next:
295 free(name);
296 free(device);
297 free(password);
298 free(options);
299 }
300
301finish:
302 return r;
303}