Bug Summary

File:build-scan/../src/sysv-generator/sysv-generator.c
Warning:line 375, column 25
Potential leak of memory pointed to by 'm'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name sysv-generator.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I systemd-sysv-generator.p -I . -I .. -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/sysv-generator/sysv-generator.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <errno(*__errno_location ()).h>
4#include <stdio.h>
5#include <unistd.h>
6
7#include "alloc-util.h"
8#include "dirent-util.h"
9#include "exit-status.h"
10#include "fd-util.h"
11#include "fileio.h"
12#include "generator.h"
13#include "hashmap.h"
14#include "hexdecoct.h"
15#include "install.h"
16#include "log.h"
17#include "mkdir.h"
18#include "path-lookup.h"
19#include "path-util.h"
20#include "set.h"
21#include "special.h"
22#include "specifier.h"
23#include "stat-util.h"
24#include "string-util.h"
25#include "strv.h"
26#include "unit-name.h"
27#include "util.h"
28
29static const struct {
30 const char *path;
31 const char *target;
32} rcnd_table[] = {
33 /* Standard SysV runlevels for start-up */
34 { "rc1.d", SPECIAL_RESCUE_TARGET"rescue.target" },
35 { "rc2.d", SPECIAL_MULTI_USER_TARGET"multi-user.target" },
36 { "rc3.d", SPECIAL_MULTI_USER_TARGET"multi-user.target" },
37 { "rc4.d", SPECIAL_MULTI_USER_TARGET"multi-user.target" },
38 { "rc5.d", SPECIAL_GRAPHICAL_TARGET"graphical.target" },
39
40 /* We ignore the SysV runlevels for shutdown here, as SysV services get default dependencies anyway, and that
41 * means they are shut down anyway at system power off if running. */
42};
43
44static const char *arg_dest = "/tmp";
45
46typedef struct SysvStub {
47 char *name;
48 char *path;
49 char *description;
50 int sysv_start_priority;
51 char *pid_file;
52 char **before;
53 char **after;
54 char **wants;
55 char **wanted_by;
56 bool_Bool has_lsb;
57 bool_Bool reload;
58 bool_Bool loaded;
59} SysvStub;
60
61static void free_sysvstub(SysvStub *s) {
62 if (!s)
63 return;
64
65 free(s->name);
66 free(s->path);
67 free(s->description);
68 free(s->pid_file);
69 strv_free(s->before);
70 strv_free(s->after);
71 strv_free(s->wants);
72 strv_free(s->wanted_by);
73 free(s);
74}
75
76DEFINE_TRIVIAL_CLEANUP_FUNC(SysvStub*, free_sysvstub)static inline void free_sysvstubp(SysvStub* *p) { if (*p) free_sysvstub
(*p); }
;
77
78static void free_sysvstub_hashmapp(Hashmap **h) {
79 hashmap_free_with_destructor(*h, free_sysvstub)({ ({ void *_item; while ((_item = hashmap_steal_first(*h))) free_sysvstub
(_item); }); hashmap_free(*h); })
;
80}
81
82static int add_alias(const char *service, const char *alias) {
83 const char *link;
84 int r;
85
86 assert(service)do { if ((__builtin_expect(!!(!(service)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("service"), "../src/sysv-generator/sysv-generator.c"
, 86, __PRETTY_FUNCTION__); } while (0)
;
87 assert(alias)do { if ((__builtin_expect(!!(!(alias)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("alias"), "../src/sysv-generator/sysv-generator.c"
, 87, __PRETTY_FUNCTION__); } while (0)
;
88
89 link = strjoina(arg_dest, "/", alias)({ const char *_appendees_[] = { arg_dest, "/", alias }; char
*_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ <
__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
90
91 r = symlink(service, link);
92 if (r < 0) {
93 if (errno(*__errno_location ()) == EEXIST17)
94 return 0;
95
96 return -errno(*__errno_location ());
97 }
98
99 return 1;
100}
101
102static int generate_unit_file(SysvStub *s) {
103 _cleanup_free___attribute__((cleanup(freep))) char *path_escaped = NULL((void*)0);
104 _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0);
105 const char *unit;
106 char **p;
107 int r;
108
109 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/sysv-generator/sysv-generator.c"
, 109, __PRETTY_FUNCTION__); } while (0)
;
110
111 if (!s->loaded)
112 return 0;
113
114 path_escaped = specifier_escape(s->path);
115 if (!path_escaped)
116 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 116, __func__)
;
117
118 unit = strjoina(arg_dest, "/", s->name)({ const char *_appendees_[] = { arg_dest, "/", s->name };
char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0;
_i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
119
120 /* We might already have a symlink with the same name from a Provides:,
121 * or from backup files like /etc/init.d/foo.bak. Real scripts always win,
122 * so remove an existing link */
123 if (is_symlink(unit) > 0) {
124 log_warning("Overwriting existing symlink %s with real service.", unit)({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/sysv-generator/sysv-generator.c", 124, __func__, "Overwriting existing symlink %s with real service."
, unit) : -abs(_e); })
;
125 (void) unlink(unit);
126 }
127
128 f = fopen(unit, "wxe");
129 if (!f)
130 return log_error_errno(errno, "Failed to create unit file %s: %m", unit)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/sysv-generator/sysv-generator.c"
, 130, __func__, "Failed to create unit file %s: %m", unit) :
-abs(_e); })
;
131
132 fprintf(f,
133 "# Automatically generated by systemd-sysv-generator\n\n"
134 "[Unit]\n"
135 "Documentation=man:systemd-sysv-generator(8)\n"
136 "SourcePath=%s\n",
137 path_escaped);
138
139 if (s->description) {
140 _cleanup_free___attribute__((cleanup(freep))) char *t;
141
142 t = specifier_escape(s->description);
143 if (!t)
144 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 144, __func__)
;
145
146 fprintf(f, "Description=%s\n", t);
147 }
148
149 STRV_FOREACH(p, s->before)for ((p) = (s->before); (p) && *(p); (p)++)
150 fprintf(f, "Before=%s\n", *p);
151 STRV_FOREACH(p, s->after)for ((p) = (s->after); (p) && *(p); (p)++)
152 fprintf(f, "After=%s\n", *p);
153 STRV_FOREACH(p, s->wants)for ((p) = (s->wants); (p) && *(p); (p)++)
154 fprintf(f, "Wants=%s\n", *p);
155
156 fprintf(f,
157 "\n[Service]\n"
158 "Type=forking\n"
159 "Restart=no\n"
160 "TimeoutSec=5min\n"
161 "IgnoreSIGPIPE=no\n"
162 "KillMode=process\n"
163 "GuessMainPID=no\n"
164 "RemainAfterExit=%s\n",
165 yes_no(!s->pid_file));
166
167 if (s->pid_file) {
168 _cleanup_free___attribute__((cleanup(freep))) char *t;
169
170 t = specifier_escape(s->pid_file);
171 if (!t)
172 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 172, __func__)
;
173
174 fprintf(f, "PIDFile=%s\n", t);
175 }
176
177 /* Consider two special LSB exit codes a clean exit */
178 if (s->has_lsb)
179 fprintf(f,
180 "SuccessExitStatus=%i %i\n",
181 EXIT_NOTINSTALLED,
182 EXIT_NOTCONFIGURED);
183
184 fprintf(f,
185 "ExecStart=%s start\n"
186 "ExecStop=%s stop\n",
187 path_escaped, path_escaped);
188
189 if (s->reload)
190 fprintf(f, "ExecReload=%s reload\n", path_escaped);
191
192 r = fflush_and_check(f);
193 if (r < 0)
194 return log_error_errno(r, "Failed to write unit %s: %m", unit)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/sysv-generator/sysv-generator.c", 194, __func__, "Failed to write unit %s: %m"
, unit) : -abs(_e); })
;
195
196 STRV_FOREACH(p, s->wanted_by)for ((p) = (s->wanted_by); (p) && *(p); (p)++)
197 (void) generator_add_symlink(arg_dest, *p, "wants", s->name);
198
199 return 1;
200}
201
202static bool_Bool usage_contains_reload(const char *line) {
203 return (strcasestr(line, "{reload|") ||
204 strcasestr(line, "{reload}") ||
205 strcasestr(line, "{reload\"") ||
206 strcasestr(line, "|reload|") ||
207 strcasestr(line, "|reload}") ||
208 strcasestr(line, "|reload\""));
209}
210
211static char *sysv_translate_name(const char *name) {
212 _cleanup_free___attribute__((cleanup(freep))) char *c = NULL((void*)0);
213 char *res;
214
215 c = strdup(name);
216 if (!c)
217 return NULL((void*)0);
218
219 res = endswith(c, ".sh");
220 if (res)
221 *res = 0;
222
223 if (unit_name_mangle(c, 0, &res) < 0)
224 return NULL((void*)0);
225
226 return res;
227}
228
229static int sysv_translate_facility(SysvStub *s, unsigned line, const char *name, char **ret) {
230
231 /* We silently ignore the $ prefix here. According to the LSB
232 * spec it simply indicates whether something is a
233 * standardized name or a distribution-specific one. Since we
234 * just follow what already exists and do not introduce new
235 * uses or names we don't care who introduced a new name. */
236
237 static const char * const table[] = {
238 /* LSB defined facilities */
239 "local_fs", NULL((void*)0),
240 "network", SPECIAL_NETWORK_ONLINE_TARGET"network-online.target",
241 "named", SPECIAL_NSS_LOOKUP_TARGET"nss-lookup.target",
242 "portmap", SPECIAL_RPCBIND_TARGET"rpcbind.target",
243 "remote_fs", SPECIAL_REMOTE_FS_TARGET"remote-fs.target",
244 "syslog", NULL((void*)0),
245 "time", SPECIAL_TIME_SYNC_TARGET"time-sync.target",
246 };
247
248 const char *filename;
249 char *filename_no_sh, *e, *m;
250 const char *n;
251 unsigned i;
252 int r;
253
254 assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("name"), "../src/sysv-generator/sysv-generator.c"
, 254, __PRETTY_FUNCTION__); } while (0)
;
43
Assuming 'name' is non-null
44
Taking false branch
45
Loop condition is false. Exiting loop
255 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/sysv-generator/sysv-generator.c"
, 255, __PRETTY_FUNCTION__); } while (0)
;
46
Taking false branch
47
Loop condition is false. Exiting loop
256 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/sysv-generator/sysv-generator.c"
, 256, __PRETTY_FUNCTION__); } while (0)
;
48
Taking false branch
49
Loop condition is false. Exiting loop
257
258 filename = basename(s->path);
259
260 n = *name == '$' ? name + 1 : name;
50
Assuming the condition is true
51
'?' condition is true
261
262 for (i = 0; i < ELEMENTSOF(table)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(table), typeof(&*(table))), sizeof(table)/sizeof(
(table)[0]), ((void)0)))
; i += 2) {
52
Loop condition is true. Entering loop body
56
Loop condition is true. Entering loop body
263 if (!streq(table[i], n)(strcmp((table[i]),(n)) == 0))
53
Assuming the condition is false
54
Taking true branch
57
Taking false branch
264 continue;
55
Execution continues on line 262
265
266 if (!table[i+1]) {
58
Taking false branch
267 *ret = NULL((void*)0);
268 return 0;
269 }
270
271 m = strdup(table[i+1]);
59
Memory is allocated
272 if (!m)
60
Assuming 'm' is non-null
61
Taking false branch
273 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 273, __func__)
;
274
275 *ret = m;
276 return 1;
277 }
278
279 /* If we don't know this name, fallback heuristics to figure
280 * out whether something is a target or a service alias. */
281
282 /* Facilities starting with $ are most likely targets */
283 if (*name == '$') {
284 r = unit_name_build(n, NULL((void*)0), ".target", ret);
285 if (r < 0)
286 return log_error_errno(r, "[%s:%u] Could not build name for facility %s: %m", s->path, line, name)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/sysv-generator/sysv-generator.c", 286, __func__, "[%s:%u] Could not build name for facility %s: %m"
, s->path, line, name) : -abs(_e); })
;
287
288 return 1;
289 }
290
291 /* Strip ".sh" suffix from file name for comparison */
292 filename_no_sh = strdupa(filename)(__extension__ ({ const char *__old = (filename); size_t __len
= strlen (__old) + 1; char *__new = (char *) __builtin_alloca
(__len); (char *) memcpy (__new, __old, __len); }))
;
293 e = endswith(filename_no_sh, ".sh");
294 if (e) {
295 *e = '\0';
296 filename = filename_no_sh;
297 }
298
299 /* Names equaling the file name of the services are redundant */
300 if (streq_ptr(n, filename)) {
301 *ret = NULL((void*)0);
302 return 0;
303 }
304
305 /* Everything else we assume to be normal service names */
306 m = sysv_translate_name(n);
307 if (!m)
308 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 308, __func__)
;
309
310 *ret = m;
311 return 1;
312}
313
314static int handle_provides(SysvStub *s, unsigned line, const char *full_text, const char *text) {
315 int r;
316
317 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/sysv-generator/sysv-generator.c"
, 317, __PRETTY_FUNCTION__); } while (0)
;
31
Taking false branch
32
Loop condition is false. Exiting loop
318 assert(full_text)do { if ((__builtin_expect(!!(!(full_text)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("full_text"), "../src/sysv-generator/sysv-generator.c"
, 318, __PRETTY_FUNCTION__); } while (0)
;
33
Taking false branch
34
Loop condition is false. Exiting loop
319 assert(text)do { if ((__builtin_expect(!!(!(text)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("text"), "../src/sysv-generator/sysv-generator.c"
, 319, __PRETTY_FUNCTION__); } while (0)
;
35
Taking false branch
36
Loop condition is false. Exiting loop
320
321 for (;;) {
37
Loop condition is true. Entering loop body
322 _cleanup_free___attribute__((cleanup(freep))) char *word = NULL((void*)0), *m = NULL((void*)0);
323
324 r = extract_first_word(&text, &word, NULL((void*)0), EXTRACT_QUOTES|EXTRACT_RELAX);
325 if (r < 0)
38
Assuming 'r' is >= 0
39
Taking false branch
326 return log_error_errno(r, "[%s:%u] Failed to parse word from provides string: %m", s->path, line)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/sysv-generator/sysv-generator.c", 326, __func__, "[%s:%u] Failed to parse word from provides string: %m"
, s->path, line) : -abs(_e); })
;
327 if (r == 0)
40
Assuming 'r' is not equal to 0
41
Taking false branch
328 break;
329
330 r = sysv_translate_facility(s, line, word, &m);
42
Calling 'sysv_translate_facility'
62
Returned allocated memory via 4th parameter
331 if (r
62.1
'r' is > 0
<= 0) /* continue on error */
63
Taking false branch
332 continue;
333
334 switch (unit_name_to_type(m)) {
64
Control jumps to the 'default' case at line 374
335
336 case UNIT_SERVICE:
337 log_debug("Adding Provides: alias '%s' for '%s'", m, s->name)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/sysv-generator/sysv-generator.c", 337, __func__, "Adding Provides: alias '%s' for '%s'"
, m, s->name) : -abs(_e); })
;
338 r = add_alias(s->name, m);
339 if (r < 0)
340 log_warning_errno(r, "[%s:%u] Failed to add LSB Provides name %s, ignoring: %m", s->path, line, m)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/sysv-generator/sysv-generator.c", 340, __func__, "[%s:%u] Failed to add LSB Provides name %s, ignoring: %m"
, s->path, line, m) : -abs(_e); })
;
341 break;
342
343 case UNIT_TARGET:
344
345 /* NB: SysV targets which are provided by a
346 * service are pulled in by the services, as
347 * an indication that the generic service is
348 * now available. This is strictly one-way.
349 * The targets do NOT pull in SysV services! */
350
351 r = strv_extend(&s->before, m);
352 if (r < 0)
353 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 353, __func__)
;
354
355 r = strv_extend(&s->wants, m);
356 if (r < 0)
357 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 357, __func__)
;
358
359 if (streq(m, SPECIAL_NETWORK_ONLINE_TARGET)(strcmp((m),("network-online.target")) == 0)) {
360 r = strv_extend(&s->before, SPECIAL_NETWORK_TARGET"network.target");
361 if (r < 0)
362 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 362, __func__)
;
363 r = strv_extend(&s->wants, SPECIAL_NETWORK_TARGET"network.target");
364 if (r < 0)
365 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 365, __func__)
;
366 }
367
368 break;
369
370 case _UNIT_TYPE_INVALID:
371 log_warning("Unit name '%s' is invalid", m)({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/sysv-generator/sysv-generator.c", 371, __func__, "Unit name '%s' is invalid"
, m) : -abs(_e); })
;
372 break;
373
374 default:
375 log_warning("Unknown unit type for unit '%s'", m)({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/sysv-generator/sysv-generator.c", 375, __func__, "Unknown unit type for unit '%s'"
, m) : -abs(_e); })
;
65
Assuming the condition is false
66
'?' condition is false
67
Potential leak of memory pointed to by 'm'
376 }
377 }
378
379 return 0;
380}
381
382static int handle_dependencies(SysvStub *s, unsigned line, const char *full_text, const char *text) {
383 int r;
384
385 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/sysv-generator/sysv-generator.c"
, 385, __PRETTY_FUNCTION__); } while (0)
;
386 assert(full_text)do { if ((__builtin_expect(!!(!(full_text)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("full_text"), "../src/sysv-generator/sysv-generator.c"
, 386, __PRETTY_FUNCTION__); } while (0)
;
387 assert(text)do { if ((__builtin_expect(!!(!(text)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("text"), "../src/sysv-generator/sysv-generator.c"
, 387, __PRETTY_FUNCTION__); } while (0)
;
388
389 for (;;) {
390 _cleanup_free___attribute__((cleanup(freep))) char *word = NULL((void*)0), *m = NULL((void*)0);
391 bool_Bool is_before;
392
393 r = extract_first_word(&text, &word, NULL((void*)0), EXTRACT_QUOTES|EXTRACT_RELAX);
394 if (r < 0)
395 return log_error_errno(r, "[%s:%u] Failed to parse word from provides string: %m", s->path, line)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/sysv-generator/sysv-generator.c", 395, __func__, "[%s:%u] Failed to parse word from provides string: %m"
, s->path, line) : -abs(_e); })
;
396 if (r == 0)
397 break;
398
399 r = sysv_translate_facility(s, line, word, &m);
400 if (r <= 0) /* continue on error */
401 continue;
402
403 is_before = startswith_no_case(full_text, "X-Start-Before:");
404
405 if (streq(m, SPECIAL_NETWORK_ONLINE_TARGET)(strcmp((m),("network-online.target")) == 0) && !is_before) {
406 /* the network-online target is special, as it needs to be actively pulled in */
407 r = strv_extend(&s->after, m);
408 if (r < 0)
409 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 409, __func__)
;
410
411 r = strv_extend(&s->wants, m);
412 } else
413 r = strv_extend(is_before ? &s->before : &s->after, m);
414 if (r < 0)
415 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 415, __func__)
;
416 }
417
418 return 0;
419}
420
421static int load_sysv(SysvStub *s) {
422 _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f;
423 unsigned line = 0;
424 int r;
425 enum {
426 NORMAL,
427 DESCRIPTION,
428 LSB,
429 LSB_DESCRIPTION,
430 USAGE_CONTINUATION
431 } state = NORMAL;
432 _cleanup_free___attribute__((cleanup(freep))) char *short_description = NULL((void*)0), *long_description = NULL((void*)0), *chkconfig_description = NULL((void*)0);
433 char *description;
434 bool_Bool supports_reload = false0;
435 char l[LINE_MAX2048];
436
437 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/sysv-generator/sysv-generator.c"
, 437, __PRETTY_FUNCTION__); } while (0)
;
1
Assuming 's' is non-null
2
Taking false branch
3
Loop condition is false. Exiting loop
438
439 f = fopen(s->path, "re");
440 if (!f) {
4
Assuming 'f' is non-null
5
Taking false branch
441 if (errno(*__errno_location ()) == ENOENT2)
442 return 0;
443
444 return log_error_errno(errno, "Failed to open %s: %m", s->path)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/sysv-generator/sysv-generator.c"
, 444, __func__, "Failed to open %s: %m", s->path) : -abs(
_e); })
;
445 }
446
447 log_debug("Loading SysV script %s", s->path)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/sysv-generator/sysv-generator.c", 447, __func__, "Loading SysV script %s"
, s->path) : -abs(_e); })
;
6
Assuming the condition is false
7
'?' condition is false
448
449 FOREACH_LINE(l, f, goto fail)for (;;) if (!fgets(l, sizeof(l), f)) { if (ferror(f)) { goto
fail; } break; } else
{
8
Loop condition is true. Entering loop body
9
Assuming the condition is false
10
Taking false branch
15
Loop condition is true. Entering loop body
16
Assuming the condition is false
17
Taking false branch
450 char *t;
451
452 line++;
453
454 t = strstrip(l);
455 if (*t != '#') {
11
Assuming the condition is false
12
Taking false branch
18
Assuming the condition is false
19
Taking false branch
456 /* Try to figure out whether this init script supports
457 * the reload operation. This heuristic looks for
458 * "Usage" lines which include the reload option. */
459 if ( state == USAGE_CONTINUATION ||
460 (state == NORMAL && strcasestr(t, "usage"))) {
461 if (usage_contains_reload(t)) {
462 supports_reload = true1;
463 state = NORMAL;
464 } else if (t[strlen(t)-1] == '\\')
465 state = USAGE_CONTINUATION;
466 else
467 state = NORMAL;
468 }
469
470 continue;
471 }
472
473 if (state
12.1
'state' is equal to NORMAL
19.1
'state' is not equal to NORMAL
== NORMAL && streq(t, "### BEGIN INIT INFO")(strcmp((t),("### BEGIN INIT INFO")) == 0)) {
13
Taking true branch
474 state = LSB;
475 s->has_lsb = true1;
476 continue;
14
Execution continues on line 449
477 }
478
479 if (IN_SET(state, LSB_DESCRIPTION, LSB)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){LSB_DESCRIPTION, LSB})/sizeof(int)]; switch
(state) { case LSB_DESCRIPTION: case LSB: _found = 1; break; default
: break; } _found; })
&& streq(t, "### END INIT INFO")(strcmp((t),("### END INIT INFO")) == 0)) {
20
Control jumps to 'case LSB:' at line 479
21
Execution continues on line 479
22
Assuming the condition is false
23
Taking false branch
480 state = NORMAL;
481 continue;
482 }
483
484 t++;
485 t += strspn(t, WHITESPACE" \t\n\r");
486
487 if (state
23.1
'state' is not equal to NORMAL
== NORMAL) {
24
Taking false branch
488
489 /* Try to parse Red Hat style description */
490
491 if (startswith_no_case(t, "description:")) {
492
493 size_t k;
494 const char *j;
495
496 k = strlen(t);
497 if (k > 0 && t[k-1] == '\\') {
498 state = DESCRIPTION;
499 t[k-1] = 0;
500 }
501
502 j = empty_to_null(strstrip(t+12));
503
504 r = free_and_strdup(&chkconfig_description, j);
505 if (r < 0)
506 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 506, __func__)
;
507
508 } else if (startswith_no_case(t, "pidfile:")) {
509 const char *fn;
510
511 state = NORMAL;
512
513 fn = strstrip(t+8);
514 if (!path_is_absolute(fn)) {
515 log_error("[%s:%u] PID file not absolute. Ignoring.", s->path, line)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/sysv-generator/sysv-generator.c", 515, __func__, "[%s:%u] PID file not absolute. Ignoring."
, s->path, line) : -abs(_e); })
;
516 continue;
517 }
518
519 r = free_and_strdup(&s->pid_file, fn);
520 if (r < 0)
521 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 521, __func__)
;
522 }
523
524 } else if (state
24.1
'state' is not equal to DESCRIPTION
== DESCRIPTION) {
25
Taking false branch
525
526 /* Try to parse Red Hat style description
527 * continuation */
528
529 size_t k;
530 char *j;
531
532 k = strlen(t);
533 if (k > 0 && t[k-1] == '\\')
534 t[k-1] = 0;
535 else
536 state = NORMAL;
537
538 j = strstrip(t);
539 if (!isempty(j)) {
540 char *d = NULL((void*)0);
541
542 if (chkconfig_description)
543 d = strjoin(chkconfig_description, " ", j)strjoin_real((chkconfig_description), " ", j, ((void*)0));
544 else
545 d = strdup(j);
546 if (!d)
547 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 547, __func__)
;
548
549 free(chkconfig_description);
550 chkconfig_description = d;
551 }
552
553 } else if (IN_SET(state, LSB, LSB_DESCRIPTION)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){LSB, LSB_DESCRIPTION})/sizeof(int)]; switch
(state) { case LSB: case LSB_DESCRIPTION: _found = 1; break; default
: break; } _found; })
) {
26
Control jumps to 'case LSB:' at line 553
27
Execution continues on line 553
28
Taking true branch
554
555 if (startswith_no_case(t, "Provides:")) {
29
Taking true branch
556 state = LSB;
557
558 r = handle_provides(s, line, t, t + 9);
30
Calling 'handle_provides'
559 if (r < 0)
560 return r;
561
562 } else if (startswith_no_case(t, "Required-Start:") ||
563 startswith_no_case(t, "Should-Start:") ||
564 startswith_no_case(t, "X-Start-Before:") ||
565 startswith_no_case(t, "X-Start-After:")) {
566
567 state = LSB;
568
569 r = handle_dependencies(s, line, t, strchr(t, ':') + 1);
570 if (r < 0)
571 return r;
572
573 } else if (startswith_no_case(t, "Description:")) {
574 const char *j;
575
576 state = LSB_DESCRIPTION;
577
578 j = empty_to_null(strstrip(t+12));
579
580 r = free_and_strdup(&long_description, j);
581 if (r < 0)
582 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 582, __func__)
;
583
584 } else if (startswith_no_case(t, "Short-Description:")) {
585 const char *j;
586
587 state = LSB;
588
589 j = empty_to_null(strstrip(t+18));
590
591 r = free_and_strdup(&short_description, j);
592 if (r < 0)
593 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 593, __func__)
;
594
595 } else if (state == LSB_DESCRIPTION) {
596
597 if (startswith(l, "#\t") || startswith(l, "# ")) {
598 const char *j;
599
600 j = strstrip(t);
601 if (!isempty(j)) {
602 char *d = NULL((void*)0);
603
604 if (long_description)
605 d = strjoin(long_description, " ", t)strjoin_real((long_description), " ", t, ((void*)0));
606 else
607 d = strdup(j);
608 if (!d)
609 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 609, __func__)
;
610
611 free(long_description);
612 long_description = d;
613 }
614
615 } else
616 state = LSB;
617 }
618 }
619 }
620
621 s->reload = supports_reload;
622
623 /* We use the long description only if
624 * no short description is set. */
625
626 if (short_description)
627 description = short_description;
628 else if (chkconfig_description)
629 description = chkconfig_description;
630 else if (long_description)
631 description = long_description;
632 else
633 description = NULL((void*)0);
634
635 if (description) {
636 char *d;
637
638 d = strappend(s->has_lsb ? "LSB: " : "SYSV: ", description);
639 if (!d)
640 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 640, __func__)
;
641
642 s->description = d;
643 }
644
645 s->loaded = true1;
646 return 0;
647
648fail:
649 return log_error_errno(errno, "Failed to read configuration file '%s': %m", s->path)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/sysv-generator/sysv-generator.c"
, 649, __func__, "Failed to read configuration file '%s': %m"
, s->path) : -abs(_e); })
;
650}
651
652static int fix_order(SysvStub *s, Hashmap *all_services) {
653 SysvStub *other;
654 Iterator j;
655 int r;
656
657 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/sysv-generator/sysv-generator.c"
, 657, __PRETTY_FUNCTION__); } while (0)
;
658
659 if (!s->loaded)
660 return 0;
661
662 if (s->sysv_start_priority < 0)
663 return 0;
664
665 HASHMAP_FOREACH(other, all_services, j)for ((j) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((all_services), &
(j), (void**)&(other), ((void*)0)); )
{
666 if (s == other)
667 continue;
668
669 if (!other->loaded)
670 continue;
671
672 if (other->sysv_start_priority < 0)
673 continue;
674
675 /* If both units have modern headers we don't care
676 * about the priorities */
677 if (s->has_lsb && other->has_lsb)
678 continue;
679
680 if (other->sysv_start_priority < s->sysv_start_priority) {
681 r = strv_extend(&s->after, other->name);
682 if (r < 0)
683 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 683, __func__)
;
684
685 } else if (other->sysv_start_priority > s->sysv_start_priority) {
686 r = strv_extend(&s->before, other->name);
687 if (r < 0)
688 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 688, __func__)
;
689 } else
690 continue;
691
692 /* FIXME: Maybe we should compare the name here lexicographically? */
693 }
694
695 return 0;
696}
697
698static int acquire_search_path(const char *def, const char *envvar, char ***ret) {
699 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **l = NULL((void*)0);
700 const char *e;
701 int r;
702
703 assert(def)do { if ((__builtin_expect(!!(!(def)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("def"), "../src/sysv-generator/sysv-generator.c"
, 703, __PRETTY_FUNCTION__); } while (0)
;
704 assert(envvar)do { if ((__builtin_expect(!!(!(envvar)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("envvar"), "../src/sysv-generator/sysv-generator.c"
, 704, __PRETTY_FUNCTION__); } while (0)
;
705
706 e = getenv(envvar);
707 if (e) {
708 r = path_split_and_make_absolute(e, &l);
709 if (r < 0)
710 return log_error_errno(r, "Failed to make $%s search path absolute: %m", envvar)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/sysv-generator/sysv-generator.c", 710, __func__, "Failed to make $%s search path absolute: %m"
, envvar) : -abs(_e); })
;
711 }
712
713 if (strv_isempty(l)) {
714 strv_free(l);
715
716 l = strv_new(def, NULL((void*)0));
717 if (!l)
718 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 718, __func__)
;
719 }
720
721 if (!path_strv_resolve_uniq(l, NULL((void*)0)))
722 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 722, __func__)
;
723
724 *ret = TAKE_PTR(l)({ typeof(l) _ptr_ = (l); (l) = ((void*)0); _ptr_; });
725
726 return 0;
727}
728
729static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
730 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **sysvinit_path = NULL((void*)0);
731 char **path;
732 int r;
733
734 assert(lp)do { if ((__builtin_expect(!!(!(lp)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("lp"), "../src/sysv-generator/sysv-generator.c"
, 734, __PRETTY_FUNCTION__); } while (0)
;
735
736 r = acquire_search_path(SYSTEM_SYSVINIT_PATH"/etc/init.d", "SYSTEMD_SYSVINIT_PATH", &sysvinit_path);
737 if (r < 0)
738 return r;
739
740 STRV_FOREACH(path, sysvinit_path)for ((path) = (sysvinit_path); (path) && *(path); (path
)++)
{
741 _cleanup_closedir___attribute__((cleanup(closedirp))) DIR *d = NULL((void*)0);
742 struct dirent *de;
743
744 d = opendir(*path);
745 if (!d) {
746 if (errno(*__errno_location ()) != ENOENT2)
747 log_warning_errno(errno, "Opening %s failed, ignoring: %m", *path)({ int _level = ((4)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/sysv-generator/sysv-generator.c"
, 747, __func__, "Opening %s failed, ignoring: %m", *path) : -
abs(_e); })
;
748 continue;
749 }
750
751 FOREACH_DIRENT(de, d, log_error_errno(errno, "Failed to enumerate directory %s, ignoring: %m", *path))for ((*__errno_location ()) = 0, de = readdir(d);; (*__errno_location
()) = 0, de = readdir(d)) if (!de) { if ((*__errno_location (
)) > 0) { ({ int _level = ((3)), _e = (((*__errno_location
()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm
(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((
_realm) << 10 | (_level)), _e, "../src/sysv-generator/sysv-generator.c"
, 751, __func__, "Failed to enumerate directory %s, ignoring: %m"
, *path) : -abs(_e); }); } break; } else if (hidden_or_backup_file
((de)->d_name)) continue; else
{
752 _cleanup_free___attribute__((cleanup(freep))) char *fpath = NULL((void*)0), *name = NULL((void*)0);
753 _cleanup_(free_sysvstubp)__attribute__((cleanup(free_sysvstubp))) SysvStub *service = NULL((void*)0);
754 struct stat st;
755
756 if (fstatat(dirfd(d), de->d_name, &st, 0) < 0) {
757 log_warning_errno(errno, "stat() failed on %s/%s, ignoring: %m", *path, de->d_name)({ int _level = ((4)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/sysv-generator/sysv-generator.c"
, 757, __func__, "stat() failed on %s/%s, ignoring: %m", *path
, de->d_name) : -abs(_e); })
;
758 continue;
759 }
760
761 if (!(st.st_mode & S_IXUSR0100))
762 continue;
763
764 if (!S_ISREG(st.st_mode)((((st.st_mode)) & 0170000) == (0100000)))
765 continue;
766
767 name = sysv_translate_name(de->d_name);
768 if (!name)
769 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 769, __func__)
;
770
771 if (hashmap_contains(all_services, name))
772 continue;
773
774 r = unit_file_exists(UNIT_FILE_SYSTEM, lp, name);
775 if (r < 0 && !IN_SET(r, -ELOOP, -ERFKILL, -EADDRNOTAVAIL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){-40, -132, -99})/sizeof(int)]; switch(r)
{ case -40: case -132: case -99: _found = 1; break; default:
break; } _found; })
) {
776 log_debug_errno(r, "Failed to detect whether %s exists, skipping: %m", name)({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/sysv-generator/sysv-generator.c", 776, __func__, "Failed to detect whether %s exists, skipping: %m"
, name) : -abs(_e); })
;
777 continue;
778 } else if (r != 0) {
779 log_debug("Native unit for %s already exists, skipping.", name)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/sysv-generator/sysv-generator.c", 779, __func__, "Native unit for %s already exists, skipping."
, name) : -abs(_e); })
;
780 continue;
781 }
782
783 fpath = strjoin(*path, "/", de->d_name)strjoin_real((*path), "/", de->d_name, ((void*)0));
784 if (!fpath)
785 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 785, __func__)
;
786
787 service = new0(SysvStub, 1)((SysvStub*) calloc((1), sizeof(SysvStub)));
788 if (!service)
789 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 789, __func__)
;
790
791 service->sysv_start_priority = -1;
792 service->name = TAKE_PTR(name)({ typeof(name) _ptr_ = (name); (name) = ((void*)0); _ptr_; }
)
;
793 service->path = TAKE_PTR(fpath)({ typeof(fpath) _ptr_ = (fpath); (fpath) = ((void*)0); _ptr_
; })
;
794
795 r = hashmap_put(all_services, service->name, service);
796 if (r < 0)
797 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 797, __func__)
;
798
799 service = NULL((void*)0);
800 }
801 }
802
803 return 0;
804}
805
806static int set_dependencies_from_rcnd(const LookupPaths *lp, Hashmap *all_services) {
807 Set *runlevel_services[ELEMENTSOF(rcnd_table)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(rcnd_table), typeof(&*(rcnd_table))), sizeof(rcnd_table
)/sizeof((rcnd_table)[0]), ((void)0)))
] = {};
808 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **sysvrcnd_path = NULL((void*)0);
809 SysvStub *service;
810 unsigned i;
811 Iterator j;
812 char **p;
813 int r;
814
815 assert(lp)do { if ((__builtin_expect(!!(!(lp)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("lp"), "../src/sysv-generator/sysv-generator.c"
, 815, __PRETTY_FUNCTION__); } while (0)
;
816
817 r = acquire_search_path(SYSTEM_SYSVRCND_PATH"/etc/rc.d", "SYSTEMD_SYSVRCND_PATH", &sysvrcnd_path);
818 if (r < 0)
819 return r;
820
821 STRV_FOREACH(p, sysvrcnd_path)for ((p) = (sysvrcnd_path); (p) && *(p); (p)++) {
822 for (i = 0; i < ELEMENTSOF(rcnd_table)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(rcnd_table), typeof(&*(rcnd_table))), sizeof(rcnd_table
)/sizeof((rcnd_table)[0]), ((void)0)))
; i ++) {
823
824 _cleanup_closedir___attribute__((cleanup(closedirp))) DIR *d = NULL((void*)0);
825 _cleanup_free___attribute__((cleanup(freep))) char *path = NULL((void*)0);
826 struct dirent *de;
827
828 path = strjoin(*p, "/", rcnd_table[i].path)strjoin_real((*p), "/", rcnd_table[i].path, ((void*)0));
829 if (!path) {
830 r = log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 830, __func__)
;
831 goto finish;
832 }
833
834 d = opendir(path);
835 if (!d) {
836 if (errno(*__errno_location ()) != ENOENT2)
837 log_warning_errno(errno, "Opening %s failed, ignoring: %m", path)({ int _level = ((4)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/sysv-generator/sysv-generator.c"
, 837, __func__, "Opening %s failed, ignoring: %m", path) : -
abs(_e); })
;
838
839 continue;
840 }
841
842 FOREACH_DIRENT(de, d, log_error_errno(errno, "Failed to enumerate directory %s, ignoring: %m", path))for ((*__errno_location ()) = 0, de = readdir(d);; (*__errno_location
()) = 0, de = readdir(d)) if (!de) { if ((*__errno_location (
)) > 0) { ({ int _level = ((3)), _e = (((*__errno_location
()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm
(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((
_realm) << 10 | (_level)), _e, "../src/sysv-generator/sysv-generator.c"
, 842, __func__, "Failed to enumerate directory %s, ignoring: %m"
, path) : -abs(_e); }); } break; } else if (hidden_or_backup_file
((de)->d_name)) continue; else
{
843 _cleanup_free___attribute__((cleanup(freep))) char *name = NULL((void*)0), *fpath = NULL((void*)0);
844 int a, b;
845
846 if (de->d_name[0] != 'S')
847 continue;
848
849 if (strlen(de->d_name) < 4)
850 continue;
851
852 a = undecchar(de->d_name[1]);
853 b = undecchar(de->d_name[2]);
854
855 if (a < 0 || b < 0)
856 continue;
857
858 fpath = strjoin(*p, "/", de->d_name)strjoin_real((*p), "/", de->d_name, ((void*)0));
859 if (!fpath) {
860 r = log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 860, __func__)
;
861 goto finish;
862 }
863
864 name = sysv_translate_name(de->d_name + 3);
865 if (!name) {
866 r = log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 866, __func__)
;
867 goto finish;
868 }
869
870 service = hashmap_get(all_services, name);
871 if (!service) {
872 log_debug("Ignoring %s symlink in %s, not generating %s.", de->d_name, rcnd_table[i].path, name)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/sysv-generator/sysv-generator.c", 872, __func__, "Ignoring %s symlink in %s, not generating %s."
, de->d_name, rcnd_table[i].path, name) : -abs(_e); })
;
873 continue;
874 }
875
876 service->sysv_start_priority = MAX(a*10 + b, service->sysv_start_priority)__extension__ ({ const typeof((a*10 + b)) __unique_prefix_A6 =
((a*10 + b)); const typeof((service->sysv_start_priority)
) __unique_prefix_B7 = ((service->sysv_start_priority)); __unique_prefix_A6
> __unique_prefix_B7 ? __unique_prefix_A6 : __unique_prefix_B7
; })
;
877
878 r = set_ensure_allocated(&runlevel_services[i], NULL)internal_set_ensure_allocated(&runlevel_services[i], ((void
*)0) )
;
879 if (r < 0) {
880 log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 880, __func__)
;
881 goto finish;
882 }
883
884 r = set_put(runlevel_services[i], service);
885 if (r < 0) {
886 log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 886, __func__)
;
887 goto finish;
888 }
889 }
890 }
891 }
892
893 for (i = 0; i < ELEMENTSOF(rcnd_table)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(rcnd_table), typeof(&*(rcnd_table))), sizeof(rcnd_table
)/sizeof((rcnd_table)[0]), ((void)0)))
; i ++)
894 SET_FOREACH(service, runlevel_services[i], j)for ((j) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); set_iterate((runlevel_services[i]),
&(j), (void**)&(service)); )
{
895 r = strv_extend(&service->before, rcnd_table[i].target);
896 if (r < 0) {
897 log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 897, __func__)
;
898 goto finish;
899 }
900 r = strv_extend(&service->wanted_by, rcnd_table[i].target);
901 if (r < 0) {
902 log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 902, __func__)
;
903 goto finish;
904 }
905 }
906
907 r = 0;
908
909finish:
910 for (i = 0; i < ELEMENTSOF(rcnd_table)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(rcnd_table), typeof(&*(rcnd_table))), sizeof(rcnd_table
)/sizeof((rcnd_table)[0]), ((void)0)))
; i++)
911 set_free(runlevel_services[i]);
912
913 return r;
914}
915
916int main(int argc, char *argv[]) {
917 _cleanup_(free_sysvstub_hashmapp)__attribute__((cleanup(free_sysvstub_hashmapp))) Hashmap *all_services = NULL((void*)0);
918 _cleanup_(lookup_paths_free)__attribute__((cleanup(lookup_paths_free))) LookupPaths lp = {};
919 SysvStub *service;
920 Iterator j;
921 int r;
922
923 if (argc > 1 && argc != 4) {
924 log_error("This program takes three or no arguments.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/sysv-generator/sysv-generator.c", 924, __func__, "This program takes three or no arguments."
) : -abs(_e); })
;
925 return EXIT_FAILURE1;
926 }
927
928 if (argc > 1)
929 arg_dest = argv[3];
930
931 log_set_prohibit_ipc(true1);
932 log_set_target(LOG_TARGET_AUTO);
933 log_parse_environment()log_parse_environment_realm(LOG_REALM_SYSTEMD);
934 log_open();
935
936 umask(0022);
937
938 r = lookup_paths_init(&lp, UNIT_FILE_SYSTEM, LOOKUP_PATHS_EXCLUDE_GENERATED, NULL((void*)0));
939 if (r < 0) {
940 log_error_errno(r, "Failed to find lookup paths: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/sysv-generator/sysv-generator.c", 940, __func__, "Failed to find lookup paths: %m"
) : -abs(_e); })
;
941 goto finish;
942 }
943
944 all_services = hashmap_new(&string_hash_ops)internal_hashmap_new(&string_hash_ops );
945 if (!all_services) {
946 r = log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/sysv-generator/sysv-generator.c"
, 946, __func__)
;
947 goto finish;
948 }
949
950 r = enumerate_sysv(&lp, all_services);
951 if (r < 0)
952 goto finish;
953
954 r = set_dependencies_from_rcnd(&lp, all_services);
955 if (r < 0)
956 goto finish;
957
958 HASHMAP_FOREACH(service, all_services, j)for ((j) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((all_services), &
(j), (void**)&(service), ((void*)0)); )
959 (void) load_sysv(service);
960
961 HASHMAP_FOREACH(service, all_services, j)for ((j) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((all_services), &
(j), (void**)&(service), ((void*)0)); )
{
962 (void) fix_order(service, all_services);
963 (void) generate_unit_file(service);
964 }
965
966 r = 0;
967
968finish:
969 return r < 0 ? EXIT_FAILURE1 : EXIT_SUCCESS0;
970}