]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/generator.c
unit: when JobTimeoutSec= is turned off, implicitly turn off JobRunningTimeoutSec...
[thirdparty/systemd.git] / src / shared / generator.c
CommitLineData
e48fdd84
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2014 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
a8fbdf54 20#include <errno.h>
e48fdd84
LP
21#include <unistd.h>
22
b5efdb8a 23#include "alloc-util.h"
4f5dd394
LP
24#include "dropin.h"
25#include "escape.h"
3ffd4af2 26#include "fd-util.h"
4f5dd394
LP
27#include "fileio.h"
28#include "fstab-util.h"
3ffd4af2 29#include "generator.h"
a8fbdf54
TA
30#include "log.h"
31#include "macro.h"
e48fdd84 32#include "mkdir.h"
4f5dd394
LP
33#include "path-util.h"
34#include "special.h"
07630cea 35#include "string-util.h"
a8fbdf54 36#include "time-util.h"
e48fdd84 37#include "unit-name.h"
4f5dd394 38#include "util.h"
e48fdd84 39
b559616f
ZJS
40int generator_add_symlink(const char *root, const char *dst, const char *dep_type, const char *src) {
41 /* Adds a symlink from <dst>.<dep_type>.d/ to ../<src> */
42
43 const char *from, *to;
44
45 from = strjoina("../", src);
46 to = strjoina(root, "/", dst, ".", dep_type, "/", src);
47
48 mkdir_parents_label(to, 0755);
49 if (symlink(from, to) < 0)
7f0cc637
ZJS
50 if (errno != EEXIST)
51 return log_error_errno(errno, "Failed to create symlink \"%s\": %m", to);
b559616f
ZJS
52
53 return 0;
54}
55
4dda4e63 56static int write_fsck_sysroot_service(const char *dir, const char *what) {
85eca92e 57 _cleanup_free_ char *device = NULL, *escaped = NULL;
4dda4e63 58 _cleanup_fclose_ FILE *f = NULL;
85eca92e 59 const char *unit;
4dda4e63
ZJS
60 int r;
61
fa05e972
AB
62 escaped = cescape(what);
63 if (!escaped)
64 return log_oom();
65
4dda4e63
ZJS
66 unit = strjoina(dir, "/systemd-fsck-root.service");
67 log_debug("Creating %s", unit);
68
69 r = unit_name_from_path(what, ".device", &device);
70 if (r < 0)
71 return log_error_errno(r, "Failed to convert device \"%s\" to unit name: %m", what);
72
73 f = fopen(unit, "wxe");
74 if (!f)
75 return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
76
77 fprintf(f,
78 "# Automatically generated by %1$s\n\n"
79 "[Unit]\n"
80 "Documentation=man:systemd-fsck-root.service(8)\n"
81 "Description=File System Check on %2$s\n"
82 "DefaultDependencies=no\n"
83 "BindsTo=%3$s\n"
0900593e 84 "After=initrd-root-device.target local-fs-pre.target %3$s\n"
4dda4e63
ZJS
85 "Before=shutdown.target\n"
86 "\n"
87 "[Service]\n"
88 "Type=oneshot\n"
89 "RemainAfterExit=yes\n"
fa05e972 90 "ExecStart=" SYSTEMD_FSCK_PATH " %4$s\n"
4dda4e63
ZJS
91 "TimeoutSec=0\n",
92 program_invocation_short_name,
93 what,
fa05e972
AB
94 device,
95 escaped);
4dda4e63 96
2929b4a6
LP
97 r = fflush_and_check(f);
98 if (r < 0)
99 return log_error_errno(r, "Failed to write unit file %s: %m", unit);
4dda4e63
ZJS
100
101 return 0;
102}
103
e48fdd84
LP
104int generator_write_fsck_deps(
105 FILE *f,
2e852276 106 const char *dir,
e48fdd84
LP
107 const char *what,
108 const char *where,
6db615c1 109 const char *fstype) {
e48fdd84 110
7410616c
LP
111 int r;
112
e48fdd84 113 assert(f);
2e852276 114 assert(dir);
6db615c1
LP
115 assert(what);
116 assert(where);
e48fdd84
LP
117
118 if (!is_device_path(what)) {
119 log_warning("Checking was requested for \"%s\", but it is not a device.", what);
120 return 0;
121 }
122
6db615c1 123 if (!isempty(fstype) && !streq(fstype, "auto")) {
eb66db55 124 r = fsck_exists(fstype);
85eca92e
LP
125 if (r < 0)
126 log_warning_errno(r, "Checking was requested for %s, but couldn't detect if fsck.%s may be used, proceeding: %m", what, fstype);
127 else if (r == 0) {
e48fdd84 128 /* treat missing check as essentially OK */
85eca92e 129 log_debug("Checking was requested for %s, but fsck.%s does not exist.", what, fstype);
571d0134 130 return 0;
85eca92e 131 }
e48fdd84
LP
132 }
133
2e852276 134 if (path_equal(where, "/")) {
85eca92e 135 const char *lnk;
e48fdd84 136
2e852276 137 lnk = strjoina(dir, "/" SPECIAL_LOCAL_FS_TARGET ".wants/systemd-fsck-root.service");
e48fdd84
LP
138
139 mkdir_parents(lnk, 0755);
4a62c710
MS
140 if (symlink(SYSTEM_DATA_UNIT_PATH "/systemd-fsck-root.service", lnk) < 0)
141 return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
e48fdd84
LP
142
143 } else {
4dda4e63
ZJS
144 _cleanup_free_ char *_fsck = NULL;
145 const char *fsck;
146
147 if (in_initrd() && path_equal(where, "/sysroot")) {
148 r = write_fsck_sysroot_service(dir, what);
149 if (r < 0)
150 return r;
151
152 fsck = "systemd-fsck-root.service";
153 } else {
154 r = unit_name_from_path_instance("systemd-fsck", what, ".service", &_fsck);
155 if (r < 0)
156 return log_error_errno(r, "Failed to create fsck service name: %m");
157
158 fsck = _fsck;
159 }
e48fdd84
LP
160
161 fprintf(f,
f32b43bd 162 "Requires=%1$s\n"
2e852276 163 "After=%1$s\n",
e48fdd84
LP
164 fsck);
165 }
166
167 return 0;
168}
29686440 169
2e852276
ZJS
170int generator_write_timeouts(
171 const char *dir,
172 const char *what,
173 const char *where,
174 const char *opts,
175 char **filtered) {
29686440
ZJS
176
177 /* Allow configuration how long we wait for a device that
178 * backs a mount point to show up. This is useful to support
179 * endless device timeouts for devices that show up only after
180 * user input, like crypto devices. */
181
d15d0333 182 _cleanup_free_ char *node = NULL, *unit = NULL, *timeout = NULL;
29686440
ZJS
183 usec_t u;
184 int r;
29686440 185
0004f698
ZJS
186 r = fstab_filter_options(opts, "comment=systemd.device-timeout\0"
187 "x-systemd.device-timeout\0",
d15d0333
ZJS
188 NULL, &timeout, filtered);
189 if (r <= 0)
190 return r;
b3208b66 191
0004f698 192 r = parse_sec_fix_0(timeout, &u);
29686440 193 if (r < 0) {
7410616c 194 log_warning("Failed to parse timeout for %s, ignoring: %s", where, timeout);
29686440
ZJS
195 return 0;
196 }
197
198 node = fstab_node_to_udev_node(what);
199 if (!node)
200 return log_oom();
c67bd1f7
N
201 if (!is_device_path(node)) {
202 log_warning("x-systemd.device-timeout ignored for %s", what);
203 return 0;
204 }
29686440 205
7410616c
LP
206 r = unit_name_from_path(node, ".device", &unit);
207 if (r < 0)
208 return log_error_errno(r, "Failed to make unit name from path: %m");
29686440 209
8eea8687
ZJS
210 return write_drop_in_format(dir, unit, 50, "device-timeout",
211 "# Automatically generated by %s\n\n"
d9732d78 212 "[Unit]\nJobRunningTimeoutSec=%s",
10c71477 213 program_invocation_short_name, timeout);
29686440 214}
7163e1ca 215
4195077a
MK
216int generator_write_device_deps(
217 const char *dir,
218 const char *what,
219 const char *where,
220 const char *opts) {
221
222 /* fstab records that specify _netdev option should apply the network
223 * ordering on the actual device depending on network connection. If we
224 * are not mounting real device (NFS, CIFS), we rely on _netdev effect
225 * on the mount unit itself. */
226
227 _cleanup_free_ char *node = NULL, *unit = NULL;
228 int r;
229
230 if (!fstab_test_option(opts, "_netdev\0"))
231 return 0;
232
233 node = fstab_node_to_udev_node(what);
234 if (!node)
235 return log_oom();
236
237 /* Nothing to apply dependencies to. */
238 if (!is_device_path(node))
239 return 0;
240
241 r = unit_name_from_path(node, ".device", &unit);
242 if (r < 0)
243 return log_error_errno(r, "Failed to make unit name from path: %m");
244
245 /* See mount_add_default_dependencies for explanation why we create such
246 * dependencies. */
247 return write_drop_in_format(dir, unit, 50, "netdev-dependencies",
248 "# Automatically generated by %s\n\n"
249 "[Unit]\n"
250 "After=" SPECIAL_NETWORK_ONLINE_TARGET " " SPECIAL_NETWORK_TARGET "\n"
251 "Wants=" SPECIAL_NETWORK_ONLINE_TARGET "\n",
252 program_invocation_short_name);
253}
254
7163e1ca
DD
255int generator_write_initrd_root_device_deps(const char *dir, const char *what) {
256 _cleanup_free_ char *unit = NULL;
257 int r;
258
259 r = unit_name_from_path(what, ".device", &unit);
260 if (r < 0)
261 return log_error_errno(r, "Failed to make unit name from path: %m");
262
263 return write_drop_in_format(dir, SPECIAL_INITRD_ROOT_DEVICE_TARGET, 50, "root-device",
264 "# Automatically generated by %s\n\n"
265 "[Unit]\nRequires=%s\nAfter=%s",
266 program_invocation_short_name, unit, unit);
267}