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