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 static int user_runtime_dir(char **ret
, const char *suffix
) {
49 e
= getenv("XDG_RUNTIME_DIR");
53 j
= strappend(e
, suffix
);
61 static int 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 static int 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 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
) {
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
;
151 /* Implement the mechanisms defined in
153 * http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
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.
160 e
= getenv("XDG_CONFIG_DIRS");
162 config_dirs
= strv_split(e
, ":");
167 r
= user_data_dir(&data_home
, "/systemd/user");
168 if (r
< 0 && r
!= -ENXIO
)
171 e
= getenv("XDG_DATA_DIRS");
173 data_dirs
= strv_split(e
, ":");
175 data_dirs
= strv_new("/usr/local/share",
181 /* Now merge everything we found. */
182 if (strv_extend(&res
, persistent_control
) < 0)
185 if (strv_extend(&res
, runtime_control
) < 0)
188 if (strv_extend(&res
, transient
) < 0)
191 if (strv_extend(&res
, generator_early
) < 0)
194 if (strv_extend_strv_concat(&res
, config_dirs
, "/systemd/user") < 0)
197 if (strv_extend(&res
, persistent_config
) < 0)
200 if (strv_extend_strv(&res
, (char**) user_config_unit_paths
, false) < 0)
203 if (strv_extend(&res
, runtime_config
) < 0)
206 if (strv_extend(&res
, generator
) < 0)
209 if (strv_extend(&res
, data_home
) < 0)
212 if (strv_extend_strv_concat(&res
, data_dirs
, "/systemd/user") < 0)
215 if (strv_extend_strv(&res
, (char**) user_data_unit_paths
, false) < 0)
218 if (strv_extend(&res
, generator_late
) < 0)
221 if (path_strv_make_absolute_cwd(res
) < 0)
230 bool path_is_user_data_dir(const char *path
) {
233 return strv_contains((char**) user_data_unit_paths
, path
);
236 bool path_is_user_config_dir(const char *path
) {
239 return strv_contains((char**) user_config_unit_paths
, path
);
242 static int acquire_generator_dirs(
246 char **generator_early
,
247 char **generator_late
) {
249 _cleanup_free_
char *x
= NULL
, *y
= NULL
, *z
= NULL
;
253 assert(generator_early
);
254 assert(generator_late
);
255 assert(IN_SET(scope
, UNIT_FILE_SYSTEM
, UNIT_FILE_USER
, UNIT_FILE_GLOBAL
));
257 if (scope
== UNIT_FILE_GLOBAL
)
263 else if (scope
== UNIT_FILE_SYSTEM
)
264 prefix
= "/run/systemd";
266 else if (scope
== UNIT_FILE_USER
) {
269 e
= getenv("XDG_RUNTIME_DIR");
273 prefix
= strjoina(e
, "/systemd");
276 x
= strappend(prefix
, "/generator");
280 y
= strappend(prefix
, "/generator.early");
284 z
= strappend(prefix
, "/generator.late");
289 *generator_early
= y
;
296 static int acquire_transient_dir(
304 assert(IN_SET(scope
, UNIT_FILE_SYSTEM
, UNIT_FILE_USER
, UNIT_FILE_GLOBAL
));
306 if (scope
== UNIT_FILE_GLOBAL
)
310 transient
= strjoin(tempdir
, "/transient");
311 else if (scope
== UNIT_FILE_SYSTEM
)
312 transient
= strdup("/run/systemd/transient");
314 return user_runtime_dir(ret
, "/systemd/transient");
322 static int acquire_config_dirs(UnitFileScope scope
, char **persistent
, char **runtime
) {
323 _cleanup_free_
char *a
= NULL
, *b
= NULL
;
331 case UNIT_FILE_SYSTEM
:
332 a
= strdup(SYSTEM_CONFIG_UNIT_PATH
);
333 b
= strdup("/run/systemd/system");
336 case UNIT_FILE_GLOBAL
:
337 a
= strdup(USER_CONFIG_UNIT_PATH
);
338 b
= strdup("/run/systemd/user");
342 r
= user_config_dir(&a
, "/systemd/user");
343 if (r
< 0 && r
!= -ENXIO
)
346 r
= user_runtime_dir(runtime
, "/systemd/user");
351 /* If XDG_RUNTIME_DIR is not set, don't consider that fatal, simply initialize the runtime
352 * directory to NULL */
362 assert_not_reached("Hmm, unexpected scope value.");
375 static int acquire_control_dirs(UnitFileScope scope
, char **persistent
, char **runtime
) {
376 _cleanup_free_
char *a
= NULL
;
384 case UNIT_FILE_SYSTEM
: {
385 _cleanup_free_
char *b
= NULL
;
387 a
= strdup("/etc/systemd/system.control");
391 b
= strdup("/run/systemd/system.control");
402 r
= user_config_dir(&a
, "/systemd/system.control");
403 if (r
< 0 && r
!= -ENXIO
)
406 r
= user_runtime_dir(runtime
, "/systemd/system.control");
411 /* If XDG_RUNTIME_DIR is not set, don't consider this fatal, simply initialize the directory to
418 case UNIT_FILE_GLOBAL
:
422 assert_not_reached("Hmm, unexpected scope value.");
431 static int patch_root_prefix(char **p
, const char *root_dir
) {
439 c
= prefix_root(root_dir
, *p
);
449 static int patch_root_prefix_strv(char **l
, const char *root_dir
) {
457 r
= patch_root_prefix(i
, root_dir
);
465 int lookup_paths_init(
468 LookupPathsFlags flags
,
469 const char *root_dir
) {
471 _cleanup_(rmdir_and_freep
) char *tempdir
= NULL
;
474 *persistent_config
= NULL
, *runtime_config
= NULL
,
475 *generator
= NULL
, *generator_early
= NULL
, *generator_late
= 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
;
485 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
487 if (!isempty(root_dir
) && !path_equal(root_dir
, "/")) {
488 if (scope
== UNIT_FILE_USER
)
491 r
= is_dir(root_dir
, true);
497 root
= strdup(root_dir
);
502 if (flags
& LOOKUP_PATHS_TEMPORARY_GENERATED
) {
503 r
= mkdtemp_malloc("/tmp/systemd-temporary-XXXXXX", &tempdir
);
505 return log_error_errno(r
, "Failed to create temporary directory: %m");
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
);
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
))
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
))
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
)
531 /* First priority is whatever has been passed to us via env vars */
532 e
= getenv("SYSTEMD_UNIT_PATH");
536 k
= endswith(e
, ":");
538 e
= strndupa(e
, k
- e
);
542 /* FIXME: empty components in other places should be rejected. */
544 r
= path_split_and_make_absolute(e
, &paths
);
549 if (!paths
|| append
) {
550 /* Let's figure something out. */
552 _cleanup_strv_free_
char **add
= NULL
;
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. */
562 case UNIT_FILE_SYSTEM
:
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
),
571 SYSTEM_CONFIG_UNIT_PATH
,
572 "/etc/systemd/system",
574 "/run/systemd/system",
575 STRV_IFNOTNULL(generator
),
576 "/usr/local/lib/systemd/system",
577 SYSTEM_DATA_UNIT_PATH
,
578 "/usr/lib/systemd/system",
580 "/lib/systemd/system",
582 STRV_IFNOTNULL(generator_late
),
586 case UNIT_FILE_GLOBAL
:
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
),
596 USER_CONFIG_UNIT_PATH
,
600 STRV_IFNOTNULL(generator
),
601 "/usr/local/lib/systemd/user",
602 "/usr/local/share/systemd/user",
604 "/usr/lib/systemd/user",
605 "/usr/share/systemd/user",
606 STRV_IFNOTNULL(generator_late
),
611 add
= user_dirs(persistent_config
, runtime_config
,
612 generator
, generator_early
, generator_late
,
614 persistent_config
, runtime_control
);
618 assert_not_reached("Hmm, unexpected scope?");
625 r
= strv_extend_strv(&paths
, add
, true);
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 */
636 r
= patch_root_prefix(&persistent_config
, root
);
639 r
= patch_root_prefix(&runtime_config
, root
);
643 r
= patch_root_prefix(&generator
, root
);
646 r
= patch_root_prefix(&generator_early
, root
);
649 r
= patch_root_prefix(&generator_late
, root
);
653 r
= patch_root_prefix(&transient
, root
);
657 r
= patch_root_prefix(&persistent_control
, root
);
661 r
= patch_root_prefix(&runtime_control
, root
);
665 r
= patch_root_prefix_strv(paths
, root
);
669 p
->search_path
= strv_uniq(paths
);
672 p
->persistent_config
= persistent_config
;
673 p
->runtime_config
= runtime_config
;
674 persistent_config
= runtime_config
= NULL
;
676 p
->generator
= generator
;
677 p
->generator_early
= generator_early
;
678 p
->generator_late
= generator_late
;
679 generator
= generator_early
= generator_late
= NULL
;
681 p
->transient
= transient
;
684 p
->persistent_control
= persistent_control
;
685 p
->runtime_control
= runtime_control
;
686 persistent_control
= runtime_control
= NULL
;
691 p
->temporary_dir
= tempdir
;
697 void lookup_paths_free(LookupPaths
*p
) {
701 p
->search_path
= strv_free(p
->search_path
);
703 p
->persistent_config
= mfree(p
->persistent_config
);
704 p
->runtime_config
= mfree(p
->runtime_config
);
706 p
->generator
= mfree(p
->generator
);
707 p
->generator_early
= mfree(p
->generator_early
);
708 p
->generator_late
= mfree(p
->generator_late
);
710 p
->transient
= mfree(p
->transient
);
712 p
->persistent_control
= mfree(p
->persistent_control
);
713 p
->runtime_control
= mfree(p
->runtime_control
);
715 p
->root_dir
= mfree(p
->root_dir
);
716 p
->temporary_dir
= mfree(p
->temporary_dir
);
719 int lookup_paths_reduce(LookupPaths
*p
) {
720 _cleanup_free_
struct stat
*stats
= NULL
;
721 size_t n_stats
= 0, allocated
= 0;
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. */
735 while (p
->search_path
[c
]) {
740 r
= lstat(p
->search_path
[c
], &st
);
742 r
= stat(p
->search_path
[c
], &st
);
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
]);
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
)
759 if (k
< n_stats
) /* Is there already an entry with the same device/inode? */
762 if (!GREEDY_REALLOC(stats
, allocated
, n_stats
+1))
765 stats
[n_stats
++] = st
;
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*));
776 if (strv_isempty(p
->search_path
)) {
777 log_debug("Ignoring unit files.");
778 p
->search_path
= strv_free(p
->search_path
);
780 _cleanup_free_
char *t
;
782 t
= strv_join(p
->search_path
, "\n\t");
786 log_debug("Looking for unit files in (higher priority first):\n\t%s", t
);
792 int lookup_paths_mkdir_generator(LookupPaths
*p
) {
797 if (!p
->generator
|| !p
->generator_early
|| !p
->generator_late
)
800 r
= mkdir_p_label(p
->generator
, 0755);
802 q
= mkdir_p_label(p
->generator_early
, 0755);
806 q
= mkdir_p_label(p
->generator_late
, 0755);
813 void lookup_paths_trim_generator(LookupPaths
*p
) {
816 /* Trim empty dirs */
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
);
826 void lookup_paths_flush_generator(LookupPaths
*p
) {
829 /* Flush the generated unit files in full */
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
);
838 if (p
->temporary_dir
)
839 (void) rm_rf(p
->temporary_dir
, REMOVE_ROOT
);
842 char **generator_binary_paths(UnitFileScope scope
) {
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
,
853 case UNIT_FILE_GLOBAL
:
855 return strv_new("/run/systemd/user-generators",
856 "/etc/systemd/user-generators",
857 "/usr/local/lib/systemd/user-generators",
862 assert_not_reached("Hmm, unexpected scope.");