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