]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/path-lookup.c
Add SPDX license identifiers to source files under the LGPL
[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 static int 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 static int 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 static int 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 static char** user_dirs(
135 const char *persistent_config,
136 const char *runtime_config,
137 const char *generator,
138 const char *generator_early,
139 const char *generator_late,
140 const char *transient,
141 const char *persistent_control,
142 const char *runtime_control) {
143
144 _cleanup_strv_free_ char **config_dirs = NULL, **data_dirs = NULL;
145 _cleanup_free_ char *data_home = NULL;
146 _cleanup_strv_free_ char **res = NULL;
147 const char *e;
148 char **tmp;
149 int r;
150
151 /* Implement the mechanisms defined in
152 *
153 * http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
154 *
155 * We look in both the config and the data dirs because we
156 * want to encourage that distributors ship their unit files
157 * as data, and allow overriding as configuration.
158 */
159
160 e = getenv("XDG_CONFIG_DIRS");
161 if (e) {
162 config_dirs = strv_split(e, ":");
163 if (!config_dirs)
164 return NULL;
165 }
166
167 r = user_data_dir(&data_home, "/systemd/user");
168 if (r < 0 && r != -ENXIO)
169 return NULL;
170
171 e = getenv("XDG_DATA_DIRS");
172 if (e)
173 data_dirs = strv_split(e, ":");
174 else
175 data_dirs = strv_new("/usr/local/share",
176 "/usr/share",
177 NULL);
178 if (!data_dirs)
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 if (strv_extend_strv(&res, (char**) user_config_unit_paths, false) < 0)
201 return NULL;
202
203 if (strv_extend(&res, runtime_config) < 0)
204 return NULL;
205
206 if (strv_extend(&res, generator) < 0)
207 return NULL;
208
209 if (strv_extend(&res, data_home) < 0)
210 return NULL;
211
212 if (strv_extend_strv_concat(&res, data_dirs, "/systemd/user") < 0)
213 return NULL;
214
215 if (strv_extend_strv(&res, (char**) user_data_unit_paths, false) < 0)
216 return NULL;
217
218 if (strv_extend(&res, generator_late) < 0)
219 return NULL;
220
221 if (path_strv_make_absolute_cwd(res) < 0)
222 return NULL;
223
224 tmp = res;
225 res = NULL;
226
227 return tmp;
228 }
229
230 bool path_is_user_data_dir(const char *path) {
231 assert(path);
232
233 return strv_contains((char**) user_data_unit_paths, path);
234 }
235
236 bool path_is_user_config_dir(const char *path) {
237 assert(path);
238
239 return strv_contains((char**) user_config_unit_paths, path);
240 }
241
242 static int acquire_generator_dirs(
243 UnitFileScope scope,
244 const char *tempdir,
245 char **generator,
246 char **generator_early,
247 char **generator_late) {
248
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 && !IN_SET(r, -EOPNOTSUPP, -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 && !IN_SET(r, -EOPNOTSUPP, -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 }