File: | build-scan/../src/delta/delta.c |
Warning: | line 213, column 25 Potential leak of memory pointed to by 'unit' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
27 | static 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 | ||||
39 | static 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 | ||||
51 | static const char have_dropins[] = | |||
52 | "systemd/system\0" | |||
53 | "systemd/user\0"; | |||
54 | ||||
55 | static bool_Bool arg_no_pager = false0; | |||
56 | static int arg_diff = -1; | |||
57 | ||||
58 | static 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 | ||||
70 | static 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 | ||||
85 | static 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 | ||||
95 | static 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 | ||||
105 | static 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 | ||||
115 | static 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 | ||||
125 | static 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 | ||||
135 | static 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 | ||||
143 | static 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 | ||||
186 | static 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); | |||
200 | ||||
201 | path = strjoin(toppath, "/", drop)strjoin_real((toppath), "/", drop, ((void*)0)); | |||
202 | if (!path) | |||
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); }); | |||
206 | ||||
207 | unit = strdup(drop); | |||
208 | if (!unit) | |||
209 | return -ENOMEM12; | |||
210 | ||||
211 | c = strrchr(unit, '.'); | |||
212 | if (!c) | |||
213 | return -EINVAL22; | |||
| ||||
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 | ||||
283 | static 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); | |||
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); | |||
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); | |||
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); | |||
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); }); | |||
302 | ||||
303 | d = opendir(path); | |||
304 | if (!d) { | |||
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 { | |||
312 | dirent_ensure_type(d, de); | |||
313 | ||||
314 | if (dropins && de->d_type == DT_DIRDT_DIR && endswith(de->d_name, ".d")) { | |||
315 | if (!GREEDY_REALLOC0(dirs, allocated_dirs, n_dirs + 2)greedy_realloc0((void**) &(dirs), &(allocated_dirs), ( n_dirs + 2), sizeof((dirs)[0]))) | |||
316 | return -ENOMEM12; | |||
317 | ||||
318 | dirs[n_dirs] = strdup(de->d_name); | |||
319 | if (!dirs[n_dirs]) | |||
320 | return -ENOMEM12; | |||
321 | n_dirs ++; | |||
322 | } | |||
323 | ||||
324 | if (!dirent_is_file(de)) | |||
325 | continue; | |||
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)++) { | |||
340 | r = enumerate_dir_d(top, bottom, drops, path, *t); | |||
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 | ||||
372 | static 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 | ||||
396 | static 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); | |||
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); | |||
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); | |||
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) { | |||
417 | r = -ENOMEM12; | |||
418 | goto finish; | |||
419 | } | |||
420 | ||||
421 | NULSTR_FOREACH(p, prefixes)for ((p) = (prefixes); (p) && *(p); (p) = strchr((p), 0)+1) { | |||
422 | _cleanup_free___attribute__((cleanup(freep))) char *t = NULL((void*)0); | |||
423 | ||||
424 | if (should_skip_path(p, suffix)) | |||
425 | continue; | |||
426 | ||||
427 | t = strjoin(p, "/", suffix)strjoin_real((p), "/", suffix, ((void*)0)); | |||
428 | if (!t) { | |||
429 | r = -ENOMEM12; | |||
430 | goto finish; | |||
431 | } | |||
432 | ||||
433 | k = enumerate_dir(top, bottom, drops, t, dropins); | |||
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 | ||||
463 | finish: | |||
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 | ||||
477 | static 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 | ||||
492 | static 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); | |||
496 | ||||
497 | if (!path_is_absolute(arg)) | |||
498 | return process_suffix(arg, NULL((void*)0)); | |||
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 | ||||
518 | static 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 | ||||
529 | static 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 | ||||
554 | static 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 | ||||
628 | int 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
| |||
| ||||
636 | goto finish; | |||
637 | ||||
638 | if (arg_flags
| |||
639 | arg_flags = SHOW_DEFAULTS; | |||
640 | ||||
641 | if (arg_diff
| |||
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) { | |||
649 | int i; | |||
650 | ||||
651 | for (i = optind; i
| |||
652 | path_simplify(argv[i], false0); | |||
653 | ||||
654 | k = process_suffix_chop(argv[i]); | |||
655 | if (k
| |||
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 | ||||
672 | finish: | |||
673 | pager_close(); | |||
674 | ||||
675 | return r < 0 ? EXIT_FAILURE1 : EXIT_SUCCESS0; | |||
676 | } |