]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-path/sd-path.c
ci: enable arm64 runner for build/unit jobs
[thirdparty/systemd.git] / src / libsystemd / sd-path / sd-path.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
9a00f57a 2
5cdf13c7
DDM
3#include <stdlib.h>
4
07630cea
LP
5#include "sd-path.h"
6
b5efdb8a 7#include "alloc-util.h"
9a00f57a 8#include "architecture.h"
3ffd4af2 9#include "fd-util.h"
0d39fa9c 10#include "fileio.h"
fccb4486 11#include "fs-util.h"
cd7d732d 12#include "network-util.h"
08af3cc5 13#include "nulstr-util.h"
9c5bb203 14#include "path-lookup.h"
9a00f57a 15#include "path-util.h"
07630cea 16#include "string-util.h"
9a00f57a 17#include "strv.h"
b1d4f8e1 18#include "user-util.h"
9a00f57a
LP
19
20static int from_environment(const char *envname, const char *fallback, const char **ret) {
21 assert(ret);
22
23 if (envname) {
24 const char *e;
25
26 e = secure_getenv(envname);
27 if (e && path_is_absolute(e)) {
28 *ret = e;
29 return 0;
30 }
31 }
32
33 if (fallback) {
34 *ret = fallback;
35 return 0;
36 }
37
38 return -ENXIO;
39}
40
d2cd1893
LP
41static int from_home_dir(
42 const char *envname,
43 const char *suffix,
44 char **buffer,
45 const char **ret) {
46
9a00f57a 47 _cleanup_free_ char *h = NULL;
9a00f57a
LP
48 int r;
49
50 assert(suffix);
51 assert(buffer);
52 assert(ret);
53
54 if (envname) {
55 const char *e = NULL;
56
57 e = secure_getenv(envname);
58 if (e && path_is_absolute(e)) {
59 *ret = e;
60 return 0;
61 }
62 }
63
64 r = get_home_dir(&h);
65 if (r < 0)
66 return r;
67
4ede9802 68 if (!path_extend(&h, suffix))
9a00f57a
LP
69 return -ENOMEM;
70
4ede9802
LP
71 *buffer = h;
72 *ret = TAKE_PTR(h);
9a00f57a
LP
73 return 0;
74}
75
8664dd3c
MY
76static int from_xdg_user_dir(const char *field, char **buffer, const char **ret) {
77 _cleanup_free_ char *user_dirs = NULL;
9a00f57a 78 _cleanup_fclose_ FILE *f = NULL;
9a00f57a
LP
79 int r;
80
81 assert(field);
82 assert(buffer);
83 assert(ret);
84
8664dd3c 85 r = sd_path_lookup(SD_PATH_USER_CONFIGURATION, "user-dirs.dirs", &user_dirs);
9a00f57a
LP
86 if (r < 0)
87 return r;
88
8664dd3c 89 f = fopen(user_dirs, "re");
9a00f57a
LP
90 if (!f) {
91 if (errno == ENOENT)
92 goto fallback;
93
94 return -errno;
95 }
96
0ff6ff2b 97 /* This is an awful parse, but it follows closely what xdg-user-dirs does upstream */
710bf2ae
LP
98 for (;;) {
99 _cleanup_free_ char *line = NULL;
0ff6ff2b 100 char *p, *e;
9a00f57a 101
0ff6ff2b 102 r = read_stripped_line(f, LONG_LINE_MAX, &line);
710bf2ae
LP
103 if (r < 0)
104 return r;
105 if (r == 0)
106 break;
107
0ff6ff2b
LP
108 p = startswith(line, field);
109 if (!p)
9a00f57a
LP
110 continue;
111
8664dd3c 112 p = skip_leading_chars(p, WHITESPACE);
9a00f57a
LP
113 if (*p != '=')
114 continue;
115 p++;
116
8664dd3c 117 p = skip_leading_chars(p, WHITESPACE);
9a00f57a
LP
118 if (*p != '"')
119 continue;
120 p++;
121
122 e = strrchr(p, '"');
123 if (!e)
124 continue;
125 *e = 0;
126
127 /* Three syntaxes permitted: relative to $HOME, $HOME itself, and absolute path */
8664dd3c
MY
128 if (streq(p, "$HOME"))
129 goto home;
9a00f57a 130
8664dd3c
MY
131 const char *s = startswith(p, "$HOME/");
132 if (s)
133 return from_home_dir(/* envname = */ NULL, s, buffer, ret);
9a00f57a 134
8664dd3c
MY
135 if (path_is_absolute(p)) {
136 char *c = strdup(p);
137 if (!c)
9a00f57a
LP
138 return -ENOMEM;
139
8664dd3c 140 *ret = *buffer = c;
9a00f57a
LP
141 return 0;
142 }
143 }
144
145fallback:
146 /* The desktop directory defaults to $HOME/Desktop, the others to $HOME */
8664dd3c
MY
147 if (streq(field, "XDG_DESKTOP_DIR"))
148 return from_home_dir(/* envname = */ NULL, "Desktop", buffer, ret);
9a00f57a 149
8664dd3c
MY
150home:
151 r = get_home_dir(buffer);
152 if (r < 0)
153 return r;
9a00f57a 154
8664dd3c 155 *ret = *buffer;
9a00f57a
LP
156 return 0;
157}
158
159static int get_path(uint64_t type, char **buffer, const char **ret) {
160 int r;
161
162 assert(buffer);
163 assert(ret);
164
165 switch (type) {
166
167 case SD_PATH_TEMPORARY:
fccb4486 168 return tmp_dir(ret);
9a00f57a
LP
169
170 case SD_PATH_TEMPORARY_LARGE:
fccb4486 171 return var_tmp_dir(ret);
9a00f57a
LP
172
173 case SD_PATH_SYSTEM_BINARIES:
174 *ret = "/usr/bin";
175 return 0;
176
177 case SD_PATH_SYSTEM_INCLUDE:
178 *ret = "/usr/include";
179 return 0;
180
181 case SD_PATH_SYSTEM_LIBRARY_PRIVATE:
182 *ret = "/usr/lib";
183 return 0;
184
185 case SD_PATH_SYSTEM_LIBRARY_ARCH:
186 *ret = LIBDIR;
187 return 0;
188
189 case SD_PATH_SYSTEM_SHARED:
190 *ret = "/usr/share";
191 return 0;
192
193 case SD_PATH_SYSTEM_CONFIGURATION_FACTORY:
194 *ret = "/usr/share/factory/etc";
195 return 0;
196
197 case SD_PATH_SYSTEM_STATE_FACTORY:
198 *ret = "/usr/share/factory/var";
199 return 0;
200
201 case SD_PATH_SYSTEM_CONFIGURATION:
202 *ret = "/etc";
203 return 0;
204
205 case SD_PATH_SYSTEM_RUNTIME:
206 *ret = "/run";
207 return 0;
208
209 case SD_PATH_SYSTEM_RUNTIME_LOGS:
210 *ret = "/run/log";
211 return 0;
212
213 case SD_PATH_SYSTEM_STATE_PRIVATE:
214 *ret = "/var/lib";
215 return 0;
216
217 case SD_PATH_SYSTEM_STATE_LOGS:
218 *ret = "/var/log";
219 return 0;
220
221 case SD_PATH_SYSTEM_STATE_CACHE:
222 *ret = "/var/cache";
223 return 0;
224
225 case SD_PATH_SYSTEM_STATE_SPOOL:
226 *ret = "/var/spool";
227 return 0;
228
229 case SD_PATH_USER_BINARIES:
230 return from_home_dir(NULL, ".local/bin", buffer, ret);
231
232 case SD_PATH_USER_LIBRARY_PRIVATE:
233 return from_home_dir(NULL, ".local/lib", buffer, ret);
234
235 case SD_PATH_USER_LIBRARY_ARCH:
613e3a26 236 return from_home_dir(NULL, ".local/lib/" LIB_ARCH_TUPLE, buffer, ret);
9a00f57a
LP
237
238 case SD_PATH_USER_SHARED:
239 return from_home_dir("XDG_DATA_HOME", ".local/share", buffer, ret);
240
241 case SD_PATH_USER_CONFIGURATION:
242 return from_home_dir("XDG_CONFIG_HOME", ".config", buffer, ret);
243
244 case SD_PATH_USER_RUNTIME:
245 return from_environment("XDG_RUNTIME_DIR", NULL, ret);
246
247 case SD_PATH_USER_STATE_CACHE:
248 return from_home_dir("XDG_CACHE_HOME", ".cache", buffer, ret);
249
9a653235
LP
250 case SD_PATH_USER_STATE_PRIVATE:
251 return from_home_dir("XDG_STATE_HOME", ".local/state", buffer, ret);
252
9a00f57a
LP
253 case SD_PATH_USER:
254 r = get_home_dir(buffer);
255 if (r < 0)
256 return r;
257
258 *ret = *buffer;
259 return 0;
260
261 case SD_PATH_USER_DOCUMENTS:
8664dd3c 262 return from_xdg_user_dir("XDG_DOCUMENTS_DIR", buffer, ret);
9a00f57a
LP
263
264 case SD_PATH_USER_MUSIC:
8664dd3c 265 return from_xdg_user_dir("XDG_MUSIC_DIR", buffer, ret);
9a00f57a
LP
266
267 case SD_PATH_USER_PICTURES:
8664dd3c 268 return from_xdg_user_dir("XDG_PICTURES_DIR", buffer, ret);
9a00f57a
LP
269
270 case SD_PATH_USER_VIDEOS:
8664dd3c 271 return from_xdg_user_dir("XDG_VIDEOS_DIR", buffer, ret);
9a00f57a
LP
272
273 case SD_PATH_USER_DOWNLOAD:
8664dd3c 274 return from_xdg_user_dir("XDG_DOWNLOAD_DIR", buffer, ret);
9a00f57a
LP
275
276 case SD_PATH_USER_PUBLIC:
8664dd3c 277 return from_xdg_user_dir("XDG_PUBLICSHARE_DIR", buffer, ret);
9a00f57a
LP
278
279 case SD_PATH_USER_TEMPLATES:
8664dd3c 280 return from_xdg_user_dir("XDG_TEMPLATES_DIR", buffer, ret);
9a00f57a
LP
281
282 case SD_PATH_USER_DESKTOP:
8664dd3c 283 return from_xdg_user_dir("XDG_DESKTOP_DIR", buffer, ret);
9c5bb203 284
ccdf03b9 285 case SD_PATH_SYSTEMD_UTIL:
b0d3095f 286 *ret = PREFIX_NOSLASH "/lib/systemd";
9c5bb203
ZJS
287 return 0;
288
ccdf03b9 289 case SD_PATH_SYSTEMD_SYSTEM_UNIT:
835cf75a 290 *ret = SYSTEM_DATA_UNIT_DIR;
9c5bb203
ZJS
291 return 0;
292
ccdf03b9 293 case SD_PATH_SYSTEMD_SYSTEM_PRESET:
b0d3095f 294 *ret = PREFIX_NOSLASH "/lib/systemd/system-preset";
9c5bb203
ZJS
295 return 0;
296
ccdf03b9 297 case SD_PATH_SYSTEMD_USER_UNIT:
96d33e4a 298 *ret = USER_DATA_UNIT_DIR;
9c5bb203
ZJS
299 return 0;
300
ccdf03b9 301 case SD_PATH_SYSTEMD_USER_PRESET:
b0d3095f 302 *ret = PREFIX_NOSLASH "/lib/systemd/user-preset";
9c5bb203
ZJS
303 return 0;
304
4a8c3951
D
305 case SD_PATH_SYSTEMD_INITRD_PRESET:
306 *ret = PREFIX_NOSLASH "/lib/systemd/initrd-preset";
307 return 0;
308
ccdf03b9 309 case SD_PATH_SYSTEMD_SYSTEM_CONF:
96d33e4a 310 *ret = SYSTEM_CONFIG_UNIT_DIR;
9c5bb203
ZJS
311 return 0;
312
ccdf03b9 313 case SD_PATH_SYSTEMD_USER_CONF:
96d33e4a 314 *ret = USER_CONFIG_UNIT_DIR;
9c5bb203
ZJS
315 return 0;
316
ccdf03b9 317 case SD_PATH_SYSTEMD_SYSTEM_GENERATOR:
96d33e4a 318 *ret = SYSTEM_GENERATOR_DIR;
9c5bb203
ZJS
319 return 0;
320
ccdf03b9 321 case SD_PATH_SYSTEMD_USER_GENERATOR:
96d33e4a 322 *ret = USER_GENERATOR_DIR;
9c5bb203
ZJS
323 return 0;
324
ccdf03b9 325 case SD_PATH_SYSTEMD_SLEEP:
b0d3095f 326 *ret = PREFIX_NOSLASH "/lib/systemd/system-sleep";
9c5bb203
ZJS
327 return 0;
328
ccdf03b9 329 case SD_PATH_SYSTEMD_SHUTDOWN:
b0d3095f 330 *ret = PREFIX_NOSLASH "/lib/systemd/system-shutdown";
9c5bb203
ZJS
331 return 0;
332
ccdf03b9 333 case SD_PATH_TMPFILES:
9c5bb203
ZJS
334 *ret = "/usr/lib/tmpfiles.d";
335 return 0;
336
ccdf03b9 337 case SD_PATH_SYSUSERS:
b0d3095f 338 *ret = PREFIX_NOSLASH "/lib/sysusers.d";
9c5bb203
ZJS
339 return 0;
340
ccdf03b9 341 case SD_PATH_SYSCTL:
b0d3095f 342 *ret = PREFIX_NOSLASH "/lib/sysctl.d";
9c5bb203
ZJS
343 return 0;
344
ccdf03b9 345 case SD_PATH_BINFMT:
b0d3095f 346 *ret = PREFIX_NOSLASH "/lib/binfmt.d";
9c5bb203
ZJS
347 return 0;
348
ccdf03b9 349 case SD_PATH_MODULES_LOAD:
b0d3095f 350 *ret = PREFIX_NOSLASH "/lib/modules-load.d";
9c5bb203
ZJS
351 return 0;
352
ccdf03b9 353 case SD_PATH_CATALOG:
9c5bb203
ZJS
354 *ret = "/usr/lib/systemd/catalog";
355 return 0;
71006538
DT
356
357 case SD_PATH_SYSTEMD_SYSTEM_ENVIRONMENT_GENERATOR:
358 *ret = SYSTEM_ENV_GENERATOR_DIR;
359 return 0;
360
361 case SD_PATH_SYSTEMD_USER_ENVIRONMENT_GENERATOR:
362 *ret = USER_ENV_GENERATOR_DIR;
363 return 0;
d2cd1893
LP
364
365 case SD_PATH_SYSTEM_CREDENTIAL_STORE:
366 *ret = "/etc/credstore";
367 return 0;
368
369 case SD_PATH_SYSTEM_CREDENTIAL_STORE_ENCRYPTED:
370 *ret = "/etc/credstore.encrypted";
371 return 0;
372
373 case SD_PATH_USER_CREDENTIAL_STORE:
374 r = xdg_user_config_dir("credstore", buffer);
375 if (r < 0)
376 return r;
377
378 *ret = *buffer;
379 return 0;
380
381 case SD_PATH_USER_CREDENTIAL_STORE_ENCRYPTED:
382 r = xdg_user_config_dir("credstore.encrypted", buffer);
383 if (r < 0)
384 return r;
385
386 *ret = *buffer;
387 return 0;
9a00f57a
LP
388 }
389
15411c0c 390 return -EOPNOTSUPP;
9a00f57a
LP
391}
392
2b19bed7 393static int get_path_alloc(uint64_t type, const char *suffix, char **ret) {
a13de89d 394 _cleanup_free_ char *buffer = NULL;
2b19bed7 395 const char *p;
9a00f57a
LP
396 int r;
397
2b19bed7 398 assert(ret);
9a00f57a 399
2b19bed7 400 r = get_path(type, &buffer, &p);
ce7eb6aa
ZJS
401 if (r < 0)
402 return r;
9a00f57a 403
616586b9 404 if (!isempty(suffix)) {
2b19bed7
MY
405 char *suffixed = path_join(p, suffix);
406 if (!suffixed)
ce7eb6aa 407 return -ENOMEM;
2b19bed7 408
616586b9 409 path_simplify_full(suffixed, PATH_SIMPLIFY_KEEP_TRAILING_SLASH);
2b19bed7
MY
410
411 free_and_replace(buffer, suffixed);
ce7eb6aa 412 } else if (!buffer) {
2b19bed7 413 buffer = strdup(p);
9a00f57a
LP
414 if (!buffer)
415 return -ENOMEM;
9a00f57a
LP
416 }
417
2b19bed7 418 *ret = TAKE_PTR(buffer);
ce7eb6aa
ZJS
419 return 0;
420}
421
2b19bed7 422_public_ int sd_path_lookup(uint64_t type, const char *suffix, char **ret) {
ce7eb6aa
ZJS
423 int r;
424
2b19bed7 425 assert_return(ret, -EINVAL);
ce7eb6aa 426
2b19bed7 427 r = get_path_alloc(type, suffix, ret);
ce7eb6aa 428 if (r != -EOPNOTSUPP)
9a00f57a
LP
429 return r;
430
ce7eb6aa
ZJS
431 /* Fall back to sd_path_lookup_strv */
432 _cleanup_strv_free_ char **l = NULL;
9a00f57a 433
ce7eb6aa
ZJS
434 r = sd_path_lookup_strv(type, suffix, &l);
435 if (r < 0)
436 return r;
9a00f57a 437
2b19bed7
MY
438 char *joined = strv_join(l, ":");
439 if (!joined)
9a00f57a
LP
440 return -ENOMEM;
441
2b19bed7 442 *ret = joined;
9a00f57a
LP
443 return 0;
444}
445
446static int search_from_environment(
c1fa6427 447 char ***ret,
9a00f57a
LP
448 const char *env_home,
449 const char *home_suffix,
450 const char *env_search,
451 bool env_search_sufficient,
452 const char *first, ...) {
453
623550af 454 _cleanup_strv_free_ char **l = NULL;
9a00f57a
LP
455 const char *e;
456 char *h = NULL;
9a00f57a
LP
457 int r;
458
c1fa6427 459 assert(ret);
9a00f57a
LP
460
461 if (env_search) {
462 e = secure_getenv(env_search);
463 if (e) {
464 l = strv_split(e, ":");
465 if (!l)
466 return -ENOMEM;
467
468 if (env_search_sufficient) {
c1fa6427 469 *ret = TAKE_PTR(l);
9a00f57a
LP
470 return 0;
471 }
472 }
473 }
474
475 if (!l && first) {
476 va_list ap;
477
478 va_start(ap, first);
479 l = strv_new_ap(first, ap);
480 va_end(ap);
481
482 if (!l)
483 return -ENOMEM;
484 }
485
486 if (env_home) {
487 e = secure_getenv(env_home);
488 if (e && path_is_absolute(e)) {
489 h = strdup(e);
623550af 490 if (!h)
9a00f57a 491 return -ENOMEM;
9a00f57a
LP
492 }
493 }
494
495 if (!h && home_suffix) {
496 e = secure_getenv("HOME");
497 if (e && path_is_absolute(e)) {
657ee2d8 498 h = path_join(e, home_suffix);
623550af 499 if (!h)
9a00f57a 500 return -ENOMEM;
9a00f57a
LP
501 }
502 }
503
504 if (h) {
505 r = strv_consume_prepend(&l, h);
623550af 506 if (r < 0)
9a00f57a 507 return -ENOMEM;
9a00f57a
LP
508 }
509
c1fa6427 510 *ret = TAKE_PTR(l);
9a00f57a
LP
511 return 0;
512}
513
671f0f8d
ZJS
514#if HAVE_SPLIT_BIN
515# define ARRAY_SBIN_BIN(x) x "sbin", x "bin"
516#else
517# define ARRAY_SBIN_BIN(x) x "bin"
518#endif
519
c1fa6427 520static int get_search(uint64_t type, char ***ret) {
9c5bb203 521 int r;
9a00f57a 522
c1fa6427 523 assert(ret);
9a00f57a 524
79893116 525 switch (type) {
9a00f57a
LP
526
527 case SD_PATH_SEARCH_BINARIES:
c1fa6427 528 return search_from_environment(ret,
9a00f57a
LP
529 NULL,
530 ".local/bin",
531 "PATH",
532 true,
671f0f8d
ZJS
533 ARRAY_SBIN_BIN("/usr/local/"),
534 ARRAY_SBIN_BIN("/usr/"),
9a00f57a
LP
535 NULL);
536
537 case SD_PATH_SEARCH_LIBRARY_PRIVATE:
c1fa6427 538 return search_from_environment(ret,
9a00f57a
LP
539 NULL,
540 ".local/lib",
541 NULL,
542 false,
543 "/usr/local/lib",
544 "/usr/lib",
9a00f57a
LP
545 NULL);
546
547 case SD_PATH_SEARCH_LIBRARY_ARCH:
c1fa6427 548 return search_from_environment(ret,
9a00f57a 549 NULL,
613e3a26 550 ".local/lib/" LIB_ARCH_TUPLE,
9a00f57a
LP
551 "LD_LIBRARY_PATH",
552 true,
553 LIBDIR,
9a00f57a
LP
554 NULL);
555
556 case SD_PATH_SEARCH_SHARED:
c1fa6427 557 return search_from_environment(ret,
9a00f57a
LP
558 "XDG_DATA_HOME",
559 ".local/share",
560 "XDG_DATA_DIRS",
561 false,
562 "/usr/local/share",
563 "/usr/share",
564 NULL);
565
566 case SD_PATH_SEARCH_CONFIGURATION_FACTORY:
c1fa6427 567 return search_from_environment(ret,
9a00f57a
LP
568 NULL,
569 NULL,
570 NULL,
571 false,
572 "/usr/local/share/factory/etc",
573 "/usr/share/factory/etc",
574 NULL);
575
576 case SD_PATH_SEARCH_STATE_FACTORY:
c1fa6427 577 return search_from_environment(ret,
9a00f57a
LP
578 NULL,
579 NULL,
580 NULL,
581 false,
582 "/usr/local/share/factory/var",
583 "/usr/share/factory/var",
584 NULL);
585
586 case SD_PATH_SEARCH_CONFIGURATION:
c1fa6427 587 return search_from_environment(ret,
9a00f57a
LP
588 "XDG_CONFIG_HOME",
589 ".config",
590 "XDG_CONFIG_DIRS",
591 false,
592 "/etc",
593 NULL);
e12d446b 594
0f36a4c8
ZJS
595 case SD_PATH_SEARCH_BINARIES_DEFAULT: {
596 char **t = strv_split(default_PATH(), ":");
597 if (!t)
598 return -ENOMEM;
599
c1fa6427 600 *ret = t;
0f36a4c8
ZJS
601 return 0;
602 }
e12d446b 603
ccdf03b9
LP
604 case SD_PATH_SYSTEMD_SEARCH_SYSTEM_UNIT:
605 case SD_PATH_SYSTEMD_SEARCH_USER_UNIT: {
7dfc7139 606 _cleanup_(lookup_paths_done) LookupPaths lp = {};
4870133b
LP
607 RuntimeScope scope = type == SD_PATH_SYSTEMD_SEARCH_SYSTEM_UNIT ?
608 RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER;
9c5bb203
ZJS
609
610 r = lookup_paths_init(&lp, scope, 0, NULL);
611 if (r < 0)
612 return r;
e12d446b 613
c1fa6427 614 *ret = TAKE_PTR(lp.search_path);
9c5bb203 615 return 0;
a7addf32 616 }
9a00f57a 617
ccdf03b9 618 case SD_PATH_SYSTEMD_SEARCH_SYSTEM_GENERATOR:
cfda202f 619 case SD_PATH_SYSTEMD_SEARCH_USER_GENERATOR:
71006538
DT
620 case SD_PATH_SYSTEMD_SEARCH_SYSTEM_ENVIRONMENT_GENERATOR:
621 case SD_PATH_SYSTEMD_SEARCH_USER_ENVIRONMENT_GENERATOR: {
cfda202f
MY
622 RuntimeScope scope = IN_SET(type, SD_PATH_SYSTEMD_SEARCH_SYSTEM_GENERATOR,
623 SD_PATH_SYSTEMD_SEARCH_SYSTEM_ENVIRONMENT_GENERATOR) ?
624 RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER;
625 bool env_generator = IN_SET(type, SD_PATH_SYSTEMD_SEARCH_SYSTEM_ENVIRONMENT_GENERATOR,
626 SD_PATH_SYSTEMD_SEARCH_USER_ENVIRONMENT_GENERATOR);
71006538 627
cfda202f 628 char **t = generator_binary_paths_internal(scope, env_generator);
71006538
DT
629 if (!t)
630 return -ENOMEM;
631
c1fa6427 632 *ret = t;
71006538
DT
633 return 0;
634 }
635
ccdf03b9 636 case SD_PATH_SYSTEMD_SEARCH_NETWORK:
c1fa6427 637 return strv_from_nulstr(ret, NETWORK_DIRS_NULSTR);
f1bb691a 638
d2cd1893
LP
639 case SD_PATH_SYSTEM_SEARCH_CREDENTIAL_STORE:
640 case SD_PATH_SYSTEM_SEARCH_CREDENTIAL_STORE_ENCRYPTED: {
641 const char *suffix =
642 type == SD_PATH_SYSTEM_SEARCH_CREDENTIAL_STORE_ENCRYPTED ? "credstore.encrypted" : "credstore";
643
644 _cleanup_strv_free_ char **l = NULL;
645 FOREACH_STRING(d, CONF_PATHS("")) {
646 char *j = path_join(d, suffix);
647 if (!j)
648 return -ENOMEM;
649
650 r = strv_consume(&l, TAKE_PTR(j));
651 if (r < 0)
652 return r;
653 }
654
655 *ret = TAKE_PTR(l);
656 return 0;
f1bb691a 657 }
9c5bb203 658
d2cd1893
LP
659 case SD_PATH_USER_SEARCH_CREDENTIAL_STORE:
660 case SD_PATH_USER_SEARCH_CREDENTIAL_STORE_ENCRYPTED: {
661 const char *suffix =
662 type == SD_PATH_USER_SEARCH_CREDENTIAL_STORE_ENCRYPTED ? "credstore.encrypted" : "credstore";
663
664 static const uint64_t dirs[] = {
665 SD_PATH_USER_CONFIGURATION,
666 SD_PATH_USER_RUNTIME,
667 SD_PATH_USER_LIBRARY_PRIVATE,
668 };
669
670 _cleanup_strv_free_ char **l = NULL;
671 FOREACH_ELEMENT(d, dirs) {
672 _cleanup_free_ char *p = NULL;
673 r = sd_path_lookup(*d, suffix, &p);
674 if (r == -ENXIO)
675 continue;
676 if (r < 0)
677 return r;
678
679 r = strv_consume(&l, TAKE_PTR(p));
680 if (r < 0)
681 return r;
682 }
683
684 *ret = TAKE_PTR(l);
685 return 0;
686 }}
687
15411c0c 688 return -EOPNOTSUPP;
9a00f57a
LP
689}
690
2b19bed7
MY
691_public_ int sd_path_lookup_strv(uint64_t type, const char *suffix, char ***ret) {
692 _cleanup_strv_free_ char **l = NULL;
9a00f57a
LP
693 int r;
694
2b19bed7 695 assert_return(ret, -EINVAL);
9a00f57a 696
ce7eb6aa
ZJS
697 r = get_search(type, &l);
698 if (r == -EOPNOTSUPP) {
699 _cleanup_free_ char *t = NULL;
9a00f57a 700
ce7eb6aa 701 r = get_path_alloc(type, suffix, &t);
9a00f57a
LP
702 if (r < 0)
703 return r;
704
705 l = new(char*, 2);
ce7eb6aa 706 if (!l)
9a00f57a 707 return -ENOMEM;
ce7eb6aa 708 l[0] = TAKE_PTR(t);
9a00f57a
LP
709 l[1] = NULL;
710
2b19bed7 711 *ret = TAKE_PTR(l);
9a00f57a
LP
712 return 0;
713 }
2b19bed7
MY
714 if (r < 0)
715 return r;
9a00f57a 716
2b19bed7
MY
717 if (suffix)
718 STRV_FOREACH(i, l) {
719 if (!path_extend(i, suffix))
720 return -ENOMEM;
9a00f57a 721
616586b9 722 path_simplify_full(*i, PATH_SIMPLIFY_KEEP_TRAILING_SLASH);
2b19bed7 723 }
ce7eb6aa 724
2b19bed7 725 *ret = TAKE_PTR(l);
9a00f57a
LP
726 return 0;
727}