File: | build-scan/../src/libsystemd/sd-path/sd-path.c |
Warning: | line 632, column 12 Use of zero-allocated memory |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
2 | /*** | |||
3 | ***/ | |||
4 | ||||
5 | #include "sd-path.h" | |||
6 | ||||
7 | #include "alloc-util.h" | |||
8 | #include "architecture.h" | |||
9 | #include "fd-util.h" | |||
10 | #include "fileio.h" | |||
11 | #include "fs-util.h" | |||
12 | #include "missing.h" | |||
13 | #include "path-util.h" | |||
14 | #include "string-util.h" | |||
15 | #include "strv.h" | |||
16 | #include "user-util.h" | |||
17 | #include "util.h" | |||
18 | ||||
19 | static int from_environment(const char *envname, const char *fallback, const char **ret) { | |||
20 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/libsystemd/sd-path/sd-path.c" , 20, __PRETTY_FUNCTION__); } while (0); | |||
21 | ||||
22 | if (envname) { | |||
23 | const char *e; | |||
24 | ||||
25 | e = secure_getenv(envname); | |||
26 | if (e && path_is_absolute(e)) { | |||
27 | *ret = e; | |||
28 | return 0; | |||
29 | } | |||
30 | } | |||
31 | ||||
32 | if (fallback) { | |||
33 | *ret = fallback; | |||
34 | return 0; | |||
35 | } | |||
36 | ||||
37 | return -ENXIO6; | |||
38 | } | |||
39 | ||||
40 | static int from_home_dir(const char *envname, const char *suffix, char **buffer, const char **ret) { | |||
41 | _cleanup_free___attribute__((cleanup(freep))) char *h = NULL((void*)0); | |||
42 | char *cc = NULL((void*)0); | |||
43 | int r; | |||
44 | ||||
45 | assert(suffix)do { if ((__builtin_expect(!!(!(suffix)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("suffix"), "../src/libsystemd/sd-path/sd-path.c" , 45, __PRETTY_FUNCTION__); } while (0); | |||
46 | assert(buffer)do { if ((__builtin_expect(!!(!(buffer)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("buffer"), "../src/libsystemd/sd-path/sd-path.c" , 46, __PRETTY_FUNCTION__); } while (0); | |||
47 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/libsystemd/sd-path/sd-path.c" , 47, __PRETTY_FUNCTION__); } while (0); | |||
48 | ||||
49 | if (envname) { | |||
50 | const char *e = NULL((void*)0); | |||
51 | ||||
52 | e = secure_getenv(envname); | |||
53 | if (e && path_is_absolute(e)) { | |||
54 | *ret = e; | |||
55 | return 0; | |||
56 | } | |||
57 | } | |||
58 | ||||
59 | r = get_home_dir(&h); | |||
60 | if (r < 0) | |||
61 | return r; | |||
62 | ||||
63 | if (endswith(h, "/")) | |||
64 | cc = strappend(h, suffix); | |||
65 | else | |||
66 | cc = strjoin(h, "/", suffix)strjoin_real((h), "/", suffix, ((void*)0)); | |||
67 | if (!cc) | |||
68 | return -ENOMEM12; | |||
69 | ||||
70 | *buffer = cc; | |||
71 | *ret = cc; | |||
72 | return 0; | |||
73 | } | |||
74 | ||||
75 | static int from_user_dir(const char *field, char **buffer, const char **ret) { | |||
76 | _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0); | |||
77 | _cleanup_free___attribute__((cleanup(freep))) char *b = NULL((void*)0); | |||
78 | _cleanup_free___attribute__((cleanup(freep))) const char *fn = NULL((void*)0); | |||
79 | const char *c = NULL((void*)0); | |||
80 | char line[LINE_MAX2048]; | |||
81 | size_t n; | |||
82 | int r; | |||
83 | ||||
84 | assert(field)do { if ((__builtin_expect(!!(!(field)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("field"), "../src/libsystemd/sd-path/sd-path.c" , 84, __PRETTY_FUNCTION__); } while (0); | |||
85 | assert(buffer)do { if ((__builtin_expect(!!(!(buffer)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("buffer"), "../src/libsystemd/sd-path/sd-path.c" , 85, __PRETTY_FUNCTION__); } while (0); | |||
86 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/libsystemd/sd-path/sd-path.c" , 86, __PRETTY_FUNCTION__); } while (0); | |||
87 | ||||
88 | r = from_home_dir("XDG_CONFIG_HOME", ".config", &b, &c); | |||
89 | if (r < 0) | |||
90 | return r; | |||
91 | ||||
92 | fn = strappend(c, "/user-dirs.dirs"); | |||
93 | if (!fn) | |||
94 | return -ENOMEM12; | |||
95 | ||||
96 | f = fopen(fn, "re"); | |||
97 | if (!f) { | |||
98 | if (errno(*__errno_location ()) == ENOENT2) | |||
99 | goto fallback; | |||
100 | ||||
101 | return -errno(*__errno_location ()); | |||
102 | } | |||
103 | ||||
104 | /* This is an awful parse, but it follows closely what | |||
105 | * xdg-user-dirs does upstream */ | |||
106 | ||||
107 | n = strlen(field); | |||
108 | FOREACH_LINE(line, f, return -errno)for (;;) if (!fgets(line, sizeof(line), f)) { if (ferror(f)) { return -(*__errno_location ()); } break; } else { | |||
109 | char *l, *p, *e; | |||
110 | ||||
111 | l = strstrip(line); | |||
112 | ||||
113 | if (!strneq(l, field, n)(strncmp((l), (field), (n)) == 0)) | |||
114 | continue; | |||
115 | ||||
116 | p = l + n; | |||
117 | p += strspn(p, WHITESPACE" \t\n\r"); | |||
118 | ||||
119 | if (*p != '=') | |||
120 | continue; | |||
121 | p++; | |||
122 | ||||
123 | p += strspn(p, WHITESPACE" \t\n\r"); | |||
124 | ||||
125 | if (*p != '"') | |||
126 | continue; | |||
127 | p++; | |||
128 | ||||
129 | e = strrchr(p, '"'); | |||
130 | if (!e) | |||
131 | continue; | |||
132 | *e = 0; | |||
133 | ||||
134 | /* Three syntaxes permitted: relative to $HOME, $HOME itself, and absolute path */ | |||
135 | if (startswith(p, "$HOME/")) { | |||
136 | _cleanup_free___attribute__((cleanup(freep))) char *h = NULL((void*)0); | |||
137 | char *cc; | |||
138 | ||||
139 | r = get_home_dir(&h); | |||
140 | if (r < 0) | |||
141 | return r; | |||
142 | ||||
143 | cc = strappend(h, p+5); | |||
144 | if (!cc) | |||
145 | return -ENOMEM12; | |||
146 | ||||
147 | *buffer = cc; | |||
148 | *ret = cc; | |||
149 | return 0; | |||
150 | } else if (streq(p, "$HOME")(strcmp((p),("$HOME")) == 0)) { | |||
151 | ||||
152 | r = get_home_dir(buffer); | |||
153 | if (r < 0) | |||
154 | return r; | |||
155 | ||||
156 | *ret = *buffer; | |||
157 | return 0; | |||
158 | } else if (path_is_absolute(p)) { | |||
159 | char *copy; | |||
160 | ||||
161 | copy = strdup(p); | |||
162 | if (!copy) | |||
163 | return -ENOMEM12; | |||
164 | ||||
165 | *buffer = copy; | |||
166 | *ret = copy; | |||
167 | return 0; | |||
168 | } | |||
169 | } | |||
170 | ||||
171 | fallback: | |||
172 | /* The desktop directory defaults to $HOME/Desktop, the others to $HOME */ | |||
173 | if (streq(field, "XDG_DESKTOP_DIR")(strcmp((field),("XDG_DESKTOP_DIR")) == 0)) { | |||
174 | _cleanup_free___attribute__((cleanup(freep))) char *h = NULL((void*)0); | |||
175 | char *cc; | |||
176 | ||||
177 | r = get_home_dir(&h); | |||
178 | if (r < 0) | |||
179 | return r; | |||
180 | ||||
181 | cc = strappend(h, "/Desktop"); | |||
182 | if (!cc) | |||
183 | return -ENOMEM12; | |||
184 | ||||
185 | *buffer = cc; | |||
186 | *ret = cc; | |||
187 | } else { | |||
188 | ||||
189 | r = get_home_dir(buffer); | |||
190 | if (r < 0) | |||
191 | return r; | |||
192 | ||||
193 | *ret = *buffer; | |||
194 | } | |||
195 | ||||
196 | return 0; | |||
197 | } | |||
198 | ||||
199 | static int get_path(uint64_t type, char **buffer, const char **ret) { | |||
200 | int r; | |||
201 | ||||
202 | assert(buffer)do { if ((__builtin_expect(!!(!(buffer)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("buffer"), "../src/libsystemd/sd-path/sd-path.c" , 202, __PRETTY_FUNCTION__); } while (0); | |||
203 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/libsystemd/sd-path/sd-path.c" , 203, __PRETTY_FUNCTION__); } while (0); | |||
204 | ||||
205 | switch (type) { | |||
206 | ||||
207 | case SD_PATH_TEMPORARY: | |||
208 | return tmp_dir(ret); | |||
209 | ||||
210 | case SD_PATH_TEMPORARY_LARGE: | |||
211 | return var_tmp_dir(ret); | |||
212 | ||||
213 | case SD_PATH_SYSTEM_BINARIES: | |||
214 | *ret = "/usr/bin"; | |||
215 | return 0; | |||
216 | ||||
217 | case SD_PATH_SYSTEM_INCLUDE: | |||
218 | *ret = "/usr/include"; | |||
219 | return 0; | |||
220 | ||||
221 | case SD_PATH_SYSTEM_LIBRARY_PRIVATE: | |||
222 | *ret = "/usr/lib"; | |||
223 | return 0; | |||
224 | ||||
225 | case SD_PATH_SYSTEM_LIBRARY_ARCH: | |||
226 | *ret = LIBDIR"/usr/lib64"; | |||
227 | return 0; | |||
228 | ||||
229 | case SD_PATH_SYSTEM_SHARED: | |||
230 | *ret = "/usr/share"; | |||
231 | return 0; | |||
232 | ||||
233 | case SD_PATH_SYSTEM_CONFIGURATION_FACTORY: | |||
234 | *ret = "/usr/share/factory/etc"; | |||
235 | return 0; | |||
236 | ||||
237 | case SD_PATH_SYSTEM_STATE_FACTORY: | |||
238 | *ret = "/usr/share/factory/var"; | |||
239 | return 0; | |||
240 | ||||
241 | case SD_PATH_SYSTEM_CONFIGURATION: | |||
242 | *ret = "/etc"; | |||
243 | return 0; | |||
244 | ||||
245 | case SD_PATH_SYSTEM_RUNTIME: | |||
246 | *ret = "/run"; | |||
247 | return 0; | |||
248 | ||||
249 | case SD_PATH_SYSTEM_RUNTIME_LOGS: | |||
250 | *ret = "/run/log"; | |||
251 | return 0; | |||
252 | ||||
253 | case SD_PATH_SYSTEM_STATE_PRIVATE: | |||
254 | *ret = "/var/lib"; | |||
255 | return 0; | |||
256 | ||||
257 | case SD_PATH_SYSTEM_STATE_LOGS: | |||
258 | *ret = "/var/log"; | |||
259 | return 0; | |||
260 | ||||
261 | case SD_PATH_SYSTEM_STATE_CACHE: | |||
262 | *ret = "/var/cache"; | |||
263 | return 0; | |||
264 | ||||
265 | case SD_PATH_SYSTEM_STATE_SPOOL: | |||
266 | *ret = "/var/spool"; | |||
267 | return 0; | |||
268 | ||||
269 | case SD_PATH_USER_BINARIES: | |||
270 | return from_home_dir(NULL((void*)0), ".local/bin", buffer, ret); | |||
271 | ||||
272 | case SD_PATH_USER_LIBRARY_PRIVATE: | |||
273 | return from_home_dir(NULL((void*)0), ".local/lib", buffer, ret); | |||
274 | ||||
275 | case SD_PATH_USER_LIBRARY_ARCH: | |||
276 | return from_home_dir(NULL((void*)0), ".local/lib/" LIB_ARCH_TUPLE"x86_64-linux-gnu", buffer, ret); | |||
277 | ||||
278 | case SD_PATH_USER_SHARED: | |||
279 | return from_home_dir("XDG_DATA_HOME", ".local/share", buffer, ret); | |||
280 | ||||
281 | case SD_PATH_USER_CONFIGURATION: | |||
282 | return from_home_dir("XDG_CONFIG_HOME", ".config", buffer, ret); | |||
283 | ||||
284 | case SD_PATH_USER_RUNTIME: | |||
285 | return from_environment("XDG_RUNTIME_DIR", NULL((void*)0), ret); | |||
286 | ||||
287 | case SD_PATH_USER_STATE_CACHE: | |||
288 | return from_home_dir("XDG_CACHE_HOME", ".cache", buffer, ret); | |||
289 | ||||
290 | case SD_PATH_USER: | |||
291 | r = get_home_dir(buffer); | |||
292 | if (r < 0) | |||
293 | return r; | |||
294 | ||||
295 | *ret = *buffer; | |||
296 | return 0; | |||
297 | ||||
298 | case SD_PATH_USER_DOCUMENTS: | |||
299 | return from_user_dir("XDG_DOCUMENTS_DIR", buffer, ret); | |||
300 | ||||
301 | case SD_PATH_USER_MUSIC: | |||
302 | return from_user_dir("XDG_MUSIC_DIR", buffer, ret); | |||
303 | ||||
304 | case SD_PATH_USER_PICTURES: | |||
305 | return from_user_dir("XDG_PICTURES_DIR", buffer, ret); | |||
306 | ||||
307 | case SD_PATH_USER_VIDEOS: | |||
308 | return from_user_dir("XDG_VIDEOS_DIR", buffer, ret); | |||
309 | ||||
310 | case SD_PATH_USER_DOWNLOAD: | |||
311 | return from_user_dir("XDG_DOWNLOAD_DIR", buffer, ret); | |||
312 | ||||
313 | case SD_PATH_USER_PUBLIC: | |||
314 | return from_user_dir("XDG_PUBLICSHARE_DIR", buffer, ret); | |||
315 | ||||
316 | case SD_PATH_USER_TEMPLATES: | |||
317 | return from_user_dir("XDG_TEMPLATES_DIR", buffer, ret); | |||
318 | ||||
319 | case SD_PATH_USER_DESKTOP: | |||
320 | return from_user_dir("XDG_DESKTOP_DIR", buffer, ret); | |||
321 | } | |||
322 | ||||
323 | return -EOPNOTSUPP95; | |||
324 | } | |||
325 | ||||
326 | _public___attribute__ ((visibility("default"))) int sd_path_home(uint64_t type, const char *suffix, char **path) { | |||
327 | char *buffer = NULL((void*)0), *cc; | |||
328 | const char *ret; | |||
329 | int r; | |||
330 | ||||
331 | assert_return(path, -EINVAL)do { if (!(((__builtin_expect(!!(path),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-path/sd-path.c" , 331, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
| ||||
332 | ||||
333 | if (IN_SET(type,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT , SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH , SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY , SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION} )/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE : case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED : case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY : case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default : break; } _found; }) | |||
334 | SD_PATH_SEARCH_BINARIES,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT , SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH , SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY , SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION} )/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE : case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED : case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY : case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default : break; } _found; }) | |||
335 | SD_PATH_SEARCH_BINARIES_DEFAULT,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT , SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH , SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY , SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION} )/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE : case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED : case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY : case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default : break; } _found; }) | |||
336 | SD_PATH_SEARCH_LIBRARY_PRIVATE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT , SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH , SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY , SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION} )/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE : case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED : case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY : case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default : break; } _found; }) | |||
337 | SD_PATH_SEARCH_LIBRARY_ARCH,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT , SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH , SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY , SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION} )/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE : case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED : case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY : case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default : break; } _found; }) | |||
338 | SD_PATH_SEARCH_SHARED,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT , SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH , SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY , SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION} )/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE : case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED : case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY : case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default : break; } _found; }) | |||
339 | SD_PATH_SEARCH_CONFIGURATION_FACTORY,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT , SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH , SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY , SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION} )/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE : case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED : case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY : case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default : break; } _found; }) | |||
340 | SD_PATH_SEARCH_STATE_FACTORY,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT , SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH , SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY , SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION} )/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE : case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED : case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY : case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default : break; } _found; }) | |||
341 | SD_PATH_SEARCH_CONFIGURATION)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT , SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH , SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY , SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION} )/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE : case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED : case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY : case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default : break; } _found; })) { | |||
342 | ||||
343 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **l = NULL((void*)0); | |||
344 | ||||
345 | r = sd_path_search(type, suffix, &l); | |||
346 | if (r < 0) | |||
347 | return r; | |||
348 | ||||
349 | buffer = strv_join(l, ":"); | |||
350 | if (!buffer) | |||
351 | return -ENOMEM12; | |||
352 | ||||
353 | *path = buffer; | |||
354 | return 0; | |||
355 | } | |||
356 | ||||
357 | r = get_path(type, &buffer, &ret); | |||
358 | if (r < 0) | |||
359 | return r; | |||
360 | ||||
361 | if (!suffix) { | |||
362 | if (!buffer) { | |||
363 | buffer = strdup(ret); | |||
364 | if (!buffer) | |||
365 | return -ENOMEM12; | |||
366 | } | |||
367 | ||||
368 | *path = buffer; | |||
369 | return 0; | |||
370 | } | |||
371 | ||||
372 | suffix += strspn(suffix, "/"); | |||
373 | ||||
374 | if (endswith(ret, "/")) | |||
375 | cc = strappend(ret, suffix); | |||
376 | else | |||
377 | cc = strjoin(ret, "/", suffix)strjoin_real((ret), "/", suffix, ((void*)0)); | |||
378 | ||||
379 | free(buffer); | |||
380 | ||||
381 | if (!cc) | |||
382 | return -ENOMEM12; | |||
383 | ||||
384 | *path = cc; | |||
385 | return 0; | |||
386 | } | |||
387 | ||||
388 | static int search_from_environment( | |||
389 | char ***list, | |||
390 | const char *env_home, | |||
391 | const char *home_suffix, | |||
392 | const char *env_search, | |||
393 | bool_Bool env_search_sufficient, | |||
394 | const char *first, ...) { | |||
395 | ||||
396 | const char *e; | |||
397 | char *h = NULL((void*)0); | |||
398 | char **l = NULL((void*)0); | |||
399 | int r; | |||
400 | ||||
401 | assert(list)do { if ((__builtin_expect(!!(!(list)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("list"), "../src/libsystemd/sd-path/sd-path.c" , 401, __PRETTY_FUNCTION__); } while (0); | |||
402 | ||||
403 | if (env_search) { | |||
404 | e = secure_getenv(env_search); | |||
405 | if (e) { | |||
406 | l = strv_split(e, ":"); | |||
407 | if (!l) | |||
408 | return -ENOMEM12; | |||
409 | ||||
410 | if (env_search_sufficient) { | |||
411 | *list = l; | |||
412 | return 0; | |||
413 | } | |||
414 | } | |||
415 | } | |||
416 | ||||
417 | if (!l && first) { | |||
418 | va_list ap; | |||
419 | ||||
420 | va_start(ap, first)__builtin_va_start(ap, first); | |||
421 | l = strv_new_ap(first, ap); | |||
422 | va_end(ap)__builtin_va_end(ap); | |||
423 | ||||
424 | if (!l) | |||
425 | return -ENOMEM12; | |||
426 | } | |||
427 | ||||
428 | if (env_home) { | |||
429 | e = secure_getenv(env_home); | |||
430 | if (e && path_is_absolute(e)) { | |||
431 | h = strdup(e); | |||
432 | if (!h) { | |||
433 | strv_free(l); | |||
434 | return -ENOMEM12; | |||
435 | } | |||
436 | } | |||
437 | } | |||
438 | ||||
439 | if (!h && home_suffix) { | |||
440 | e = secure_getenv("HOME"); | |||
441 | if (e && path_is_absolute(e)) { | |||
442 | if (endswith(e, "/")) | |||
443 | h = strappend(e, home_suffix); | |||
444 | else | |||
445 | h = strjoin(e, "/", home_suffix)strjoin_real((e), "/", home_suffix, ((void*)0)); | |||
446 | ||||
447 | if (!h) { | |||
448 | strv_free(l); | |||
449 | return -ENOMEM12; | |||
450 | } | |||
451 | } | |||
452 | } | |||
453 | ||||
454 | if (h) { | |||
455 | r = strv_consume_prepend(&l, h); | |||
456 | if (r < 0) { | |||
457 | strv_free(l); | |||
458 | return -ENOMEM12; | |||
459 | } | |||
460 | } | |||
461 | ||||
462 | *list = l; | |||
463 | return 0; | |||
464 | } | |||
465 | ||||
466 | #if HAVE_SPLIT_BIN1 | |||
467 | # define ARRAY_SBIN_BIN(x)x "sbin", x "bin" x "sbin", x "bin" | |||
468 | #else | |||
469 | # define ARRAY_SBIN_BIN(x)x "sbin", x "bin" x "bin" | |||
470 | #endif | |||
471 | ||||
472 | static int get_search(uint64_t type, char ***list) { | |||
473 | ||||
474 | assert(list)do { if ((__builtin_expect(!!(!(list)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("list"), "../src/libsystemd/sd-path/sd-path.c" , 474, __PRETTY_FUNCTION__); } while (0); | |||
475 | ||||
476 | switch(type) { | |||
477 | ||||
478 | case SD_PATH_SEARCH_BINARIES: | |||
479 | return search_from_environment(list, | |||
480 | NULL((void*)0), | |||
481 | ".local/bin", | |||
482 | "PATH", | |||
483 | true1, | |||
484 | ARRAY_SBIN_BIN("/usr/local/")"/usr/local/" "sbin", "/usr/local/" "bin", | |||
485 | ARRAY_SBIN_BIN("/usr/")"/usr/" "sbin", "/usr/" "bin", | |||
486 | #if HAVE_SPLIT_USR0 | |||
487 | ARRAY_SBIN_BIN("/")"/" "sbin", "/" "bin", | |||
488 | #endif | |||
489 | NULL((void*)0)); | |||
490 | ||||
491 | case SD_PATH_SEARCH_LIBRARY_PRIVATE: | |||
492 | return search_from_environment(list, | |||
493 | NULL((void*)0), | |||
494 | ".local/lib", | |||
495 | NULL((void*)0), | |||
496 | false0, | |||
497 | "/usr/local/lib", | |||
498 | "/usr/lib", | |||
499 | #if HAVE_SPLIT_USR0 | |||
500 | "/lib", | |||
501 | #endif | |||
502 | NULL((void*)0)); | |||
503 | ||||
504 | case SD_PATH_SEARCH_LIBRARY_ARCH: | |||
505 | return search_from_environment(list, | |||
506 | NULL((void*)0), | |||
507 | ".local/lib/" LIB_ARCH_TUPLE"x86_64-linux-gnu", | |||
508 | "LD_LIBRARY_PATH", | |||
509 | true1, | |||
510 | LIBDIR"/usr/lib64", | |||
511 | #if HAVE_SPLIT_USR0 | |||
512 | ROOTLIBDIR"/usr/lib64", | |||
513 | #endif | |||
514 | NULL((void*)0)); | |||
515 | ||||
516 | case SD_PATH_SEARCH_SHARED: | |||
517 | return search_from_environment(list, | |||
518 | "XDG_DATA_HOME", | |||
519 | ".local/share", | |||
520 | "XDG_DATA_DIRS", | |||
521 | false0, | |||
522 | "/usr/local/share", | |||
523 | "/usr/share", | |||
524 | NULL((void*)0)); | |||
525 | ||||
526 | case SD_PATH_SEARCH_CONFIGURATION_FACTORY: | |||
527 | return search_from_environment(list, | |||
528 | NULL((void*)0), | |||
529 | NULL((void*)0), | |||
530 | NULL((void*)0), | |||
531 | false0, | |||
532 | "/usr/local/share/factory/etc", | |||
533 | "/usr/share/factory/etc", | |||
534 | NULL((void*)0)); | |||
535 | ||||
536 | case SD_PATH_SEARCH_STATE_FACTORY: | |||
537 | return search_from_environment(list, | |||
538 | NULL((void*)0), | |||
539 | NULL((void*)0), | |||
540 | NULL((void*)0), | |||
541 | false0, | |||
542 | "/usr/local/share/factory/var", | |||
543 | "/usr/share/factory/var", | |||
544 | NULL((void*)0)); | |||
545 | ||||
546 | case SD_PATH_SEARCH_CONFIGURATION: | |||
547 | return search_from_environment(list, | |||
548 | "XDG_CONFIG_HOME", | |||
549 | ".config", | |||
550 | "XDG_CONFIG_DIRS", | |||
551 | false0, | |||
552 | "/etc", | |||
553 | NULL((void*)0)); | |||
554 | ||||
555 | case SD_PATH_SEARCH_BINARIES_DEFAULT: { | |||
556 | char **t; | |||
557 | ||||
558 | t = strv_split_nulstr(DEFAULT_PATH_NULSTR"/usr/local/" "sbin\0" "/usr/local/" "bin\0" "/usr/" "sbin\0" "/usr/" "bin\0"); | |||
559 | if (!t) | |||
560 | return -ENOMEM12; | |||
561 | ||||
562 | *list = t; | |||
563 | return 0; | |||
564 | }} | |||
565 | ||||
566 | return -EOPNOTSUPP95; | |||
567 | } | |||
568 | ||||
569 | _public___attribute__ ((visibility("default"))) int sd_path_search(uint64_t type, const char *suffix, char ***paths) { | |||
570 | char **i, **j; | |||
571 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **l = NULL((void*)0), **n = NULL((void*)0); | |||
572 | int r; | |||
573 | ||||
574 | assert_return(paths, -EINVAL)do { if (!(((__builtin_expect(!!(paths),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("paths"), "../src/libsystemd/sd-path/sd-path.c" , 574, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
575 | ||||
576 | if (!IN_SET(type,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT , SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH , SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY , SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION} )/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE : case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED : case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY : case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default : break; } _found; }) | |||
577 | SD_PATH_SEARCH_BINARIES,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT , SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH , SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY , SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION} )/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE : case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED : case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY : case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default : break; } _found; }) | |||
578 | SD_PATH_SEARCH_BINARIES_DEFAULT,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT , SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH , SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY , SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION} )/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE : case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED : case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY : case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default : break; } _found; }) | |||
579 | SD_PATH_SEARCH_LIBRARY_PRIVATE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT , SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH , SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY , SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION} )/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE : case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED : case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY : case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default : break; } _found; }) | |||
580 | SD_PATH_SEARCH_LIBRARY_ARCH,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT , SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH , SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY , SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION} )/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE : case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED : case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY : case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default : break; } _found; }) | |||
581 | SD_PATH_SEARCH_SHARED,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT , SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH , SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY , SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION} )/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE : case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED : case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY : case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default : break; } _found; }) | |||
582 | SD_PATH_SEARCH_CONFIGURATION_FACTORY,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT , SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH , SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY , SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION} )/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE : case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED : case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY : case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default : break; } _found; }) | |||
583 | SD_PATH_SEARCH_STATE_FACTORY,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT , SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH , SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY , SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION} )/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE : case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED : case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY : case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default : break; } _found; }) | |||
584 | SD_PATH_SEARCH_CONFIGURATION)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT , SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH , SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY , SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION} )/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE : case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED : case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY : case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default : break; } _found; })) { | |||
585 | ||||
586 | char *p; | |||
587 | ||||
588 | r = sd_path_home(type, suffix, &p); | |||
589 | if (r < 0) | |||
590 | return r; | |||
591 | ||||
592 | l = new(char*, 2)((char**) malloc_multiply(sizeof(char*), (2))); | |||
593 | if (!l) { | |||
594 | free(p); | |||
595 | return -ENOMEM12; | |||
596 | } | |||
597 | ||||
598 | l[0] = p; | |||
599 | l[1] = NULL((void*)0); | |||
600 | ||||
601 | *paths = TAKE_PTR(l)({ typeof(l) _ptr_ = (l); (l) = ((void*)0); _ptr_; }); | |||
602 | return 0; | |||
603 | } | |||
604 | ||||
605 | r = get_search(type, &l); | |||
606 | if (r < 0) | |||
607 | return r; | |||
608 | ||||
609 | if (!suffix) { | |||
610 | *paths = TAKE_PTR(l)({ typeof(l) _ptr_ = (l); (l) = ((void*)0); _ptr_; }); | |||
611 | return 0; | |||
612 | } | |||
613 | ||||
614 | n = new(char*, strv_length(l)+1)((char**) malloc_multiply(sizeof(char*), (strv_length(l)+1))); | |||
615 | if (!n) | |||
616 | return -ENOMEM12; | |||
617 | ||||
618 | j = n; | |||
619 | STRV_FOREACH(i, l)for ((i) = (l); (i) && *(i); (i)++) { | |||
620 | ||||
621 | if (endswith(*i, "/")) | |||
622 | *j = strappend(*i, suffix); | |||
623 | else | |||
624 | *j = strjoin(*i, "/", suffix)strjoin_real((*i), "/", suffix, ((void*)0)); | |||
625 | ||||
626 | if (!*j) | |||
627 | return -ENOMEM12; | |||
628 | ||||
629 | j++; | |||
630 | } | |||
631 | ||||
632 | *j = NULL((void*)0); | |||
| ||||
633 | *paths = TAKE_PTR(n)({ typeof(n) _ptr_ = (n); (n) = ((void*)0); _ptr_; }); | |||
634 | return 0; | |||
635 | } |
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
2 | #pragma once |
3 | |
4 | #include <alloca.h> |
5 | #include <stddef.h> |
6 | #include <stdlib.h> |
7 | #include <string.h> |
8 | |
9 | #include "macro.h" |
10 | |
11 | #define new(t, n)((t*) malloc_multiply(sizeof(t), (n))) ((t*) malloc_multiply(sizeof(t), (n))) |
12 | |
13 | #define new0(t, n)((t*) calloc((n), sizeof(t))) ((t*) calloc((n), sizeof(t))) |
14 | |
15 | #define newa(t, n)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)" ), "../src/basic/alloc-util.h", 15, __PRETTY_FUNCTION__); } while (0); (t*) __builtin_alloca (sizeof(t)*(n)); }) \ |
16 | ({ \ |
17 | assert(!size_multiply_overflow(sizeof(t), n))do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)" ), "../src/basic/alloc-util.h", 17, __PRETTY_FUNCTION__); } while (0); \ |
18 | (t*) alloca(sizeof(t)*(n))__builtin_alloca (sizeof(t)*(n)); \ |
19 | }) |
20 | |
21 | #define newa0(t, n)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)" ), "../src/basic/alloc-util.h", 21, __PRETTY_FUNCTION__); } while (0); (t*) ({ char *_new_; size_t _len_ = sizeof(t)*(n); _new_ = __builtin_alloca (_len_); (void *) memset(_new_, 0, _len_) ; }); }) \ |
22 | ({ \ |
23 | assert(!size_multiply_overflow(sizeof(t), n))do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)" ), "../src/basic/alloc-util.h", 23, __PRETTY_FUNCTION__); } while (0); \ |
24 | (t*) alloca0(sizeof(t)*(n))({ char *_new_; size_t _len_ = sizeof(t)*(n); _new_ = __builtin_alloca (_len_); (void *) memset(_new_, 0, _len_); }); \ |
25 | }) |
26 | |
27 | #define newdup(t, p, n)((t*) memdup_multiply(p, sizeof(t), (n))) ((t*) memdup_multiply(p, sizeof(t), (n))) |
28 | |
29 | #define newdup_suffix0(t, p, n)((t*) memdup_suffix0_multiply(p, sizeof(t), (n))) ((t*) memdup_suffix0_multiply(p, sizeof(t), (n))) |
30 | |
31 | #define malloc0(n)(calloc(1, (n))) (calloc(1, (n))) |
32 | |
33 | static inline void *mfree(void *memory) { |
34 | free(memory); |
35 | return NULL((void*)0); |
36 | } |
37 | |
38 | #define free_and_replace(a, b)({ free(a); (a) = (b); (b) = ((void*)0); 0; }) \ |
39 | ({ \ |
40 | free(a); \ |
41 | (a) = (b); \ |
42 | (b) = NULL((void*)0); \ |
43 | 0; \ |
44 | }) |
45 | |
46 | void* memdup(const void *p, size_t l) _alloc_(2); |
47 | void* memdup_suffix0(const void *p, size_t l) _alloc_(2); |
48 | |
49 | static inline void freep(void *p) { |
50 | free(*(void**) p); |
51 | } |
52 | |
53 | #define _cleanup_free___attribute__((cleanup(freep))) _cleanup_(freep)__attribute__((cleanup(freep))) |
54 | |
55 | static inline bool_Bool size_multiply_overflow(size_t size, size_t need) { |
56 | return _unlikely_(need != 0 && size > (SIZE_MAX / need))(__builtin_expect(!!(need != 0 && size > ((18446744073709551615UL ) / need)),0)); |
57 | } |
58 | |
59 | _malloc___attribute__ ((malloc)) _alloc_(1, 2) static inline void *malloc_multiply(size_t size, size_t need) { |
60 | if (size_multiply_overflow(size, need)) |
61 | return NULL((void*)0); |
62 | |
63 | return malloc(size * need); |
64 | } |
65 | |
66 | #if !HAVE_REALLOCARRAY1 |
67 | _alloc_(2, 3) static inline void *reallocarray(void *p, size_t need, size_t size) { |
68 | if (size_multiply_overflow(size, need)) |
69 | return NULL((void*)0); |
70 | |
71 | return realloc(p, size * need); |
72 | } |
73 | #endif |
74 | |
75 | _alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) { |
76 | if (size_multiply_overflow(size, need)) |
77 | return NULL((void*)0); |
78 | |
79 | return memdup(p, size * need); |
80 | } |
81 | |
82 | _alloc_(2, 3) static inline void *memdup_suffix0_multiply(const void *p, size_t size, size_t need) { |
83 | if (size_multiply_overflow(size, need)) |
84 | return NULL((void*)0); |
85 | |
86 | return memdup_suffix0(p, size * need); |
87 | } |
88 | |
89 | void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size); |
90 | void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size); |
91 | |
92 | #define GREEDY_REALLOC(array, allocated, need)greedy_realloc((void**) &(array), &(allocated), (need ), sizeof((array)[0])) \ |
93 | greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0])) |
94 | |
95 | #define GREEDY_REALLOC0(array, allocated, need)greedy_realloc0((void**) &(array), &(allocated), (need ), sizeof((array)[0])) \ |
96 | greedy_realloc0((void**) &(array), &(allocated), (need), sizeof((array)[0])) |
97 | |
98 | #define alloca0(n)({ char *_new_; size_t _len_ = n; _new_ = __builtin_alloca (_len_ ); (void *) memset(_new_, 0, _len_); }) \ |
99 | ({ \ |
100 | char *_new_; \ |
101 | size_t _len_ = n; \ |
102 | _new_ = alloca(_len_)__builtin_alloca (_len_); \ |
103 | (void *) memset(_new_, 0, _len_); \ |
104 | }) |
105 | |
106 | /* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */ |
107 | #define alloca_align(size, align)({ void *_ptr_; size_t _mask_ = (align) - 1; _ptr_ = __builtin_alloca ((size) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); }) \ |
108 | ({ \ |
109 | void *_ptr_; \ |
110 | size_t _mask_ = (align) - 1; \ |
111 | _ptr_ = alloca((size) + _mask_)__builtin_alloca ((size) + _mask_); \ |
112 | (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \ |
113 | }) |
114 | |
115 | #define alloca0_align(size, align)({ void *_new_; size_t _size_ = (size); _new_ = ({ void *_ptr_ ; size_t _mask_ = ((align)) - 1; _ptr_ = __builtin_alloca ((_size_ ) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_ ); }); (void*)memset(_new_, 0, _size_); }) \ |
116 | ({ \ |
117 | void *_new_; \ |
118 | size_t _size_ = (size); \ |
119 | _new_ = alloca_align(_size_, (align))({ void *_ptr_; size_t _mask_ = ((align)) - 1; _ptr_ = __builtin_alloca ((_size_) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); }); \ |
120 | (void*)memset(_new_, 0, _size_); \ |
121 | }) |
122 | |
123 | /* Takes inspiration from Rusts's Option::take() method: reads and returns a pointer, but at the same time resets it to |
124 | * NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */ |
125 | #define TAKE_PTR(ptr)({ typeof(ptr) _ptr_ = (ptr); (ptr) = ((void*)0); _ptr_; }) \ |
126 | ({ \ |
127 | typeof(ptr) _ptr_ = (ptr); \ |
128 | (ptr) = NULL((void*)0); \ |
129 | _ptr_; \ |
130 | }) |