1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
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.
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.
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/>.
26 #include "alloc-util.h"
33 #include "path-lookup.h"
34 #include "path-util.h"
36 #include "stat-util.h"
37 #include "string-util.h"
39 #include "user-util.h"
42 int xdg_user_runtime_dir(char **ret
, const char *suffix
) {
49 e
= getenv("XDG_RUNTIME_DIR");
53 j
= strappend(e
, suffix
);
61 int xdg_user_config_dir(char **ret
, const char *suffix
) {
68 e
= getenv("XDG_CONFIG_HOME");
70 j
= strappend(e
, suffix
);
72 _cleanup_free_
char *home
= NULL
;
74 r
= get_home_dir(&home
);
78 j
= strjoin(home
, "/.config", suffix
);
88 int xdg_user_data_dir(char **ret
, const char *suffix
) {
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. */
100 e
= getenv("XDG_DATA_HOME");
102 j
= strappend(e
, suffix
);
104 _cleanup_free_
char *home
= NULL
;
106 r
= get_home_dir(&home
);
110 j
= strjoin(home
, "/.local/share", suffix
);
119 static const char* const user_data_unit_paths
[] = {
120 "/usr/local/lib/systemd/user",
121 "/usr/local/share/systemd/user",
123 "/usr/lib/systemd/user",
124 "/usr/share/systemd/user",
128 static const char* const user_config_unit_paths
[] = {
129 USER_CONFIG_UNIT_PATH
,
134 int xdg_user_dirs(char ***ret_config_dirs
, char ***ret_data_dirs
) {
135 /* Implement the mechanisms defined in
137 * http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
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.
144 _cleanup_strv_free_
char **config_dirs
= NULL
, **data_dirs
= NULL
;
146 e
= getenv("XDG_CONFIG_DIRS");
148 config_dirs
= strv_split(e
, ":");
153 e
= getenv("XDG_DATA_DIRS");
155 data_dirs
= strv_split(e
, ":");
157 data_dirs
= strv_new("/usr/local/share",
163 *ret_config_dirs
= config_dirs
;
164 *ret_data_dirs
= data_dirs
;
165 config_dirs
= data_dirs
= NULL
;
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
) {
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
;
187 r
= xdg_user_dirs(&config_dirs
, &data_dirs
);
191 r
= xdg_user_data_dir(&data_home
, "/systemd/user");
192 if (r
< 0 && r
!= -ENXIO
)
195 /* Now merge everything we found. */
196 if (strv_extend(&res
, persistent_control
) < 0)
199 if (strv_extend(&res
, runtime_control
) < 0)
202 if (strv_extend(&res
, transient
) < 0)
205 if (strv_extend(&res
, generator_early
) < 0)
208 if (strv_extend_strv_concat(&res
, config_dirs
, "/systemd/user") < 0)
211 if (strv_extend(&res
, persistent_config
) < 0)
214 /* global config has lower priority than the user config of the same type */
215 if (strv_extend(&res
, global_persistent_config
) < 0)
218 if (strv_extend_strv(&res
, (char**) user_config_unit_paths
, false) < 0)
221 if (strv_extend(&res
, runtime_config
) < 0)
224 if (strv_extend(&res
, global_runtime_config
) < 0)
227 if (strv_extend(&res
, generator
) < 0)
230 if (strv_extend(&res
, data_home
) < 0)
233 if (strv_extend_strv_concat(&res
, data_dirs
, "/systemd/user") < 0)
236 if (strv_extend_strv(&res
, (char**) user_data_unit_paths
, false) < 0)
239 if (strv_extend(&res
, generator_late
) < 0)
242 if (path_strv_make_absolute_cwd(res
) < 0)
251 bool path_is_user_data_dir(const char *path
) {
254 return strv_contains((char**) user_data_unit_paths
, path
);
257 bool path_is_user_config_dir(const char *path
) {
260 return strv_contains((char**) user_config_unit_paths
, path
);
263 static int acquire_generator_dirs(
267 char **generator_early
,
268 char **generator_late
) {
270 _cleanup_free_
char *x
= NULL
, *y
= NULL
, *z
= NULL
;
274 assert(generator_early
);
275 assert(generator_late
);
276 assert(IN_SET(scope
, UNIT_FILE_SYSTEM
, UNIT_FILE_USER
, UNIT_FILE_GLOBAL
));
278 if (scope
== UNIT_FILE_GLOBAL
)
284 else if (scope
== UNIT_FILE_SYSTEM
)
285 prefix
= "/run/systemd";
287 else if (scope
== UNIT_FILE_USER
) {
290 e
= getenv("XDG_RUNTIME_DIR");
294 prefix
= strjoina(e
, "/systemd");
297 x
= strappend(prefix
, "/generator");
301 y
= strappend(prefix
, "/generator.early");
305 z
= strappend(prefix
, "/generator.late");
310 *generator_early
= y
;
317 static int acquire_transient_dir(
325 assert(IN_SET(scope
, UNIT_FILE_SYSTEM
, UNIT_FILE_USER
, UNIT_FILE_GLOBAL
));
327 if (scope
== UNIT_FILE_GLOBAL
)
331 transient
= strjoin(tempdir
, "/transient");
332 else if (scope
== UNIT_FILE_SYSTEM
)
333 transient
= strdup("/run/systemd/transient");
335 return xdg_user_runtime_dir(ret
, "/systemd/transient");
343 static int acquire_config_dirs(UnitFileScope scope
, char **persistent
, char **runtime
) {
344 _cleanup_free_
char *a
= NULL
, *b
= NULL
;
352 case UNIT_FILE_SYSTEM
:
353 a
= strdup(SYSTEM_CONFIG_UNIT_PATH
);
354 b
= strdup("/run/systemd/system");
357 case UNIT_FILE_GLOBAL
:
358 a
= strdup(USER_CONFIG_UNIT_PATH
);
359 b
= strdup("/run/systemd/user");
363 r
= xdg_user_config_dir(&a
, "/systemd/user");
364 if (r
< 0 && r
!= -ENXIO
)
367 r
= xdg_user_runtime_dir(runtime
, "/systemd/user");
372 /* If XDG_RUNTIME_DIR is not set, don't consider that fatal, simply initialize the runtime
373 * directory to NULL */
383 assert_not_reached("Hmm, unexpected scope value.");
396 static int acquire_control_dirs(UnitFileScope scope
, char **persistent
, char **runtime
) {
397 _cleanup_free_
char *a
= NULL
;
405 case UNIT_FILE_SYSTEM
: {
406 _cleanup_free_
char *b
= NULL
;
408 a
= strdup("/etc/systemd/system.control");
412 b
= strdup("/run/systemd/system.control");
423 r
= xdg_user_config_dir(&a
, "/systemd/user.control");
424 if (r
< 0 && r
!= -ENXIO
)
427 r
= xdg_user_runtime_dir(runtime
, "/systemd/user.control");
432 /* If XDG_RUNTIME_DIR is not set, don't consider this fatal, simply initialize the directory to
439 case UNIT_FILE_GLOBAL
:
443 assert_not_reached("Hmm, unexpected scope value.");
452 static int patch_root_prefix(char **p
, const char *root_dir
) {
460 c
= prefix_root(root_dir
, *p
);
470 static int patch_root_prefix_strv(char **l
, const char *root_dir
) {
478 r
= patch_root_prefix(i
, root_dir
);
486 int lookup_paths_init(
489 LookupPathsFlags flags
,
490 const char *root_dir
) {
492 _cleanup_(rmdir_and_freep
) char *tempdir
= 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
,
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
;
507 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
509 if (!isempty(root_dir
) && !path_equal(root_dir
, "/")) {
510 if (scope
== UNIT_FILE_USER
)
513 r
= is_dir(root_dir
, true);
519 root
= strdup(root_dir
);
524 if (flags
& LOOKUP_PATHS_TEMPORARY_GENERATED
) {
525 r
= mkdtemp_malloc("/tmp/systemd-temporary-XXXXXX", &tempdir
);
527 return log_error_errno(r
, "Failed to create temporary directory: %m");
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
);
535 if (scope
== UNIT_FILE_USER
) {
536 r
= acquire_config_dirs(UNIT_FILE_GLOBAL
, &global_persistent_config
, &global_runtime_config
);
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
))
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
))
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
)
559 /* First priority is whatever has been passed to us via env vars */
560 e
= getenv("SYSTEMD_UNIT_PATH");
564 k
= endswith(e
, ":");
566 e
= strndupa(e
, k
- e
);
570 /* FIXME: empty components in other places should be rejected. */
572 r
= path_split_and_make_absolute(e
, &paths
);
577 if (!paths
|| append
) {
578 /* Let's figure something out. */
580 _cleanup_strv_free_
char **add
= NULL
;
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. */
590 case UNIT_FILE_SYSTEM
:
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
),
599 SYSTEM_CONFIG_UNIT_PATH
,
600 "/etc/systemd/system",
602 "/run/systemd/system",
603 STRV_IFNOTNULL(generator
),
604 "/usr/local/lib/systemd/system",
605 SYSTEM_DATA_UNIT_PATH
,
606 "/usr/lib/systemd/system",
608 "/lib/systemd/system",
610 STRV_IFNOTNULL(generator_late
),
614 case UNIT_FILE_GLOBAL
:
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
),
624 USER_CONFIG_UNIT_PATH
,
628 STRV_IFNOTNULL(generator
),
629 "/usr/local/share/systemd/user",
630 "/usr/share/systemd/user",
631 "/usr/local/lib/systemd/user",
633 "/usr/lib/systemd/user",
634 STRV_IFNOTNULL(generator_late
),
639 add
= user_dirs(persistent_config
, runtime_config
,
640 global_persistent_config
, global_runtime_config
,
641 generator
, generator_early
, generator_late
,
643 persistent_control
, runtime_control
);
647 assert_not_reached("Hmm, unexpected scope?");
654 r
= strv_extend_strv(&paths
, add
, true);
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 */
665 r
= patch_root_prefix(&persistent_config
, root
);
668 r
= patch_root_prefix(&runtime_config
, root
);
672 r
= patch_root_prefix(&generator
, root
);
675 r
= patch_root_prefix(&generator_early
, root
);
678 r
= patch_root_prefix(&generator_late
, root
);
682 r
= patch_root_prefix(&transient
, root
);
686 r
= patch_root_prefix(&persistent_control
, root
);
690 r
= patch_root_prefix(&runtime_control
, root
);
694 r
= patch_root_prefix_strv(paths
, root
);
698 p
->search_path
= strv_uniq(paths
);
701 p
->persistent_config
= persistent_config
;
702 p
->runtime_config
= runtime_config
;
703 persistent_config
= runtime_config
= NULL
;
705 p
->generator
= generator
;
706 p
->generator_early
= generator_early
;
707 p
->generator_late
= generator_late
;
708 generator
= generator_early
= generator_late
= NULL
;
710 p
->transient
= transient
;
713 p
->persistent_control
= persistent_control
;
714 p
->runtime_control
= runtime_control
;
715 persistent_control
= runtime_control
= NULL
;
720 p
->temporary_dir
= tempdir
;
726 void lookup_paths_free(LookupPaths
*p
) {
730 p
->search_path
= strv_free(p
->search_path
);
732 p
->persistent_config
= mfree(p
->persistent_config
);
733 p
->runtime_config
= mfree(p
->runtime_config
);
735 p
->generator
= mfree(p
->generator
);
736 p
->generator_early
= mfree(p
->generator_early
);
737 p
->generator_late
= mfree(p
->generator_late
);
739 p
->transient
= mfree(p
->transient
);
741 p
->persistent_control
= mfree(p
->persistent_control
);
742 p
->runtime_control
= mfree(p
->runtime_control
);
744 p
->root_dir
= mfree(p
->root_dir
);
745 p
->temporary_dir
= mfree(p
->temporary_dir
);
748 int lookup_paths_reduce(LookupPaths
*p
) {
749 _cleanup_free_
struct stat
*stats
= NULL
;
750 size_t n_stats
= 0, allocated
= 0;
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. */
764 while (p
->search_path
[c
]) {
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
)) {
777 r
= lstat(p
->search_path
[c
], &st
);
779 r
= stat(p
->search_path
[c
], &st
);
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
]);
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
)
796 if (k
< n_stats
) /* Is there already an entry with the same device/inode? */
799 if (!GREEDY_REALLOC(stats
, allocated
, n_stats
+1))
802 stats
[n_stats
++] = st
;
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*));
813 if (strv_isempty(p
->search_path
)) {
814 log_debug("Ignoring unit files.");
815 p
->search_path
= strv_free(p
->search_path
);
817 _cleanup_free_
char *t
;
819 t
= strv_join(p
->search_path
, "\n\t");
823 log_debug("Looking for unit files in (higher priority first):\n\t%s", t
);
829 int lookup_paths_mkdir_generator(LookupPaths
*p
) {
834 if (!p
->generator
|| !p
->generator_early
|| !p
->generator_late
)
837 r
= mkdir_p_label(p
->generator
, 0755);
839 q
= mkdir_p_label(p
->generator_early
, 0755);
843 q
= mkdir_p_label(p
->generator_late
, 0755);
850 void lookup_paths_trim_generator(LookupPaths
*p
) {
853 /* Trim empty dirs */
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
);
863 void lookup_paths_flush_generator(LookupPaths
*p
) {
866 /* Flush the generated unit files in full */
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
);
875 if (p
->temporary_dir
)
876 (void) rm_rf(p
->temporary_dir
, REMOVE_ROOT
);
879 char **generator_binary_paths(UnitFileScope scope
) {
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
,
890 case UNIT_FILE_GLOBAL
:
892 return strv_new("/run/systemd/user-generators",
893 "/etc/systemd/user-generators",
894 "/usr/local/lib/systemd/user-generators",
899 assert_not_reached("Hmm, unexpected scope.");