2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
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.
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.
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/>.
25 #include "alloc-util.h"
32 #include "path-lookup.h"
33 #include "path-util.h"
35 #include "stat-util.h"
36 #include "string-util.h"
38 #include "user-util.h"
41 static int user_runtime_dir(char **ret
, const char *suffix
) {
48 e
= getenv("XDG_RUNTIME_DIR");
52 j
= strappend(e
, suffix
);
60 static int user_config_dir(char **ret
, const char *suffix
) {
67 e
= getenv("XDG_CONFIG_HOME");
69 j
= strappend(e
, suffix
);
71 _cleanup_free_
char *home
= NULL
;
73 r
= get_home_dir(&home
);
77 j
= strjoin(home
, "/.config", suffix
);
87 static int user_data_dir(char **ret
, const char *suffix
) {
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. */
99 e
= getenv("XDG_DATA_HOME");
101 j
= strappend(e
, suffix
);
103 _cleanup_free_
char *home
= NULL
;
105 r
= get_home_dir(&home
);
109 j
= strjoin(home
, "/.local/share", suffix
);
118 static char** user_dirs(
119 const char *persistent_config
,
120 const char *runtime_config
,
121 const char *generator
,
122 const char *generator_early
,
123 const char *generator_late
,
124 const char *transient
,
125 const char *persistent_control
,
126 const char *runtime_control
) {
128 const char * const config_unit_paths
[] = {
129 USER_CONFIG_UNIT_PATH
,
134 const char * const data_unit_paths
[] = {
135 "/usr/local/lib/systemd/user",
136 "/usr/local/share/systemd/user",
138 "/usr/lib/systemd/user",
139 "/usr/share/systemd/user",
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
;
150 /* Implement the mechanisms defined in
152 * http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
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.
159 e
= getenv("XDG_CONFIG_DIRS");
161 config_dirs
= strv_split(e
, ":");
166 r
= user_data_dir(&data_home
, "/systemd/user");
167 if (r
< 0 && r
!= -ENXIO
)
170 e
= getenv("XDG_DATA_DIRS");
172 data_dirs
= strv_split(e
, ":");
174 data_dirs
= strv_new("/usr/local/share",
180 /* Now merge everything we found. */
181 if (strv_extend(&res
, persistent_control
) < 0)
184 if (strv_extend(&res
, runtime_control
) < 0)
187 if (strv_extend(&res
, transient
) < 0)
190 if (strv_extend(&res
, generator_early
) < 0)
193 if (strv_extend_strv_concat(&res
, config_dirs
, "/systemd/user") < 0)
196 if (strv_extend(&res
, persistent_config
) < 0)
199 if (strv_extend_strv(&res
, (char**) config_unit_paths
, false) < 0)
202 if (strv_extend(&res
, runtime_config
) < 0)
205 if (strv_extend(&res
, generator
) < 0)
208 if (strv_extend(&res
, data_home
) < 0)
211 if (strv_extend_strv_concat(&res
, data_dirs
, "/systemd/user") < 0)
214 if (strv_extend_strv(&res
, (char**) data_unit_paths
, false) < 0)
217 if (strv_extend(&res
, generator_late
) < 0)
220 if (path_strv_make_absolute_cwd(res
) < 0)
229 static int acquire_generator_dirs(
233 char **generator_early
,
234 char **generator_late
) {
236 _cleanup_(rmdir_and_freep
) char *t
= NULL
;
237 _cleanup_free_
char *x
= NULL
, *y
= NULL
, *z
= NULL
;
241 assert(generator_early
);
242 assert(generator_late
);
243 assert(IN_SET(scope
, UNIT_FILE_SYSTEM
, UNIT_FILE_USER
, UNIT_FILE_GLOBAL
));
245 if (scope
== UNIT_FILE_GLOBAL
)
251 else if (scope
== UNIT_FILE_SYSTEM
)
252 prefix
= "/run/systemd";
254 else if (scope
== UNIT_FILE_USER
) {
257 e
= getenv("XDG_RUNTIME_DIR");
261 prefix
= strjoina(e
, "/systemd");
264 x
= strappend(prefix
, "/generator");
268 y
= strappend(prefix
, "/generator.early");
272 z
= strappend(prefix
, "/generator.late");
277 *generator_early
= y
;
284 static int acquire_transient_dir(
292 assert(IN_SET(scope
, UNIT_FILE_SYSTEM
, UNIT_FILE_USER
, UNIT_FILE_GLOBAL
));
294 if (scope
== UNIT_FILE_GLOBAL
)
298 transient
= strjoin(tempdir
, "/transient");
299 else if (scope
== UNIT_FILE_SYSTEM
)
300 transient
= strdup("/run/systemd/transient");
302 return user_runtime_dir(ret
, "/systemd/transient");
310 static int acquire_config_dirs(UnitFileScope scope
, char **persistent
, char **runtime
) {
311 _cleanup_free_
char *a
= NULL
, *b
= NULL
;
319 case UNIT_FILE_SYSTEM
:
320 a
= strdup(SYSTEM_CONFIG_UNIT_PATH
);
321 b
= strdup("/run/systemd/system");
324 case UNIT_FILE_GLOBAL
:
325 a
= strdup(USER_CONFIG_UNIT_PATH
);
326 b
= strdup("/run/systemd/user");
330 r
= user_config_dir(&a
, "/systemd/user");
331 if (r
< 0 && r
!= -ENXIO
)
334 r
= user_runtime_dir(runtime
, "/systemd/user");
339 /* If XDG_RUNTIME_DIR is not set, don't consider that fatal, simply initialize the runtime
340 * directory to NULL */
350 assert_not_reached("Hmm, unexpected scope value.");
363 static int acquire_control_dirs(UnitFileScope scope
, char **persistent
, char **runtime
) {
364 _cleanup_free_
char *a
= NULL
;
372 case UNIT_FILE_SYSTEM
: {
373 _cleanup_free_
char *b
= NULL
;
375 a
= strdup("/etc/systemd/system.control");
379 b
= strdup("/run/systemd/system.control");
390 r
= user_config_dir(&a
, "/systemd/system.control");
391 if (r
< 0 && r
!= -ENXIO
)
394 r
= user_runtime_dir(runtime
, "/systemd/system.control");
399 /* If XDG_RUNTIME_DIR is not set, don't consider this fatal, simply initialize the directory to
406 case UNIT_FILE_GLOBAL
:
410 assert_not_reached("Hmm, unexpected scope value.");
419 static int patch_root_prefix(char **p
, const char *root_dir
) {
427 c
= prefix_root(root_dir
, *p
);
437 static int patch_root_prefix_strv(char **l
, const char *root_dir
) {
445 r
= patch_root_prefix(i
, root_dir
);
453 int lookup_paths_init(
456 LookupPathsFlags flags
,
457 const char *root_dir
) {
459 _cleanup_(rmdir_and_freep
) char *tempdir
= NULL
;
462 *persistent_config
= NULL
, *runtime_config
= NULL
,
463 *generator
= NULL
, *generator_early
= NULL
, *generator_late
= NULL
,
465 *persistent_control
= NULL
, *runtime_control
= NULL
;
466 bool append
= false; /* Add items from SYSTEMD_UNIT_PATH before normal directories */
467 _cleanup_strv_free_
char **paths
= NULL
;
473 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
475 if (!isempty(root_dir
) && !path_equal(root_dir
, "/")) {
476 if (scope
== UNIT_FILE_USER
)
479 r
= is_dir(root_dir
, true);
485 root
= strdup(root_dir
);
490 if (flags
& LOOKUP_PATHS_TEMPORARY_GENERATED
) {
491 r
= mkdtemp_malloc("/tmp/systemd-temporary-XXXXXX", &tempdir
);
493 return log_error_errno(r
, "Failed to create temporary directory: %m");
496 /* Note: when XDG_RUNTIME_DIR is not set this will not return -ENXIO, but simply set runtime_config to NULL */
497 r
= acquire_config_dirs(scope
, &persistent_config
, &runtime_config
);
501 if ((flags
& LOOKUP_PATHS_EXCLUDE_GENERATED
) == 0) {
502 /* Note: if XDG_RUNTIME_DIR is not set, this will fail completely with ENXIO */
503 r
= acquire_generator_dirs(scope
, tempdir
,
504 &generator
, &generator_early
, &generator_late
);
505 if (r
< 0 && r
!= -EOPNOTSUPP
&& r
!= -ENXIO
)
509 /* Note: if XDG_RUNTIME_DIR is not set, this will fail completely with ENXIO */
510 r
= acquire_transient_dir(scope
, tempdir
, &transient
);
511 if (r
< 0 && r
!= -EOPNOTSUPP
&& r
!= -ENXIO
)
514 /* Note: when XDG_RUNTIME_DIR is not set this will not return -ENXIO, but simply set runtime_control to NULL */
515 r
= acquire_control_dirs(scope
, &persistent_control
, &runtime_control
);
516 if (r
< 0 && r
!= -EOPNOTSUPP
)
519 /* First priority is whatever has been passed to us via env vars */
520 e
= getenv("SYSTEMD_UNIT_PATH");
524 k
= endswith(e
, ":");
526 e
= strndupa(e
, k
- e
);
530 /* FIXME: empty components in other places should be rejected. */
532 r
= path_split_and_make_absolute(e
, &paths
);
537 if (!paths
|| append
) {
538 /* Let's figure something out. */
540 _cleanup_strv_free_
char **add
= NULL
;
542 /* For the user units we include share/ in the search
543 * path in order to comply with the XDG basedir spec.
544 * For the system stuff we avoid such nonsense. OTOH
545 * we include /lib in the search path for the system
546 * stuff but avoid it for user stuff. */
550 case UNIT_FILE_SYSTEM
:
552 /* If you modify this you also want to modify
553 * systemdsystemunitpath= in systemd.pc.in! */
554 STRV_IFNOTNULL(persistent_control
),
555 STRV_IFNOTNULL(runtime_control
),
556 STRV_IFNOTNULL(transient
),
557 STRV_IFNOTNULL(generator_early
),
559 SYSTEM_CONFIG_UNIT_PATH
,
560 "/etc/systemd/system",
562 "/run/systemd/system",
563 STRV_IFNOTNULL(generator
),
564 "/usr/local/lib/systemd/system",
565 SYSTEM_DATA_UNIT_PATH
,
566 "/usr/lib/systemd/system",
567 #ifdef HAVE_SPLIT_USR
568 "/lib/systemd/system",
570 STRV_IFNOTNULL(generator_late
),
574 case UNIT_FILE_GLOBAL
:
576 /* If you modify this you also want to modify
577 * systemduserunitpath= in systemd.pc.in, and
578 * the arrays in user_dirs() above! */
579 STRV_IFNOTNULL(persistent_control
),
580 STRV_IFNOTNULL(runtime_control
),
581 STRV_IFNOTNULL(transient
),
582 STRV_IFNOTNULL(generator_early
),
584 USER_CONFIG_UNIT_PATH
,
588 STRV_IFNOTNULL(generator
),
589 "/usr/local/lib/systemd/user",
590 "/usr/local/share/systemd/user",
592 "/usr/lib/systemd/user",
593 "/usr/share/systemd/user",
594 STRV_IFNOTNULL(generator_late
),
599 add
= user_dirs(persistent_config
, runtime_config
,
600 generator
, generator_early
, generator_late
,
602 persistent_config
, runtime_control
);
606 assert_not_reached("Hmm, unexpected scope?");
613 r
= strv_extend_strv(&paths
, add
, true);
617 /* Small optimization: if paths is NULL (and it usually is), we can simply assign 'add' to it,
618 * and don't have to copy anything */
624 r
= patch_root_prefix(&persistent_config
, root
);
627 r
= patch_root_prefix(&runtime_config
, root
);
631 r
= patch_root_prefix(&generator
, root
);
634 r
= patch_root_prefix(&generator_early
, root
);
637 r
= patch_root_prefix(&generator_late
, root
);
641 r
= patch_root_prefix(&transient
, root
);
645 r
= patch_root_prefix(&persistent_control
, root
);
649 r
= patch_root_prefix(&runtime_control
, root
);
653 r
= patch_root_prefix_strv(paths
, root
);
657 p
->search_path
= strv_uniq(paths
);
660 p
->persistent_config
= persistent_config
;
661 p
->runtime_config
= runtime_config
;
662 persistent_config
= runtime_config
= NULL
;
664 p
->generator
= generator
;
665 p
->generator_early
= generator_early
;
666 p
->generator_late
= generator_late
;
667 generator
= generator_early
= generator_late
= NULL
;
669 p
->transient
= transient
;
672 p
->persistent_control
= persistent_control
;
673 p
->runtime_control
= runtime_control
;
674 persistent_control
= runtime_control
= NULL
;
679 p
->temporary_dir
= tempdir
;
685 void lookup_paths_free(LookupPaths
*p
) {
689 p
->search_path
= strv_free(p
->search_path
);
691 p
->persistent_config
= mfree(p
->persistent_config
);
692 p
->runtime_config
= mfree(p
->runtime_config
);
694 p
->generator
= mfree(p
->generator
);
695 p
->generator_early
= mfree(p
->generator_early
);
696 p
->generator_late
= mfree(p
->generator_late
);
698 p
->transient
= mfree(p
->transient
);
700 p
->persistent_control
= mfree(p
->persistent_control
);
701 p
->runtime_control
= mfree(p
->runtime_control
);
703 p
->root_dir
= mfree(p
->root_dir
);
704 p
->temporary_dir
= mfree(p
->temporary_dir
);
707 int lookup_paths_reduce(LookupPaths
*p
) {
708 _cleanup_free_
struct stat
*stats
= NULL
;
709 size_t n_stats
= 0, allocated
= 0;
715 /* Drop duplicates and non-existing directories from the search path. We figure out whether two directories are
716 * the same by comparing their device and inode numbers. Note one special tweak: when we have a root path set,
717 * we do not follow symlinks when retrieving them, because the kernel wouldn't take the root prefix into
718 * account when following symlinks. When we have no root path set this restriction does not apply however. */
723 while (p
->search_path
[c
]) {
728 r
= lstat(p
->search_path
[c
], &st
);
730 r
= stat(p
->search_path
[c
], &st
);
735 /* If something we don't grok happened, let's better leave it in. */
736 log_debug_errno(errno
, "Failed to stat %s: %m", p
->search_path
[c
]);
741 for (k
= 0; k
< n_stats
; k
++) {
742 if (stats
[k
].st_dev
== st
.st_dev
&&
743 stats
[k
].st_ino
== st
.st_ino
)
747 if (k
< n_stats
) /* Is there already an entry with the same device/inode? */
750 if (!GREEDY_REALLOC(stats
, allocated
, n_stats
+1))
753 stats
[n_stats
++] = st
;
758 free(p
->search_path
[c
]);
759 memmove(p
->search_path
+ c
,
760 p
->search_path
+ c
+ 1,
761 (strv_length(p
->search_path
+ c
+ 1) + 1) * sizeof(char*));
764 if (strv_isempty(p
->search_path
)) {
765 log_debug("Ignoring unit files.");
766 p
->search_path
= strv_free(p
->search_path
);
768 _cleanup_free_
char *t
;
770 t
= strv_join(p
->search_path
, "\n\t");
774 log_debug("Looking for unit files in (higher priority first):\n\t%s", t
);
780 int lookup_paths_mkdir_generator(LookupPaths
*p
) {
785 if (!p
->generator
|| !p
->generator_early
|| !p
->generator_late
)
788 r
= mkdir_p_label(p
->generator
, 0755);
790 q
= mkdir_p_label(p
->generator_early
, 0755);
794 q
= mkdir_p_label(p
->generator_late
, 0755);
801 void lookup_paths_trim_generator(LookupPaths
*p
) {
804 /* Trim empty dirs */
807 (void) rmdir(p
->generator
);
808 if (p
->generator_early
)
809 (void) rmdir(p
->generator_early
);
810 if (p
->generator_late
)
811 (void) rmdir(p
->generator_late
);
814 void lookup_paths_flush_generator(LookupPaths
*p
) {
817 /* Flush the generated unit files in full */
820 (void) rm_rf(p
->generator
, REMOVE_ROOT
);
821 if (p
->generator_early
)
822 (void) rm_rf(p
->generator_early
, REMOVE_ROOT
);
823 if (p
->generator_late
)
824 (void) rm_rf(p
->generator_late
, REMOVE_ROOT
);
826 if (p
->temporary_dir
)
827 (void) rm_rf(p
->temporary_dir
, REMOVE_ROOT
);
830 char **generator_binary_paths(UnitFileScope scope
) {
834 case UNIT_FILE_SYSTEM
:
835 return strv_new("/run/systemd/system-generators",
836 "/etc/systemd/system-generators",
837 "/usr/local/lib/systemd/system-generators",
838 SYSTEM_GENERATOR_PATH
,
841 case UNIT_FILE_GLOBAL
:
843 return strv_new("/run/systemd/user-generators",
844 "/etc/systemd/user-generators",
845 "/usr/local/lib/systemd/user-generators",
850 assert_not_reached("Hmm, unexpected scope.");