]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/path-lookup.c
path-lookup: move generator_binary_paths() to end of file
[thirdparty/systemd.git] / src / shared / path-lookup.c
CommitLineData
84e3543e
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
84e3543e
LP
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 14 Lesser General Public License for more details.
84e3543e 15
5430f7f2 16 You should have received a copy of the GNU Lesser General Public License
84e3543e
LP
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
cf0fbc49 20#include <errno.h>
84e3543e 21#include <stdio.h>
cf0fbc49 22#include <stdlib.h>
67445f4e 23#include <string.h>
84e3543e 24
b5efdb8a 25#include "alloc-util.h"
a8ffe6fb 26#include "install.h"
a8fbdf54
TA
27#include "log.h"
28#include "macro.h"
cd64fd56 29#include "mkdir.h"
07630cea 30#include "path-lookup.h"
cf0fbc49 31#include "path-util.h"
80b1ae32 32#include "rm-rf.h"
e4bb56c7 33#include "stat-util.h"
cf0fbc49
TA
34#include "string-util.h"
35#include "strv.h"
36#include "util.h"
84e3543e 37
80b1ae32 38static int user_runtime_dir(char **ret, const char *suffix) {
10e87ee7 39 const char *e;
205dd21e
LP
40 char *j;
41
42 assert(ret);
80b1ae32 43 assert(suffix);
10e87ee7 44
80b1ae32
LP
45 e = getenv("XDG_RUNTIME_DIR");
46 if (!e)
47 return -ENXIO;
205dd21e 48
80b1ae32
LP
49 j = strappend(e, suffix);
50 if (!j)
51 return -ENOMEM;
10e87ee7 52
205dd21e 53 *ret = j;
10e87ee7
LP
54 return 0;
55}
56
80b1ae32 57static int user_config_dir(char **ret, const char *suffix) {
718880ba 58 const char *e;
205dd21e
LP
59 char *j;
60
61 assert(ret);
718880ba 62
80b1ae32
LP
63 e = getenv("XDG_CONFIG_HOME");
64 if (e)
65 j = strappend(e, suffix);
66 else {
67 const char *home;
68
69 home = getenv("HOME");
70 if (!home)
71 return -ENXIO;
72
73 j = strjoin(home, "/.config", suffix, NULL);
74 }
718880ba 75
205dd21e
LP
76 if (!j)
77 return -ENOMEM;
718880ba 78
205dd21e 79 *ret = j;
718880ba
SA
80 return 0;
81}
82
80b1ae32 83static int user_data_dir(char **ret, const char *suffix) {
e801700e 84 const char *e;
205dd21e
LP
85 char *j;
86
87 assert(ret);
a7527131 88 assert(suffix);
e801700e
ZJS
89
90 /* We don't treat /etc/xdg/systemd here as the spec
91 * suggests because we assume that that is a link to
92 * /etc/systemd/ anyway. */
93
94 e = getenv("XDG_DATA_HOME");
95 if (e)
205dd21e 96 j = strappend(e, suffix);
e801700e
ZJS
97 else {
98 const char *home;
99
100 home = getenv("HOME");
205dd21e
LP
101 if (!home)
102 return -ENXIO;
103
104
105 j = strjoin(home, "/.local/share", suffix, NULL);
e801700e 106 }
205dd21e 107 if (!j)
e801700e
ZJS
108 return -ENOMEM;
109
205dd21e 110 *ret = j;
463d0d15 111 return 1;
e801700e
ZJS
112}
113
07719a21 114static char** user_dirs(
a0f84a10
LP
115 const char *persistent_config,
116 const char *runtime_config,
07719a21
LP
117 const char *generator,
118 const char *generator_early,
39591351 119 const char *generator_late,
80b1ae32
LP
120 const char *transient,
121 const char *persistent_control,
122 const char *runtime_control) {
07719a21 123
f437d5d2 124 const char * const config_unit_paths[] = {
f437d5d2 125 USER_CONFIG_UNIT_PATH,
4bf2bbb6
LP
126 "/etc/systemd/user",
127 NULL
f437d5d2
LP
128 };
129
130 const char * const data_unit_paths[] = {
131 "/usr/local/lib/systemd/user",
132 "/usr/local/share/systemd/user",
133 USER_DATA_UNIT_PATH,
134 "/usr/lib/systemd/user",
4bf2bbb6
LP
135 "/usr/share/systemd/user",
136 NULL
f437d5d2
LP
137 };
138
e801700e 139 const char *e;
e3e45d4f 140 _cleanup_strv_free_ char **config_dirs = NULL, **data_dirs = NULL;
205dd21e 141 _cleanup_free_ char *data_home = NULL;
e801700e
ZJS
142 _cleanup_free_ char **res = NULL;
143 char **tmp;
144 int r;
84e3543e
LP
145
146 /* Implement the mechanisms defined in
147 *
148 * http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
149 *
150 * We look in both the config and the data dirs because we
151 * want to encourage that distributors ship their unit files
152 * as data, and allow overriding as configuration.
153 */
154
07719a21
LP
155 e = getenv("XDG_CONFIG_DIRS");
156 if (e) {
157 config_dirs = strv_split(e, ":");
158 if (!config_dirs)
e801700e 159 return NULL;
07719a21 160 }
84e3543e 161
80b1ae32 162 r = user_data_dir(&data_home, "/systemd/user");
205dd21e 163 if (r < 0 && r != -ENXIO)
e801700e 164 return NULL;
84e3543e 165
07719a21
LP
166 e = getenv("XDG_DATA_DIRS");
167 if (e)
84e3543e
LP
168 data_dirs = strv_split(e, ":");
169 else
ef3102bf 170 data_dirs = strv_new("/usr/local/share",
ef3102bf 171 "/usr/share",
ef3102bf 172 NULL);
84e3543e 173 if (!data_dirs)
e801700e 174 return NULL;
84e3543e
LP
175
176 /* Now merge everything we found. */
80b1ae32
LP
177 if (strv_extend(&res, persistent_control) < 0)
178 return NULL;
39591351 179
80b1ae32
LP
180 if (strv_extend(&res, runtime_control) < 0)
181 return NULL;
182
183 if (strv_extend(&res, transient) < 0)
184 return NULL;
185
186 if (strv_extend(&res, generator_early) < 0)
187 return NULL;
07719a21 188
aa08982d 189 if (!strv_isempty(config_dirs))
e801700e
ZJS
190 if (strv_extend_strv_concat(&res, config_dirs, "/systemd/user") < 0)
191 return NULL;
718880ba 192
a0f84a10
LP
193 if (strv_extend(&res, persistent_config) < 0)
194 return NULL;
195
e287086b 196 if (strv_extend_strv(&res, (char**) config_unit_paths, false) < 0)
e801700e 197 return NULL;
718880ba 198
a0f84a10 199 if (strv_extend(&res, runtime_config) < 0)
e801700e 200 return NULL;
84e3543e 201
80b1ae32
LP
202 if (strv_extend(&res, generator) < 0)
203 return NULL;
07719a21 204
80b1ae32
LP
205 if (strv_extend(&res, data_home) < 0)
206 return NULL;
84e3543e 207
e3e45d4f 208 if (!strv_isempty(data_dirs))
e801700e
ZJS
209 if (strv_extend_strv_concat(&res, data_dirs, "/systemd/user") < 0)
210 return NULL;
84e3543e 211
e287086b 212 if (strv_extend_strv(&res, (char**) data_unit_paths, false) < 0)
e801700e 213 return NULL;
84e3543e 214
80b1ae32
LP
215 if (strv_extend(&res, generator_late) < 0)
216 return NULL;
07719a21 217
0f474365 218 if (path_strv_make_absolute_cwd(res) < 0)
e801700e 219 return NULL;
84e3543e 220
e801700e
ZJS
221 tmp = res;
222 res = NULL;
223 return tmp;
224}
84e3543e 225
a3c4eb07 226static int acquire_generator_dirs(
463d0d15 227 UnitFileScope scope,
a3c4eb07
LP
228 char **generator,
229 char **generator_early,
230 char **generator_late) {
231
232 _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL;
233 const char *prefix;
234
235 assert(generator);
236 assert(generator_early);
237 assert(generator_late);
238
463d0d15
LP
239 switch (scope) {
240
241 case UNIT_FILE_SYSTEM:
a3c4eb07 242 prefix = "/run/systemd/";
463d0d15 243 break;
a3c4eb07 244
463d0d15
LP
245 case UNIT_FILE_USER: {
246 const char *e;
a3c4eb07
LP
247
248 e = getenv("XDG_RUNTIME_DIR");
249 if (!e)
463d0d15 250 return -ENXIO;
a3c4eb07
LP
251
252 prefix = strjoina(e, "/systemd/", NULL);
463d0d15
LP
253 break;
254 }
255
256 case UNIT_FILE_GLOBAL:
257 return -EOPNOTSUPP;
258
259 default:
260 assert_not_reached("Hmm, unexpected scope value.");
a3c4eb07
LP
261 }
262
263 x = strappend(prefix, "generator");
264 if (!x)
265 return -ENOMEM;
266
267 y = strappend(prefix, "generator.early");
268 if (!y)
269 return -ENOMEM;
270
271 z = strappend(prefix, "generator.late");
272 if (!z)
273 return -ENOMEM;
274
275 *generator = x;
276 *generator_early = y;
277 *generator_late = z;
278
279 x = y = z = NULL;
280 return 0;
281}
282
39591351 283static int acquire_transient_dir(UnitFileScope scope, char **ret) {
39591351
LP
284 assert(ret);
285
286 switch (scope) {
287
a7527131
LP
288 case UNIT_FILE_SYSTEM: {
289 char *transient;
39591351 290
a7527131
LP
291 transient = strdup("/run/systemd/transient");
292 if (!transient)
293 return -ENOMEM;
39591351 294
a7527131
LP
295 *ret = transient;
296 return 0;
39591351
LP
297 }
298
a7527131
LP
299 case UNIT_FILE_USER:
300 return user_runtime_dir(ret, "/systemd/transient");
301
39591351
LP
302 case UNIT_FILE_GLOBAL:
303 return -EOPNOTSUPP;
304
305 default:
306 assert_not_reached("Hmm, unexpected scope value.");
307 }
39591351
LP
308}
309
463d0d15 310static int acquire_config_dirs(UnitFileScope scope, char **persistent, char **runtime) {
a0f84a10
LP
311 _cleanup_free_ char *a = NULL, *b = NULL;
312 int r;
313
314 assert(persistent);
315 assert(runtime);
316
463d0d15
LP
317 switch (scope) {
318
319 case UNIT_FILE_SYSTEM:
a0f84a10
LP
320 a = strdup(SYSTEM_CONFIG_UNIT_PATH);
321 b = strdup("/run/systemd/system");
463d0d15
LP
322 break;
323
324 case UNIT_FILE_GLOBAL:
325 a = strdup(USER_CONFIG_UNIT_PATH);
326 b = strdup("/run/systemd/user");
327 break;
a0f84a10 328
463d0d15 329 case UNIT_FILE_USER:
80b1ae32 330 r = user_config_dir(&a, "/systemd/user");
a0f84a10
LP
331 if (r < 0)
332 return r;
333
a7527131 334 r = user_runtime_dir(runtime, "/systemd/user");
a0f84a10
LP
335 if (r < 0)
336 return r;
337
338 *persistent = a;
339 a = NULL;
340
341 return 0;
a0f84a10 342
463d0d15
LP
343 default:
344 assert_not_reached("Hmm, unexpected scope value.");
a0f84a10
LP
345 }
346
347 if (!a || !b)
348 return -ENOMEM;
349
350 *persistent = a;
351 *runtime = b;
352 a = b = NULL;
353
354 return 0;
355}
356
80b1ae32
LP
357static int acquire_control_dirs(UnitFileScope scope, char **persistent, char **runtime) {
358 _cleanup_free_ char *a = NULL;
359 int r;
360
361 assert(persistent);
362 assert(runtime);
363
364 switch (scope) {
365
366 case UNIT_FILE_SYSTEM: {
367 _cleanup_free_ char *b = NULL;
368
369 a = strdup("/etc/systemd/system.control");
370 if (!a)
371 return -ENOMEM;
372
373 b = strdup("/run/systemd/system.control");
374 if (!b)
375 return -ENOMEM;
376
377 *runtime = b;
378 b = NULL;
379
380 break;
381 }
382
383 case UNIT_FILE_USER:
384 r = user_config_dir(&a, "/systemd/system.control");
385 if (r < 0)
386 return r;
387
388 r = user_runtime_dir(runtime, "/systemd/system.control");
389 if (r < 0)
390 return r;
391
392 break;
393
394 case UNIT_FILE_GLOBAL:
395 return -EOPNOTSUPP;
396
397 default:
398 assert_not_reached("Hmm, unexpected scope value.");
399 }
400
401 *persistent = a;
402 a = NULL;
403
404 return 0;
405}
406
a3c4eb07
LP
407static int patch_root_prefix(char **p, const char *root_dir) {
408 char *c;
409
410 assert(p);
411
412 if (!*p)
413 return 0;
414
a3c4eb07
LP
415 c = prefix_root(root_dir, *p);
416 if (!c)
417 return -ENOMEM;
418
419 free(*p);
420 *p = c;
421
422 return 0;
423}
424
a1453343
LP
425static int patch_root_prefix_strv(char **l, const char *root_dir) {
426 char **i;
427 int r;
428
429 if (!root_dir)
430 return 0;
431
432 STRV_FOREACH(i, l) {
433 r = patch_root_prefix(i, root_dir);
434 if (r < 0)
435 return r;
436 }
437
438 return 0;
439}
440
07719a21
LP
441int lookup_paths_init(
442 LookupPaths *p,
463d0d15 443 UnitFileScope scope,
a3c4eb07 444 const char *root_dir) {
07719a21 445
e4bb56c7
LP
446 _cleanup_free_ char
447 *root = NULL,
39591351 448 *persistent_config = NULL, *runtime_config = NULL,
e4bb56c7 449 *generator = NULL, *generator_early = NULL, *generator_late = NULL,
80b1ae32
LP
450 *transient = NULL,
451 *persistent_control = NULL, *runtime_control = NULL;
cf7d80a5 452 bool append = false; /* Add items from SYSTEMD_UNIT_PATH before normal directories */
a3c4eb07
LP
453 char **l = NULL;
454 const char *e;
0f474365 455 int r;
84e3543e
LP
456
457 assert(p);
463d0d15
LP
458 assert(scope >= 0);
459 assert(scope < _UNIT_FILE_SCOPE_MAX);
a3c4eb07 460
e4bb56c7
LP
461 if (!isempty(root_dir) && !path_equal(root_dir, "/")) {
462 if (scope == UNIT_FILE_USER)
463 return -EINVAL;
464
465 r = is_dir(root_dir, true);
466 if (r < 0)
467 return r;
468 if (r == 0)
469 return -ENOTDIR;
470
471 root = strdup(root_dir);
472 if (!root)
473 return -ENOMEM;
474 }
475
463d0d15 476 r = acquire_config_dirs(scope, &persistent_config, &runtime_config);
205dd21e 477 if (r < 0 && r != -ENXIO)
a0f84a10
LP
478 return r;
479
463d0d15
LP
480 r = acquire_generator_dirs(scope, &generator, &generator_early, &generator_late);
481 if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO)
a3c4eb07 482 return r;
84e3543e 483
39591351
LP
484 r = acquire_transient_dir(scope, &transient);
485 if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO)
486 return r;
487
80b1ae32
LP
488 r = acquire_control_dirs(scope, &persistent_control, &runtime_control);
489 if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO)
490 return r;
491
cd64fd56 492 /* First priority is whatever has been passed to us via env vars */
07719a21
LP
493 e = getenv("SYSTEMD_UNIT_PATH");
494 if (e) {
a3c4eb07
LP
495 const char *k;
496
497 k = endswith(e, ":");
498 if (k) {
499 e = strndupa(e, k - e);
cf7d80a5
ZJS
500 append = true;
501 }
502
503 /* FIXME: empty components in other places should be
504 * rejected. */
505
a3c4eb07 506 r = path_split_and_make_absolute(e, &l);
0f474365
LP
507 if (r < 0)
508 return r;
07719a21 509 } else
a3c4eb07 510 l = NULL;
84e3543e 511
a3c4eb07 512 if (!l || append) {
cf7d80a5
ZJS
513 /* Let's figure something out. */
514
a3c4eb07 515 _cleanup_strv_free_ char **add = NULL;
84e3543e 516
07719a21 517 /* For the user units we include share/ in the search
cf7d80a5
ZJS
518 * path in order to comply with the XDG basedir spec.
519 * For the system stuff we avoid such nonsense. OTOH
520 * we include /lib in the search path for the system
521 * stuff but avoid it for user stuff. */
07719a21 522
463d0d15
LP
523 switch (scope) {
524
525 case UNIT_FILE_SYSTEM:
526 add = strv_new(
527 /* If you modify this you also want to modify
528 * systemdsystemunitpath= in systemd.pc.in! */
80b1ae32
LP
529 STRV_IFNOTNULL(persistent_control),
530 STRV_IFNOTNULL(runtime_control),
39591351 531 STRV_IFNOTNULL(transient),
463d0d15
LP
532 STRV_IFNOTNULL(generator_early),
533 persistent_config,
5f0a41da 534 SYSTEM_CONFIG_UNIT_PATH,
463d0d15
LP
535 "/etc/systemd/system",
536 runtime_config,
537 "/run/systemd/system",
538 STRV_IFNOTNULL(generator),
539 "/usr/local/lib/systemd/system",
540 SYSTEM_DATA_UNIT_PATH,
541 "/usr/lib/systemd/system",
542#ifdef HAVE_SPLIT_USR
543 "/lib/systemd/system",
544#endif
545 STRV_IFNOTNULL(generator_late),
546 NULL);
547 break;
548
549 case UNIT_FILE_GLOBAL:
550 add = strv_new(
07719a21 551 /* If you modify this you also want to modify
cf7d80a5
ZJS
552 * systemduserunitpath= in systemd.pc.in, and
553 * the arrays in user_dirs() above! */
80b1ae32
LP
554 STRV_IFNOTNULL(persistent_control),
555 STRV_IFNOTNULL(runtime_control),
39591351 556 STRV_IFNOTNULL(transient),
463d0d15 557 STRV_IFNOTNULL(generator_early),
a0f84a10 558 persistent_config,
5f0a41da 559 USER_CONFIG_UNIT_PATH,
cf7d80a5 560 "/etc/systemd/user",
a0f84a10 561 runtime_config,
cf7d80a5 562 "/run/systemd/user",
463d0d15 563 STRV_IFNOTNULL(generator),
cf7d80a5
ZJS
564 "/usr/local/lib/systemd/user",
565 "/usr/local/share/systemd/user",
566 USER_DATA_UNIT_PATH,
567 "/usr/lib/systemd/user",
568 "/usr/share/systemd/user",
463d0d15 569 STRV_IFNOTNULL(generator_late),
07719a21 570 NULL);
463d0d15
LP
571 break;
572
573 case UNIT_FILE_USER:
574 add = user_dirs(persistent_config, runtime_config,
39591351 575 generator, generator_early, generator_late,
80b1ae32
LP
576 transient,
577 persistent_config, runtime_control);
463d0d15
LP
578 break;
579
580 default:
581 assert_not_reached("Hmm, unexpected scope?");
582 }
07719a21 583
a3c4eb07 584 if (!add)
cf7d80a5
ZJS
585 return -ENOMEM;
586
a3c4eb07
LP
587 if (l) {
588 r = strv_extend_strv(&l, add, false);
589 if (r < 0)
590 return r;
591 } else {
592 l = add;
593 add = NULL;
594 }
84e3543e
LP
595 }
596
e4bb56c7 597 r = patch_root_prefix(&persistent_config, root);
a0f84a10
LP
598 if (r < 0)
599 return r;
e4bb56c7 600 r = patch_root_prefix(&runtime_config, root);
a0f84a10
LP
601 if (r < 0)
602 return r;
603
e4bb56c7 604 r = patch_root_prefix(&generator, root);
a3c4eb07
LP
605 if (r < 0)
606 return r;
e4bb56c7 607 r = patch_root_prefix(&generator_early, root);
a3c4eb07
LP
608 if (r < 0)
609 return r;
e4bb56c7 610 r = patch_root_prefix(&generator_late, root);
a3c4eb07
LP
611 if (r < 0)
612 return r;
613
39591351
LP
614 r = patch_root_prefix(&transient, root);
615 if (r < 0)
616 return r;
617
80b1ae32
LP
618 r = patch_root_prefix(&persistent_control, root);
619 if (r < 0)
620 return r;
621
622 r = patch_root_prefix(&runtime_control, root);
623 if (r < 0)
624 return r;
625
a1453343
LP
626 r = patch_root_prefix_strv(l, root);
627 if (r < 0)
07719a21 628 return -ENOMEM;
07459bb6 629
a1453343 630 p->search_path = strv_uniq(l);
a3c4eb07
LP
631 l = NULL;
632
a0f84a10
LP
633 p->persistent_config = persistent_config;
634 p->runtime_config = runtime_config;
635 persistent_config = runtime_config = NULL;
636
a3c4eb07
LP
637 p->generator = generator;
638 p->generator_early = generator_early;
639 p->generator_late = generator_late;
640 generator = generator_early = generator_late = NULL;
84e3543e 641
39591351
LP
642 p->transient = transient;
643 transient = NULL;
644
80b1ae32
LP
645 p->persistent_control = persistent_control;
646 p->runtime_control = runtime_control;
647 persistent_control = runtime_control = NULL;
648
e4bb56c7
LP
649 p->root_dir = root;
650 root = NULL;
651
84e3543e
LP
652 return 0;
653}
654
655void lookup_paths_free(LookupPaths *p) {
a3c4eb07
LP
656 if (!p)
657 return;
84e3543e 658
a3c4eb07 659 p->search_path = strv_free(p->search_path);
a0f84a10
LP
660
661 p->persistent_config = mfree(p->persistent_config);
662 p->runtime_config = mfree(p->runtime_config);
663
a3c4eb07
LP
664 p->generator = mfree(p->generator);
665 p->generator_early = mfree(p->generator_early);
666 p->generator_late = mfree(p->generator_late);
e4bb56c7 667
39591351
LP
668 p->transient = mfree(p->transient);
669
80b1ae32
LP
670 p->persistent_control = mfree(p->persistent_control);
671 p->runtime_control = mfree(p->runtime_control);
672
e4bb56c7 673 p->root_dir = mfree(p->root_dir);
84e3543e 674}
cd64fd56 675
a1453343
LP
676int lookup_paths_reduce(LookupPaths *p) {
677 _cleanup_free_ struct stat *stats = NULL;
678 size_t n_stats = 0, allocated = 0;
679 unsigned c = 0;
680 int r;
681
682 assert(p);
683
684 /* Drop duplicates and non-existing directories from the search path. We figure out whether two directories are
685 * the same by comparing their device and inode numbers. Note one special tweak: when we have a root path set,
686 * we do not follow symlinks when retrieving them, because the kernel wouldn't take the root prefix into
687 * account when following symlinks. When we have no root path set this restriction does not apply however. */
688
689 if (!p->search_path)
690 return 0;
691
692 while (p->search_path[c]) {
693 struct stat st;
694 unsigned k;
695
696 if (p->root_dir)
697 r = lstat(p->search_path[c], &st);
698 else
699 r = stat(p->search_path[c], &st);
700 if (r < 0) {
701 if (errno == ENOENT)
702 goto remove_item;
703
704 /* If something we don't grok happened, let's better leave it in. */
705 log_debug_errno(errno, "Failed to stat %s: %m", p->search_path[c]);
706 c++;
707 continue;
708 }
709
710 for (k = 0; k < n_stats; k++) {
711 if (stats[k].st_dev == st.st_dev &&
712 stats[k].st_ino == st.st_ino)
713 break;
714 }
715
716 if (k < n_stats) /* Is there already an entry with the same device/inode? */
717 goto remove_item;
718
719 if (!GREEDY_REALLOC(stats, allocated, n_stats+1))
720 return -ENOMEM;
721
722 stats[n_stats++] = st;
723 c++;
724 continue;
725
726 remove_item:
727 free(p->search_path[c]);
728 memmove(p->search_path + c,
729 p->search_path + c + 1,
730 (strv_length(p->search_path + c + 1) + 1) * sizeof(char*));
731 }
732
733 if (strv_isempty(p->search_path)) {
734 log_debug("Ignoring unit files.");
735 p->search_path = strv_free(p->search_path);
736 } else {
737 _cleanup_free_ char *t;
738
739 t = strv_join(p->search_path, "\n\t");
740 if (!t)
741 return -ENOMEM;
742
743 log_debug("Looking for unit files in (higher priority first):\n\t%s", t);
744 }
745
746 return 0;
747}
748
cd64fd56
LP
749int lookup_paths_mkdir_generator(LookupPaths *p) {
750 int r, q;
751
752 assert(p);
753
754 r = mkdir_p_label(p->generator, 0755);
755
756 q = mkdir_p_label(p->generator_early, 0755);
757 if (q < 0 && r >= 0)
758 r = q;
759
760 q = mkdir_p_label(p->generator_late, 0755);
761 if (q < 0 && r >= 0)
762 r = q;
763
764 return r;
765}
766
767void lookup_paths_trim_generator(LookupPaths *p) {
768 assert(p);
769
770 /* Trim empty dirs */
771
772 if (p->generator)
773 (void) rmdir(p->generator);
774
775 if (p->generator_early)
776 (void) rmdir(p->generator_early);
777
778 if (p->generator_late)
779 (void) rmdir(p->generator_late);
780}
07a78643
LP
781
782void lookup_paths_flush_generator(LookupPaths *p) {
783 assert(p);
784
80b1ae32
LP
785 /* Flush the generated unit files in full */
786
07a78643
LP
787 if (p->generator)
788 (void) rm_rf(p->generator, REMOVE_ROOT);
789 if (p->generator_early)
790 (void) rm_rf(p->generator_early, REMOVE_ROOT);
791 if (p->generator_late)
792 (void) rm_rf(p->generator_late, REMOVE_ROOT);
793}
a69b4fb0
LP
794
795char **generator_binary_paths(UnitFileScope scope) {
796
797 switch (scope) {
798
799 case UNIT_FILE_SYSTEM:
800 return strv_new("/run/systemd/system-generators",
801 "/etc/systemd/system-generators",
802 "/usr/local/lib/systemd/system-generators",
803 SYSTEM_GENERATOR_PATH,
804 NULL);
805
806 case UNIT_FILE_GLOBAL:
807 case UNIT_FILE_USER:
808 return strv_new("/run/systemd/user-generators",
809 "/etc/systemd/user-generators",
810 "/usr/local/lib/systemd/user-generators",
811 USER_GENERATOR_PATH,
812 NULL);
813
814 default:
815 assert_not_reached("Hmm, unexpected scope.");
816 }
817}