Coverage Report

Created: 2026-04-29 07:06

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