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