Bug Summary

File:build-scan/../src/delta/delta.c
Warning:line 213, column 25
Potential leak of memory pointed to by 'unit'

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 delta.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-delta.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/delta/delta.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <errno(*__errno_location ()).h>
4#include <getopt.h>
5#include <string.h>
6#include <sys/prctl.h>
7#include <unistd.h>
8
9#include "alloc-util.h"
10#include "dirent-util.h"
11#include "fd-util.h"
12#include "fs-util.h"
13#include "hashmap.h"
14#include "locale-util.h"
15#include "log.h"
16#include "pager.h"
17#include "parse-util.h"
18#include "path-util.h"
19#include "process-util.h"
20#include "signal-util.h"
21#include "stat-util.h"
22#include "string-util.h"
23#include "strv.h"
24#include "terminal-util.h"
25#include "util.h"
26
27static const char prefixes[] =
28 "/etc\0"
29 "/run\0"
30 "/usr/local/lib\0"
31 "/usr/local/share\0"
32 "/usr/lib\0"
33 "/usr/share\0"
34#if HAVE_SPLIT_USR0
35 "/lib\0"
36#endif
37 ;
38
39static const char suffixes[] =
40 "sysctl.d\0"
41 "tmpfiles.d\0"
42 "modules-load.d\0"
43 "binfmt.d\0"
44 "systemd/system\0"
45 "systemd/user\0"
46 "systemd/system-preset\0"
47 "systemd/user-preset\0"
48 "udev/rules.d\0"
49 "modprobe.d\0";
50
51static const char have_dropins[] =
52 "systemd/system\0"
53 "systemd/user\0";
54
55static bool_Bool arg_no_pager = false0;
56static int arg_diff = -1;
57
58static enum {
59 SHOW_MASKED = 1 << 0,
60 SHOW_EQUIVALENT = 1 << 1,
61 SHOW_REDIRECTED = 1 << 2,
62 SHOW_OVERRIDDEN = 1 << 3,
63 SHOW_UNCHANGED = 1 << 4,
64 SHOW_EXTENDED = 1 << 5,
65
66 SHOW_DEFAULTS =
67 (SHOW_MASKED | SHOW_EQUIVALENT | SHOW_REDIRECTED | SHOW_OVERRIDDEN | SHOW_EXTENDED)
68} arg_flags = 0;
69
70static int equivalent(const char *a, const char *b) {
71 _cleanup_free___attribute__((cleanup(freep))) char *x = NULL((void*)0), *y = NULL((void*)0);
72 int r;
73
74 r = chase_symlinks(a, NULL((void*)0), CHASE_TRAIL_SLASH, &x);
75 if (r < 0)
76 return r;
77
78 r = chase_symlinks(b, NULL((void*)0), CHASE_TRAIL_SLASH, &y);
79 if (r < 0)
80 return r;
81
82 return path_equal(x, y);
83}
84
85static int notify_override_masked(const char *top, const char *bottom) {
86 if (!(arg_flags & SHOW_MASKED))
87 return 0;
88
89 printf("%s%s%s %s %s %s\n",
90 ansi_highlight_red(), "[MASKED]", ansi_normal(),
91 top, special_glyph(ARROW), bottom);
92 return 1;
93}
94
95static int notify_override_equivalent(const char *top, const char *bottom) {
96 if (!(arg_flags & SHOW_EQUIVALENT))
97 return 0;
98
99 printf("%s%s%s %s %s %s\n",
100 ansi_highlight_green(), "[EQUIVALENT]", ansi_normal(),
101 top, special_glyph(ARROW), bottom);
102 return 1;
103}
104
105static int notify_override_redirected(const char *top, const char *bottom) {
106 if (!(arg_flags & SHOW_REDIRECTED))
107 return 0;
108
109 printf("%s%s%s %s %s %s\n",
110 ansi_highlight(), "[REDIRECTED]", ansi_normal(),
111 top, special_glyph(ARROW), bottom);
112 return 1;
113}
114
115static int notify_override_overridden(const char *top, const char *bottom) {
116 if (!(arg_flags & SHOW_OVERRIDDEN))
117 return 0;
118
119 printf("%s%s%s %s %s %s\n",
120 ansi_highlight(), "[OVERRIDDEN]", ansi_normal(),
121 top, special_glyph(ARROW), bottom);
122 return 1;
123}
124
125static int notify_override_extended(const char *top, const char *bottom) {
126 if (!(arg_flags & SHOW_EXTENDED))
127 return 0;
128
129 printf("%s%s%s %s %s %s\n",
130 ansi_highlight(), "[EXTENDED]", ansi_normal(),
131 top, special_glyph(ARROW), bottom);
132 return 1;
133}
134
135static int notify_override_unchanged(const char *f) {
136 if (!(arg_flags & SHOW_UNCHANGED))
137 return 0;
138
139 printf("[UNCHANGED] %s\n", f);
140 return 1;
141}
142
143static int found_override(const char *top, const char *bottom) {
144 _cleanup_free___attribute__((cleanup(freep))) char *dest = NULL((void*)0);
145 pid_t pid;
146 int r;
147
148 assert(top)do { if ((__builtin_expect(!!(!(top)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("top"), "../src/delta/delta.c", 148, __PRETTY_FUNCTION__
); } while (0)
;
149 assert(bottom)do { if ((__builtin_expect(!!(!(bottom)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bottom"), "../src/delta/delta.c", 149, __PRETTY_FUNCTION__
); } while (0)
;
150
151 if (null_or_empty_path(top) > 0)
152 return notify_override_masked(top, bottom);
153
154 r = readlink_malloc(top, &dest);
155 if (r >= 0) {
156 if (equivalent(dest, bottom) > 0)
157 return notify_override_equivalent(top, bottom);
158 else
159 return notify_override_redirected(top, bottom);
160 }
161
162 r = notify_override_overridden(top, bottom);
163 if (!arg_diff)
164 return r;
165
166 putchar('\n');
167
168 fflush(stdoutstdout);
169
170 r = safe_fork("(diff)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
171 if (r < 0)
172 return r;
173 if (r == 0) {
174 execlp("diff", "diff", "-us", "--", bottom, top, NULL((void*)0));
175 log_open();
176 log_error_errno(errno, "Failed to execute diff: %m")({ 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/delta/delta.c", 176, __func__, "Failed to execute diff: %m"
) : -abs(_e); })
;
177 _exit(EXIT_FAILURE1);
178 }
179
180 (void) wait_for_terminate_and_check("diff", pid, WAIT_LOG_ABNORMAL);
181 putchar('\n');
182
183 return r;
184}
185
186static int enumerate_dir_d(
187 OrderedHashmap *top,
188 OrderedHashmap *bottom,
189 OrderedHashmap *drops,
190 const char *toppath, const char *drop) {
191
192 _cleanup_free___attribute__((cleanup(freep))) char *unit = NULL((void*)0);
193 _cleanup_free___attribute__((cleanup(freep))) char *path = NULL((void*)0);
194 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **list = NULL((void*)0);
195 char **file;
196 char *c;
197 int r;
198
199 assert(!endswith(drop, "/"))do { if ((__builtin_expect(!!(!(!endswith(drop, "/"))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("!endswith(drop, \"/\")"), "../src/delta/delta.c"
, 199, __PRETTY_FUNCTION__); } while (0)
;
67
Assuming the condition is true
68
Taking false branch
69
Loop condition is false. Exiting loop
200
201 path = strjoin(toppath, "/", drop)strjoin_real((toppath), "/", drop, ((void*)0));
202 if (!path)
70
Assuming 'path' is non-null
71
Taking false branch
203 return -ENOMEM12;
204
205 log_debug("Looking at %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/delta/delta.c", 205, __func__, "Looking at %s", path
) : -abs(_e); })
;
72
Assuming the condition is false
73
'?' condition is false
206
207 unit = strdup(drop);
74
Memory is allocated
208 if (!unit)
75
Assuming 'unit' is non-null
76
Taking false branch
209 return -ENOMEM12;
210
211 c = strrchr(unit, '.');
212 if (!c)
77
Assuming 'c' is null
78
Taking true branch
213 return -EINVAL22;
79
Potential leak of memory pointed to by 'unit'
214 *c = 0;
215
216 r = get_files_in_directory(path, &list);
217 if (r < 0)
218 return log_error_errno(r, "Failed to enumerate %s: %m", path)({ 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/delta/delta.c", 218, __func__, "Failed to enumerate %s: %m"
, path) : -abs(_e); })
;
219
220 strv_sort(list);
221
222 STRV_FOREACH(file, list)for ((file) = (list); (file) && *(file); (file)++) {
223 OrderedHashmap *h;
224 int k;
225 char *p;
226 char *d;
227
228 if (!endswith(*file, ".conf"))
229 continue;
230
231 p = strjoin(path, "/", *file)strjoin_real((path), "/", *file, ((void*)0));
232 if (!p)
233 return -ENOMEM12;
234 d = p + strlen(toppath) + 1;
235
236 log_debug("Adding at top: %s %s %s", d, special_glyph(ARROW), p)({ 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/delta/delta.c", 236, __func__, "Adding at top: %s %s %s"
, d, special_glyph(ARROW), p) : -abs(_e); })
;
237 k = ordered_hashmap_put(top, d, p);
238 if (k >= 0) {
239 p = strdup(p);
240 if (!p)
241 return -ENOMEM12;
242 d = p + strlen(toppath) + 1;
243 } else if (k != -EEXIST17) {
244 free(p);
245 return k;
246 }
247
248 log_debug("Adding at bottom: %s %s %s", d, special_glyph(ARROW), p)({ 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/delta/delta.c", 248, __func__, "Adding at bottom: %s %s %s"
, d, special_glyph(ARROW), p) : -abs(_e); })
;
249 free(ordered_hashmap_remove(bottom, d));
250 k = ordered_hashmap_put(bottom, d, p);
251 if (k < 0) {
252 free(p);
253 return k;
254 }
255
256 h = ordered_hashmap_get(drops, unit);
257 if (!h) {
258 h = ordered_hashmap_new(&string_hash_ops)internal_ordered_hashmap_new(&string_hash_ops );
259 if (!h)
260 return -ENOMEM12;
261 ordered_hashmap_put(drops, unit, h);
262 unit = strdup(unit);
263 if (!unit)
264 return -ENOMEM12;
265 }
266
267 p = strdup(p);
268 if (!p)
269 return -ENOMEM12;
270
271 log_debug("Adding to drops: %s %s %s %s %s",({ 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/delta/delta.c", 272, __func__, "Adding to drops: %s %s %s %s %s"
, unit, special_glyph(ARROW), basename(p), special_glyph(ARROW
), p) : -abs(_e); })
272 unit, special_glyph(ARROW), basename(p), special_glyph(ARROW), p)({ 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/delta/delta.c", 272, __func__, "Adding to drops: %s %s %s %s %s"
, unit, special_glyph(ARROW), basename(p), special_glyph(ARROW
), p) : -abs(_e); })
;
273 k = ordered_hashmap_put(h, basename(p), p);
274 if (k < 0) {
275 free(p);
276 if (k != -EEXIST17)
277 return k;
278 }
279 }
280 return 0;
281}
282
283static int enumerate_dir(
284 OrderedHashmap *top,
285 OrderedHashmap *bottom,
286 OrderedHashmap *drops,
287 const char *path, bool_Bool dropins) {
288
289 _cleanup_closedir___attribute__((cleanup(closedirp))) DIR *d = NULL((void*)0);
290 struct dirent *de;
291 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **files = NULL((void*)0), **dirs = NULL((void*)0);
292 size_t n_files = 0, allocated_files = 0, n_dirs = 0, allocated_dirs = 0;
293 char **t;
294 int r;
295
296 assert(top)do { if ((__builtin_expect(!!(!(top)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("top"), "../src/delta/delta.c", 296, __PRETTY_FUNCTION__
); } while (0)
;
33
Taking false branch
34
Loop condition is false. Exiting loop
297 assert(bottom)do { if ((__builtin_expect(!!(!(bottom)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bottom"), "../src/delta/delta.c", 297, __PRETTY_FUNCTION__
); } while (0)
;
35
Taking false branch
36
Loop condition is false. Exiting loop
298 assert(drops)do { if ((__builtin_expect(!!(!(drops)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("drops"), "../src/delta/delta.c", 298, __PRETTY_FUNCTION__
); } while (0)
;
37
Taking false branch
38
Loop condition is false. Exiting loop
299 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/delta/delta.c", 299, __PRETTY_FUNCTION__
); } while (0)
;
39
Taking false branch
40
Loop condition is false. Exiting loop
300
301 log_debug("Looking at %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/delta/delta.c", 301, __func__, "Looking at %s", path
) : -abs(_e); })
;
41
Assuming the condition is false
42
'?' condition is false
302
303 d = opendir(path);
304 if (!d) {
43
Assuming 'd' is non-null
44
Taking false branch
305 if (errno(*__errno_location ()) == ENOENT2)
306 return 0;
307
308 return log_error_errno(errno, "Failed to open %s: %m", 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/delta/delta.c", 308, __func__, "Failed to open %s: %m"
, path) : -abs(_e); })
;
309 }
310
311 FOREACH_DIRENT_ALL(de, d, return -errno)for ((*__errno_location ()) = 0, de = readdir(d);; (*__errno_location
()) = 0, de = readdir(d)) if (!de) { if ((*__errno_location (
)) > 0) { return -(*__errno_location ()); } break; } else
{
45
Loop condition is true. Entering loop body
46
Assuming 'de' is non-null
47
Taking false branch
59
Loop condition is true. Entering loop body
60
Assuming 'de' is null
61
Taking true branch
62
Assuming the condition is false
63
Taking false branch
64
Execution continues on line 336
312 dirent_ensure_type(d, de);
313
314 if (dropins && de->d_type == DT_DIRDT_DIR && endswith(de->d_name, ".d")) {
48
Assuming 'dropins' is true
49
Assuming field 'd_type' is equal to DT_DIR
50
Assuming the condition is true
51
Taking true branch
315 if (!GREEDY_REALLOC0(dirs, allocated_dirs, n_dirs + 2)greedy_realloc0((void**) &(dirs), &(allocated_dirs), (
n_dirs + 2), sizeof((dirs)[0]))
)
52
Assuming the condition is false
53
Taking false branch
316 return -ENOMEM12;
317
318 dirs[n_dirs] = strdup(de->d_name);
319 if (!dirs[n_dirs])
54
Assuming the condition is false
55
Taking false branch
320 return -ENOMEM12;
321 n_dirs ++;
322 }
323
324 if (!dirent_is_file(de))
56
Assuming the condition is true
57
Taking true branch
325 continue;
58
Execution continues on line 311
326
327 if (!GREEDY_REALLOC0(files, allocated_files, n_files + 2)greedy_realloc0((void**) &(files), &(allocated_files)
, (n_files + 2), sizeof((files)[0]))
)
328 return -ENOMEM12;
329
330 files[n_files] = strdup(de->d_name);
331 if (!files[n_files])
332 return -ENOMEM12;
333 n_files ++;
334 }
335
336 strv_sort(dirs);
337 strv_sort(files);
338
339 STRV_FOREACH(t, dirs)for ((t) = (dirs); (t) && *(t); (t)++) {
65
Loop condition is true. Entering loop body
340 r = enumerate_dir_d(top, bottom, drops, path, *t);
66
Calling 'enumerate_dir_d'
341 if (r < 0)
342 return r;
343 }
344
345 STRV_FOREACH(t, files)for ((t) = (files); (t) && *(t); (t)++) {
346 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
347
348 p = strjoin(path, "/", *t)strjoin_real((path), "/", *t, ((void*)0));
349 if (!p)
350 return -ENOMEM12;
351
352 log_debug("Adding at top: %s %s %s", basename(p), special_glyph(ARROW), p)({ 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/delta/delta.c", 352, __func__, "Adding at top: %s %s %s"
, basename(p), special_glyph(ARROW), p) : -abs(_e); })
;
353 r = ordered_hashmap_put(top, basename(p), p);
354 if (r >= 0) {
355 p = strdup(p);
356 if (!p)
357 return -ENOMEM12;
358 } else if (r != -EEXIST17)
359 return r;
360
361 log_debug("Adding at bottom: %s %s %s", basename(p), special_glyph(ARROW), p)({ 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/delta/delta.c", 361, __func__, "Adding at bottom: %s %s %s"
, basename(p), special_glyph(ARROW), p) : -abs(_e); })
;
362 free(ordered_hashmap_remove(bottom, basename(p)));
363 r = ordered_hashmap_put(bottom, basename(p), p);
364 if (r < 0)
365 return r;
366 p = NULL((void*)0);
367 }
368
369 return 0;
370}
371
372static bool_Bool should_skip_path(const char *prefix, const char *suffix) {
373#if HAVE_SPLIT_USR0
374 _cleanup_free___attribute__((cleanup(freep))) char *target = NULL((void*)0);
375 const char *p;
376 char *dirname;
377
378 dirname = strjoina(prefix, "/", suffix)({ const char *_appendees_[] = { prefix, "/", suffix }; 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_; })
;
379
380 if (chase_symlinks(dirname, NULL((void*)0), 0, &target) < 0)
381 return false0;
382
383 NULSTR_FOREACH(p, prefixes)for ((p) = (prefixes); (p) && *(p); (p) = strchr((p),
0)+1)
{
384 if (path_startswith(dirname, p))
385 continue;
386
387 if (path_equal(target, strjoina(p, "/", suffix)({ const char *_appendees_[] = { p, "/", suffix }; 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_; })
)) {
388 log_debug("%s redirects to %s, skipping.", dirname, target)({ 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/delta/delta.c", 388, __func__, "%s redirects to %s, skipping."
, dirname, target) : -abs(_e); })
;
389 return true1;
390 }
391 }
392#endif
393 return false0;
394}
395
396static int process_suffix(const char *suffix, const char *onlyprefix) {
397 const char *p;
398 char *f;
399 OrderedHashmap *top, *bottom, *drops;
400 OrderedHashmap *h;
401 char *key;
402 int r = 0, k;
403 Iterator i, j;
404 int n_found = 0;
405 bool_Bool dropins;
406
407 assert(suffix)do { if ((__builtin_expect(!!(!(suffix)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("suffix"), "../src/delta/delta.c", 407, __PRETTY_FUNCTION__
); } while (0)
;
17
Taking false branch
18
Loop condition is false. Exiting loop
408 assert(!startswith(suffix, "/"))do { if ((__builtin_expect(!!(!(!startswith(suffix, "/"))),0)
)) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!startswith(suffix, \"/\")"
), "../src/delta/delta.c", 408, __PRETTY_FUNCTION__); } while
(0)
;
19
Taking false branch
20
Loop condition is false. Exiting loop
409 assert(!strstr(suffix, "//"))do { if ((__builtin_expect(!!(!(!strstr(suffix, "//"))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("!strstr(suffix, \"//\")"), "../src/delta/delta.c"
, 409, __PRETTY_FUNCTION__); } while (0)
;
21
Assuming the condition is true
22
Taking false branch
23
Loop condition is false. Exiting loop
410
411 dropins = nulstr_contains(have_dropins, suffix);
412
413 top = ordered_hashmap_new(&string_hash_ops)internal_ordered_hashmap_new(&string_hash_ops );
414 bottom = ordered_hashmap_new(&string_hash_ops)internal_ordered_hashmap_new(&string_hash_ops );
415 drops = ordered_hashmap_new(&string_hash_ops)internal_ordered_hashmap_new(&string_hash_ops );
416 if (!top || !bottom || !drops) {
24
Assuming 'top' is non-null
25
Assuming 'bottom' is non-null
26
Assuming 'drops' is non-null
27
Taking false branch
417 r = -ENOMEM12;
418 goto finish;
419 }
420
421 NULSTR_FOREACH(p, prefixes)for ((p) = (prefixes); (p) && *(p); (p) = strchr((p),
0)+1)
{
28
Loop condition is true. Entering loop body
422 _cleanup_free___attribute__((cleanup(freep))) char *t = NULL((void*)0);
423
424 if (should_skip_path(p, suffix))
29
Taking false branch
425 continue;
426
427 t = strjoin(p, "/", suffix)strjoin_real((p), "/", suffix, ((void*)0));
428 if (!t) {
30
Assuming 't' is non-null
31
Taking false branch
429 r = -ENOMEM12;
430 goto finish;
431 }
432
433 k = enumerate_dir(top, bottom, drops, t, dropins);
32
Calling 'enumerate_dir'
434 if (r == 0)
435 r = k;
436 }
437
438 ORDERED_HASHMAP_FOREACH_KEY(f, key, top, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); ordered_hashmap_iterate((top), &
(i), (void**)&(f), (const void**) &(key)); )
{
439 char *o;
440
441 o = ordered_hashmap_get(bottom, key);
442 assert(o)do { if ((__builtin_expect(!!(!(o)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("o"), "../src/delta/delta.c", 442, __PRETTY_FUNCTION__
); } while (0)
;
443
444 if (!onlyprefix || startswith(o, onlyprefix)) {
445 if (path_equal(o, f)) {
446 notify_override_unchanged(f);
447 } else {
448 k = found_override(f, o);
449 if (k < 0)
450 r = k;
451 else
452 n_found += k;
453 }
454 }
455
456 h = ordered_hashmap_get(drops, key);
457 if (h)
458 ORDERED_HASHMAP_FOREACH(o, h, j)for ((j) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); ordered_hashmap_iterate((h), &(
j), (void**)&(o), ((void*)0)); )
459 if (!onlyprefix || startswith(o, onlyprefix))
460 n_found += notify_override_extended(f, o);
461 }
462
463finish:
464 ordered_hashmap_free_free(top);
465 ordered_hashmap_free_free(bottom);
466
467 ORDERED_HASHMAP_FOREACH_KEY(h, key, drops, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); ordered_hashmap_iterate((drops), &
(i), (void**)&(h), (const void**) &(key)); )
{
468 ordered_hashmap_free_free(ordered_hashmap_remove(drops, key));
469 ordered_hashmap_remove(drops, key);
470 free(key);
471 }
472 ordered_hashmap_free(drops);
473
474 return r < 0 ? r : n_found;
475}
476
477static int process_suffixes(const char *onlyprefix) {
478 const char *n;
479 int n_found = 0, r;
480
481 NULSTR_FOREACH(n, suffixes)for ((n) = (suffixes); (n) && *(n); (n) = strchr((n),
0)+1)
{
482 r = process_suffix(n, onlyprefix);
483 if (r < 0)
484 return r;
485
486 n_found += r;
487 }
488
489 return n_found;
490}
491
492static int process_suffix_chop(const char *arg) {
493 const char *p;
494
495 assert(arg)do { if ((__builtin_expect(!!(!(arg)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("arg"), "../src/delta/delta.c", 495, __PRETTY_FUNCTION__
); } while (0)
;
11
Assuming 'arg' is non-null
12
Taking false branch
13
Loop condition is false. Exiting loop
496
497 if (!path_is_absolute(arg))
14
Assuming the condition is true
15
Taking true branch
498 return process_suffix(arg, NULL((void*)0));
16
Calling 'process_suffix'
499
500 /* Strip prefix from the suffix */
501 NULSTR_FOREACH(p, prefixes)for ((p) = (prefixes); (p) && *(p); (p) = strchr((p),
0)+1)
{
502 const char *suffix;
503
504 suffix = startswith(arg, p);
505 if (suffix) {
506 suffix += strspn(suffix, "/");
507 if (*suffix)
508 return process_suffix(suffix, p);
509 else
510 return process_suffixes(arg);
511 }
512 }
513
514 log_error("Invalid suffix specification %s.", arg)({ 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/delta/delta.c", 514, __func__, "Invalid suffix specification %s."
, arg) : -abs(_e); })
;
515 return -EINVAL22;
516}
517
518static void help(void) {
519 printf("%s [OPTIONS...] [SUFFIX...]\n\n"
520 "Find overridden configuration files.\n\n"
521 " -h --help Show this help\n"
522 " --version Show package version\n"
523 " --no-pager Do not pipe output into a pager\n"
524 " --diff[=1|0] Show a diff when overridden files differ\n"
525 " -t --type=LIST... Only display a selected set of override types\n"
526 , program_invocation_short_name);
527}
528
529static int parse_flags(const char *flag_str, int flags) {
530 const char *word, *state;
531 size_t l;
532
533 FOREACH_WORD_SEPARATOR(word, l, flag_str, ",", state)for ((state) = (flag_str), (word) = split(&(state), &
(l), (","), (0)); (word); (word) = split(&(state), &(
l), (","), (0)))
{
534 if (strneq("masked", word, l)(strncmp(("masked"), (word), (l)) == 0))
535 flags |= SHOW_MASKED;
536 else if (strneq ("equivalent", word, l)(strncmp(("equivalent"), (word), (l)) == 0))
537 flags |= SHOW_EQUIVALENT;
538 else if (strneq("redirected", word, l)(strncmp(("redirected"), (word), (l)) == 0))
539 flags |= SHOW_REDIRECTED;
540 else if (strneq("overridden", word, l)(strncmp(("overridden"), (word), (l)) == 0))
541 flags |= SHOW_OVERRIDDEN;
542 else if (strneq("unchanged", word, l)(strncmp(("unchanged"), (word), (l)) == 0))
543 flags |= SHOW_UNCHANGED;
544 else if (strneq("extended", word, l)(strncmp(("extended"), (word), (l)) == 0))
545 flags |= SHOW_EXTENDED;
546 else if (strneq("default", word, l)(strncmp(("default"), (word), (l)) == 0))
547 flags |= SHOW_DEFAULTS;
548 else
549 return -EINVAL22;
550 }
551 return flags;
552}
553
554static int parse_argv(int argc, char *argv[]) {
555
556 enum {
557 ARG_NO_PAGER = 0x100,
558 ARG_DIFF,
559 ARG_VERSION
560 };
561
562 static const struct option options[] = {
563 { "help", no_argument0, NULL((void*)0), 'h' },
564 { "version", no_argument0, NULL((void*)0), ARG_VERSION },
565 { "no-pager", no_argument0, NULL((void*)0), ARG_NO_PAGER },
566 { "diff", optional_argument2, NULL((void*)0), ARG_DIFF },
567 { "type", required_argument1, NULL((void*)0), 't' },
568 {}
569 };
570
571 int c;
572
573 assert(argc >= 1)do { if ((__builtin_expect(!!(!(argc >= 1)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("argc >= 1"), "../src/delta/delta.c",
573, __PRETTY_FUNCTION__); } while (0)
;
574 assert(argv)do { if ((__builtin_expect(!!(!(argv)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("argv"), "../src/delta/delta.c", 574, __PRETTY_FUNCTION__
); } while (0)
;
575
576 while ((c = getopt_long(argc, argv, "ht:", options, NULL((void*)0))) >= 0)
577
578 switch (c) {
579
580 case 'h':
581 help();
582 return 0;
583
584 case ARG_VERSION:
585 return version();
586
587 case ARG_NO_PAGER:
588 arg_no_pager = true1;
589 break;
590
591 case 't': {
592 int f;
593 f = parse_flags(optarg, arg_flags);
594 if (f < 0) {
595 log_error("Failed to parse flags field.")({ 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/delta/delta.c", 595, __func__, "Failed to parse flags field."
) : -abs(_e); })
;
596 return -EINVAL22;
597 }
598 arg_flags = f;
599 break;
600 }
601
602 case ARG_DIFF:
603 if (!optarg)
604 arg_diff = 1;
605 else {
606 int b;
607
608 b = parse_boolean(optarg);
609 if (b < 0) {
610 log_error("Failed to parse diff boolean.")({ 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/delta/delta.c", 610, __func__, "Failed to parse diff boolean."
) : -abs(_e); })
;
611 return -EINVAL22;
612 }
613
614 arg_diff = b;
615 }
616 break;
617
618 case '?':
619 return -EINVAL22;
620
621 default:
622 assert_not_reached("Unhandled option")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, (
"Unhandled option"), "../src/delta/delta.c", 622, __PRETTY_FUNCTION__
); } while (0)
;
623 }
624
625 return 1;
626}
627
628int main(int argc, char *argv[]) {
629 int r, k, n_found = 0;
630
631 log_parse_environment()log_parse_environment_realm(LOG_REALM_SYSTEMD);
632 log_open();
633
634 r = parse_argv(argc, argv);
635 if (r
0.1
'r' is > 0
<= 0)
1
Taking false branch
636 goto finish;
637
638 if (arg_flags
1.1
'arg_flags' is equal to 0
== 0)
2
Taking true branch
639 arg_flags = SHOW_DEFAULTS;
640
641 if (arg_diff
2.1
'arg_diff' is < 0
< 0)
3
Taking true branch
642 arg_diff = !!(arg_flags & SHOW_OVERRIDDEN);
643 else if (arg_diff)
644 arg_flags |= SHOW_OVERRIDDEN;
645
646 (void) pager_open(arg_no_pager, false0);
647
648 if (optind < argc) {
4
Assuming 'optind' is < 'argc'
5
Taking true branch
649 int i;
650
651 for (i = optind; i
5.1
'i' is < 'argc'
< argc
; i++) {
6
Loop condition is true. Entering loop body
8
Assuming 'i' is < 'argc'
9
Loop condition is true. Entering loop body
652 path_simplify(argv[i], false0);
653
654 k = process_suffix_chop(argv[i]);
10
Calling 'process_suffix_chop'
655 if (k
6.1
'k' is < 0
< 0)
7
Taking true branch
656 r = k;
657 else
658 n_found += k;
659 }
660
661 } else {
662 k = process_suffixes(NULL((void*)0));
663 if (k < 0)
664 r = k;
665 else
666 n_found += k;
667 }
668
669 if (r >= 0)
670 printf("%s%i overridden configuration files found.\n", n_found ? "\n" : "", n_found);
671
672finish:
673 pager_close();
674
675 return r < 0 ? EXIT_FAILURE1 : EXIT_SUCCESS0;
676}