]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/generator.c
Merge pull request #2828 from mineo/run-help
[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
4dda4e63 40static int write_fsck_sysroot_service(const char *dir, const char *what) {
85eca92e 41 _cleanup_free_ char *device = NULL, *escaped = NULL;
4dda4e63 42 _cleanup_fclose_ FILE *f = NULL;
85eca92e 43 const char *unit;
4dda4e63
ZJS
44 int r;
45
fa05e972
AB
46 escaped = cescape(what);
47 if (!escaped)
48 return log_oom();
49
4dda4e63
ZJS
50 unit = strjoina(dir, "/systemd-fsck-root.service");
51 log_debug("Creating %s", unit);
52
53 r = unit_name_from_path(what, ".device", &device);
54 if (r < 0)
55 return log_error_errno(r, "Failed to convert device \"%s\" to unit name: %m", what);
56
57 f = fopen(unit, "wxe");
58 if (!f)
59 return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
60
61 fprintf(f,
62 "# Automatically generated by %1$s\n\n"
63 "[Unit]\n"
64 "Documentation=man:systemd-fsck-root.service(8)\n"
65 "Description=File System Check on %2$s\n"
66 "DefaultDependencies=no\n"
67 "BindsTo=%3$s\n"
5fd534d9 68 "After=%3$s local-fs-pre.target\n"
4dda4e63
ZJS
69 "Before=shutdown.target\n"
70 "\n"
71 "[Service]\n"
72 "Type=oneshot\n"
73 "RemainAfterExit=yes\n"
fa05e972 74 "ExecStart=" SYSTEMD_FSCK_PATH " %4$s\n"
4dda4e63
ZJS
75 "TimeoutSec=0\n",
76 program_invocation_short_name,
77 what,
fa05e972
AB
78 device,
79 escaped);
4dda4e63 80
2929b4a6
LP
81 r = fflush_and_check(f);
82 if (r < 0)
83 return log_error_errno(r, "Failed to write unit file %s: %m", unit);
4dda4e63
ZJS
84
85 return 0;
86}
87
e48fdd84
LP
88int generator_write_fsck_deps(
89 FILE *f,
2e852276 90 const char *dir,
e48fdd84
LP
91 const char *what,
92 const char *where,
6db615c1 93 const char *fstype) {
e48fdd84 94
7410616c
LP
95 int r;
96
e48fdd84 97 assert(f);
2e852276 98 assert(dir);
6db615c1
LP
99 assert(what);
100 assert(where);
e48fdd84
LP
101
102 if (!is_device_path(what)) {
103 log_warning("Checking was requested for \"%s\", but it is not a device.", what);
104 return 0;
105 }
106
6db615c1 107 if (!isempty(fstype) && !streq(fstype, "auto")) {
eb66db55 108 r = fsck_exists(fstype);
85eca92e
LP
109 if (r < 0)
110 log_warning_errno(r, "Checking was requested for %s, but couldn't detect if fsck.%s may be used, proceeding: %m", what, fstype);
111 else if (r == 0) {
e48fdd84 112 /* treat missing check as essentially OK */
85eca92e 113 log_debug("Checking was requested for %s, but fsck.%s does not exist.", what, fstype);
571d0134 114 return 0;
85eca92e 115 }
e48fdd84
LP
116 }
117
2e852276 118 if (path_equal(where, "/")) {
85eca92e 119 const char *lnk;
e48fdd84 120
2e852276 121 lnk = strjoina(dir, "/" SPECIAL_LOCAL_FS_TARGET ".wants/systemd-fsck-root.service");
e48fdd84
LP
122
123 mkdir_parents(lnk, 0755);
4a62c710
MS
124 if (symlink(SYSTEM_DATA_UNIT_PATH "/systemd-fsck-root.service", lnk) < 0)
125 return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
e48fdd84
LP
126
127 } else {
4dda4e63
ZJS
128 _cleanup_free_ char *_fsck = NULL;
129 const char *fsck;
130
131 if (in_initrd() && path_equal(where, "/sysroot")) {
132 r = write_fsck_sysroot_service(dir, what);
133 if (r < 0)
134 return r;
135
136 fsck = "systemd-fsck-root.service";
137 } else {
138 r = unit_name_from_path_instance("systemd-fsck", what, ".service", &_fsck);
139 if (r < 0)
140 return log_error_errno(r, "Failed to create fsck service name: %m");
141
142 fsck = _fsck;
143 }
e48fdd84
LP
144
145 fprintf(f,
f32b43bd 146 "Requires=%1$s\n"
2e852276 147 "After=%1$s\n",
e48fdd84
LP
148 fsck);
149 }
150
151 return 0;
152}
29686440 153
2e852276
ZJS
154int generator_write_timeouts(
155 const char *dir,
156 const char *what,
157 const char *where,
158 const char *opts,
159 char **filtered) {
29686440
ZJS
160
161 /* Allow configuration how long we wait for a device that
162 * backs a mount point to show up. This is useful to support
163 * endless device timeouts for devices that show up only after
164 * user input, like crypto devices. */
165
d15d0333 166 _cleanup_free_ char *node = NULL, *unit = NULL, *timeout = NULL;
29686440
ZJS
167 usec_t u;
168 int r;
29686440 169
d15d0333
ZJS
170 r = fstab_filter_options(opts, "comment=systemd.device-timeout\0" "x-systemd.device-timeout\0",
171 NULL, &timeout, filtered);
172 if (r <= 0)
173 return r;
b3208b66 174
d15d0333 175 r = parse_sec(timeout, &u);
29686440 176 if (r < 0) {
7410616c 177 log_warning("Failed to parse timeout for %s, ignoring: %s", where, timeout);
29686440
ZJS
178 return 0;
179 }
180
181 node = fstab_node_to_udev_node(what);
182 if (!node)
183 return log_oom();
184
7410616c
LP
185 r = unit_name_from_path(node, ".device", &unit);
186 if (r < 0)
187 return log_error_errno(r, "Failed to make unit name from path: %m");
29686440 188
8eea8687
ZJS
189 return write_drop_in_format(dir, unit, 50, "device-timeout",
190 "# Automatically generated by %s\n\n"
10c71477
FB
191 "[Unit]\nJobTimeoutSec=%s",
192 program_invocation_short_name, timeout);
29686440 193}