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"
30 #include "path-lookup.h"
31 #include "path-util.h"
33 #include "stat-util.h"
34 #include "string-util.h"
38 static int user_runtime_dir(char **ret
, const char *suffix
) {
45 e
= getenv("XDG_RUNTIME_DIR");
49 j
= strappend(e
, suffix
);
57 static int user_config_dir(char **ret
, const char *suffix
) {
63 e
= getenv("XDG_CONFIG_HOME");
65 j
= strappend(e
, suffix
);
69 home
= getenv("HOME");
73 j
= strjoin(home
, "/.config", suffix
, NULL
);
83 static int user_data_dir(char **ret
, const char *suffix
) {
90 /* We don't treat /etc/xdg/systemd here as the spec
91 * suggests because we assume that is a link to
92 * /etc/systemd/ anyway. */
94 e
= getenv("XDG_DATA_HOME");
96 j
= strappend(e
, suffix
);
100 home
= getenv("HOME");
105 j
= strjoin(home
, "/.local/share", suffix
, NULL
);
114 static char** user_dirs(
115 const char *persistent_config
,
116 const char *runtime_config
,
117 const char *generator
,
118 const char *generator_early
,
119 const char *generator_late
,
120 const char *transient
,
121 const char *persistent_control
,
122 const char *runtime_control
) {
124 const char * const config_unit_paths
[] = {
125 USER_CONFIG_UNIT_PATH
,
130 const char * const data_unit_paths
[] = {
131 "/usr/local/lib/systemd/user",
132 "/usr/local/share/systemd/user",
134 "/usr/lib/systemd/user",
135 "/usr/share/systemd/user",
140 _cleanup_strv_free_
char **config_dirs
= NULL
, **data_dirs
= NULL
;
141 _cleanup_free_
char *data_home
= NULL
;
142 _cleanup_free_
char **res
= NULL
;
146 /* Implement the mechanisms defined in
148 * http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
150 * We look in both the config and the data dirs because we
151 * want to encourage that distributors ship their unit files
152 * as data, and allow overriding as configuration.
155 e
= getenv("XDG_CONFIG_DIRS");
157 config_dirs
= strv_split(e
, ":");
162 r
= user_data_dir(&data_home
, "/systemd/user");
163 if (r
< 0 && r
!= -ENXIO
)
166 e
= getenv("XDG_DATA_DIRS");
168 data_dirs
= strv_split(e
, ":");
170 data_dirs
= strv_new("/usr/local/share",
176 /* Now merge everything we found. */
177 if (strv_extend(&res
, persistent_control
) < 0)
180 if (strv_extend(&res
, runtime_control
) < 0)
183 if (strv_extend(&res
, transient
) < 0)
186 if (strv_extend(&res
, generator_early
) < 0)
189 if (!strv_isempty(config_dirs
))
190 if (strv_extend_strv_concat(&res
, config_dirs
, "/systemd/user") < 0)
193 if (strv_extend(&res
, persistent_config
) < 0)
196 if (strv_extend_strv(&res
, (char**) config_unit_paths
, false) < 0)
199 if (strv_extend(&res
, runtime_config
) < 0)
202 if (strv_extend(&res
, generator
) < 0)
205 if (strv_extend(&res
, data_home
) < 0)
208 if (!strv_isempty(data_dirs
))
209 if (strv_extend_strv_concat(&res
, data_dirs
, "/systemd/user") < 0)
212 if (strv_extend_strv(&res
, (char**) data_unit_paths
, false) < 0)
215 if (strv_extend(&res
, generator_late
) < 0)
218 if (path_strv_make_absolute_cwd(res
) < 0)
226 static int acquire_generator_dirs(
229 char **generator_early
,
230 char **generator_late
) {
232 _cleanup_free_
char *x
= NULL
, *y
= NULL
, *z
= NULL
;
236 assert(generator_early
);
237 assert(generator_late
);
241 case UNIT_FILE_SYSTEM
:
242 prefix
= "/run/systemd/";
245 case UNIT_FILE_USER
: {
248 e
= getenv("XDG_RUNTIME_DIR");
252 prefix
= strjoina(e
, "/systemd/");
256 case UNIT_FILE_GLOBAL
:
260 assert_not_reached("Hmm, unexpected scope value.");
263 x
= strappend(prefix
, "generator");
267 y
= strappend(prefix
, "generator.early");
271 z
= strappend(prefix
, "generator.late");
276 *generator_early
= y
;
283 static int acquire_transient_dir(UnitFileScope scope
, char **ret
) {
288 case UNIT_FILE_SYSTEM
: {
291 transient
= strdup("/run/systemd/transient");
300 return user_runtime_dir(ret
, "/systemd/transient");
302 case UNIT_FILE_GLOBAL
:
306 assert_not_reached("Hmm, unexpected scope value.");
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");
334 r
= user_runtime_dir(runtime
, "/systemd/user");
344 assert_not_reached("Hmm, unexpected scope value.");
357 static int acquire_control_dirs(UnitFileScope scope
, char **persistent
, char **runtime
) {
358 _cleanup_free_
char *a
= NULL
;
366 case UNIT_FILE_SYSTEM
: {
367 _cleanup_free_
char *b
= NULL
;
369 a
= strdup("/etc/systemd/system.control");
373 b
= strdup("/run/systemd/system.control");
384 r
= user_config_dir(&a
, "/systemd/system.control");
388 r
= user_runtime_dir(runtime
, "/systemd/system.control");
394 case UNIT_FILE_GLOBAL
:
398 assert_not_reached("Hmm, unexpected scope value.");
407 static int patch_root_prefix(char **p
, const char *root_dir
) {
415 c
= prefix_root(root_dir
, *p
);
425 static int patch_root_prefix_strv(char **l
, const char *root_dir
) {
433 r
= patch_root_prefix(i
, root_dir
);
441 int lookup_paths_init(
444 LookupPathsFlags flags
,
445 const char *root_dir
) {
449 *persistent_config
= NULL
, *runtime_config
= NULL
,
450 *generator
= NULL
, *generator_early
= NULL
, *generator_late
= NULL
,
452 *persistent_control
= NULL
, *runtime_control
= NULL
;
453 bool append
= false; /* Add items from SYSTEMD_UNIT_PATH before normal directories */
454 _cleanup_strv_free_
char **paths
= NULL
;
460 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
462 if (!isempty(root_dir
) && !path_equal(root_dir
, "/")) {
463 if (scope
== UNIT_FILE_USER
)
466 r
= is_dir(root_dir
, true);
472 root
= strdup(root_dir
);
477 r
= acquire_config_dirs(scope
, &persistent_config
, &runtime_config
);
478 if (r
< 0 && r
!= -ENXIO
)
481 if ((flags
& LOOKUP_PATHS_EXCLUDE_GENERATED
) == 0) {
482 r
= acquire_generator_dirs(scope
, &generator
, &generator_early
, &generator_late
);
483 if (r
< 0 && r
!= -EOPNOTSUPP
&& r
!= -ENXIO
)
487 r
= acquire_transient_dir(scope
, &transient
);
488 if (r
< 0 && r
!= -EOPNOTSUPP
&& r
!= -ENXIO
)
491 r
= acquire_control_dirs(scope
, &persistent_control
, &runtime_control
);
492 if (r
< 0 && r
!= -EOPNOTSUPP
&& r
!= -ENXIO
)
495 /* First priority is whatever has been passed to us via env vars */
496 e
= getenv("SYSTEMD_UNIT_PATH");
500 k
= endswith(e
, ":");
502 e
= strndupa(e
, k
- e
);
506 /* FIXME: empty components in other places should be
509 r
= path_split_and_make_absolute(e
, &paths
);
514 if (!paths
|| append
) {
515 /* Let's figure something out. */
517 _cleanup_strv_free_
char **add
= NULL
;
519 /* For the user units we include share/ in the search
520 * path in order to comply with the XDG basedir spec.
521 * For the system stuff we avoid such nonsense. OTOH
522 * we include /lib in the search path for the system
523 * stuff but avoid it for user stuff. */
527 case UNIT_FILE_SYSTEM
:
529 /* If you modify this you also want to modify
530 * systemdsystemunitpath= in systemd.pc.in! */
531 STRV_IFNOTNULL(persistent_control
),
532 STRV_IFNOTNULL(runtime_control
),
533 STRV_IFNOTNULL(transient
),
534 STRV_IFNOTNULL(generator_early
),
536 SYSTEM_CONFIG_UNIT_PATH
,
537 "/etc/systemd/system",
539 "/run/systemd/system",
540 STRV_IFNOTNULL(generator
),
541 "/usr/local/lib/systemd/system",
542 SYSTEM_DATA_UNIT_PATH
,
543 "/usr/lib/systemd/system",
544 #ifdef HAVE_SPLIT_USR
545 "/lib/systemd/system",
547 STRV_IFNOTNULL(generator_late
),
551 case UNIT_FILE_GLOBAL
:
553 /* If you modify this you also want to modify
554 * systemduserunitpath= in systemd.pc.in, and
555 * the arrays in user_dirs() above! */
556 STRV_IFNOTNULL(persistent_control
),
557 STRV_IFNOTNULL(runtime_control
),
558 STRV_IFNOTNULL(transient
),
559 STRV_IFNOTNULL(generator_early
),
561 USER_CONFIG_UNIT_PATH
,
565 STRV_IFNOTNULL(generator
),
566 "/usr/local/lib/systemd/user",
567 "/usr/local/share/systemd/user",
569 "/usr/lib/systemd/user",
570 "/usr/share/systemd/user",
571 STRV_IFNOTNULL(generator_late
),
576 add
= user_dirs(persistent_config
, runtime_config
,
577 generator
, generator_early
, generator_late
,
579 persistent_config
, runtime_control
);
583 assert_not_reached("Hmm, unexpected scope?");
590 r
= strv_extend_strv(&paths
, add
, true);
594 /* Small optimization: if paths is NULL (and it usually is), we can simply assign 'add' to it,
595 * and don't have to copy anything */
601 r
= patch_root_prefix(&persistent_config
, root
);
604 r
= patch_root_prefix(&runtime_config
, root
);
608 r
= patch_root_prefix(&generator
, root
);
611 r
= patch_root_prefix(&generator_early
, root
);
614 r
= patch_root_prefix(&generator_late
, root
);
618 r
= patch_root_prefix(&transient
, root
);
622 r
= patch_root_prefix(&persistent_control
, root
);
626 r
= patch_root_prefix(&runtime_control
, root
);
630 r
= patch_root_prefix_strv(paths
, root
);
634 p
->search_path
= strv_uniq(paths
);
637 p
->persistent_config
= persistent_config
;
638 p
->runtime_config
= runtime_config
;
639 persistent_config
= runtime_config
= NULL
;
641 p
->generator
= generator
;
642 p
->generator_early
= generator_early
;
643 p
->generator_late
= generator_late
;
644 generator
= generator_early
= generator_late
= NULL
;
646 p
->transient
= transient
;
649 p
->persistent_control
= persistent_control
;
650 p
->runtime_control
= runtime_control
;
651 persistent_control
= runtime_control
= NULL
;
659 void lookup_paths_free(LookupPaths
*p
) {
663 p
->search_path
= strv_free(p
->search_path
);
665 p
->persistent_config
= mfree(p
->persistent_config
);
666 p
->runtime_config
= mfree(p
->runtime_config
);
668 p
->generator
= mfree(p
->generator
);
669 p
->generator_early
= mfree(p
->generator_early
);
670 p
->generator_late
= mfree(p
->generator_late
);
672 p
->transient
= mfree(p
->transient
);
674 p
->persistent_control
= mfree(p
->persistent_control
);
675 p
->runtime_control
= mfree(p
->runtime_control
);
677 p
->root_dir
= mfree(p
->root_dir
);
680 int lookup_paths_reduce(LookupPaths
*p
) {
681 _cleanup_free_
struct stat
*stats
= NULL
;
682 size_t n_stats
= 0, allocated
= 0;
688 /* Drop duplicates and non-existing directories from the search path. We figure out whether two directories are
689 * the same by comparing their device and inode numbers. Note one special tweak: when we have a root path set,
690 * we do not follow symlinks when retrieving them, because the kernel wouldn't take the root prefix into
691 * account when following symlinks. When we have no root path set this restriction does not apply however. */
696 while (p
->search_path
[c
]) {
701 r
= lstat(p
->search_path
[c
], &st
);
703 r
= stat(p
->search_path
[c
], &st
);
708 /* If something we don't grok happened, let's better leave it in. */
709 log_debug_errno(errno
, "Failed to stat %s: %m", p
->search_path
[c
]);
714 for (k
= 0; k
< n_stats
; k
++) {
715 if (stats
[k
].st_dev
== st
.st_dev
&&
716 stats
[k
].st_ino
== st
.st_ino
)
720 if (k
< n_stats
) /* Is there already an entry with the same device/inode? */
723 if (!GREEDY_REALLOC(stats
, allocated
, n_stats
+1))
726 stats
[n_stats
++] = st
;
731 free(p
->search_path
[c
]);
732 memmove(p
->search_path
+ c
,
733 p
->search_path
+ c
+ 1,
734 (strv_length(p
->search_path
+ c
+ 1) + 1) * sizeof(char*));
737 if (strv_isempty(p
->search_path
)) {
738 log_debug("Ignoring unit files.");
739 p
->search_path
= strv_free(p
->search_path
);
741 _cleanup_free_
char *t
;
743 t
= strv_join(p
->search_path
, "\n\t");
747 log_debug("Looking for unit files in (higher priority first):\n\t%s", t
);
753 int lookup_paths_mkdir_generator(LookupPaths
*p
) {
758 if (!p
->generator
|| !p
->generator_early
|| !p
->generator_late
)
761 r
= mkdir_p_label(p
->generator
, 0755);
763 q
= mkdir_p_label(p
->generator_early
, 0755);
767 q
= mkdir_p_label(p
->generator_late
, 0755);
774 void lookup_paths_trim_generator(LookupPaths
*p
) {
777 /* Trim empty dirs */
780 (void) rmdir(p
->generator
);
781 if (p
->generator_early
)
782 (void) rmdir(p
->generator_early
);
783 if (p
->generator_late
)
784 (void) rmdir(p
->generator_late
);
787 void lookup_paths_flush_generator(LookupPaths
*p
) {
790 /* Flush the generated unit files in full */
793 (void) rm_rf(p
->generator
, REMOVE_ROOT
);
794 if (p
->generator_early
)
795 (void) rm_rf(p
->generator_early
, REMOVE_ROOT
);
796 if (p
->generator_late
)
797 (void) rm_rf(p
->generator_late
, REMOVE_ROOT
);
800 char **generator_binary_paths(UnitFileScope scope
) {
804 case UNIT_FILE_SYSTEM
:
805 return strv_new("/run/systemd/system-generators",
806 "/etc/systemd/system-generators",
807 "/usr/local/lib/systemd/system-generators",
808 SYSTEM_GENERATOR_PATH
,
811 case UNIT_FILE_GLOBAL
:
813 return strv_new("/run/systemd/user-generators",
814 "/etc/systemd/user-generators",
815 "/usr/local/lib/systemd/user-generators",
820 assert_not_reached("Hmm, unexpected scope.");