]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/path-lookup.c
Merge pull request #8134 from keszybz/unit-load-paths
[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 char **tmp;
185 int r;
186
187 r = xdg_user_dirs(&config_dirs, &data_dirs);
188 if (r < 0)
189 return NULL;
190
191 r = xdg_user_data_dir(&data_home, "/systemd/user");
192 if (r < 0 && r != -ENXIO)
193 return NULL;
194
195 /* Now merge everything we found. */
196 if (strv_extend(&res, persistent_control) < 0)
197 return NULL;
198
199 if (strv_extend(&res, runtime_control) < 0)
200 return NULL;
201
202 if (strv_extend(&res, transient) < 0)
203 return NULL;
204
205 if (strv_extend(&res, generator_early) < 0)
206 return NULL;
207
208 if (strv_extend_strv_concat(&res, config_dirs, "/systemd/user") < 0)
209 return NULL;
210
211 if (strv_extend(&res, persistent_config) < 0)
212 return NULL;
213
214 /* global config has lower priority than the user config of the same type */
215 if (strv_extend(&res, global_persistent_config) < 0)
216 return NULL;
217
218 if (strv_extend_strv(&res, (char**) user_config_unit_paths, false) < 0)
219 return NULL;
220
221 if (strv_extend(&res, runtime_config) < 0)
222 return NULL;
223
224 if (strv_extend(&res, global_runtime_config) < 0)
225 return NULL;
226
227 if (strv_extend(&res, generator) < 0)
228 return NULL;
229
230 if (strv_extend(&res, data_home) < 0)
231 return NULL;
232
233 if (strv_extend_strv_concat(&res, data_dirs, "/systemd/user") < 0)
234 return NULL;
235
236 if (strv_extend_strv(&res, (char**) user_data_unit_paths, false) < 0)
237 return NULL;
238
239 if (strv_extend(&res, generator_late) < 0)
240 return NULL;
241
242 if (path_strv_make_absolute_cwd(res) < 0)
243 return NULL;
244
245 tmp = res;
246 res = NULL;
247
248 return tmp;
249 }
250
251 bool path_is_user_data_dir(const char *path) {
252 assert(path);
253
254 return strv_contains((char**) user_data_unit_paths, path);
255 }
256
257 bool path_is_user_config_dir(const char *path) {
258 assert(path);
259
260 return strv_contains((char**) user_config_unit_paths, path);
261 }
262
263 static int acquire_generator_dirs(
264 UnitFileScope scope,
265 const char *tempdir,
266 char **generator,
267 char **generator_early,
268 char **generator_late) {
269
270 _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL;
271 const char *prefix;
272
273 assert(generator);
274 assert(generator_early);
275 assert(generator_late);
276 assert(IN_SET(scope, UNIT_FILE_SYSTEM, UNIT_FILE_USER, UNIT_FILE_GLOBAL));
277
278 if (scope == UNIT_FILE_GLOBAL)
279 return -EOPNOTSUPP;
280
281 if (tempdir)
282 prefix = tempdir;
283
284 else if (scope == UNIT_FILE_SYSTEM)
285 prefix = "/run/systemd";
286
287 else if (scope == UNIT_FILE_USER) {
288 const char *e;
289
290 e = getenv("XDG_RUNTIME_DIR");
291 if (!e)
292 return -ENXIO;
293
294 prefix = strjoina(e, "/systemd");
295 }
296
297 x = strappend(prefix, "/generator");
298 if (!x)
299 return -ENOMEM;
300
301 y = strappend(prefix, "/generator.early");
302 if (!y)
303 return -ENOMEM;
304
305 z = strappend(prefix, "/generator.late");
306 if (!z)
307 return -ENOMEM;
308
309 *generator = x;
310 *generator_early = y;
311 *generator_late = z;
312
313 x = y = z = NULL;
314 return 0;
315 }
316
317 static int acquire_transient_dir(
318 UnitFileScope scope,
319 const char *tempdir,
320 char **ret) {
321
322 char *transient;
323
324 assert(ret);
325 assert(IN_SET(scope, UNIT_FILE_SYSTEM, UNIT_FILE_USER, UNIT_FILE_GLOBAL));
326
327 if (scope == UNIT_FILE_GLOBAL)
328 return -EOPNOTSUPP;
329
330 if (tempdir)
331 transient = strjoin(tempdir, "/transient");
332 else if (scope == UNIT_FILE_SYSTEM)
333 transient = strdup("/run/systemd/transient");
334 else
335 return xdg_user_runtime_dir(ret, "/systemd/transient");
336
337 if (!transient)
338 return -ENOMEM;
339 *ret = transient;
340 return 0;
341 }
342
343 static int acquire_config_dirs(UnitFileScope scope, char **persistent, char **runtime) {
344 _cleanup_free_ char *a = NULL, *b = NULL;
345 int r;
346
347 assert(persistent);
348 assert(runtime);
349
350 switch (scope) {
351
352 case UNIT_FILE_SYSTEM:
353 a = strdup(SYSTEM_CONFIG_UNIT_PATH);
354 b = strdup("/run/systemd/system");
355 break;
356
357 case UNIT_FILE_GLOBAL:
358 a = strdup(USER_CONFIG_UNIT_PATH);
359 b = strdup("/run/systemd/user");
360 break;
361
362 case UNIT_FILE_USER:
363 r = xdg_user_config_dir(&a, "/systemd/user");
364 if (r < 0 && r != -ENXIO)
365 return r;
366
367 r = xdg_user_runtime_dir(runtime, "/systemd/user");
368 if (r < 0) {
369 if (r != -ENXIO)
370 return r;
371
372 /* If XDG_RUNTIME_DIR is not set, don't consider that fatal, simply initialize the runtime
373 * directory to NULL */
374 *runtime = NULL;
375 }
376
377 *persistent = a;
378 a = NULL;
379
380 return 0;
381
382 default:
383 assert_not_reached("Hmm, unexpected scope value.");
384 }
385
386 if (!a || !b)
387 return -ENOMEM;
388
389 *persistent = a;
390 *runtime = b;
391 a = b = NULL;
392
393 return 0;
394 }
395
396 static int acquire_control_dirs(UnitFileScope scope, char **persistent, char **runtime) {
397 _cleanup_free_ char *a = NULL;
398 int r;
399
400 assert(persistent);
401 assert(runtime);
402
403 switch (scope) {
404
405 case UNIT_FILE_SYSTEM: {
406 _cleanup_free_ char *b = NULL;
407
408 a = strdup("/etc/systemd/system.control");
409 if (!a)
410 return -ENOMEM;
411
412 b = strdup("/run/systemd/system.control");
413 if (!b)
414 return -ENOMEM;
415
416 *runtime = b;
417 b = NULL;
418
419 break;
420 }
421
422 case UNIT_FILE_USER:
423 r = xdg_user_config_dir(&a, "/systemd/user.control");
424 if (r < 0 && r != -ENXIO)
425 return r;
426
427 r = xdg_user_runtime_dir(runtime, "/systemd/user.control");
428 if (r < 0) {
429 if (r != -ENXIO)
430 return r;
431
432 /* If XDG_RUNTIME_DIR is not set, don't consider this fatal, simply initialize the directory to
433 * NULL */
434 *runtime = NULL;
435 }
436
437 break;
438
439 case UNIT_FILE_GLOBAL:
440 return -EOPNOTSUPP;
441
442 default:
443 assert_not_reached("Hmm, unexpected scope value.");
444 }
445
446 *persistent = a;
447 a = NULL;
448
449 return 0;
450 }
451
452 static int patch_root_prefix(char **p, const char *root_dir) {
453 char *c;
454
455 assert(p);
456
457 if (!*p)
458 return 0;
459
460 c = prefix_root(root_dir, *p);
461 if (!c)
462 return -ENOMEM;
463
464 free(*p);
465 *p = c;
466
467 return 0;
468 }
469
470 static int patch_root_prefix_strv(char **l, const char *root_dir) {
471 char **i;
472 int r;
473
474 if (!root_dir)
475 return 0;
476
477 STRV_FOREACH(i, l) {
478 r = patch_root_prefix(i, root_dir);
479 if (r < 0)
480 return r;
481 }
482
483 return 0;
484 }
485
486 int lookup_paths_init(
487 LookupPaths *p,
488 UnitFileScope scope,
489 LookupPathsFlags flags,
490 const char *root_dir) {
491
492 _cleanup_(rmdir_and_freep) char *tempdir = NULL;
493 _cleanup_free_ char
494 *root = NULL,
495 *persistent_config = NULL, *runtime_config = NULL,
496 *global_persistent_config = NULL, *global_runtime_config = NULL,
497 *generator = NULL, *generator_early = NULL, *generator_late = NULL,
498 *transient = NULL,
499 *persistent_control = NULL, *runtime_control = NULL;
500 bool append = false; /* Add items from SYSTEMD_UNIT_PATH before normal directories */
501 _cleanup_strv_free_ char **paths = NULL;
502 const char *e;
503 int r;
504
505 assert(p);
506 assert(scope >= 0);
507 assert(scope < _UNIT_FILE_SCOPE_MAX);
508
509 if (!isempty(root_dir) && !path_equal(root_dir, "/")) {
510 if (scope == UNIT_FILE_USER)
511 return -EINVAL;
512
513 r = is_dir(root_dir, true);
514 if (r < 0)
515 return r;
516 if (r == 0)
517 return -ENOTDIR;
518
519 root = strdup(root_dir);
520 if (!root)
521 return -ENOMEM;
522 }
523
524 if (flags & LOOKUP_PATHS_TEMPORARY_GENERATED) {
525 r = mkdtemp_malloc("/tmp/systemd-temporary-XXXXXX", &tempdir);
526 if (r < 0)
527 return log_error_errno(r, "Failed to create temporary directory: %m");
528 }
529
530 /* Note: when XDG_RUNTIME_DIR is not set this will not return -ENXIO, but simply set runtime_config to NULL */
531 r = acquire_config_dirs(scope, &persistent_config, &runtime_config);
532 if (r < 0)
533 return r;
534
535 if (scope == UNIT_FILE_USER) {
536 r = acquire_config_dirs(UNIT_FILE_GLOBAL, &global_persistent_config, &global_runtime_config);
537 if (r < 0)
538 return r;
539 }
540
541 if ((flags & LOOKUP_PATHS_EXCLUDE_GENERATED) == 0) {
542 /* Note: if XDG_RUNTIME_DIR is not set, this will fail completely with ENXIO */
543 r = acquire_generator_dirs(scope, tempdir,
544 &generator, &generator_early, &generator_late);
545 if (r < 0 && !IN_SET(r, -EOPNOTSUPP, -ENXIO))
546 return r;
547 }
548
549 /* Note: if XDG_RUNTIME_DIR is not set, this will fail completely with ENXIO */
550 r = acquire_transient_dir(scope, tempdir, &transient);
551 if (r < 0 && !IN_SET(r, -EOPNOTSUPP, -ENXIO))
552 return r;
553
554 /* Note: when XDG_RUNTIME_DIR is not set this will not return -ENXIO, but simply set runtime_control to NULL */
555 r = acquire_control_dirs(scope, &persistent_control, &runtime_control);
556 if (r < 0 && r != -EOPNOTSUPP)
557 return r;
558
559 /* First priority is whatever has been passed to us via env vars */
560 e = getenv("SYSTEMD_UNIT_PATH");
561 if (e) {
562 const char *k;
563
564 k = endswith(e, ":");
565 if (k) {
566 e = strndupa(e, k - e);
567 append = true;
568 }
569
570 /* FIXME: empty components in other places should be rejected. */
571
572 r = path_split_and_make_absolute(e, &paths);
573 if (r < 0)
574 return r;
575 }
576
577 if (!paths || append) {
578 /* Let's figure something out. */
579
580 _cleanup_strv_free_ char **add = NULL;
581
582 /* For the user units we include share/ in the search
583 * path in order to comply with the XDG basedir spec.
584 * For the system stuff we avoid such nonsense. OTOH
585 * we include /lib in the search path for the system
586 * stuff but avoid it for user stuff. */
587
588 switch (scope) {
589
590 case UNIT_FILE_SYSTEM:
591 add = strv_new(
592 /* If you modify this you also want to modify
593 * systemdsystemunitpath= in systemd.pc.in! */
594 STRV_IFNOTNULL(persistent_control),
595 STRV_IFNOTNULL(runtime_control),
596 STRV_IFNOTNULL(transient),
597 STRV_IFNOTNULL(generator_early),
598 persistent_config,
599 SYSTEM_CONFIG_UNIT_PATH,
600 "/etc/systemd/system",
601 runtime_config,
602 "/run/systemd/system",
603 STRV_IFNOTNULL(generator),
604 "/usr/local/lib/systemd/system",
605 SYSTEM_DATA_UNIT_PATH,
606 "/usr/lib/systemd/system",
607 #if HAVE_SPLIT_USR
608 "/lib/systemd/system",
609 #endif
610 STRV_IFNOTNULL(generator_late),
611 NULL);
612 break;
613
614 case UNIT_FILE_GLOBAL:
615 add = strv_new(
616 /* If you modify this you also want to modify
617 * systemduserunitpath= in systemd.pc.in, and
618 * the arrays in user_dirs() above! */
619 STRV_IFNOTNULL(persistent_control),
620 STRV_IFNOTNULL(runtime_control),
621 STRV_IFNOTNULL(transient),
622 STRV_IFNOTNULL(generator_early),
623 persistent_config,
624 USER_CONFIG_UNIT_PATH,
625 "/etc/systemd/user",
626 runtime_config,
627 "/run/systemd/user",
628 STRV_IFNOTNULL(generator),
629 "/usr/local/share/systemd/user",
630 "/usr/share/systemd/user",
631 "/usr/local/lib/systemd/user",
632 USER_DATA_UNIT_PATH,
633 "/usr/lib/systemd/user",
634 STRV_IFNOTNULL(generator_late),
635 NULL);
636 break;
637
638 case UNIT_FILE_USER:
639 add = user_dirs(persistent_config, runtime_config,
640 global_persistent_config, global_runtime_config,
641 generator, generator_early, generator_late,
642 transient,
643 persistent_control, runtime_control);
644 break;
645
646 default:
647 assert_not_reached("Hmm, unexpected scope?");
648 }
649
650 if (!add)
651 return -ENOMEM;
652
653 if (paths) {
654 r = strv_extend_strv(&paths, add, true);
655 if (r < 0)
656 return r;
657 } else {
658 /* Small optimization: if paths is NULL (and it usually is), we can simply assign 'add' to it,
659 * and don't have to copy anything */
660 paths = add;
661 add = NULL;
662 }
663 }
664
665 r = patch_root_prefix(&persistent_config, root);
666 if (r < 0)
667 return r;
668 r = patch_root_prefix(&runtime_config, root);
669 if (r < 0)
670 return r;
671
672 r = patch_root_prefix(&generator, root);
673 if (r < 0)
674 return r;
675 r = patch_root_prefix(&generator_early, root);
676 if (r < 0)
677 return r;
678 r = patch_root_prefix(&generator_late, root);
679 if (r < 0)
680 return r;
681
682 r = patch_root_prefix(&transient, root);
683 if (r < 0)
684 return r;
685
686 r = patch_root_prefix(&persistent_control, root);
687 if (r < 0)
688 return r;
689
690 r = patch_root_prefix(&runtime_control, root);
691 if (r < 0)
692 return r;
693
694 r = patch_root_prefix_strv(paths, root);
695 if (r < 0)
696 return -ENOMEM;
697
698 p->search_path = strv_uniq(paths);
699 paths = NULL;
700
701 p->persistent_config = persistent_config;
702 p->runtime_config = runtime_config;
703 persistent_config = runtime_config = NULL;
704
705 p->generator = generator;
706 p->generator_early = generator_early;
707 p->generator_late = generator_late;
708 generator = generator_early = generator_late = NULL;
709
710 p->transient = transient;
711 transient = NULL;
712
713 p->persistent_control = persistent_control;
714 p->runtime_control = runtime_control;
715 persistent_control = runtime_control = NULL;
716
717 p->root_dir = root;
718 root = NULL;
719
720 p->temporary_dir = tempdir;
721 tempdir = NULL;
722
723 return 0;
724 }
725
726 void lookup_paths_free(LookupPaths *p) {
727 if (!p)
728 return;
729
730 p->search_path = strv_free(p->search_path);
731
732 p->persistent_config = mfree(p->persistent_config);
733 p->runtime_config = mfree(p->runtime_config);
734
735 p->generator = mfree(p->generator);
736 p->generator_early = mfree(p->generator_early);
737 p->generator_late = mfree(p->generator_late);
738
739 p->transient = mfree(p->transient);
740
741 p->persistent_control = mfree(p->persistent_control);
742 p->runtime_control = mfree(p->runtime_control);
743
744 p->root_dir = mfree(p->root_dir);
745 p->temporary_dir = mfree(p->temporary_dir);
746 }
747
748 int lookup_paths_reduce(LookupPaths *p) {
749 _cleanup_free_ struct stat *stats = NULL;
750 size_t n_stats = 0, allocated = 0;
751 unsigned c = 0;
752 int r;
753
754 assert(p);
755
756 /* Drop duplicates and non-existing directories from the search path. We figure out whether two directories are
757 * the same by comparing their device and inode numbers. Note one special tweak: when we have a root path set,
758 * we do not follow symlinks when retrieving them, because the kernel wouldn't take the root prefix into
759 * account when following symlinks. When we have no root path set this restriction does not apply however. */
760
761 if (!p->search_path)
762 return 0;
763
764 while (p->search_path[c]) {
765 struct stat st;
766 unsigned k;
767
768 /* Never strip the transient and control directories from the path */
769 if (path_equal_ptr(p->search_path[c], p->transient) ||
770 path_equal_ptr(p->search_path[c], p->persistent_control) ||
771 path_equal_ptr(p->search_path[c], p->runtime_control)) {
772 c++;
773 continue;
774 }
775
776 if (p->root_dir)
777 r = lstat(p->search_path[c], &st);
778 else
779 r = stat(p->search_path[c], &st);
780 if (r < 0) {
781 if (errno == ENOENT)
782 goto remove_item;
783
784 /* If something we don't grok happened, let's better leave it in. */
785 log_debug_errno(errno, "Failed to stat %s: %m", p->search_path[c]);
786 c++;
787 continue;
788 }
789
790 for (k = 0; k < n_stats; k++) {
791 if (stats[k].st_dev == st.st_dev &&
792 stats[k].st_ino == st.st_ino)
793 break;
794 }
795
796 if (k < n_stats) /* Is there already an entry with the same device/inode? */
797 goto remove_item;
798
799 if (!GREEDY_REALLOC(stats, allocated, n_stats+1))
800 return -ENOMEM;
801
802 stats[n_stats++] = st;
803 c++;
804 continue;
805
806 remove_item:
807 free(p->search_path[c]);
808 memmove(p->search_path + c,
809 p->search_path + c + 1,
810 (strv_length(p->search_path + c + 1) + 1) * sizeof(char*));
811 }
812
813 if (strv_isempty(p->search_path)) {
814 log_debug("Ignoring unit files.");
815 p->search_path = strv_free(p->search_path);
816 } else {
817 _cleanup_free_ char *t;
818
819 t = strv_join(p->search_path, "\n\t");
820 if (!t)
821 return -ENOMEM;
822
823 log_debug("Looking for unit files in (higher priority first):\n\t%s", t);
824 }
825
826 return 0;
827 }
828
829 int lookup_paths_mkdir_generator(LookupPaths *p) {
830 int r, q;
831
832 assert(p);
833
834 if (!p->generator || !p->generator_early || !p->generator_late)
835 return -EINVAL;
836
837 r = mkdir_p_label(p->generator, 0755);
838
839 q = mkdir_p_label(p->generator_early, 0755);
840 if (q < 0 && r >= 0)
841 r = q;
842
843 q = mkdir_p_label(p->generator_late, 0755);
844 if (q < 0 && r >= 0)
845 r = q;
846
847 return r;
848 }
849
850 void lookup_paths_trim_generator(LookupPaths *p) {
851 assert(p);
852
853 /* Trim empty dirs */
854
855 if (p->generator)
856 (void) rmdir(p->generator);
857 if (p->generator_early)
858 (void) rmdir(p->generator_early);
859 if (p->generator_late)
860 (void) rmdir(p->generator_late);
861 }
862
863 void lookup_paths_flush_generator(LookupPaths *p) {
864 assert(p);
865
866 /* Flush the generated unit files in full */
867
868 if (p->generator)
869 (void) rm_rf(p->generator, REMOVE_ROOT);
870 if (p->generator_early)
871 (void) rm_rf(p->generator_early, REMOVE_ROOT);
872 if (p->generator_late)
873 (void) rm_rf(p->generator_late, REMOVE_ROOT);
874
875 if (p->temporary_dir)
876 (void) rm_rf(p->temporary_dir, REMOVE_ROOT);
877 }
878
879 char **generator_binary_paths(UnitFileScope scope) {
880
881 switch (scope) {
882
883 case UNIT_FILE_SYSTEM:
884 return strv_new("/run/systemd/system-generators",
885 "/etc/systemd/system-generators",
886 "/usr/local/lib/systemd/system-generators",
887 SYSTEM_GENERATOR_PATH,
888 NULL);
889
890 case UNIT_FILE_GLOBAL:
891 case UNIT_FILE_USER:
892 return strv_new("/run/systemd/user-generators",
893 "/etc/systemd/user-generators",
894 "/usr/local/lib/systemd/user-generators",
895 USER_GENERATOR_PATH,
896 NULL);
897
898 default:
899 assert_not_reached("Hmm, unexpected scope.");
900 }
901 }