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