1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
12 #include "alloc-util.h"
13 #include "conf-files.h"
14 #include "conf-parser.h"
16 #include "dirent-util.h"
17 #include "errno-list.h"
18 #include "extract-word.h"
23 #include "install-printf.h"
25 #include "locale-util.h"
29 #include "path-lookup.h"
30 #include "path-util.h"
34 #include "stat-util.h"
35 #include "string-table.h"
36 #include "string-util.h"
38 #include "unit-file.h"
40 #define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
42 typedef enum SearchFlags
{
44 SEARCH_FOLLOW_CONFIG_SYMLINKS
= 1 << 1,
45 SEARCH_DROPIN
= 1 << 2,
49 OrderedHashmap
*will_process
;
50 OrderedHashmap
*have_processed
;
59 struct UnitFilePresetRule
{
65 static bool unit_file_install_info_has_rules(const UnitFileInstallInfo
*i
) {
68 return !strv_isempty(i
->aliases
) ||
69 !strv_isempty(i
->wanted_by
) ||
70 !strv_isempty(i
->required_by
);
73 static bool unit_file_install_info_has_also(const UnitFileInstallInfo
*i
) {
76 return !strv_isempty(i
->also
);
79 void unit_file_presets_freep(UnitFilePresets
*p
) {
83 for (size_t i
= 0; i
< p
->n_rules
; i
++) {
84 free(p
->rules
[i
].pattern
);
85 strv_free(p
->rules
[i
].instances
);
92 static const char *const unit_file_type_table
[_UNIT_FILE_TYPE_MAX
] = {
93 [UNIT_FILE_TYPE_REGULAR
] = "regular",
94 [UNIT_FILE_TYPE_SYMLINK
] = "symlink",
95 [UNIT_FILE_TYPE_MASKED
] = "masked",
98 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(unit_file_type
, UnitFileType
);
100 static int in_search_path(const LookupPaths
*p
, const char *path
) {
101 _cleanup_free_
char *parent
= NULL
;
105 parent
= dirname_malloc(path
);
109 return path_strv_contains(p
->search_path
, parent
);
112 static const char* skip_root(const LookupPaths
*p
, const char *path
) {
121 e
= path_startswith(path
, p
->root_dir
);
125 /* Make sure the returned path starts with a slash */
127 if (e
== path
|| e
[-1] != '/')
136 static int path_is_generator(const LookupPaths
*p
, const char *path
) {
137 _cleanup_free_
char *parent
= NULL
;
142 parent
= dirname_malloc(path
);
146 return path_equal_ptr(parent
, p
->generator
) ||
147 path_equal_ptr(parent
, p
->generator_early
) ||
148 path_equal_ptr(parent
, p
->generator_late
);
151 static int path_is_transient(const LookupPaths
*p
, const char *path
) {
152 _cleanup_free_
char *parent
= NULL
;
157 parent
= dirname_malloc(path
);
161 return path_equal_ptr(parent
, p
->transient
);
164 static int path_is_control(const LookupPaths
*p
, const char *path
) {
165 _cleanup_free_
char *parent
= NULL
;
170 parent
= dirname_malloc(path
);
174 return path_equal_ptr(parent
, p
->persistent_control
) ||
175 path_equal_ptr(parent
, p
->runtime_control
);
178 static int path_is_config(const LookupPaths
*p
, const char *path
, bool check_parent
) {
179 _cleanup_free_
char *parent
= NULL
;
184 /* Note that we do *not* have generic checks for /etc or /run in place, since with
185 * them we couldn't discern configuration from transient or generated units */
188 parent
= dirname_malloc(path
);
195 return path_equal_ptr(path
, p
->persistent_config
) ||
196 path_equal_ptr(path
, p
->runtime_config
);
199 static int path_is_runtime(const LookupPaths
*p
, const char *path
, bool check_parent
) {
200 _cleanup_free_
char *parent
= NULL
;
206 /* Everything in /run is considered runtime. On top of that we also add
207 * explicit checks for the various runtime directories, as safety net. */
209 rpath
= skip_root(p
, path
);
210 if (rpath
&& path_startswith(rpath
, "/run"))
214 parent
= dirname_malloc(path
);
221 return path_equal_ptr(path
, p
->runtime_config
) ||
222 path_equal_ptr(path
, p
->generator
) ||
223 path_equal_ptr(path
, p
->generator_early
) ||
224 path_equal_ptr(path
, p
->generator_late
) ||
225 path_equal_ptr(path
, p
->transient
) ||
226 path_equal_ptr(path
, p
->runtime_control
);
229 static int path_is_vendor_or_generator(const LookupPaths
*p
, const char *path
) {
235 rpath
= skip_root(p
, path
);
239 if (path_startswith(rpath
, "/usr"))
243 if (path_startswith(rpath
, "/lib"))
247 if (path_is_generator(p
, rpath
))
250 return path_equal(rpath
, SYSTEM_DATA_UNIT_DIR
);
253 static const char* config_path_from_flags(const LookupPaths
*paths
, UnitFileFlags flags
) {
256 if (FLAGS_SET(flags
, UNIT_FILE_PORTABLE
))
257 return FLAGS_SET(flags
, UNIT_FILE_RUNTIME
) ? paths
->runtime_attached
: paths
->persistent_attached
;
259 return FLAGS_SET(flags
, UNIT_FILE_RUNTIME
) ? paths
->runtime_config
: paths
->persistent_config
;
262 int unit_file_changes_add(
263 UnitFileChange
**changes
,
265 int type_or_errno
, /* UNIT_FILE_SYMLINK, _UNLINK, _IS_MASKED, _IS_DANGLING if positive or errno if negative */
267 const char *source
) {
269 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
272 assert(!changes
== !n_changes
);
274 if (type_or_errno
>= 0)
275 assert(type_or_errno
< _UNIT_FILE_CHANGE_TYPE_MAX
);
277 assert(type_or_errno
>= -ERRNO_MAX
);
282 c
= reallocarray(*changes
, *n_changes
+ 1, sizeof(UnitFileChange
));
303 c
[(*n_changes
)++] = (UnitFileChange
) {
304 .type_or_errno
= type_or_errno
,
306 .source
= TAKE_PTR(s
),
312 void unit_file_changes_free(UnitFileChange
*changes
, size_t n_changes
) {
313 assert(changes
|| n_changes
== 0);
315 for (size_t i
= 0; i
< n_changes
; i
++) {
316 free(changes
[i
].path
);
317 free(changes
[i
].source
);
323 void unit_file_dump_changes(int r
, const char *verb
, const UnitFileChange
*changes
, size_t n_changes
, bool quiet
) {
326 assert(changes
|| n_changes
== 0);
327 /* If verb is not specified, errors are not allowed! */
328 assert(verb
|| r
>= 0);
330 for (size_t i
= 0; i
< n_changes
; i
++) {
331 assert(verb
|| changes
[i
].type_or_errno
>= 0);
333 switch(changes
[i
].type_or_errno
) {
334 case UNIT_FILE_SYMLINK
:
336 log_info("Created symlink %s %s %s.",
338 special_glyph(SPECIAL_GLYPH_ARROW
),
341 case UNIT_FILE_UNLINK
:
343 log_info("Removed %s.", changes
[i
].path
);
345 case UNIT_FILE_IS_MASKED
:
347 log_info("Unit %s is masked, ignoring.", changes
[i
].path
);
349 case UNIT_FILE_IS_DANGLING
:
351 log_info("Unit %s is an alias to a unit that is not present, ignoring.",
354 case UNIT_FILE_DESTINATION_NOT_PRESENT
:
356 log_warning("Unit %s is added as a dependency to a non-existent unit %s.",
357 changes
[i
].source
, changes
[i
].path
);
359 case UNIT_FILE_AUXILIARY_FAILED
:
361 log_warning("Failed to enable auxiliary unit %s, ignoring.", changes
[i
].source
);
364 if (changes
[i
].source
)
365 log_error_errno(changes
[i
].type_or_errno
,
366 "Failed to %s unit, file %s already exists and is a symlink to %s.",
367 verb
, changes
[i
].path
, changes
[i
].source
);
369 log_error_errno(changes
[i
].type_or_errno
,
370 "Failed to %s unit, file %s already exists.",
371 verb
, changes
[i
].path
);
375 log_error_errno(changes
[i
].type_or_errno
, "Failed to %s unit, unit %s is masked.",
376 verb
, changes
[i
].path
);
380 log_error_errno(changes
[i
].type_or_errno
, "Failed to %s unit, unit %s is transient or generated.",
381 verb
, changes
[i
].path
);
385 log_error_errno(changes
[i
].type_or_errno
, "Failed to %s %s, destination unit %s is a non-template unit.",
386 verb
, changes
[i
].source
, changes
[i
].path
);
390 log_error_errno(changes
[i
].type_or_errno
,
391 "Failed to %s unit, \"%s\" is not a valid unit name.",
392 verb
, changes
[i
].path
);
396 log_error_errno(changes
[i
].type_or_errno
, "Failed to %s unit, refusing to operate on linked unit file %s",
397 verb
, changes
[i
].path
);
402 log_error_errno(changes
[i
].type_or_errno
, "Failed to %s unit, unit %s does not exist.", verb
, changes
[i
].path
);
407 assert(changes
[i
].type_or_errno
< 0);
408 log_error_errno(changes
[i
].type_or_errno
, "Failed to %s unit, file %s: %m.",
409 verb
, changes
[i
].path
);
414 if (r
< 0 && !logged
)
415 log_error_errno(r
, "Failed to %s: %m.", verb
);
419 * Checks if two paths or symlinks from wd are the same, when root is the root of the filesystem.
420 * wc should be the full path in the host file system.
422 static bool chroot_symlinks_same(const char *root
, const char *wd
, const char *a
, const char *b
) {
423 assert(path_is_absolute(wd
));
425 /* This will give incorrect results if the paths are relative and go outside
426 * of the chroot. False negatives are possible. */
431 a
= strjoina(path_is_absolute(a
) ? root
: wd
, "/", a
);
432 b
= strjoina(path_is_absolute(b
) ? root
: wd
, "/", b
);
433 return path_equal_or_files_same(a
, b
, 0);
436 static int create_symlink(
437 const LookupPaths
*paths
,
438 const char *old_path
,
439 const char *new_path
,
441 UnitFileChange
**changes
,
444 _cleanup_free_
char *dest
= NULL
, *dirname
= NULL
;
451 rp
= skip_root(paths
, old_path
);
455 /* Actually create a symlink, and remember that we did. Is
456 * smart enough to check if there's already a valid symlink in
459 * Returns 1 if a symlink was created or already exists and points to
460 * the right place, or negative on error.
463 mkdir_parents_label(new_path
, 0755);
465 if (symlink(old_path
, new_path
) >= 0) {
466 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
470 if (errno
!= EEXIST
) {
471 unit_file_changes_add(changes
, n_changes
, -errno
, new_path
, NULL
);
475 r
= readlink_malloc(new_path
, &dest
);
477 /* translate EINVAL (non-symlink exists) to EEXIST */
481 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
485 dirname
= dirname_malloc(new_path
);
489 if (chroot_symlinks_same(paths
->root_dir
, dirname
, dest
, old_path
)) {
490 log_debug("Symlink %s → %s already exists", new_path
, dest
);
495 unit_file_changes_add(changes
, n_changes
, -EEXIST
, new_path
, dest
);
499 r
= symlink_atomic(old_path
, new_path
);
501 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
505 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, new_path
, NULL
);
506 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
511 static int mark_symlink_for_removal(
512 Set
**remove_symlinks_to
,
520 r
= set_ensure_allocated(remove_symlinks_to
, &path_hash_ops
);
530 r
= set_consume(*remove_symlinks_to
, n
);
539 static int remove_marked_symlinks_fd(
540 Set
*remove_symlinks_to
,
543 const char *config_path
,
544 const LookupPaths
*lp
,
547 UnitFileChange
**changes
,
550 _cleanup_closedir_
DIR *d
= NULL
;
554 assert(remove_symlinks_to
);
569 FOREACH_DIRENT(de
, d
, return -errno
) {
571 if (de
->d_type
== DT_DIR
) {
572 _cleanup_free_
char *p
= NULL
;
575 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
585 p
= path_make_absolute(de
->d_name
, path
);
591 /* This will close nfd, regardless whether it succeeds or not */
592 q
= remove_marked_symlinks_fd(remove_symlinks_to
, nfd
, p
, config_path
, lp
, dry_run
, restart
, changes
, n_changes
);
596 } else if (de
->d_type
== DT_LNK
) {
597 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
602 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
605 p
= path_make_absolute(de
->d_name
, path
);
610 q
= chase_symlinks(p
, NULL
, CHASE_NONEXISTENT
, &dest
, NULL
);
619 /* We remove all links pointing to a file or path that is marked, as well as all files sharing
620 * the same name as a file that is marked. */
622 found
= set_contains(remove_symlinks_to
, dest
) ||
623 set_contains(remove_symlinks_to
, basename(dest
)) ||
624 set_contains(remove_symlinks_to
, de
->d_name
);
630 if (unlinkat(fd
, de
->d_name
, 0) < 0 && errno
!= ENOENT
) {
633 unit_file_changes_add(changes
, n_changes
, -errno
, p
, NULL
);
637 (void) rmdir_parents(p
, config_path
);
640 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, p
, NULL
);
642 /* Now, remember the full path (but with the root prefix removed) of
643 * the symlink we just removed, and remove any symlinks to it, too. */
645 rp
= skip_root(lp
, p
);
646 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: p
);
649 if (q
> 0 && !dry_run
)
657 static int remove_marked_symlinks(
658 Set
*remove_symlinks_to
,
659 const char *config_path
,
660 const LookupPaths
*lp
,
662 UnitFileChange
**changes
,
665 _cleanup_close_
int fd
= -1;
672 if (set_size(remove_symlinks_to
) <= 0)
675 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
);
677 return errno
== ENOENT
? 0 : -errno
;
683 cfd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
687 /* This takes possession of cfd and closes it */
688 q
= remove_marked_symlinks_fd(remove_symlinks_to
, cfd
, config_path
, config_path
, lp
, dry_run
, &restart
, changes
, n_changes
);
696 static int is_symlink_with_known_name(const UnitFileInstallInfo
*i
, const char *name
) {
699 if (streq(name
, i
->name
))
702 if (strv_contains(i
->aliases
, name
))
705 /* Look for template symlink matching DefaultInstance */
706 if (i
->default_instance
&& unit_name_is_valid(i
->name
, UNIT_NAME_TEMPLATE
)) {
707 _cleanup_free_
char *s
= NULL
;
709 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &s
);
714 } else if (streq(name
, s
))
721 static int find_symlinks_in_directory(
723 const char *dir_path
,
724 const char *root_dir
,
725 const UnitFileInstallInfo
*i
,
727 bool ignore_same_name
,
728 const char *config_path
,
729 bool *same_name_link
) {
734 FOREACH_DIRENT(de
, dir
, return -errno
) {
735 _cleanup_free_
char *dest
= NULL
;
736 bool found_path
= false, found_dest
, b
= false;
739 if (de
->d_type
!= DT_LNK
)
742 /* Acquire symlink destination */
743 q
= readlinkat_malloc(dirfd(dir
), de
->d_name
, &dest
);
753 if (!path_is_absolute(dest
)) {
756 x
= path_join(dir_path
, dest
);
760 free_and_replace(dest
, x
);
763 assert(unit_name_is_valid(i
->name
, UNIT_NAME_ANY
));
764 if (!ignore_same_name
)
765 /* Check if the symlink itself matches what we are looking for.
767 * If ignore_same_name is specified, we are in one of the directories which
768 * have lower priority than the unit file, and even if a file or symlink with
769 * this name was found, we should ignore it. */
770 found_path
= streq(de
->d_name
, i
->name
);
772 /* Check if what the symlink points to matches what we are looking for */
773 found_dest
= streq(basename(dest
), i
->name
);
775 if (found_path
&& found_dest
) {
776 _cleanup_free_
char *p
= NULL
, *t
= NULL
;
778 /* Filter out same name links in the main
780 p
= path_make_absolute(de
->d_name
, dir_path
);
781 t
= path_make_absolute(i
->name
, config_path
);
786 b
= path_equal(p
, t
);
790 *same_name_link
= true;
791 else if (found_path
|| found_dest
) {
795 /* Check if symlink name is in the set of names used by [Install] */
796 q
= is_symlink_with_known_name(i
, de
->d_name
);
807 static int find_symlinks(
808 const char *root_dir
,
809 const UnitFileInstallInfo
*i
,
811 bool ignore_same_name
,
812 const char *config_path
,
813 bool *same_name_link
) {
815 _cleanup_closedir_
DIR *config_dir
= NULL
;
821 assert(same_name_link
);
823 config_dir
= opendir(config_path
);
825 if (IN_SET(errno
, ENOENT
, ENOTDIR
, EACCES
))
830 FOREACH_DIRENT(de
, config_dir
, return -errno
) {
832 _cleanup_free_
const char *path
= NULL
;
833 _cleanup_closedir_
DIR *d
= NULL
;
835 if (de
->d_type
!= DT_DIR
)
838 suffix
= strrchr(de
->d_name
, '.');
839 if (!STRPTR_IN_SET(suffix
, ".wants", ".requires"))
842 path
= path_join(config_path
, de
->d_name
);
848 log_error_errno(errno
, "Failed to open directory '%s' while scanning for symlinks, ignoring: %m", path
);
852 r
= find_symlinks_in_directory(d
, path
, root_dir
, i
, match_name
, ignore_same_name
, config_path
, same_name_link
);
856 log_debug_errno(r
, "Failed to lookup for symlinks in '%s': %m", path
);
859 /* We didn't find any suitable symlinks in .wants or .requires directories, let's look for linked unit files in this directory. */
860 rewinddir(config_dir
);
861 return find_symlinks_in_directory(config_dir
, config_path
, root_dir
, i
, match_name
, ignore_same_name
, config_path
, same_name_link
);
864 static int find_symlinks_in_scope(
866 const LookupPaths
*paths
,
867 const UnitFileInstallInfo
*i
,
869 UnitFileState
*state
) {
871 bool same_name_link_runtime
= false, same_name_link_config
= false;
872 bool enabled_in_runtime
= false, enabled_at_all
= false;
873 bool ignore_same_name
= false;
880 /* As we iterate over the list of search paths in paths->search_path, we may encounter "same name"
881 * symlinks. The ones which are "below" (i.e. have lower priority) than the unit file itself are
882 * effectively masked, so we should ignore them. */
884 STRV_FOREACH(p
, paths
->search_path
) {
885 bool same_name_link
= false;
887 r
= find_symlinks(paths
->root_dir
, i
, match_name
, ignore_same_name
, *p
, &same_name_link
);
891 /* We found symlinks in this dir? Yay! Let's see where precisely it is enabled. */
893 if (path_equal_ptr(*p
, paths
->persistent_config
)) {
894 /* This is the best outcome, let's return it immediately. */
895 *state
= UNIT_FILE_ENABLED
;
899 /* look for global enablement of user units */
900 if (scope
== UNIT_FILE_USER
&& path_is_user_config_dir(*p
)) {
901 *state
= UNIT_FILE_ENABLED
;
905 r
= path_is_runtime(paths
, *p
, false);
909 enabled_in_runtime
= true;
911 enabled_at_all
= true;
913 } else if (same_name_link
) {
914 if (path_equal_ptr(*p
, paths
->persistent_config
))
915 same_name_link_config
= true;
917 r
= path_is_runtime(paths
, *p
, false);
921 same_name_link_runtime
= true;
925 /* Check if next iteration will be "below" the unit file (either a regular file
926 * or a symlink), and hence should be ignored */
927 if (!ignore_same_name
&& path_startswith(i
->path
, *p
))
928 ignore_same_name
= true;
931 if (enabled_in_runtime
) {
932 *state
= UNIT_FILE_ENABLED_RUNTIME
;
936 /* Here's a special rule: if the unit we are looking for is an instance, and it symlinked in the search path
937 * outside of runtime and configuration directory, then we consider it statically enabled. Note we do that only
938 * for instance, not for regular names, as those are merely aliases, while instances explicitly instantiate
939 * something, and hence are a much stronger concept. */
940 if (enabled_at_all
&& unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
)) {
941 *state
= UNIT_FILE_STATIC
;
945 /* Hmm, we didn't find it, but maybe we found the same name
947 if (same_name_link_config
) {
948 *state
= UNIT_FILE_LINKED
;
951 if (same_name_link_runtime
) {
952 *state
= UNIT_FILE_LINKED_RUNTIME
;
959 static void install_info_free(UnitFileInstallInfo
*i
) {
967 strv_free(i
->aliases
);
968 strv_free(i
->wanted_by
);
969 strv_free(i
->required_by
);
971 free(i
->default_instance
);
972 free(i
->symlink_target
);
976 static void install_context_done(InstallContext
*c
) {
979 c
->will_process
= ordered_hashmap_free_with_destructor(c
->will_process
, install_info_free
);
980 c
->have_processed
= ordered_hashmap_free_with_destructor(c
->have_processed
, install_info_free
);
983 static UnitFileInstallInfo
*install_info_find(InstallContext
*c
, const char *name
) {
984 UnitFileInstallInfo
*i
;
986 i
= ordered_hashmap_get(c
->have_processed
, name
);
990 return ordered_hashmap_get(c
->will_process
, name
);
993 static int install_info_may_process(
994 const UnitFileInstallInfo
*i
,
995 const LookupPaths
*paths
,
996 UnitFileChange
**changes
,
1001 /* Checks whether the loaded unit file is one we should process, or is masked,
1002 * transient or generated and thus not subject to enable/disable operations. */
1004 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
1005 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, i
->path
, NULL
);
1008 if (path_is_generator(paths
, i
->path
) ||
1009 path_is_transient(paths
, i
->path
)) {
1010 unit_file_changes_add(changes
, n_changes
, -EADDRNOTAVAIL
, i
->path
, NULL
);
1011 return -EADDRNOTAVAIL
;
1018 * Adds a new UnitFileInstallInfo entry under name in the InstallContext.will_process
1019 * hashmap, or retrieves the existing one if already present.
1021 * Returns negative on error, 0 if the unit was already known, 1 otherwise.
1023 static int install_info_add(
1029 UnitFileInstallInfo
**ret
) {
1031 UnitFileInstallInfo
*i
= NULL
;
1037 /* 'name' and 'path' must not both be null. Check here 'path' using assert_se() to
1038 * workaround a bug in gcc that generates a -Wnonnull warning when calling basename(),
1039 * but this cannot be possible in any code path (See #6119). */
1041 name
= basename(path
);
1044 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
1047 i
= install_info_find(c
, name
);
1049 i
->auxiliary
= i
->auxiliary
&& auxiliary
;
1056 i
= new(UnitFileInstallInfo
, 1);
1060 *i
= (UnitFileInstallInfo
) {
1061 .type
= _UNIT_FILE_TYPE_INVALID
,
1062 .auxiliary
= auxiliary
,
1065 i
->name
= strdup(name
);
1072 i
->root
= strdup(root
);
1080 i
->path
= strdup(path
);
1087 r
= ordered_hashmap_ensure_put(&c
->will_process
, &string_hash_ops
, i
->name
, i
);
1097 install_info_free(i
);
1101 static int config_parse_alias(
1103 const char *filename
,
1105 const char *section
,
1106 unsigned section_line
,
1120 type
= unit_name_to_type(unit
);
1121 if (!unit_type_may_alias(type
))
1122 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1123 "Alias= is not allowed for %s units, ignoring.",
1124 unit_type_to_string(type
));
1126 return config_parse_strv(unit
, filename
, line
, section
, section_line
,
1127 lvalue
, ltype
, rvalue
, data
, userdata
);
1130 static int config_parse_also(
1132 const char *filename
,
1134 const char *section
,
1135 unsigned section_line
,
1142 UnitFileInstallInfo
*info
= userdata
;
1143 InstallContext
*c
= data
;
1152 _cleanup_free_
char *word
= NULL
, *printed
= NULL
;
1154 r
= extract_first_word(&rvalue
, &word
, NULL
, 0);
1160 r
= install_name_printf(info
, word
, info
->root
, &printed
);
1164 r
= install_info_add(c
, printed
, NULL
, info
->root
, /* auxiliary= */ true, NULL
);
1168 r
= strv_push(&info
->also
, printed
);
1178 static int config_parse_default_instance(
1180 const char *filename
,
1182 const char *section
,
1183 unsigned section_line
,
1190 UnitFileInstallInfo
*i
= data
;
1191 _cleanup_free_
char *printed
= NULL
;
1199 if (unit_name_is_valid(unit
, UNIT_NAME_INSTANCE
))
1200 /* When enabling an instance, we might be using a template unit file,
1201 * but we should ignore DefaultInstance silently. */
1203 if (!unit_name_is_valid(unit
, UNIT_NAME_TEMPLATE
))
1204 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1205 "DefaultInstance= only makes sense for template units, ignoring.");
1207 r
= install_name_printf(i
, rvalue
, i
->root
, &printed
);
1211 if (isempty(printed
)) {
1212 i
->default_instance
= mfree(i
->default_instance
);
1216 if (!unit_instance_is_valid(printed
))
1217 return log_syntax(unit
, LOG_WARNING
, filename
, line
, SYNTHETIC_ERRNO(EINVAL
),
1218 "Invalid DefaultInstance= value \"%s\".", printed
);
1220 return free_and_replace(i
->default_instance
, printed
);
1223 static int unit_file_load(
1225 UnitFileInstallInfo
*info
,
1227 const char *root_dir
,
1228 SearchFlags flags
) {
1230 const ConfigTableItem items
[] = {
1231 { "Install", "Alias", config_parse_alias
, 0, &info
->aliases
},
1232 { "Install", "WantedBy", config_parse_strv
, 0, &info
->wanted_by
},
1233 { "Install", "RequiredBy", config_parse_strv
, 0, &info
->required_by
},
1234 { "Install", "DefaultInstance", config_parse_default_instance
, 0, info
},
1235 { "Install", "Also", config_parse_also
, 0, c
},
1240 _cleanup_fclose_
FILE *f
= NULL
;
1241 _cleanup_close_
int fd
= -1;
1248 if (!(flags
& SEARCH_DROPIN
)) {
1249 /* Loading or checking for the main unit file… */
1251 type
= unit_name_to_type(info
->name
);
1254 if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
|UNIT_NAME_INSTANCE
) && !unit_type_may_template(type
))
1255 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1256 "%s: unit type %s cannot be templated, ignoring.", path
, unit_type_to_string(type
));
1258 if (!(flags
& SEARCH_LOAD
)) {
1259 if (lstat(path
, &st
) < 0)
1262 if (null_or_empty(&st
))
1263 info
->type
= UNIT_FILE_TYPE_MASKED
;
1264 else if (S_ISREG(st
.st_mode
))
1265 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1266 else if (S_ISLNK(st
.st_mode
))
1268 else if (S_ISDIR(st
.st_mode
))
1276 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
1280 /* Operating on a drop-in file. If we aren't supposed to load the unit file drop-ins don't matter, let's hence shortcut this. */
1282 if (!(flags
& SEARCH_LOAD
))
1285 fd
= chase_symlinks_and_open(path
, root_dir
, 0, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
, NULL
);
1290 if (fstat(fd
, &st
) < 0)
1293 if (null_or_empty(&st
)) {
1294 if ((flags
& SEARCH_DROPIN
) == 0)
1295 info
->type
= UNIT_FILE_TYPE_MASKED
;
1300 r
= stat_verify_regular(&st
);
1304 f
= take_fdopen(&fd
, "r");
1308 /* c is only needed if we actually load the file (it's referenced from items[] btw, in case you wonder.) */
1311 r
= config_parse(info
->name
, path
, f
,
1325 config_item_table_lookup
, items
,
1329 return log_debug_errno(r
, "Failed to parse %s: %m", info
->name
);
1331 if ((flags
& SEARCH_DROPIN
) == 0)
1332 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1335 (int) strv_length(info
->aliases
) +
1336 (int) strv_length(info
->wanted_by
) +
1337 (int) strv_length(info
->required_by
);
1340 static int unit_file_load_or_readlink(
1342 UnitFileInstallInfo
*info
,
1344 const char *root_dir
,
1345 SearchFlags flags
) {
1347 _cleanup_free_
char *resolved
= NULL
;
1350 r
= unit_file_load(c
, info
, path
, root_dir
, flags
);
1351 if (r
!= -ELOOP
|| (flags
& SEARCH_DROPIN
))
1354 r
= chase_symlinks(path
, root_dir
, CHASE_WARN
| CHASE_NONEXISTENT
, &resolved
, NULL
);
1357 path_equal_ptr(path_startswith(resolved
, root_dir
), "dev/null"))
1358 /* When looking under root_dir, we can't expect /dev/ to be mounted,
1359 * so let's see if the path is a (possibly dangling) symlink to /dev/null. */
1360 info
->type
= UNIT_FILE_TYPE_MASKED
;
1362 else if (r
> 0 && null_or_empty_path(resolved
) > 0)
1364 info
->type
= UNIT_FILE_TYPE_MASKED
;
1367 _cleanup_free_
char *target
= NULL
;
1371 /* This is a symlink, let's read it. We read the link again, because last time
1372 * we followed the link until resolution, and here we need to do one step. */
1374 r
= readlink_malloc(path
, &target
);
1378 bn
= basename(target
);
1380 if (unit_name_is_valid(info
->name
, UNIT_NAME_PLAIN
)) {
1382 if (!unit_name_is_valid(bn
, UNIT_NAME_PLAIN
))
1385 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1387 if (!unit_name_is_valid(bn
, UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
))
1390 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
)) {
1392 if (!unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
))
1397 /* Enforce that the symlink destination does not
1398 * change the unit file type. */
1400 a
= unit_name_to_type(info
->name
);
1401 b
= unit_name_to_type(bn
);
1402 if (a
< 0 || b
< 0 || a
!= b
)
1405 if (path_is_absolute(target
))
1406 /* This is an absolute path, prefix the root so that we always deal with fully qualified paths */
1407 info
->symlink_target
= path_join(root_dir
, target
);
1409 /* This is a relative path, take it relative to the dir the symlink is located in. */
1410 info
->symlink_target
= file_in_same_dir(path
, target
);
1411 if (!info
->symlink_target
)
1414 info
->type
= UNIT_FILE_TYPE_SYMLINK
;
1420 static int unit_file_search(
1422 UnitFileInstallInfo
*info
,
1423 const LookupPaths
*paths
,
1424 SearchFlags flags
) {
1426 const char *dropin_dir_name
= NULL
, *dropin_template_dir_name
= NULL
;
1427 _cleanup_strv_free_
char **dirs
= NULL
, **files
= NULL
;
1428 _cleanup_free_
char *template = NULL
;
1429 bool found_unit
= false;
1436 /* Was this unit already loaded? */
1437 if (info
->type
!= _UNIT_FILE_TYPE_INVALID
)
1441 return unit_file_load_or_readlink(c
, info
, info
->path
, paths
->root_dir
, flags
);
1445 if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1446 r
= unit_name_template(info
->name
, &template);
1451 STRV_FOREACH(p
, paths
->search_path
) {
1452 _cleanup_free_
char *path
= NULL
;
1454 path
= path_join(*p
, info
->name
);
1458 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1460 info
->path
= TAKE_PTR(path
);
1464 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1468 if (!found_unit
&& template) {
1470 /* Unit file doesn't exist, however instance
1471 * enablement was requested. We will check if it is
1472 * possible to load template unit file. */
1474 STRV_FOREACH(p
, paths
->search_path
) {
1475 _cleanup_free_
char *path
= NULL
;
1477 path
= path_join(*p
, template);
1481 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1483 info
->path
= TAKE_PTR(path
);
1487 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1493 return log_debug_errno(SYNTHETIC_ERRNO(ENOENT
),
1494 "Cannot find unit %s%s%s.",
1495 info
->name
, template ? " or " : "", strempty(template));
1497 if (info
->type
== UNIT_FILE_TYPE_MASKED
)
1500 /* Search for drop-in directories */
1502 dropin_dir_name
= strjoina(info
->name
, ".d");
1503 STRV_FOREACH(p
, paths
->search_path
) {
1506 path
= path_join(*p
, dropin_dir_name
);
1510 r
= strv_consume(&dirs
, path
);
1516 dropin_template_dir_name
= strjoina(template, ".d");
1517 STRV_FOREACH(p
, paths
->search_path
) {
1520 path
= path_join(*p
, dropin_template_dir_name
);
1524 r
= strv_consume(&dirs
, path
);
1530 /* Load drop-in conf files */
1532 r
= conf_files_list_strv(&files
, ".conf", NULL
, 0, (const char**) dirs
);
1534 return log_debug_errno(r
, "Failed to get list of conf files: %m");
1536 STRV_FOREACH(p
, files
) {
1537 r
= unit_file_load_or_readlink(c
, info
, *p
, paths
->root_dir
, flags
| SEARCH_DROPIN
);
1539 return log_debug_errno(r
, "Failed to load conf file %s: %m", *p
);
1545 static int install_info_follow(
1547 UnitFileInstallInfo
*i
,
1548 const char *root_dir
,
1550 bool ignore_different_name
) {
1555 if (i
->type
!= UNIT_FILE_TYPE_SYMLINK
)
1557 if (!i
->symlink_target
)
1560 /* If the basename doesn't match, the caller should add a
1561 * complete new entry for this. */
1563 if (!ignore_different_name
&& !streq(basename(i
->symlink_target
), i
->name
))
1566 free_and_replace(i
->path
, i
->symlink_target
);
1567 i
->type
= _UNIT_FILE_TYPE_INVALID
;
1569 return unit_file_load_or_readlink(c
, i
, i
->path
, root_dir
, flags
);
1573 * Search for the unit file. If the unit name is a symlink, follow the symlink to the
1574 * target, maybe more than once. Propagate the instance name if present.
1576 static int install_info_traverse(
1577 UnitFileScope scope
,
1579 const LookupPaths
*paths
,
1580 UnitFileInstallInfo
*start
,
1582 UnitFileInstallInfo
**ret
) {
1584 UnitFileInstallInfo
*i
;
1592 r
= unit_file_search(c
, start
, paths
, flags
);
1597 while (i
->type
== UNIT_FILE_TYPE_SYMLINK
) {
1598 /* Follow the symlink */
1600 if (++k
> UNIT_FILE_FOLLOW_SYMLINK_MAX
)
1603 if (!(flags
& SEARCH_FOLLOW_CONFIG_SYMLINKS
)) {
1604 r
= path_is_config(paths
, i
->path
, true);
1611 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
, false);
1613 _cleanup_free_
char *buffer
= NULL
;
1616 /* Target has a different name, create a new
1617 * install info object for that, and continue
1620 bn
= basename(i
->symlink_target
);
1622 if (unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
) &&
1623 unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
)) {
1625 _cleanup_free_
char *instance
= NULL
;
1627 r
= unit_name_to_instance(i
->name
, &instance
);
1631 r
= unit_name_replace_instance(bn
, instance
, &buffer
);
1635 if (streq(buffer
, i
->name
)) {
1637 /* We filled in the instance, and the target stayed the same? If so, then let's
1638 * honour the link as it is. */
1640 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
, true);
1650 r
= install_info_add(c
, bn
, NULL
, paths
->root_dir
, /* auxiliary= */ false, &i
);
1654 /* Try again, with the new target we found. */
1655 r
= unit_file_search(c
, i
, paths
, flags
);
1657 /* Translate error code to highlight this specific case */
1672 * Call install_info_add() with name_or_path as the path (if name_or_path starts with "/")
1673 * or the name (otherwise). root_dir is prepended to the path.
1675 static int install_info_add_auto(
1677 const LookupPaths
*paths
,
1678 const char *name_or_path
,
1679 UnitFileInstallInfo
**ret
) {
1682 assert(name_or_path
);
1684 if (path_is_absolute(name_or_path
)) {
1687 pp
= prefix_roota(paths
->root_dir
, name_or_path
);
1689 return install_info_add(c
, NULL
, pp
, paths
->root_dir
, /* auxiliary= */ false, ret
);
1691 return install_info_add(c
, name_or_path
, NULL
, paths
->root_dir
, /* auxiliary= */ false, ret
);
1694 static int install_info_discover(
1695 UnitFileScope scope
,
1697 const LookupPaths
*paths
,
1700 UnitFileInstallInfo
**ret
,
1701 UnitFileChange
**changes
,
1702 size_t *n_changes
) {
1704 UnitFileInstallInfo
*i
;
1711 r
= install_info_add_auto(c
, paths
, name
, &i
);
1713 r
= install_info_traverse(scope
, c
, paths
, i
, flags
, ret
);
1716 unit_file_changes_add(changes
, n_changes
, r
, name
, NULL
);
1720 static int install_info_discover_and_check(
1721 UnitFileScope scope
,
1723 const LookupPaths
*paths
,
1726 UnitFileInstallInfo
**ret
,
1727 UnitFileChange
**changes
,
1728 size_t *n_changes
) {
1732 r
= install_info_discover(scope
, c
, paths
, name
, flags
, ret
, changes
, n_changes
);
1736 return install_info_may_process(ret
? *ret
: NULL
, paths
, changes
, n_changes
);
1739 int unit_file_verify_alias(const UnitFileInstallInfo
*i
, const char *dst
, char **ret_dst
) {
1740 _cleanup_free_
char *dst_updated
= NULL
;
1743 /* Verify that dst is a valid either a valid alias or a valid .wants/.requires symlink for the target
1744 * unit *i. Return negative on error or if not compatible, zero on success.
1746 * ret_dst is set in cases where "instance propagation" happens, i.e. when the instance part is
1747 * inserted into dst. It is not normally set, even on success, so that the caller can easily
1748 * distinguish the case where instance propagation occurred.
1751 const char *path_alias
= strrchr(dst
, '/');
1753 /* This branch covers legacy Alias= function of creating .wants and .requires symlinks. */
1754 _cleanup_free_
char *dir
= NULL
;
1757 path_alias
++; /* skip over slash */
1759 dir
= dirname_malloc(dst
);
1763 p
= endswith(dir
, ".wants");
1765 p
= endswith(dir
, ".requires");
1767 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV
),
1768 "Invalid path \"%s\" in alias.", dir
);
1769 *p
= '\0'; /* dir should now be a unit name */
1771 UnitNameFlags type
= unit_name_classify(dir
);
1773 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV
),
1774 "Invalid unit name component \"%s\" in alias.", dir
);
1776 const bool instance_propagation
= type
== UNIT_NAME_TEMPLATE
;
1778 /* That's the name we want to use for verification. */
1779 r
= unit_symlink_name_compatible(path_alias
, i
->name
, instance_propagation
);
1781 return log_error_errno(r
, "Failed to verify alias validity: %m");
1783 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV
),
1784 "Invalid unit %s symlink %s.",
1788 /* If the symlink target has an instance set and the symlink source doesn't, we "propagate
1789 * the instance", i.e. instantiate the symlink source with the target instance. */
1790 if (unit_name_is_valid(dst
, UNIT_NAME_TEMPLATE
)) {
1791 _cleanup_free_
char *inst
= NULL
;
1793 UnitNameFlags type
= unit_name_to_instance(i
->name
, &inst
);
1795 return log_error_errno(type
, "Failed to extract instance name from %s: %m", i
->name
);
1797 if (type
== UNIT_NAME_INSTANCE
) {
1798 r
= unit_name_replace_instance(dst
, inst
, &dst_updated
);
1800 return log_error_errno(r
, "Failed to build unit name from %s+%s: %m",
1805 r
= unit_validate_alias_symlink_and_warn(dst_updated
?: dst
, i
->name
);
1811 *ret_dst
= TAKE_PTR(dst_updated
);
1815 static int install_info_symlink_alias(
1816 UnitFileInstallInfo
*i
,
1817 const LookupPaths
*paths
,
1818 const char *config_path
,
1820 UnitFileChange
**changes
,
1821 size_t *n_changes
) {
1828 assert(config_path
);
1830 STRV_FOREACH(s
, i
->aliases
) {
1831 _cleanup_free_
char *alias_path
= NULL
, *dst
= NULL
, *dst_updated
= NULL
;
1833 q
= install_path_printf(i
, *s
, i
->root
, &dst
);
1837 q
= unit_file_verify_alias(i
, dst
, &dst_updated
);
1841 alias_path
= path_make_absolute(dst_updated
?: dst
, config_path
);
1845 q
= create_symlink(paths
, i
->path
, alias_path
, force
, changes
, n_changes
);
1853 static int install_info_symlink_wants(
1854 UnitFileScope scope
,
1855 UnitFileFlags file_flags
,
1856 UnitFileInstallInfo
*i
,
1857 const LookupPaths
*paths
,
1858 const char *config_path
,
1861 UnitFileChange
**changes
,
1862 size_t *n_changes
) {
1864 _cleanup_free_
char *buf
= NULL
;
1865 UnitNameFlags valid_dst_type
= UNIT_NAME_ANY
;
1872 assert(config_path
);
1874 if (strv_isempty(list
))
1877 if (unit_name_is_valid(i
->name
, UNIT_NAME_PLAIN
| UNIT_NAME_INSTANCE
))
1878 /* Not a template unit. Use the name directly. */
1881 else if (i
->default_instance
) {
1882 UnitFileInstallInfo instance
= {
1883 .type
= _UNIT_FILE_TYPE_INVALID
,
1885 _cleanup_free_
char *path
= NULL
;
1887 /* If this is a template, and we have a default instance, use it. */
1889 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &buf
);
1893 instance
.name
= buf
;
1894 r
= unit_file_search(NULL
, &instance
, paths
, SEARCH_FOLLOW_CONFIG_SYMLINKS
);
1898 path
= TAKE_PTR(instance
.path
);
1900 if (instance
.type
== UNIT_FILE_TYPE_MASKED
) {
1901 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, path
, NULL
);
1908 /* We have a template, but no instance yet. When used with an instantiated unit, we will get
1909 * the instance from that unit. Cannot be used with non-instance units. */
1911 valid_dst_type
= UNIT_NAME_INSTANCE
| UNIT_NAME_TEMPLATE
;
1915 STRV_FOREACH(s
, list
) {
1916 _cleanup_free_
char *path
= NULL
, *dst
= NULL
;
1918 q
= install_name_printf(i
, *s
, i
->root
, &dst
);
1922 if (!unit_name_is_valid(dst
, valid_dst_type
)) {
1923 /* Generate a proper error here: EUCLEAN if the name is generally bad, EIDRM if the
1924 * template status doesn't match. If we are doing presets don't bother reporting the
1925 * error. This also covers cases like 'systemctl preset serial-getty@.service', which
1926 * has no DefaultInstance, so there is nothing we can do. At the same time,
1927 * 'systemctl enable serial-getty@.service' should fail, the user should specify an
1928 * instance like in 'systemctl enable serial-getty@ttyS0.service'.
1930 if (file_flags
& UNIT_FILE_IGNORE_AUXILIARY_FAILURE
)
1933 if (unit_name_is_valid(dst
, UNIT_NAME_ANY
)) {
1934 unit_file_changes_add(changes
, n_changes
, -EIDRM
, dst
, n
);
1937 unit_file_changes_add(changes
, n_changes
, -EUCLEAN
, dst
, NULL
);
1944 path
= strjoin(config_path
, "/", dst
, suffix
, n
);
1948 q
= create_symlink(paths
, i
->path
, path
, true, changes
, n_changes
);
1952 if (unit_file_exists(scope
, paths
, dst
) == 0)
1953 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_DESTINATION_NOT_PRESENT
, dst
, i
->path
);
1959 static int install_info_symlink_link(
1960 UnitFileInstallInfo
*i
,
1961 const LookupPaths
*paths
,
1962 const char *config_path
,
1964 UnitFileChange
**changes
,
1965 size_t *n_changes
) {
1967 _cleanup_free_
char *path
= NULL
;
1972 assert(config_path
);
1975 r
= in_search_path(paths
, i
->path
);
1981 path
= path_join(config_path
, i
->name
);
1985 return create_symlink(paths
, i
->path
, path
, force
, changes
, n_changes
);
1988 static int install_info_apply(
1989 UnitFileScope scope
,
1990 UnitFileFlags file_flags
,
1991 UnitFileInstallInfo
*i
,
1992 const LookupPaths
*paths
,
1993 const char *config_path
,
1994 UnitFileChange
**changes
,
1995 size_t *n_changes
) {
2001 assert(config_path
);
2003 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
2006 bool force
= file_flags
& UNIT_FILE_FORCE
;
2008 r
= install_info_symlink_alias(i
, paths
, config_path
, force
, changes
, n_changes
);
2010 q
= install_info_symlink_wants(scope
, file_flags
, i
, paths
, config_path
, i
->wanted_by
, ".wants/", changes
, n_changes
);
2014 q
= install_info_symlink_wants(scope
, file_flags
, i
, paths
, config_path
, i
->required_by
, ".requires/", changes
, n_changes
);
2018 q
= install_info_symlink_link(i
, paths
, config_path
, force
, changes
, n_changes
);
2019 /* Do not count links to the unit file towards the "carries_install_info" count */
2020 if (r
== 0 && q
< 0)
2026 static int install_context_apply(
2027 UnitFileScope scope
,
2028 UnitFileFlags file_flags
,
2030 const LookupPaths
*paths
,
2031 const char *config_path
,
2033 UnitFileChange
**changes
,
2034 size_t *n_changes
) {
2036 UnitFileInstallInfo
*i
;
2041 assert(config_path
);
2043 if (ordered_hashmap_isempty(c
->will_process
))
2046 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
2051 while ((i
= ordered_hashmap_first(c
->will_process
))) {
2054 q
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
2058 q
= install_info_traverse(scope
, c
, paths
, i
, flags
, NULL
);
2061 q
= unit_file_changes_add(changes
, n_changes
, UNIT_FILE_AUXILIARY_FAILED
, NULL
, i
->name
);
2067 unit_file_changes_add(changes
, n_changes
, q
, i
->name
, NULL
);
2071 /* We can attempt to process a masked unit when a different unit
2072 * that we were processing specifies it in Also=. */
2073 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
2074 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_MASKED
, i
->path
, NULL
);
2076 /* Assume that something *could* have been enabled here,
2077 * avoid "empty [Install] section" warning. */
2082 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
2085 q
= install_info_apply(scope
, file_flags
, i
, paths
, config_path
, changes
, n_changes
);
2097 static int install_context_mark_for_removal(
2098 UnitFileScope scope
,
2100 const LookupPaths
*paths
,
2101 Set
**remove_symlinks_to
,
2102 const char *config_path
,
2103 UnitFileChange
**changes
,
2104 size_t *n_changes
) {
2106 UnitFileInstallInfo
*i
;
2111 assert(config_path
);
2113 /* Marks all items for removal */
2115 if (ordered_hashmap_isempty(c
->will_process
))
2118 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
2122 while ((i
= ordered_hashmap_first(c
->will_process
))) {
2124 r
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
2128 r
= install_info_traverse(scope
, c
, paths
, i
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, NULL
);
2129 if (r
== -ENOLINK
) {
2130 log_debug_errno(r
, "Name %s leads to a dangling symlink, removing name.", i
->name
);
2131 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_DANGLING
, i
->path
?: i
->name
, NULL
);
2132 } else if (r
== -ENOENT
) {
2134 if (i
->auxiliary
) /* some unit specified in Also= or similar is missing */
2135 log_debug_errno(r
, "Auxiliary unit of %s not found, removing name.", i
->name
);
2137 log_debug_errno(r
, "Unit %s not found, removing name.", i
->name
);
2138 unit_file_changes_add(changes
, n_changes
, r
, i
->path
?: i
->name
, NULL
);
2142 log_debug_errno(r
, "Failed to find unit %s, removing name: %m", i
->name
);
2143 unit_file_changes_add(changes
, n_changes
, r
, i
->path
?: i
->name
, NULL
);
2144 } else if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
2145 log_debug("Unit file %s is masked, ignoring.", i
->name
);
2146 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_MASKED
, i
->path
?: i
->name
, NULL
);
2148 } else if (i
->type
!= UNIT_FILE_TYPE_REGULAR
) {
2149 log_debug("Unit %s has type %s, ignoring.", i
->name
, unit_file_type_to_string(i
->type
) ?: "invalid");
2153 r
= mark_symlink_for_removal(remove_symlinks_to
, i
->name
);
2162 UnitFileScope scope
,
2163 UnitFileFlags flags
,
2164 const char *root_dir
,
2166 UnitFileChange
**changes
,
2167 size_t *n_changes
) {
2169 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2170 const char *config_path
;
2175 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2177 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2181 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2185 STRV_FOREACH(i
, files
) {
2186 _cleanup_free_
char *path
= NULL
;
2189 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
)) {
2195 path
= path_make_absolute(*i
, config_path
);
2199 q
= create_symlink(&paths
, "/dev/null", path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2200 if (q
< 0 && r
>= 0)
2207 int unit_file_unmask(
2208 UnitFileScope scope
,
2209 UnitFileFlags flags
,
2210 const char *root_dir
,
2212 UnitFileChange
**changes
,
2213 size_t *n_changes
) {
2215 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2216 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2217 _cleanup_strv_free_
char **todo
= NULL
;
2218 const char *config_path
;
2225 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2227 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2231 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2235 dry_run
= !!(flags
& UNIT_FILE_DRY_RUN
);
2237 STRV_FOREACH(i
, files
) {
2238 _cleanup_free_
char *path
= NULL
;
2240 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2243 path
= path_make_absolute(*i
, config_path
);
2247 r
= null_or_empty_path(path
);
2255 if (!GREEDY_REALLOC0(todo
, n_todo
+ 2))
2258 todo
[n_todo
] = strdup(*i
);
2268 STRV_FOREACH(i
, todo
) {
2269 _cleanup_free_
char *path
= NULL
;
2272 path
= path_make_absolute(*i
, config_path
);
2276 if (!dry_run
&& unlink(path
) < 0) {
2277 if (errno
!= ENOENT
) {
2280 unit_file_changes_add(changes
, n_changes
, -errno
, path
, NULL
);
2286 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
2288 rp
= skip_root(&paths
, path
);
2289 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: path
);
2294 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, dry_run
, changes
, n_changes
);
2302 UnitFileScope scope
,
2303 UnitFileFlags flags
,
2304 const char *root_dir
,
2306 UnitFileChange
**changes
,
2307 size_t *n_changes
) {
2309 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2310 _cleanup_strv_free_
char **todo
= NULL
;
2311 const char *config_path
;
2317 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2319 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2323 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2327 STRV_FOREACH(i
, files
) {
2328 _cleanup_free_
char *full
= NULL
;
2332 if (!path_is_absolute(*i
))
2336 if (!unit_name_is_valid(fn
, UNIT_NAME_ANY
))
2339 full
= path_join(paths
.root_dir
, *i
);
2343 if (lstat(full
, &st
) < 0)
2345 r
= stat_verify_regular(&st
);
2349 q
= in_search_path(&paths
, *i
);
2355 if (!GREEDY_REALLOC0(todo
, n_todo
+ 2))
2358 todo
[n_todo
] = strdup(*i
);
2368 STRV_FOREACH(i
, todo
) {
2369 _cleanup_free_
char *new_path
= NULL
;
2371 new_path
= path_make_absolute(basename(*i
), config_path
);
2375 q
= create_symlink(&paths
, *i
, new_path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2376 if (q
< 0 && r
>= 0)
2383 static int path_shall_revert(const LookupPaths
*paths
, const char *path
) {
2389 /* Checks whether the path is one where the drop-in directories shall be removed. */
2391 r
= path_is_config(paths
, path
, true);
2395 r
= path_is_control(paths
, path
);
2399 return path_is_transient(paths
, path
);
2402 int unit_file_revert(
2403 UnitFileScope scope
,
2404 const char *root_dir
,
2406 UnitFileChange
**changes
,
2407 size_t *n_changes
) {
2409 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2410 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2411 _cleanup_strv_free_
char **todo
= NULL
;
2416 /* Puts a unit file back into vendor state. This means:
2418 * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and
2419 * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated").
2421 * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in
2422 * "config", but not in "transient" or "control" or even "generated").
2424 * We remove all that in both the runtime and the persistent directories, if that applies.
2427 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2431 STRV_FOREACH(i
, files
) {
2432 bool has_vendor
= false;
2435 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2438 STRV_FOREACH(p
, paths
.search_path
) {
2439 _cleanup_free_
char *path
= NULL
, *dropin
= NULL
;
2442 path
= path_make_absolute(*i
, *p
);
2446 r
= lstat(path
, &st
);
2448 if (errno
!= ENOENT
)
2450 } else if (S_ISREG(st
.st_mode
)) {
2451 /* Check if there's a vendor version */
2452 r
= path_is_vendor_or_generator(&paths
, path
);
2459 dropin
= strjoin(path
, ".d");
2463 r
= lstat(dropin
, &st
);
2465 if (errno
!= ENOENT
)
2467 } else if (S_ISDIR(st
.st_mode
)) {
2468 /* Remove the drop-ins */
2469 r
= path_shall_revert(&paths
, dropin
);
2473 if (!GREEDY_REALLOC0(todo
, n_todo
+ 2))
2476 todo
[n_todo
++] = TAKE_PTR(dropin
);
2484 /* OK, there's a vendor version, hence drop all configuration versions */
2485 STRV_FOREACH(p
, paths
.search_path
) {
2486 _cleanup_free_
char *path
= NULL
;
2489 path
= path_make_absolute(*i
, *p
);
2493 r
= lstat(path
, &st
);
2495 if (errno
!= ENOENT
)
2497 } else if (S_ISREG(st
.st_mode
) || S_ISLNK(st
.st_mode
)) {
2498 r
= path_is_config(&paths
, path
, true);
2502 if (!GREEDY_REALLOC0(todo
, n_todo
+ 2))
2505 todo
[n_todo
++] = TAKE_PTR(path
);
2514 STRV_FOREACH(i
, todo
) {
2515 _cleanup_strv_free_
char **fs
= NULL
;
2519 (void) get_files_in_directory(*i
, &fs
);
2521 q
= rm_rf(*i
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
2522 if (q
< 0 && q
!= -ENOENT
&& r
>= 0) {
2527 STRV_FOREACH(j
, fs
) {
2528 _cleanup_free_
char *t
= NULL
;
2530 t
= path_join(*i
, *j
);
2534 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, t
, NULL
);
2537 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, *i
, NULL
);
2539 rp
= skip_root(&paths
, *i
);
2540 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: *i
);
2545 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.runtime_config
, &paths
, false, changes
, n_changes
);
2549 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.persistent_config
, &paths
, false, changes
, n_changes
);
2556 int unit_file_add_dependency(
2557 UnitFileScope scope
,
2558 UnitFileFlags file_flags
,
2559 const char *root_dir
,
2563 UnitFileChange
**changes
,
2564 size_t *n_changes
) {
2566 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2567 _cleanup_(install_context_done
) InstallContext c
= {};
2568 UnitFileInstallInfo
*i
, *target_info
;
2569 const char *config_path
;
2574 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2577 if (!IN_SET(dep
, UNIT_WANTS
, UNIT_REQUIRES
))
2580 if (!unit_name_is_valid(target
, UNIT_NAME_ANY
))
2583 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2587 config_path
= (file_flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2591 r
= install_info_discover_and_check(scope
, &c
, &paths
, target
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2592 &target_info
, changes
, n_changes
);
2596 assert(target_info
->type
== UNIT_FILE_TYPE_REGULAR
);
2598 STRV_FOREACH(f
, files
) {
2601 r
= install_info_discover_and_check(scope
, &c
, &paths
, *f
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2602 &i
, changes
, n_changes
);
2606 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2608 /* We didn't actually load anything from the unit
2609 * file, but instead just add in our new symlink to
2612 if (dep
== UNIT_WANTS
)
2615 l
= &i
->required_by
;
2618 *l
= strv_new(target_info
->name
);
2623 return install_context_apply(scope
, file_flags
, &c
, &paths
, config_path
,
2624 SEARCH_FOLLOW_CONFIG_SYMLINKS
, changes
, n_changes
);
2627 int unit_file_enable(
2628 UnitFileScope scope
,
2629 UnitFileFlags file_flags
,
2630 const char *root_dir
,
2632 UnitFileChange
**changes
,
2633 size_t *n_changes
) {
2635 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2636 _cleanup_(install_context_done
) InstallContext c
= {};
2637 const char *config_path
;
2638 UnitFileInstallInfo
*i
;
2643 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2645 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2649 config_path
= config_path_from_flags(&paths
, file_flags
);
2653 STRV_FOREACH(f
, files
) {
2654 r
= install_info_discover_and_check(scope
, &c
, &paths
, *f
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2655 &i
, changes
, n_changes
);
2659 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2662 /* This will return the number of symlink rules that were
2663 supposed to be created, not the ones actually created. This
2664 is useful to determine whether the passed files had any
2665 installation data at all. */
2667 return install_context_apply(scope
, file_flags
, &c
, &paths
, config_path
, SEARCH_LOAD
, changes
, n_changes
);
2670 int unit_file_disable(
2671 UnitFileScope scope
,
2672 UnitFileFlags flags
,
2673 const char *root_dir
,
2675 UnitFileChange
**changes
,
2676 size_t *n_changes
) {
2678 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2679 _cleanup_(install_context_done
) InstallContext c
= {};
2680 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2681 const char *config_path
;
2686 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2688 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2692 config_path
= config_path_from_flags(&paths
, flags
);
2696 STRV_FOREACH(i
, files
) {
2697 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2700 r
= install_info_add(&c
, *i
, NULL
, paths
.root_dir
, /* auxiliary= */ false, NULL
);
2705 r
= install_context_mark_for_removal(scope
, &c
, &paths
, &remove_symlinks_to
, config_path
, changes
, n_changes
);
2709 return remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, !!(flags
& UNIT_FILE_DRY_RUN
), changes
, n_changes
);
2712 int unit_file_reenable(
2713 UnitFileScope scope
,
2714 UnitFileFlags flags
,
2715 const char *root_dir
,
2717 UnitFileChange
**changes
,
2718 size_t *n_changes
) {
2724 /* First, we invoke the disable command with only the basename... */
2725 l
= strv_length(files
);
2726 n
= newa(char*, l
+1);
2727 for (i
= 0; i
< l
; i
++)
2728 n
[i
] = basename(files
[i
]);
2731 r
= unit_file_disable(scope
, flags
, root_dir
, n
, changes
, n_changes
);
2735 /* But the enable command with the full name */
2736 return unit_file_enable(scope
, flags
, root_dir
, files
, changes
, n_changes
);
2739 int unit_file_set_default(
2740 UnitFileScope scope
,
2741 UnitFileFlags flags
,
2742 const char *root_dir
,
2744 UnitFileChange
**changes
,
2745 size_t *n_changes
) {
2747 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2748 _cleanup_(install_context_done
) InstallContext c
= {};
2749 UnitFileInstallInfo
*i
;
2750 const char *new_path
;
2754 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2757 if (unit_name_to_type(name
) != UNIT_TARGET
) /* this also validates the name */
2759 if (streq(name
, SPECIAL_DEFAULT_TARGET
))
2762 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2766 r
= install_info_discover_and_check(scope
, &c
, &paths
, name
, 0, &i
, changes
, n_changes
);
2770 new_path
= strjoina(paths
.persistent_config
, "/" SPECIAL_DEFAULT_TARGET
);
2771 return create_symlink(&paths
, i
->path
, new_path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2774 int unit_file_get_default(
2775 UnitFileScope scope
,
2776 const char *root_dir
,
2779 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2780 _cleanup_(install_context_done
) InstallContext c
= {};
2781 UnitFileInstallInfo
*i
;
2786 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2789 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2793 r
= install_info_discover(scope
, &c
, &paths
, SPECIAL_DEFAULT_TARGET
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2797 r
= install_info_may_process(i
, &paths
, NULL
, 0);
2801 n
= strdup(i
->name
);
2809 int unit_file_lookup_state(
2810 UnitFileScope scope
,
2811 const LookupPaths
*paths
,
2813 UnitFileState
*ret
) {
2815 _cleanup_(install_context_done
) InstallContext c
= {};
2816 UnitFileInstallInfo
*i
;
2817 UnitFileState state
;
2823 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2826 r
= install_info_discover(scope
, &c
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2829 return log_debug_errno(r
, "Failed to discover unit %s: %m", name
);
2831 assert(IN_SET(i
->type
, UNIT_FILE_TYPE_REGULAR
, UNIT_FILE_TYPE_MASKED
));
2832 log_debug("Found unit %s at %s (%s)", name
, strna(i
->path
),
2833 i
->type
== UNIT_FILE_TYPE_REGULAR
? "regular file" : "mask");
2835 /* Shortcut things, if the caller just wants to know if this unit exists. */
2841 case UNIT_FILE_TYPE_MASKED
:
2842 r
= path_is_runtime(paths
, i
->path
, true);
2846 state
= r
> 0 ? UNIT_FILE_MASKED_RUNTIME
: UNIT_FILE_MASKED
;
2849 case UNIT_FILE_TYPE_REGULAR
:
2850 /* Check if the name we were querying is actually an alias */
2851 if (!streq(name
, basename(i
->path
)) && !unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
)) {
2852 state
= UNIT_FILE_ALIAS
;
2856 r
= path_is_generator(paths
, i
->path
);
2860 state
= UNIT_FILE_GENERATED
;
2864 r
= path_is_transient(paths
, i
->path
);
2868 state
= UNIT_FILE_TRANSIENT
;
2872 /* Check if any of the Alias= symlinks have been created.
2873 * We ignore other aliases, and only check those that would
2874 * be created by systemctl enable for this unit. */
2875 r
= find_symlinks_in_scope(scope
, paths
, i
, true, &state
);
2881 /* Check if the file is known under other names. If it is,
2882 * it might be in use. Report that as UNIT_FILE_INDIRECT. */
2883 r
= find_symlinks_in_scope(scope
, paths
, i
, false, &state
);
2887 state
= UNIT_FILE_INDIRECT
;
2889 if (unit_file_install_info_has_rules(i
))
2890 state
= UNIT_FILE_DISABLED
;
2891 else if (unit_file_install_info_has_also(i
))
2892 state
= UNIT_FILE_INDIRECT
;
2894 state
= UNIT_FILE_STATIC
;
2900 assert_not_reached("Unexpected unit file type.");
2907 int unit_file_get_state(
2908 UnitFileScope scope
,
2909 const char *root_dir
,
2911 UnitFileState
*ret
) {
2913 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2917 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2920 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2924 return unit_file_lookup_state(scope
, &paths
, name
, ret
);
2927 int unit_file_exists(UnitFileScope scope
, const LookupPaths
*paths
, const char *name
) {
2928 _cleanup_(install_context_done
) InstallContext c
= {};
2934 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2937 r
= install_info_discover(scope
, &c
, paths
, name
, 0, NULL
, NULL
, NULL
);
2946 static int split_pattern_into_name_and_instances(const char *pattern
, char **out_unit_name
, char ***out_instances
) {
2947 _cleanup_strv_free_
char **instances
= NULL
;
2948 _cleanup_free_
char *unit_name
= NULL
;
2952 assert(out_instances
);
2953 assert(out_unit_name
);
2955 r
= extract_first_word(&pattern
, &unit_name
, NULL
, EXTRACT_RETAIN_ESCAPE
);
2959 /* We handle the instances logic when unit name is extracted */
2961 /* We only create instances when a rule of templated unit
2962 * is seen. A rule like enable foo@.service a b c will
2963 * result in an array of (a, b, c) as instance names */
2964 if (!unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
))
2967 instances
= strv_split(pattern
, WHITESPACE
);
2971 *out_instances
= TAKE_PTR(instances
);
2974 *out_unit_name
= TAKE_PTR(unit_name
);
2979 static int presets_find_config(UnitFileScope scope
, const char *root_dir
, char ***files
) {
2980 static const char* const system_dirs
[] = {CONF_PATHS("systemd/system-preset"), NULL
};
2981 static const char* const user_dirs
[] = {CONF_PATHS_USR("systemd/user-preset"), NULL
};
2982 const char* const* dirs
;
2985 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2987 if (scope
== UNIT_FILE_SYSTEM
)
2989 else if (IN_SET(scope
, UNIT_FILE_GLOBAL
, UNIT_FILE_USER
))
2992 assert_not_reached("Invalid unit file scope");
2994 return conf_files_list_strv(files
, ".preset", root_dir
, 0, dirs
);
2997 static int read_presets(UnitFileScope scope
, const char *root_dir
, UnitFilePresets
*presets
) {
2998 _cleanup_(unit_file_presets_freep
) UnitFilePresets ps
= {};
2999 _cleanup_strv_free_
char **files
= NULL
;
3004 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3007 r
= presets_find_config(scope
, root_dir
, &files
);
3011 STRV_FOREACH(p
, files
) {
3012 _cleanup_fclose_
FILE *f
= NULL
;
3015 f
= fopen(*p
, "re");
3017 if (errno
== ENOENT
)
3024 _cleanup_free_
char *line
= NULL
;
3025 UnitFilePresetRule rule
= {};
3026 const char *parameter
;
3029 r
= read_line(f
, LONG_LINE_MAX
, &line
);
3040 if (strchr(COMMENTS
, *l
))
3043 parameter
= first_word(l
, "enable");
3046 char **instances
= NULL
;
3048 /* Unit_name will remain the same as parameter when no instances are specified */
3049 r
= split_pattern_into_name_and_instances(parameter
, &unit_name
, &instances
);
3051 log_syntax(NULL
, LOG_WARNING
, *p
, n
, r
, "Couldn't parse line '%s'. Ignoring.", line
);
3055 rule
= (UnitFilePresetRule
) {
3056 .pattern
= unit_name
,
3057 .action
= PRESET_ENABLE
,
3058 .instances
= instances
,
3062 parameter
= first_word(l
, "disable");
3066 pattern
= strdup(parameter
);
3070 rule
= (UnitFilePresetRule
) {
3072 .action
= PRESET_DISABLE
,
3077 if (!GREEDY_REALLOC(ps
.rules
, ps
.n_rules
+ 1))
3080 ps
.rules
[ps
.n_rules
++] = rule
;
3084 log_syntax(NULL
, LOG_WARNING
, *p
, n
, 0, "Couldn't parse line '%s'. Ignoring.", line
);
3088 ps
.initialized
= true;
3090 ps
= (UnitFilePresets
){};
3095 static int pattern_match_multiple_instances(
3096 const UnitFilePresetRule rule
,
3097 const char *unit_name
,
3100 _cleanup_free_
char *templated_name
= NULL
;
3103 /* If no ret is needed or the rule itself does not have instances
3104 * initialized, we return not matching */
3105 if (!ret
|| !rule
.instances
)
3108 r
= unit_name_template(unit_name
, &templated_name
);
3111 if (!streq(rule
.pattern
, templated_name
))
3114 /* Compose a list of specified instances when unit name is a template */
3115 if (unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
3116 _cleanup_strv_free_
char **out_strv
= NULL
;
3119 STRV_FOREACH(iter
, rule
.instances
) {
3120 _cleanup_free_
char *name
= NULL
;
3122 r
= unit_name_replace_instance(unit_name
, *iter
, &name
);
3126 r
= strv_consume(&out_strv
, TAKE_PTR(name
));
3131 *ret
= TAKE_PTR(out_strv
);
3134 /* We now know the input unit name is an instance name */
3135 _cleanup_free_
char *instance_name
= NULL
;
3137 r
= unit_name_to_instance(unit_name
, &instance_name
);
3141 if (strv_find(rule
.instances
, instance_name
))
3147 static int query_presets(const char *name
, const UnitFilePresets
*presets
, char ***instance_name_list
) {
3148 PresetAction action
= PRESET_UNKNOWN
;
3150 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
3153 for (size_t i
= 0; i
< presets
->n_rules
; i
++)
3154 if (pattern_match_multiple_instances(presets
->rules
[i
], name
, instance_name_list
) > 0 ||
3155 fnmatch(presets
->rules
[i
].pattern
, name
, FNM_NOESCAPE
) == 0) {
3156 action
= presets
->rules
[i
].action
;
3161 case PRESET_UNKNOWN
:
3162 log_debug("Preset files don't specify rule for %s. Enabling.", name
);
3165 if (instance_name_list
&& *instance_name_list
) {
3167 STRV_FOREACH(s
, *instance_name_list
)
3168 log_debug("Preset files say enable %s.", *s
);
3170 log_debug("Preset files say enable %s.", name
);
3172 case PRESET_DISABLE
:
3173 log_debug("Preset files say disable %s.", name
);
3176 assert_not_reached("invalid preset action");
3180 int unit_file_query_preset(UnitFileScope scope
, const char *root_dir
, const char *name
, UnitFilePresets
*cached
) {
3181 _cleanup_(unit_file_presets_freep
) UnitFilePresets tmp
= {};
3186 if (!cached
->initialized
) {
3187 r
= read_presets(scope
, root_dir
, cached
);
3192 return query_presets(name
, cached
, NULL
);
3195 static int execute_preset(
3196 UnitFileScope scope
,
3197 UnitFileFlags file_flags
,
3198 InstallContext
*plus
,
3199 InstallContext
*minus
,
3200 const LookupPaths
*paths
,
3201 const char *config_path
,
3203 UnitFilePresetMode mode
,
3204 UnitFileChange
**changes
,
3205 size_t *n_changes
) {
3212 assert(config_path
);
3214 if (mode
!= UNIT_FILE_PRESET_ENABLE_ONLY
) {
3215 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
3217 r
= install_context_mark_for_removal(scope
, minus
, paths
, &remove_symlinks_to
, config_path
, changes
, n_changes
);
3221 r
= remove_marked_symlinks(remove_symlinks_to
, config_path
, paths
, false, changes
, n_changes
);
3225 if (mode
!= UNIT_FILE_PRESET_DISABLE_ONLY
) {
3228 /* Returns number of symlinks that where supposed to be installed. */
3229 q
= install_context_apply(scope
,
3230 file_flags
| UNIT_FILE_IGNORE_AUXILIARY_FAILURE
,
3231 plus
, paths
, config_path
, SEARCH_LOAD
, changes
, n_changes
);
3243 static int preset_prepare_one(
3244 UnitFileScope scope
,
3245 InstallContext
*plus
,
3246 InstallContext
*minus
,
3249 const UnitFilePresets
*presets
,
3250 UnitFileChange
**changes
,
3251 size_t *n_changes
) {
3253 _cleanup_(install_context_done
) InstallContext tmp
= {};
3254 _cleanup_strv_free_
char **instance_name_list
= NULL
;
3255 UnitFileInstallInfo
*i
;
3258 if (install_info_find(plus
, name
) || install_info_find(minus
, name
))
3261 r
= install_info_discover(scope
, &tmp
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3262 &i
, changes
, n_changes
);
3265 if (!streq(name
, i
->name
)) {
3266 log_debug("Skipping %s because it is an alias for %s.", name
, i
->name
);
3270 r
= query_presets(name
, presets
, &instance_name_list
);
3275 if (instance_name_list
) {
3277 STRV_FOREACH(s
, instance_name_list
) {
3278 r
= install_info_discover_and_check(scope
, plus
, paths
, *s
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3279 &i
, changes
, n_changes
);
3284 r
= install_info_discover_and_check(scope
, plus
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3285 &i
, changes
, n_changes
);
3291 r
= install_info_discover(scope
, minus
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3292 &i
, changes
, n_changes
);
3297 int unit_file_preset(
3298 UnitFileScope scope
,
3299 UnitFileFlags file_flags
,
3300 const char *root_dir
,
3302 UnitFilePresetMode mode
,
3303 UnitFileChange
**changes
,
3304 size_t *n_changes
) {
3306 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
3307 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3308 _cleanup_(unit_file_presets_freep
) UnitFilePresets presets
= {};
3309 const char *config_path
;
3314 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3315 assert(mode
< _UNIT_FILE_PRESET_MAX
);
3317 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3321 config_path
= (file_flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
3325 r
= read_presets(scope
, root_dir
, &presets
);
3329 STRV_FOREACH(i
, files
) {
3330 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, *i
, &presets
, changes
, n_changes
);
3335 return execute_preset(scope
, file_flags
, &plus
, &minus
, &paths
, config_path
, files
, mode
, changes
, n_changes
);
3338 int unit_file_preset_all(
3339 UnitFileScope scope
,
3340 UnitFileFlags file_flags
,
3341 const char *root_dir
,
3342 UnitFilePresetMode mode
,
3343 UnitFileChange
**changes
,
3344 size_t *n_changes
) {
3346 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
3347 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3348 _cleanup_(unit_file_presets_freep
) UnitFilePresets presets
= {};
3349 const char *config_path
= NULL
;
3354 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3355 assert(mode
< _UNIT_FILE_PRESET_MAX
);
3357 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3361 config_path
= (file_flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
3365 r
= read_presets(scope
, root_dir
, &presets
);
3369 STRV_FOREACH(i
, paths
.search_path
) {
3370 _cleanup_closedir_
DIR *d
= NULL
;
3375 if (errno
== ENOENT
)
3381 FOREACH_DIRENT(de
, d
, return -errno
) {
3383 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
3386 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
3389 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, de
->d_name
, &presets
, changes
, n_changes
);
3391 !IN_SET(r
, -EEXIST
, -ERFKILL
, -EADDRNOTAVAIL
, -EIDRM
, -EUCLEAN
, -ELOOP
, -ENOENT
))
3392 /* Ignore generated/transient/missing/invalid units when applying preset, propagate other errors.
3393 * Coordinate with unit_file_dump_changes() above. */
3398 return execute_preset(scope
, file_flags
, &plus
, &minus
, &paths
, config_path
, NULL
, mode
, changes
, n_changes
);
3401 static UnitFileList
* unit_file_list_free_one(UnitFileList
*f
) {
3409 Hashmap
* unit_file_list_free(Hashmap
*h
) {
3410 return hashmap_free_with_destructor(h
, unit_file_list_free_one
);
3413 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList
*, unit_file_list_free_one
);
3415 int unit_file_get_list(
3416 UnitFileScope scope
,
3417 const char *root_dir
,
3422 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3427 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3430 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3434 STRV_FOREACH(dirname
, paths
.search_path
) {
3435 _cleanup_closedir_
DIR *d
= NULL
;
3438 d
= opendir(*dirname
);
3440 if (errno
== ENOENT
)
3442 if (IN_SET(errno
, ENOTDIR
, EACCES
)) {
3443 log_debug_errno(errno
, "Failed to open \"%s\": %m", *dirname
);
3450 FOREACH_DIRENT(de
, d
, return -errno
) {
3451 _cleanup_(unit_file_list_free_onep
) UnitFileList
*f
= NULL
;
3453 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
3456 if (!strv_fnmatch_or_empty(patterns
, de
->d_name
, FNM_NOESCAPE
))
3459 if (hashmap_get(h
, de
->d_name
))
3462 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
3465 f
= new0(UnitFileList
, 1);
3469 f
->path
= path_make_absolute(de
->d_name
, *dirname
);
3473 r
= unit_file_lookup_state(scope
, &paths
, de
->d_name
, &f
->state
);
3475 f
->state
= UNIT_FILE_BAD
;
3477 if (!strv_isempty(states
) &&
3478 !strv_contains(states
, unit_file_state_to_string(f
->state
)))
3481 r
= hashmap_put(h
, basename(f
->path
), f
);
3485 f
= NULL
; /* prevent cleanup */
3492 static const char* const unit_file_state_table
[_UNIT_FILE_STATE_MAX
] = {
3493 [UNIT_FILE_ENABLED
] = "enabled",
3494 [UNIT_FILE_ENABLED_RUNTIME
] = "enabled-runtime",
3495 [UNIT_FILE_LINKED
] = "linked",
3496 [UNIT_FILE_LINKED_RUNTIME
] = "linked-runtime",
3497 [UNIT_FILE_ALIAS
] = "alias",
3498 [UNIT_FILE_MASKED
] = "masked",
3499 [UNIT_FILE_MASKED_RUNTIME
] = "masked-runtime",
3500 [UNIT_FILE_STATIC
] = "static",
3501 [UNIT_FILE_DISABLED
] = "disabled",
3502 [UNIT_FILE_INDIRECT
] = "indirect",
3503 [UNIT_FILE_GENERATED
] = "generated",
3504 [UNIT_FILE_TRANSIENT
] = "transient",
3505 [UNIT_FILE_BAD
] = "bad",
3508 DEFINE_STRING_TABLE_LOOKUP(unit_file_state
, UnitFileState
);
3510 static const char* const unit_file_change_type_table
[_UNIT_FILE_CHANGE_TYPE_MAX
] = {
3511 [UNIT_FILE_SYMLINK
] = "symlink",
3512 [UNIT_FILE_UNLINK
] = "unlink",
3513 [UNIT_FILE_IS_MASKED
] = "masked",
3514 [UNIT_FILE_IS_DANGLING
] = "dangling",
3515 [UNIT_FILE_DESTINATION_NOT_PRESENT
] = "destination not present",
3516 [UNIT_FILE_AUXILIARY_FAILED
] = "auxiliary unit failed",
3519 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type
, int);
3521 static const char* const unit_file_preset_mode_table
[_UNIT_FILE_PRESET_MAX
] = {
3522 [UNIT_FILE_PRESET_FULL
] = "full",
3523 [UNIT_FILE_PRESET_ENABLE_ONLY
] = "enable-only",
3524 [UNIT_FILE_PRESET_DISABLE_ONLY
] = "disable-only",
3527 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode
, UnitFilePresetMode
);