1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
12 #include "alloc-util.h"
13 #include "chase-symlinks.h"
14 #include "conf-files.h"
15 #include "conf-parser.h"
17 #include "dirent-util.h"
18 #include "errno-list.h"
19 #include "extract-word.h"
24 #include "install-printf.h"
26 #include "locale-util.h"
29 #include "mkdir-label.h"
30 #include "path-lookup.h"
31 #include "path-util.h"
35 #include "stat-util.h"
36 #include "string-table.h"
37 #include "string-util.h"
39 #include "unit-file.h"
41 #define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
43 typedef enum SearchFlags
{
45 SEARCH_FOLLOW_CONFIG_SYMLINKS
= 1 << 1,
46 SEARCH_DROPIN
= 1 << 2,
50 OrderedHashmap
*will_process
;
51 OrderedHashmap
*have_processed
;
60 struct UnitFilePresetRule
{
66 static bool unit_file_install_info_has_rules(const UnitFileInstallInfo
*i
) {
69 return !strv_isempty(i
->aliases
) ||
70 !strv_isempty(i
->wanted_by
) ||
71 !strv_isempty(i
->required_by
);
74 static bool unit_file_install_info_has_also(const UnitFileInstallInfo
*i
) {
77 return !strv_isempty(i
->also
);
80 void unit_file_presets_freep(UnitFilePresets
*p
) {
84 for (size_t i
= 0; i
< p
->n_rules
; i
++) {
85 free(p
->rules
[i
].pattern
);
86 strv_free(p
->rules
[i
].instances
);
93 static const char *const unit_file_type_table
[_UNIT_FILE_TYPE_MAX
] = {
94 [UNIT_FILE_TYPE_REGULAR
] = "regular",
95 [UNIT_FILE_TYPE_SYMLINK
] = "symlink",
96 [UNIT_FILE_TYPE_MASKED
] = "masked",
99 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(unit_file_type
, UnitFileType
);
101 static int in_search_path(const LookupPaths
*p
, const char *path
) {
102 _cleanup_free_
char *parent
= NULL
;
106 parent
= dirname_malloc(path
);
110 return path_strv_contains(p
->search_path
, parent
);
113 static const char* skip_root(const LookupPaths
*p
, const char *path
) {
122 e
= path_startswith(path
, p
->root_dir
);
126 /* Make sure the returned path starts with a slash */
128 if (e
== path
|| e
[-1] != '/')
137 static int path_is_generator(const LookupPaths
*p
, const char *path
) {
138 _cleanup_free_
char *parent
= NULL
;
143 parent
= dirname_malloc(path
);
147 return path_equal_ptr(parent
, p
->generator
) ||
148 path_equal_ptr(parent
, p
->generator_early
) ||
149 path_equal_ptr(parent
, p
->generator_late
);
152 static int path_is_transient(const LookupPaths
*p
, const char *path
) {
153 _cleanup_free_
char *parent
= NULL
;
158 parent
= dirname_malloc(path
);
162 return path_equal_ptr(parent
, p
->transient
);
165 static int path_is_control(const LookupPaths
*p
, const char *path
) {
166 _cleanup_free_
char *parent
= NULL
;
171 parent
= dirname_malloc(path
);
175 return path_equal_ptr(parent
, p
->persistent_control
) ||
176 path_equal_ptr(parent
, p
->runtime_control
);
179 static int path_is_config(const LookupPaths
*p
, const char *path
, bool check_parent
) {
180 _cleanup_free_
char *parent
= NULL
;
185 /* Note that we do *not* have generic checks for /etc or /run in place, since with
186 * them we couldn't discern configuration from transient or generated units */
189 parent
= dirname_malloc(path
);
196 return path_equal_ptr(path
, p
->persistent_config
) ||
197 path_equal_ptr(path
, p
->runtime_config
);
200 static int path_is_runtime(const LookupPaths
*p
, const char *path
, bool check_parent
) {
201 _cleanup_free_
char *parent
= NULL
;
207 /* Everything in /run is considered runtime. On top of that we also add
208 * explicit checks for the various runtime directories, as safety net. */
210 rpath
= skip_root(p
, path
);
211 if (rpath
&& path_startswith(rpath
, "/run"))
215 parent
= dirname_malloc(path
);
222 return path_equal_ptr(path
, p
->runtime_config
) ||
223 path_equal_ptr(path
, p
->generator
) ||
224 path_equal_ptr(path
, p
->generator_early
) ||
225 path_equal_ptr(path
, p
->generator_late
) ||
226 path_equal_ptr(path
, p
->transient
) ||
227 path_equal_ptr(path
, p
->runtime_control
);
230 static int path_is_vendor_or_generator(const LookupPaths
*p
, const char *path
) {
236 rpath
= skip_root(p
, path
);
240 if (path_startswith(rpath
, "/usr"))
244 if (path_startswith(rpath
, "/lib"))
248 if (path_is_generator(p
, rpath
))
251 return path_equal(rpath
, SYSTEM_DATA_UNIT_DIR
);
254 static const char* config_path_from_flags(const LookupPaths
*paths
, UnitFileFlags flags
) {
257 if (FLAGS_SET(flags
, UNIT_FILE_PORTABLE
))
258 return FLAGS_SET(flags
, UNIT_FILE_RUNTIME
) ? paths
->runtime_attached
: paths
->persistent_attached
;
260 return FLAGS_SET(flags
, UNIT_FILE_RUNTIME
) ? paths
->runtime_config
: paths
->persistent_config
;
263 int unit_file_changes_add(
264 UnitFileChange
**changes
,
266 int type_or_errno
, /* UNIT_FILE_SYMLINK, _UNLINK, _IS_MASKED, _IS_DANGLING if positive or errno if negative */
268 const char *source
) {
270 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
273 assert(!changes
== !n_changes
);
275 if (type_or_errno
>= 0)
276 assert(type_or_errno
< _UNIT_FILE_CHANGE_TYPE_MAX
);
278 assert(type_or_errno
>= -ERRNO_MAX
);
283 c
= reallocarray(*changes
, *n_changes
+ 1, sizeof(UnitFileChange
));
304 c
[(*n_changes
)++] = (UnitFileChange
) {
305 .type_or_errno
= type_or_errno
,
307 .source
= TAKE_PTR(s
),
313 void unit_file_changes_free(UnitFileChange
*changes
, size_t n_changes
) {
314 assert(changes
|| n_changes
== 0);
316 for (size_t i
= 0; i
< n_changes
; i
++) {
317 free(changes
[i
].path
);
318 free(changes
[i
].source
);
324 void unit_file_dump_changes(int r
, const char *verb
, const UnitFileChange
*changes
, size_t n_changes
, bool quiet
) {
327 assert(changes
|| n_changes
== 0);
328 /* If verb is not specified, errors are not allowed! */
329 assert(verb
|| r
>= 0);
331 for (size_t i
= 0; i
< n_changes
; i
++) {
332 assert(verb
|| changes
[i
].type_or_errno
>= 0);
334 switch(changes
[i
].type_or_errno
) {
335 case UNIT_FILE_SYMLINK
:
337 log_info("Created symlink %s %s %s.",
339 special_glyph(SPECIAL_GLYPH_ARROW
),
342 case UNIT_FILE_UNLINK
:
344 log_info("Removed %s.", changes
[i
].path
);
346 case UNIT_FILE_IS_MASKED
:
348 log_info("Unit %s is masked, ignoring.", changes
[i
].path
);
350 case UNIT_FILE_IS_DANGLING
:
352 log_info("Unit %s is an alias to a unit that is not present, ignoring.",
355 case UNIT_FILE_DESTINATION_NOT_PRESENT
:
357 log_warning("Unit %s is added as a dependency to a non-existent unit %s.",
358 changes
[i
].source
, changes
[i
].path
);
360 case UNIT_FILE_AUXILIARY_FAILED
:
362 log_warning("Failed to enable auxiliary unit %s, ignoring.", changes
[i
].source
);
365 if (changes
[i
].source
)
366 log_error_errno(changes
[i
].type_or_errno
,
367 "Failed to %s unit, file %s already exists and is a symlink to %s.",
368 verb
, changes
[i
].path
, changes
[i
].source
);
370 log_error_errno(changes
[i
].type_or_errno
,
371 "Failed to %s unit, file %s already exists.",
372 verb
, changes
[i
].path
);
376 log_error_errno(changes
[i
].type_or_errno
, "Failed to %s unit, unit %s is masked.",
377 verb
, changes
[i
].path
);
381 log_error_errno(changes
[i
].type_or_errno
, "Failed to %s unit, unit %s is transient or generated.",
382 verb
, changes
[i
].path
);
386 log_error_errno(changes
[i
].type_or_errno
, "Failed to %s %s, destination unit %s is a non-template unit.",
387 verb
, changes
[i
].source
, changes
[i
].path
);
391 log_error_errno(changes
[i
].type_or_errno
,
392 "Failed to %s unit, \"%s\" is not a valid unit name.",
393 verb
, changes
[i
].path
);
397 log_error_errno(changes
[i
].type_or_errno
, "Failed to %s unit, refusing to operate on linked unit file %s",
398 verb
, changes
[i
].path
);
403 log_error_errno(changes
[i
].type_or_errno
, "Failed to %s unit, unit %s does not exist.", verb
, changes
[i
].path
);
408 assert(changes
[i
].type_or_errno
< 0);
409 log_error_errno(changes
[i
].type_or_errno
, "Failed to %s unit, file %s: %m.",
410 verb
, changes
[i
].path
);
415 if (r
< 0 && !logged
)
416 log_error_errno(r
, "Failed to %s: %m.", verb
);
420 * Checks if two paths or symlinks from wd are the same, when root is the root of the filesystem.
421 * wc should be the full path in the host file system.
423 static bool chroot_symlinks_same(const char *root
, const char *wd
, const char *a
, const char *b
) {
424 assert(path_is_absolute(wd
));
426 /* This will give incorrect results if the paths are relative and go outside
427 * of the chroot. False negatives are possible. */
432 a
= strjoina(path_is_absolute(a
) ? root
: wd
, "/", a
);
433 b
= strjoina(path_is_absolute(b
) ? root
: wd
, "/", b
);
434 return path_equal_or_files_same(a
, b
, 0);
437 static int create_symlink(
438 const LookupPaths
*paths
,
439 const char *old_path
,
440 const char *new_path
,
442 UnitFileChange
**changes
,
445 _cleanup_free_
char *dest
= NULL
, *dirname
= NULL
;
452 rp
= skip_root(paths
, old_path
);
456 /* Actually create a symlink, and remember that we did. Is
457 * smart enough to check if there's already a valid symlink in
460 * Returns 1 if a symlink was created or already exists and points to
461 * the right place, or negative on error.
464 (void) mkdir_parents_label(new_path
, 0755);
466 if (symlink(old_path
, new_path
) >= 0) {
467 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
471 if (errno
!= EEXIST
) {
472 unit_file_changes_add(changes
, n_changes
, -errno
, new_path
, NULL
);
476 r
= readlink_malloc(new_path
, &dest
);
478 /* translate EINVAL (non-symlink exists) to EEXIST */
482 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
486 dirname
= dirname_malloc(new_path
);
490 if (chroot_symlinks_same(paths
->root_dir
, dirname
, dest
, old_path
)) {
491 log_debug("Symlink %s → %s already exists", new_path
, dest
);
496 unit_file_changes_add(changes
, n_changes
, -EEXIST
, new_path
, dest
);
500 r
= symlink_atomic(old_path
, new_path
);
502 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
506 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, new_path
, NULL
);
507 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
512 static int mark_symlink_for_removal(
513 Set
**remove_symlinks_to
,
521 r
= set_ensure_allocated(remove_symlinks_to
, &path_hash_ops
);
531 r
= set_consume(*remove_symlinks_to
, n
);
540 static int remove_marked_symlinks_fd(
541 Set
*remove_symlinks_to
,
544 const char *config_path
,
545 const LookupPaths
*lp
,
548 UnitFileChange
**changes
,
551 _cleanup_closedir_
DIR *d
= NULL
;
555 assert(remove_symlinks_to
);
570 FOREACH_DIRENT(de
, d
, return -errno
) {
572 if (de
->d_type
== DT_DIR
) {
573 _cleanup_free_
char *p
= NULL
;
576 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
586 p
= path_make_absolute(de
->d_name
, path
);
592 /* This will close nfd, regardless whether it succeeds or not */
593 q
= remove_marked_symlinks_fd(remove_symlinks_to
, nfd
, p
, config_path
, lp
, dry_run
, restart
, changes
, n_changes
);
597 } else if (de
->d_type
== DT_LNK
) {
598 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
603 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
606 p
= path_make_absolute(de
->d_name
, path
);
611 q
= chase_symlinks(p
, NULL
, CHASE_NONEXISTENT
, &dest
, NULL
);
620 /* We remove all links pointing to a file or path that is marked, as well as all files sharing
621 * the same name as a file that is marked. */
623 found
= set_contains(remove_symlinks_to
, dest
) ||
624 set_contains(remove_symlinks_to
, basename(dest
)) ||
625 set_contains(remove_symlinks_to
, de
->d_name
);
631 if (unlinkat(fd
, de
->d_name
, 0) < 0 && errno
!= ENOENT
) {
634 unit_file_changes_add(changes
, n_changes
, -errno
, p
, NULL
);
638 (void) rmdir_parents(p
, config_path
);
641 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, p
, NULL
);
643 /* Now, remember the full path (but with the root prefix removed) of
644 * the symlink we just removed, and remove any symlinks to it, too. */
646 rp
= skip_root(lp
, p
);
647 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: p
);
650 if (q
> 0 && !dry_run
)
658 static int remove_marked_symlinks(
659 Set
*remove_symlinks_to
,
660 const char *config_path
,
661 const LookupPaths
*lp
,
663 UnitFileChange
**changes
,
666 _cleanup_close_
int fd
= -1;
673 if (set_size(remove_symlinks_to
) <= 0)
676 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
);
678 return errno
== ENOENT
? 0 : -errno
;
684 cfd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
688 /* This takes possession of cfd and closes it */
689 q
= remove_marked_symlinks_fd(remove_symlinks_to
, cfd
, config_path
, config_path
, lp
, dry_run
, &restart
, changes
, n_changes
);
697 static int is_symlink_with_known_name(const UnitFileInstallInfo
*i
, const char *name
) {
700 if (streq(name
, i
->name
))
703 if (strv_contains(i
->aliases
, name
))
706 /* Look for template symlink matching DefaultInstance */
707 if (i
->default_instance
&& unit_name_is_valid(i
->name
, UNIT_NAME_TEMPLATE
)) {
708 _cleanup_free_
char *s
= NULL
;
710 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &s
);
715 } else if (streq(name
, s
))
722 static int find_symlinks_in_directory(
724 const char *dir_path
,
725 const char *root_dir
,
726 const UnitFileInstallInfo
*i
,
728 bool ignore_same_name
,
729 const char *config_path
,
730 bool *same_name_link
) {
735 FOREACH_DIRENT(de
, dir
, return -errno
) {
736 _cleanup_free_
char *dest
= NULL
;
737 bool found_path
= false, found_dest
, b
= false;
740 if (de
->d_type
!= DT_LNK
)
743 /* Acquire symlink destination */
744 q
= readlinkat_malloc(dirfd(dir
), de
->d_name
, &dest
);
754 if (!path_is_absolute(dest
)) {
757 x
= path_join(dir_path
, dest
);
761 free_and_replace(dest
, x
);
764 assert(unit_name_is_valid(i
->name
, UNIT_NAME_ANY
));
765 if (!ignore_same_name
)
766 /* Check if the symlink itself matches what we are looking for.
768 * If ignore_same_name is specified, we are in one of the directories which
769 * have lower priority than the unit file, and even if a file or symlink with
770 * this name was found, we should ignore it. */
771 found_path
= streq(de
->d_name
, i
->name
);
773 /* Check if what the symlink points to matches what we are looking for */
774 found_dest
= streq(basename(dest
), i
->name
);
776 if (found_path
&& found_dest
) {
777 _cleanup_free_
char *p
= NULL
, *t
= NULL
;
779 /* Filter out same name links in the main
781 p
= path_make_absolute(de
->d_name
, dir_path
);
782 t
= path_make_absolute(i
->name
, config_path
);
787 b
= path_equal(p
, t
);
791 *same_name_link
= true;
792 else if (found_path
|| found_dest
) {
796 /* Check if symlink name is in the set of names used by [Install] */
797 q
= is_symlink_with_known_name(i
, de
->d_name
);
808 static int find_symlinks(
809 const char *root_dir
,
810 const UnitFileInstallInfo
*i
,
812 bool ignore_same_name
,
813 const char *config_path
,
814 bool *same_name_link
) {
816 _cleanup_closedir_
DIR *config_dir
= NULL
;
822 assert(same_name_link
);
824 config_dir
= opendir(config_path
);
826 if (IN_SET(errno
, ENOENT
, ENOTDIR
, EACCES
))
831 FOREACH_DIRENT(de
, config_dir
, return -errno
) {
833 _cleanup_free_
const char *path
= NULL
;
834 _cleanup_closedir_
DIR *d
= NULL
;
836 if (de
->d_type
!= DT_DIR
)
839 suffix
= strrchr(de
->d_name
, '.');
840 if (!STRPTR_IN_SET(suffix
, ".wants", ".requires"))
843 path
= path_join(config_path
, de
->d_name
);
849 log_error_errno(errno
, "Failed to open directory '%s' while scanning for symlinks, ignoring: %m", path
);
853 r
= find_symlinks_in_directory(d
, path
, root_dir
, i
, match_name
, ignore_same_name
, config_path
, same_name_link
);
857 log_debug_errno(r
, "Failed to lookup for symlinks in '%s': %m", path
);
860 /* We didn't find any suitable symlinks in .wants or .requires directories, let's look for linked unit files in this directory. */
861 rewinddir(config_dir
);
862 return find_symlinks_in_directory(config_dir
, config_path
, root_dir
, i
, match_name
, ignore_same_name
, config_path
, same_name_link
);
865 static int find_symlinks_in_scope(
867 const LookupPaths
*paths
,
868 const UnitFileInstallInfo
*i
,
870 UnitFileState
*state
) {
872 bool same_name_link_runtime
= false, same_name_link_config
= false;
873 bool enabled_in_runtime
= false, enabled_at_all
= false;
874 bool ignore_same_name
= false;
881 /* As we iterate over the list of search paths in paths->search_path, we may encounter "same name"
882 * symlinks. The ones which are "below" (i.e. have lower priority) than the unit file itself are
883 * effectively masked, so we should ignore them. */
885 STRV_FOREACH(p
, paths
->search_path
) {
886 bool same_name_link
= false;
888 r
= find_symlinks(paths
->root_dir
, i
, match_name
, ignore_same_name
, *p
, &same_name_link
);
892 /* We found symlinks in this dir? Yay! Let's see where precisely it is enabled. */
894 if (path_equal_ptr(*p
, paths
->persistent_config
)) {
895 /* This is the best outcome, let's return it immediately. */
896 *state
= UNIT_FILE_ENABLED
;
900 /* look for global enablement of user units */
901 if (scope
== UNIT_FILE_USER
&& path_is_user_config_dir(*p
)) {
902 *state
= UNIT_FILE_ENABLED
;
906 r
= path_is_runtime(paths
, *p
, false);
910 enabled_in_runtime
= true;
912 enabled_at_all
= true;
914 } else if (same_name_link
) {
915 if (path_equal_ptr(*p
, paths
->persistent_config
))
916 same_name_link_config
= true;
918 r
= path_is_runtime(paths
, *p
, false);
922 same_name_link_runtime
= true;
926 /* Check if next iteration will be "below" the unit file (either a regular file
927 * or a symlink), and hence should be ignored */
928 if (!ignore_same_name
&& path_startswith(i
->path
, *p
))
929 ignore_same_name
= true;
932 if (enabled_in_runtime
) {
933 *state
= UNIT_FILE_ENABLED_RUNTIME
;
937 /* Here's a special rule: if the unit we are looking for is an instance, and it symlinked in the search path
938 * outside of runtime and configuration directory, then we consider it statically enabled. Note we do that only
939 * for instance, not for regular names, as those are merely aliases, while instances explicitly instantiate
940 * something, and hence are a much stronger concept. */
941 if (enabled_at_all
&& unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
)) {
942 *state
= UNIT_FILE_STATIC
;
946 /* Hmm, we didn't find it, but maybe we found the same name
948 if (same_name_link_config
) {
949 *state
= UNIT_FILE_LINKED
;
952 if (same_name_link_runtime
) {
953 *state
= UNIT_FILE_LINKED_RUNTIME
;
960 static void install_info_free(UnitFileInstallInfo
*i
) {
968 strv_free(i
->aliases
);
969 strv_free(i
->wanted_by
);
970 strv_free(i
->required_by
);
972 free(i
->default_instance
);
973 free(i
->symlink_target
);
977 static void install_context_done(InstallContext
*c
) {
980 c
->will_process
= ordered_hashmap_free_with_destructor(c
->will_process
, install_info_free
);
981 c
->have_processed
= ordered_hashmap_free_with_destructor(c
->have_processed
, install_info_free
);
984 static UnitFileInstallInfo
*install_info_find(InstallContext
*c
, const char *name
) {
985 UnitFileInstallInfo
*i
;
987 i
= ordered_hashmap_get(c
->have_processed
, name
);
991 return ordered_hashmap_get(c
->will_process
, name
);
994 static int install_info_may_process(
995 const UnitFileInstallInfo
*i
,
996 const LookupPaths
*paths
,
997 UnitFileChange
**changes
,
1002 /* Checks whether the loaded unit file is one we should process, or is masked,
1003 * transient or generated and thus not subject to enable/disable operations. */
1005 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
1006 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, i
->path
, NULL
);
1009 if (path_is_generator(paths
, i
->path
) ||
1010 path_is_transient(paths
, i
->path
)) {
1011 unit_file_changes_add(changes
, n_changes
, -EADDRNOTAVAIL
, i
->path
, NULL
);
1012 return -EADDRNOTAVAIL
;
1019 * Adds a new UnitFileInstallInfo entry under name in the InstallContext.will_process
1020 * hashmap, or retrieves the existing one if already present.
1022 * Returns negative on error, 0 if the unit was already known, 1 otherwise.
1024 static int install_info_add(
1030 UnitFileInstallInfo
**ret
) {
1032 UnitFileInstallInfo
*i
= NULL
;
1038 /* 'name' and 'path' must not both be null. Check here 'path' using assert_se() to
1039 * workaround a bug in gcc that generates a -Wnonnull warning when calling basename(),
1040 * but this cannot be possible in any code path (See #6119). */
1042 name
= basename(path
);
1045 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
1048 i
= install_info_find(c
, name
);
1050 i
->auxiliary
= i
->auxiliary
&& auxiliary
;
1057 i
= new(UnitFileInstallInfo
, 1);
1061 *i
= (UnitFileInstallInfo
) {
1062 .type
= _UNIT_FILE_TYPE_INVALID
,
1063 .auxiliary
= auxiliary
,
1066 i
->name
= strdup(name
);
1073 i
->root
= strdup(root
);
1081 i
->path
= strdup(path
);
1088 r
= ordered_hashmap_ensure_put(&c
->will_process
, &string_hash_ops
, i
->name
, i
);
1098 install_info_free(i
);
1102 static int config_parse_alias(
1104 const char *filename
,
1106 const char *section
,
1107 unsigned section_line
,
1121 type
= unit_name_to_type(unit
);
1122 if (!unit_type_may_alias(type
))
1123 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1124 "Alias= is not allowed for %s units, ignoring.",
1125 unit_type_to_string(type
));
1127 return config_parse_strv(unit
, filename
, line
, section
, section_line
,
1128 lvalue
, ltype
, rvalue
, data
, userdata
);
1131 static int config_parse_also(
1133 const char *filename
,
1135 const char *section
,
1136 unsigned section_line
,
1143 UnitFileInstallInfo
*info
= userdata
;
1144 InstallContext
*c
= data
;
1153 _cleanup_free_
char *word
= NULL
, *printed
= NULL
;
1155 r
= extract_first_word(&rvalue
, &word
, NULL
, 0);
1161 r
= install_name_printf(info
, word
, info
->root
, &printed
);
1165 r
= install_info_add(c
, printed
, NULL
, info
->root
, /* auxiliary= */ true, NULL
);
1169 r
= strv_push(&info
->also
, printed
);
1179 static int config_parse_default_instance(
1181 const char *filename
,
1183 const char *section
,
1184 unsigned section_line
,
1191 UnitFileInstallInfo
*i
= data
;
1192 _cleanup_free_
char *printed
= NULL
;
1200 if (unit_name_is_valid(unit
, UNIT_NAME_INSTANCE
))
1201 /* When enabling an instance, we might be using a template unit file,
1202 * but we should ignore DefaultInstance silently. */
1204 if (!unit_name_is_valid(unit
, UNIT_NAME_TEMPLATE
))
1205 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1206 "DefaultInstance= only makes sense for template units, ignoring.");
1208 r
= install_name_printf(i
, rvalue
, i
->root
, &printed
);
1212 if (isempty(printed
)) {
1213 i
->default_instance
= mfree(i
->default_instance
);
1217 if (!unit_instance_is_valid(printed
))
1218 return log_syntax(unit
, LOG_WARNING
, filename
, line
, SYNTHETIC_ERRNO(EINVAL
),
1219 "Invalid DefaultInstance= value \"%s\".", printed
);
1221 return free_and_replace(i
->default_instance
, printed
);
1224 static int unit_file_load(
1226 UnitFileInstallInfo
*info
,
1228 const char *root_dir
,
1229 SearchFlags flags
) {
1231 const ConfigTableItem items
[] = {
1232 { "Install", "Alias", config_parse_alias
, 0, &info
->aliases
},
1233 { "Install", "WantedBy", config_parse_strv
, 0, &info
->wanted_by
},
1234 { "Install", "RequiredBy", config_parse_strv
, 0, &info
->required_by
},
1235 { "Install", "DefaultInstance", config_parse_default_instance
, 0, info
},
1236 { "Install", "Also", config_parse_also
, 0, c
},
1241 _cleanup_fclose_
FILE *f
= NULL
;
1242 _cleanup_close_
int fd
= -1;
1249 if (!(flags
& SEARCH_DROPIN
)) {
1250 /* Loading or checking for the main unit file… */
1252 type
= unit_name_to_type(info
->name
);
1255 if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
|UNIT_NAME_INSTANCE
) && !unit_type_may_template(type
))
1256 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1257 "%s: unit type %s cannot be templated, ignoring.", path
, unit_type_to_string(type
));
1259 if (!(flags
& SEARCH_LOAD
)) {
1260 if (lstat(path
, &st
) < 0)
1263 if (null_or_empty(&st
))
1264 info
->type
= UNIT_FILE_TYPE_MASKED
;
1265 else if (S_ISREG(st
.st_mode
))
1266 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1267 else if (S_ISLNK(st
.st_mode
))
1269 else if (S_ISDIR(st
.st_mode
))
1277 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
1281 /* 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. */
1283 if (!(flags
& SEARCH_LOAD
))
1286 fd
= chase_symlinks_and_open(path
, root_dir
, 0, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
, NULL
);
1291 if (fstat(fd
, &st
) < 0)
1294 if (null_or_empty(&st
)) {
1295 if ((flags
& SEARCH_DROPIN
) == 0)
1296 info
->type
= UNIT_FILE_TYPE_MASKED
;
1301 r
= stat_verify_regular(&st
);
1305 f
= take_fdopen(&fd
, "r");
1309 /* c is only needed if we actually load the file (it's referenced from items[] btw, in case you wonder.) */
1312 r
= config_parse(info
->name
, path
, f
,
1326 config_item_table_lookup
, items
,
1330 return log_debug_errno(r
, "Failed to parse %s: %m", info
->name
);
1332 if ((flags
& SEARCH_DROPIN
) == 0)
1333 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1336 (int) strv_length(info
->aliases
) +
1337 (int) strv_length(info
->wanted_by
) +
1338 (int) strv_length(info
->required_by
);
1341 static int unit_file_load_or_readlink(
1343 UnitFileInstallInfo
*info
,
1345 const char *root_dir
,
1346 SearchFlags flags
) {
1348 _cleanup_free_
char *resolved
= NULL
;
1351 r
= unit_file_load(c
, info
, path
, root_dir
, flags
);
1352 if (r
!= -ELOOP
|| (flags
& SEARCH_DROPIN
))
1355 r
= chase_symlinks(path
, root_dir
, CHASE_WARN
| CHASE_NONEXISTENT
, &resolved
, NULL
);
1358 path_equal_ptr(path_startswith(resolved
, root_dir
), "dev/null"))
1359 /* When looking under root_dir, we can't expect /dev/ to be mounted,
1360 * so let's see if the path is a (possibly dangling) symlink to /dev/null. */
1361 info
->type
= UNIT_FILE_TYPE_MASKED
;
1363 else if (r
> 0 && null_or_empty_path(resolved
) > 0)
1365 info
->type
= UNIT_FILE_TYPE_MASKED
;
1368 _cleanup_free_
char *target
= NULL
;
1372 /* This is a symlink, let's read it. We read the link again, because last time
1373 * we followed the link until resolution, and here we need to do one step. */
1375 r
= readlink_malloc(path
, &target
);
1379 bn
= basename(target
);
1381 if (unit_name_is_valid(info
->name
, UNIT_NAME_PLAIN
)) {
1383 if (!unit_name_is_valid(bn
, UNIT_NAME_PLAIN
))
1386 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1388 if (!unit_name_is_valid(bn
, UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
))
1391 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
)) {
1393 if (!unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
))
1398 /* Enforce that the symlink destination does not
1399 * change the unit file type. */
1401 a
= unit_name_to_type(info
->name
);
1402 b
= unit_name_to_type(bn
);
1403 if (a
< 0 || b
< 0 || a
!= b
)
1406 if (path_is_absolute(target
))
1407 /* This is an absolute path, prefix the root so that we always deal with fully qualified paths */
1408 info
->symlink_target
= path_join(root_dir
, target
);
1410 /* This is a relative path, take it relative to the dir the symlink is located in. */
1411 info
->symlink_target
= file_in_same_dir(path
, target
);
1412 if (!info
->symlink_target
)
1415 info
->type
= UNIT_FILE_TYPE_SYMLINK
;
1421 static int unit_file_search(
1423 UnitFileInstallInfo
*info
,
1424 const LookupPaths
*paths
,
1425 SearchFlags flags
) {
1427 const char *dropin_dir_name
= NULL
, *dropin_template_dir_name
= NULL
;
1428 _cleanup_strv_free_
char **dirs
= NULL
, **files
= NULL
;
1429 _cleanup_free_
char *template = NULL
;
1430 bool found_unit
= false;
1437 /* Was this unit already loaded? */
1438 if (info
->type
!= _UNIT_FILE_TYPE_INVALID
)
1442 return unit_file_load_or_readlink(c
, info
, info
->path
, paths
->root_dir
, flags
);
1446 if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1447 r
= unit_name_template(info
->name
, &template);
1452 STRV_FOREACH(p
, paths
->search_path
) {
1453 _cleanup_free_
char *path
= NULL
;
1455 path
= path_join(*p
, info
->name
);
1459 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1461 info
->path
= TAKE_PTR(path
);
1465 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1469 if (!found_unit
&& template) {
1471 /* Unit file doesn't exist, however instance
1472 * enablement was requested. We will check if it is
1473 * possible to load template unit file. */
1475 STRV_FOREACH(p
, paths
->search_path
) {
1476 _cleanup_free_
char *path
= NULL
;
1478 path
= path_join(*p
, template);
1482 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1484 info
->path
= TAKE_PTR(path
);
1488 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1494 return log_debug_errno(SYNTHETIC_ERRNO(ENOENT
),
1495 "Cannot find unit %s%s%s.",
1496 info
->name
, template ? " or " : "", strempty(template));
1498 if (info
->type
== UNIT_FILE_TYPE_MASKED
)
1501 /* Search for drop-in directories */
1503 dropin_dir_name
= strjoina(info
->name
, ".d");
1504 STRV_FOREACH(p
, paths
->search_path
) {
1507 path
= path_join(*p
, dropin_dir_name
);
1511 r
= strv_consume(&dirs
, path
);
1517 dropin_template_dir_name
= strjoina(template, ".d");
1518 STRV_FOREACH(p
, paths
->search_path
) {
1521 path
= path_join(*p
, dropin_template_dir_name
);
1525 r
= strv_consume(&dirs
, path
);
1531 /* Load drop-in conf files */
1533 r
= conf_files_list_strv(&files
, ".conf", NULL
, 0, (const char**) dirs
);
1535 return log_debug_errno(r
, "Failed to get list of conf files: %m");
1537 STRV_FOREACH(p
, files
) {
1538 r
= unit_file_load_or_readlink(c
, info
, *p
, paths
->root_dir
, flags
| SEARCH_DROPIN
);
1540 return log_debug_errno(r
, "Failed to load conf file %s: %m", *p
);
1546 static int install_info_follow(
1548 UnitFileInstallInfo
*i
,
1549 const char *root_dir
,
1551 bool ignore_different_name
) {
1556 if (i
->type
!= UNIT_FILE_TYPE_SYMLINK
)
1558 if (!i
->symlink_target
)
1561 /* If the basename doesn't match, the caller should add a
1562 * complete new entry for this. */
1564 if (!ignore_different_name
&& !streq(basename(i
->symlink_target
), i
->name
))
1567 free_and_replace(i
->path
, i
->symlink_target
);
1568 i
->type
= _UNIT_FILE_TYPE_INVALID
;
1570 return unit_file_load_or_readlink(c
, i
, i
->path
, root_dir
, flags
);
1574 * Search for the unit file. If the unit name is a symlink, follow the symlink to the
1575 * target, maybe more than once. Propagate the instance name if present.
1577 static int install_info_traverse(
1578 UnitFileScope scope
,
1580 const LookupPaths
*paths
,
1581 UnitFileInstallInfo
*start
,
1583 UnitFileInstallInfo
**ret
) {
1585 UnitFileInstallInfo
*i
;
1593 r
= unit_file_search(c
, start
, paths
, flags
);
1598 while (i
->type
== UNIT_FILE_TYPE_SYMLINK
) {
1599 /* Follow the symlink */
1601 if (++k
> UNIT_FILE_FOLLOW_SYMLINK_MAX
)
1604 if (!(flags
& SEARCH_FOLLOW_CONFIG_SYMLINKS
)) {
1605 r
= path_is_config(paths
, i
->path
, true);
1612 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
, false);
1614 _cleanup_free_
char *buffer
= NULL
;
1617 /* Target has a different name, create a new
1618 * install info object for that, and continue
1621 bn
= basename(i
->symlink_target
);
1623 if (unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
) &&
1624 unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
)) {
1626 _cleanup_free_
char *instance
= NULL
;
1628 r
= unit_name_to_instance(i
->name
, &instance
);
1632 r
= unit_name_replace_instance(bn
, instance
, &buffer
);
1636 if (streq(buffer
, i
->name
)) {
1638 /* We filled in the instance, and the target stayed the same? If so, then let's
1639 * honour the link as it is. */
1641 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
, true);
1651 r
= install_info_add(c
, bn
, NULL
, paths
->root_dir
, /* auxiliary= */ false, &i
);
1655 /* Try again, with the new target we found. */
1656 r
= unit_file_search(c
, i
, paths
, flags
);
1658 /* Translate error code to highlight this specific case */
1673 * Call install_info_add() with name_or_path as the path (if name_or_path starts with "/")
1674 * or the name (otherwise). root_dir is prepended to the path.
1676 static int install_info_add_auto(
1678 const LookupPaths
*paths
,
1679 const char *name_or_path
,
1680 UnitFileInstallInfo
**ret
) {
1683 assert(name_or_path
);
1685 if (path_is_absolute(name_or_path
)) {
1688 pp
= prefix_roota(paths
->root_dir
, name_or_path
);
1690 return install_info_add(c
, NULL
, pp
, paths
->root_dir
, /* auxiliary= */ false, ret
);
1692 return install_info_add(c
, name_or_path
, NULL
, paths
->root_dir
, /* auxiliary= */ false, ret
);
1695 static int install_info_discover(
1696 UnitFileScope scope
,
1698 const LookupPaths
*paths
,
1701 UnitFileInstallInfo
**ret
,
1702 UnitFileChange
**changes
,
1703 size_t *n_changes
) {
1705 UnitFileInstallInfo
*i
;
1712 r
= install_info_add_auto(c
, paths
, name
, &i
);
1714 r
= install_info_traverse(scope
, c
, paths
, i
, flags
, ret
);
1717 unit_file_changes_add(changes
, n_changes
, r
, name
, NULL
);
1721 static int install_info_discover_and_check(
1722 UnitFileScope scope
,
1724 const LookupPaths
*paths
,
1727 UnitFileInstallInfo
**ret
,
1728 UnitFileChange
**changes
,
1729 size_t *n_changes
) {
1733 r
= install_info_discover(scope
, c
, paths
, name
, flags
, ret
, changes
, n_changes
);
1737 return install_info_may_process(ret
? *ret
: NULL
, paths
, changes
, n_changes
);
1740 int unit_file_verify_alias(const UnitFileInstallInfo
*i
, const char *dst
, char **ret_dst
) {
1741 _cleanup_free_
char *dst_updated
= NULL
;
1744 /* Verify that dst is a valid either a valid alias or a valid .wants/.requires symlink for the target
1745 * unit *i. Return negative on error or if not compatible, zero on success.
1747 * ret_dst is set in cases where "instance propagation" happens, i.e. when the instance part is
1748 * inserted into dst. It is not normally set, even on success, so that the caller can easily
1749 * distinguish the case where instance propagation occurred.
1752 const char *path_alias
= strrchr(dst
, '/');
1754 /* This branch covers legacy Alias= function of creating .wants and .requires symlinks. */
1755 _cleanup_free_
char *dir
= NULL
;
1758 path_alias
++; /* skip over slash */
1760 dir
= dirname_malloc(dst
);
1764 p
= endswith(dir
, ".wants");
1766 p
= endswith(dir
, ".requires");
1768 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV
),
1769 "Invalid path \"%s\" in alias.", dir
);
1770 *p
= '\0'; /* dir should now be a unit name */
1772 UnitNameFlags type
= unit_name_classify(dir
);
1774 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV
),
1775 "Invalid unit name component \"%s\" in alias.", dir
);
1777 const bool instance_propagation
= type
== UNIT_NAME_TEMPLATE
;
1779 /* That's the name we want to use for verification. */
1780 r
= unit_symlink_name_compatible(path_alias
, i
->name
, instance_propagation
);
1782 return log_error_errno(r
, "Failed to verify alias validity: %m");
1784 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV
),
1785 "Invalid unit %s symlink %s.",
1789 /* If the symlink target has an instance set and the symlink source doesn't, we "propagate
1790 * the instance", i.e. instantiate the symlink source with the target instance. */
1791 if (unit_name_is_valid(dst
, UNIT_NAME_TEMPLATE
)) {
1792 _cleanup_free_
char *inst
= NULL
;
1794 UnitNameFlags type
= unit_name_to_instance(i
->name
, &inst
);
1796 return log_error_errno(type
, "Failed to extract instance name from %s: %m", i
->name
);
1798 if (type
== UNIT_NAME_INSTANCE
) {
1799 r
= unit_name_replace_instance(dst
, inst
, &dst_updated
);
1801 return log_error_errno(r
, "Failed to build unit name from %s+%s: %m",
1806 r
= unit_validate_alias_symlink_and_warn(dst_updated
?: dst
, i
->name
);
1812 *ret_dst
= TAKE_PTR(dst_updated
);
1816 static int install_info_symlink_alias(
1817 UnitFileInstallInfo
*i
,
1818 const LookupPaths
*paths
,
1819 const char *config_path
,
1821 UnitFileChange
**changes
,
1822 size_t *n_changes
) {
1829 assert(config_path
);
1831 STRV_FOREACH(s
, i
->aliases
) {
1832 _cleanup_free_
char *alias_path
= NULL
, *dst
= NULL
, *dst_updated
= NULL
;
1834 q
= install_path_printf(i
, *s
, i
->root
, &dst
);
1838 q
= unit_file_verify_alias(i
, dst
, &dst_updated
);
1842 alias_path
= path_make_absolute(dst_updated
?: dst
, config_path
);
1846 q
= create_symlink(paths
, i
->path
, alias_path
, force
, changes
, n_changes
);
1854 static int install_info_symlink_wants(
1855 UnitFileScope scope
,
1856 UnitFileFlags file_flags
,
1857 UnitFileInstallInfo
*i
,
1858 const LookupPaths
*paths
,
1859 const char *config_path
,
1862 UnitFileChange
**changes
,
1863 size_t *n_changes
) {
1865 _cleanup_free_
char *buf
= NULL
;
1866 UnitNameFlags valid_dst_type
= UNIT_NAME_ANY
;
1873 assert(config_path
);
1875 if (strv_isempty(list
))
1878 if (unit_name_is_valid(i
->name
, UNIT_NAME_PLAIN
| UNIT_NAME_INSTANCE
))
1879 /* Not a template unit. Use the name directly. */
1882 else if (i
->default_instance
) {
1883 UnitFileInstallInfo instance
= {
1884 .type
= _UNIT_FILE_TYPE_INVALID
,
1886 _cleanup_free_
char *path
= NULL
;
1888 /* If this is a template, and we have a default instance, use it. */
1890 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &buf
);
1894 instance
.name
= buf
;
1895 r
= unit_file_search(NULL
, &instance
, paths
, SEARCH_FOLLOW_CONFIG_SYMLINKS
);
1899 path
= TAKE_PTR(instance
.path
);
1901 if (instance
.type
== UNIT_FILE_TYPE_MASKED
) {
1902 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, path
, NULL
);
1909 /* We have a template, but no instance yet. When used with an instantiated unit, we will get
1910 * the instance from that unit. Cannot be used with non-instance units. */
1912 valid_dst_type
= UNIT_NAME_INSTANCE
| UNIT_NAME_TEMPLATE
;
1916 STRV_FOREACH(s
, list
) {
1917 _cleanup_free_
char *path
= NULL
, *dst
= NULL
;
1919 q
= install_name_printf(i
, *s
, i
->root
, &dst
);
1923 if (!unit_name_is_valid(dst
, valid_dst_type
)) {
1924 /* Generate a proper error here: EUCLEAN if the name is generally bad, EIDRM if the
1925 * template status doesn't match. If we are doing presets don't bother reporting the
1926 * error. This also covers cases like 'systemctl preset serial-getty@.service', which
1927 * has no DefaultInstance, so there is nothing we can do. At the same time,
1928 * 'systemctl enable serial-getty@.service' should fail, the user should specify an
1929 * instance like in 'systemctl enable serial-getty@ttyS0.service'.
1931 if (file_flags
& UNIT_FILE_IGNORE_AUXILIARY_FAILURE
)
1934 if (unit_name_is_valid(dst
, UNIT_NAME_ANY
)) {
1935 unit_file_changes_add(changes
, n_changes
, -EIDRM
, dst
, n
);
1938 unit_file_changes_add(changes
, n_changes
, -EUCLEAN
, dst
, NULL
);
1945 path
= strjoin(config_path
, "/", dst
, suffix
, n
);
1949 q
= create_symlink(paths
, i
->path
, path
, true, changes
, n_changes
);
1953 if (unit_file_exists(scope
, paths
, dst
) == 0)
1954 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_DESTINATION_NOT_PRESENT
, dst
, i
->path
);
1960 static int install_info_symlink_link(
1961 UnitFileInstallInfo
*i
,
1962 const LookupPaths
*paths
,
1963 const char *config_path
,
1965 UnitFileChange
**changes
,
1966 size_t *n_changes
) {
1968 _cleanup_free_
char *path
= NULL
;
1973 assert(config_path
);
1976 r
= in_search_path(paths
, i
->path
);
1982 path
= path_join(config_path
, i
->name
);
1986 return create_symlink(paths
, i
->path
, path
, force
, changes
, n_changes
);
1989 static int install_info_apply(
1990 UnitFileScope scope
,
1991 UnitFileFlags file_flags
,
1992 UnitFileInstallInfo
*i
,
1993 const LookupPaths
*paths
,
1994 const char *config_path
,
1995 UnitFileChange
**changes
,
1996 size_t *n_changes
) {
2002 assert(config_path
);
2004 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
2007 bool force
= file_flags
& UNIT_FILE_FORCE
;
2009 r
= install_info_symlink_alias(i
, paths
, config_path
, force
, changes
, n_changes
);
2011 q
= install_info_symlink_wants(scope
, file_flags
, i
, paths
, config_path
, i
->wanted_by
, ".wants/", changes
, n_changes
);
2015 q
= install_info_symlink_wants(scope
, file_flags
, i
, paths
, config_path
, i
->required_by
, ".requires/", changes
, n_changes
);
2019 q
= install_info_symlink_link(i
, paths
, config_path
, force
, changes
, n_changes
);
2020 /* Do not count links to the unit file towards the "carries_install_info" count */
2021 if (r
== 0 && q
< 0)
2027 static int install_context_apply(
2028 UnitFileScope scope
,
2029 UnitFileFlags file_flags
,
2031 const LookupPaths
*paths
,
2032 const char *config_path
,
2034 UnitFileChange
**changes
,
2035 size_t *n_changes
) {
2037 UnitFileInstallInfo
*i
;
2042 assert(config_path
);
2044 if (ordered_hashmap_isempty(c
->will_process
))
2047 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
2052 while ((i
= ordered_hashmap_first(c
->will_process
))) {
2055 q
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
2059 q
= install_info_traverse(scope
, c
, paths
, i
, flags
, NULL
);
2062 q
= unit_file_changes_add(changes
, n_changes
, UNIT_FILE_AUXILIARY_FAILED
, NULL
, i
->name
);
2068 unit_file_changes_add(changes
, n_changes
, q
, i
->name
, NULL
);
2072 /* We can attempt to process a masked unit when a different unit
2073 * that we were processing specifies it in Also=. */
2074 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
2075 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_MASKED
, i
->path
, NULL
);
2077 /* Assume that something *could* have been enabled here,
2078 * avoid "empty [Install] section" warning. */
2083 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
2086 q
= install_info_apply(scope
, file_flags
, i
, paths
, config_path
, changes
, n_changes
);
2098 static int install_context_mark_for_removal(
2099 UnitFileScope scope
,
2101 const LookupPaths
*paths
,
2102 Set
**remove_symlinks_to
,
2103 const char *config_path
,
2104 UnitFileChange
**changes
,
2105 size_t *n_changes
) {
2107 UnitFileInstallInfo
*i
;
2112 assert(config_path
);
2114 /* Marks all items for removal */
2116 if (ordered_hashmap_isempty(c
->will_process
))
2119 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
2123 while ((i
= ordered_hashmap_first(c
->will_process
))) {
2125 r
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
2129 r
= install_info_traverse(scope
, c
, paths
, i
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, NULL
);
2130 if (r
== -ENOLINK
) {
2131 log_debug_errno(r
, "Name %s leads to a dangling symlink, removing name.", i
->name
);
2132 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_DANGLING
, i
->path
?: i
->name
, NULL
);
2133 } else if (r
== -ENOENT
) {
2135 if (i
->auxiliary
) /* some unit specified in Also= or similar is missing */
2136 log_debug_errno(r
, "Auxiliary unit of %s not found, removing name.", i
->name
);
2138 log_debug_errno(r
, "Unit %s not found, removing name.", i
->name
);
2139 unit_file_changes_add(changes
, n_changes
, r
, i
->path
?: i
->name
, NULL
);
2143 log_debug_errno(r
, "Failed to find unit %s, removing name: %m", i
->name
);
2144 unit_file_changes_add(changes
, n_changes
, r
, i
->path
?: i
->name
, NULL
);
2145 } else if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
2146 log_debug("Unit file %s is masked, ignoring.", i
->name
);
2147 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_MASKED
, i
->path
?: i
->name
, NULL
);
2149 } else if (i
->type
!= UNIT_FILE_TYPE_REGULAR
) {
2150 log_debug("Unit %s has type %s, ignoring.", i
->name
, unit_file_type_to_string(i
->type
) ?: "invalid");
2154 r
= mark_symlink_for_removal(remove_symlinks_to
, i
->name
);
2163 UnitFileScope scope
,
2164 UnitFileFlags flags
,
2165 const char *root_dir
,
2167 UnitFileChange
**changes
,
2168 size_t *n_changes
) {
2170 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2171 const char *config_path
;
2176 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2178 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2182 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2186 STRV_FOREACH(i
, files
) {
2187 _cleanup_free_
char *path
= NULL
;
2190 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
)) {
2196 path
= path_make_absolute(*i
, config_path
);
2200 q
= create_symlink(&paths
, "/dev/null", path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2201 if (q
< 0 && r
>= 0)
2208 int unit_file_unmask(
2209 UnitFileScope scope
,
2210 UnitFileFlags flags
,
2211 const char *root_dir
,
2213 UnitFileChange
**changes
,
2214 size_t *n_changes
) {
2216 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2217 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2218 _cleanup_strv_free_
char **todo
= NULL
;
2219 const char *config_path
;
2226 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2228 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2232 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2236 dry_run
= !!(flags
& UNIT_FILE_DRY_RUN
);
2238 STRV_FOREACH(i
, files
) {
2239 _cleanup_free_
char *path
= NULL
;
2241 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2244 path
= path_make_absolute(*i
, config_path
);
2248 r
= null_or_empty_path(path
);
2256 if (!GREEDY_REALLOC0(todo
, n_todo
+ 2))
2259 todo
[n_todo
] = strdup(*i
);
2269 STRV_FOREACH(i
, todo
) {
2270 _cleanup_free_
char *path
= NULL
;
2273 path
= path_make_absolute(*i
, config_path
);
2277 if (!dry_run
&& unlink(path
) < 0) {
2278 if (errno
!= ENOENT
) {
2281 unit_file_changes_add(changes
, n_changes
, -errno
, path
, NULL
);
2287 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
2289 rp
= skip_root(&paths
, path
);
2290 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: path
);
2295 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, dry_run
, changes
, n_changes
);
2303 UnitFileScope scope
,
2304 UnitFileFlags flags
,
2305 const char *root_dir
,
2307 UnitFileChange
**changes
,
2308 size_t *n_changes
) {
2310 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2311 _cleanup_strv_free_
char **todo
= NULL
;
2312 const char *config_path
;
2318 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2320 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2324 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2328 STRV_FOREACH(i
, files
) {
2329 _cleanup_free_
char *full
= NULL
;
2333 if (!path_is_absolute(*i
))
2337 if (!unit_name_is_valid(fn
, UNIT_NAME_ANY
))
2340 full
= path_join(paths
.root_dir
, *i
);
2344 if (lstat(full
, &st
) < 0)
2346 r
= stat_verify_regular(&st
);
2350 q
= in_search_path(&paths
, *i
);
2356 if (!GREEDY_REALLOC0(todo
, n_todo
+ 2))
2359 todo
[n_todo
] = strdup(*i
);
2369 STRV_FOREACH(i
, todo
) {
2370 _cleanup_free_
char *new_path
= NULL
;
2372 new_path
= path_make_absolute(basename(*i
), config_path
);
2376 q
= create_symlink(&paths
, *i
, new_path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2377 if (q
< 0 && r
>= 0)
2384 static int path_shall_revert(const LookupPaths
*paths
, const char *path
) {
2390 /* Checks whether the path is one where the drop-in directories shall be removed. */
2392 r
= path_is_config(paths
, path
, true);
2396 r
= path_is_control(paths
, path
);
2400 return path_is_transient(paths
, path
);
2403 int unit_file_revert(
2404 UnitFileScope scope
,
2405 const char *root_dir
,
2407 UnitFileChange
**changes
,
2408 size_t *n_changes
) {
2410 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2411 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2412 _cleanup_strv_free_
char **todo
= NULL
;
2417 /* Puts a unit file back into vendor state. This means:
2419 * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and
2420 * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated").
2422 * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in
2423 * "config", but not in "transient" or "control" or even "generated").
2425 * We remove all that in both the runtime and the persistent directories, if that applies.
2428 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2432 STRV_FOREACH(i
, files
) {
2433 bool has_vendor
= false;
2436 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2439 STRV_FOREACH(p
, paths
.search_path
) {
2440 _cleanup_free_
char *path
= NULL
, *dropin
= NULL
;
2443 path
= path_make_absolute(*i
, *p
);
2447 r
= lstat(path
, &st
);
2449 if (errno
!= ENOENT
)
2451 } else if (S_ISREG(st
.st_mode
)) {
2452 /* Check if there's a vendor version */
2453 r
= path_is_vendor_or_generator(&paths
, path
);
2460 dropin
= strjoin(path
, ".d");
2464 r
= lstat(dropin
, &st
);
2466 if (errno
!= ENOENT
)
2468 } else if (S_ISDIR(st
.st_mode
)) {
2469 /* Remove the drop-ins */
2470 r
= path_shall_revert(&paths
, dropin
);
2474 if (!GREEDY_REALLOC0(todo
, n_todo
+ 2))
2477 todo
[n_todo
++] = TAKE_PTR(dropin
);
2485 /* OK, there's a vendor version, hence drop all configuration versions */
2486 STRV_FOREACH(p
, paths
.search_path
) {
2487 _cleanup_free_
char *path
= NULL
;
2490 path
= path_make_absolute(*i
, *p
);
2494 r
= lstat(path
, &st
);
2496 if (errno
!= ENOENT
)
2498 } else if (S_ISREG(st
.st_mode
) || S_ISLNK(st
.st_mode
)) {
2499 r
= path_is_config(&paths
, path
, true);
2503 if (!GREEDY_REALLOC0(todo
, n_todo
+ 2))
2506 todo
[n_todo
++] = TAKE_PTR(path
);
2515 STRV_FOREACH(i
, todo
) {
2516 _cleanup_strv_free_
char **fs
= NULL
;
2520 (void) get_files_in_directory(*i
, &fs
);
2522 q
= rm_rf(*i
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
2523 if (q
< 0 && q
!= -ENOENT
&& r
>= 0) {
2528 STRV_FOREACH(j
, fs
) {
2529 _cleanup_free_
char *t
= NULL
;
2531 t
= path_join(*i
, *j
);
2535 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, t
, NULL
);
2538 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, *i
, NULL
);
2540 rp
= skip_root(&paths
, *i
);
2541 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: *i
);
2546 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.runtime_config
, &paths
, false, changes
, n_changes
);
2550 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.persistent_config
, &paths
, false, changes
, n_changes
);
2557 int unit_file_add_dependency(
2558 UnitFileScope scope
,
2559 UnitFileFlags file_flags
,
2560 const char *root_dir
,
2564 UnitFileChange
**changes
,
2565 size_t *n_changes
) {
2567 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2568 _cleanup_(install_context_done
) InstallContext c
= {};
2569 UnitFileInstallInfo
*i
, *target_info
;
2570 const char *config_path
;
2575 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2578 if (!IN_SET(dep
, UNIT_WANTS
, UNIT_REQUIRES
))
2581 if (!unit_name_is_valid(target
, UNIT_NAME_ANY
))
2584 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2588 config_path
= (file_flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2592 r
= install_info_discover_and_check(scope
, &c
, &paths
, target
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2593 &target_info
, changes
, n_changes
);
2597 assert(target_info
->type
== UNIT_FILE_TYPE_REGULAR
);
2599 STRV_FOREACH(f
, files
) {
2602 r
= install_info_discover_and_check(scope
, &c
, &paths
, *f
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2603 &i
, changes
, n_changes
);
2607 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2609 /* We didn't actually load anything from the unit
2610 * file, but instead just add in our new symlink to
2613 if (dep
== UNIT_WANTS
)
2616 l
= &i
->required_by
;
2619 *l
= strv_new(target_info
->name
);
2624 return install_context_apply(scope
, file_flags
, &c
, &paths
, config_path
,
2625 SEARCH_FOLLOW_CONFIG_SYMLINKS
, changes
, n_changes
);
2628 int unit_file_enable(
2629 UnitFileScope scope
,
2630 UnitFileFlags file_flags
,
2631 const char *root_dir
,
2633 UnitFileChange
**changes
,
2634 size_t *n_changes
) {
2636 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2637 _cleanup_(install_context_done
) InstallContext c
= {};
2638 const char *config_path
;
2639 UnitFileInstallInfo
*i
;
2644 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2646 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2650 config_path
= config_path_from_flags(&paths
, file_flags
);
2654 STRV_FOREACH(f
, files
) {
2655 r
= install_info_discover_and_check(scope
, &c
, &paths
, *f
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2656 &i
, changes
, n_changes
);
2660 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2663 /* This will return the number of symlink rules that were
2664 supposed to be created, not the ones actually created. This
2665 is useful to determine whether the passed files had any
2666 installation data at all. */
2668 return install_context_apply(scope
, file_flags
, &c
, &paths
, config_path
, SEARCH_LOAD
, changes
, n_changes
);
2671 int unit_file_disable(
2672 UnitFileScope scope
,
2673 UnitFileFlags flags
,
2674 const char *root_dir
,
2676 UnitFileChange
**changes
,
2677 size_t *n_changes
) {
2679 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2680 _cleanup_(install_context_done
) InstallContext c
= {};
2681 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2682 const char *config_path
;
2687 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2689 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2693 config_path
= config_path_from_flags(&paths
, flags
);
2697 STRV_FOREACH(i
, files
) {
2698 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2701 r
= install_info_add(&c
, *i
, NULL
, paths
.root_dir
, /* auxiliary= */ false, NULL
);
2706 r
= install_context_mark_for_removal(scope
, &c
, &paths
, &remove_symlinks_to
, config_path
, changes
, n_changes
);
2710 return remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, !!(flags
& UNIT_FILE_DRY_RUN
), changes
, n_changes
);
2713 int unit_file_reenable(
2714 UnitFileScope scope
,
2715 UnitFileFlags flags
,
2716 const char *root_dir
,
2718 UnitFileChange
**changes
,
2719 size_t *n_changes
) {
2725 /* First, we invoke the disable command with only the basename... */
2726 l
= strv_length(files
);
2727 n
= newa(char*, l
+1);
2728 for (i
= 0; i
< l
; i
++)
2729 n
[i
] = basename(files
[i
]);
2732 r
= unit_file_disable(scope
, flags
, root_dir
, n
, changes
, n_changes
);
2736 /* But the enable command with the full name */
2737 return unit_file_enable(scope
, flags
, root_dir
, files
, changes
, n_changes
);
2740 int unit_file_set_default(
2741 UnitFileScope scope
,
2742 UnitFileFlags flags
,
2743 const char *root_dir
,
2745 UnitFileChange
**changes
,
2746 size_t *n_changes
) {
2748 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2749 _cleanup_(install_context_done
) InstallContext c
= {};
2750 UnitFileInstallInfo
*i
;
2751 const char *new_path
;
2755 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2758 if (unit_name_to_type(name
) != UNIT_TARGET
) /* this also validates the name */
2760 if (streq(name
, SPECIAL_DEFAULT_TARGET
))
2763 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2767 r
= install_info_discover_and_check(scope
, &c
, &paths
, name
, 0, &i
, changes
, n_changes
);
2771 new_path
= strjoina(paths
.persistent_config
, "/" SPECIAL_DEFAULT_TARGET
);
2772 return create_symlink(&paths
, i
->path
, new_path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2775 int unit_file_get_default(
2776 UnitFileScope scope
,
2777 const char *root_dir
,
2780 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2781 _cleanup_(install_context_done
) InstallContext c
= {};
2782 UnitFileInstallInfo
*i
;
2787 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2790 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2794 r
= install_info_discover(scope
, &c
, &paths
, SPECIAL_DEFAULT_TARGET
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2798 r
= install_info_may_process(i
, &paths
, NULL
, 0);
2802 n
= strdup(i
->name
);
2810 int unit_file_lookup_state(
2811 UnitFileScope scope
,
2812 const LookupPaths
*paths
,
2814 UnitFileState
*ret
) {
2816 _cleanup_(install_context_done
) InstallContext c
= {};
2817 UnitFileInstallInfo
*i
;
2818 UnitFileState state
;
2824 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2827 r
= install_info_discover(scope
, &c
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2830 return log_debug_errno(r
, "Failed to discover unit %s: %m", name
);
2832 assert(IN_SET(i
->type
, UNIT_FILE_TYPE_REGULAR
, UNIT_FILE_TYPE_MASKED
));
2833 log_debug("Found unit %s at %s (%s)", name
, strna(i
->path
),
2834 i
->type
== UNIT_FILE_TYPE_REGULAR
? "regular file" : "mask");
2836 /* Shortcut things, if the caller just wants to know if this unit exists. */
2842 case UNIT_FILE_TYPE_MASKED
:
2843 r
= path_is_runtime(paths
, i
->path
, true);
2847 state
= r
> 0 ? UNIT_FILE_MASKED_RUNTIME
: UNIT_FILE_MASKED
;
2850 case UNIT_FILE_TYPE_REGULAR
:
2851 /* Check if the name we were querying is actually an alias */
2852 if (!streq(name
, basename(i
->path
)) && !unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
)) {
2853 state
= UNIT_FILE_ALIAS
;
2857 r
= path_is_generator(paths
, i
->path
);
2861 state
= UNIT_FILE_GENERATED
;
2865 r
= path_is_transient(paths
, i
->path
);
2869 state
= UNIT_FILE_TRANSIENT
;
2873 /* Check if any of the Alias= symlinks have been created.
2874 * We ignore other aliases, and only check those that would
2875 * be created by systemctl enable for this unit. */
2876 r
= find_symlinks_in_scope(scope
, paths
, i
, true, &state
);
2882 /* Check if the file is known under other names. If it is,
2883 * it might be in use. Report that as UNIT_FILE_INDIRECT. */
2884 r
= find_symlinks_in_scope(scope
, paths
, i
, false, &state
);
2888 state
= UNIT_FILE_INDIRECT
;
2890 if (unit_file_install_info_has_rules(i
))
2891 state
= UNIT_FILE_DISABLED
;
2892 else if (unit_file_install_info_has_also(i
))
2893 state
= UNIT_FILE_INDIRECT
;
2895 state
= UNIT_FILE_STATIC
;
2901 assert_not_reached();
2908 int unit_file_get_state(
2909 UnitFileScope scope
,
2910 const char *root_dir
,
2912 UnitFileState
*ret
) {
2914 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2918 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2921 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2925 return unit_file_lookup_state(scope
, &paths
, name
, ret
);
2928 int unit_file_exists(UnitFileScope scope
, const LookupPaths
*paths
, const char *name
) {
2929 _cleanup_(install_context_done
) InstallContext c
= {};
2935 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2938 r
= install_info_discover(scope
, &c
, paths
, name
, 0, NULL
, NULL
, NULL
);
2947 static int split_pattern_into_name_and_instances(const char *pattern
, char **out_unit_name
, char ***out_instances
) {
2948 _cleanup_strv_free_
char **instances
= NULL
;
2949 _cleanup_free_
char *unit_name
= NULL
;
2953 assert(out_instances
);
2954 assert(out_unit_name
);
2956 r
= extract_first_word(&pattern
, &unit_name
, NULL
, EXTRACT_RETAIN_ESCAPE
);
2960 /* We handle the instances logic when unit name is extracted */
2962 /* We only create instances when a rule of templated unit
2963 * is seen. A rule like enable foo@.service a b c will
2964 * result in an array of (a, b, c) as instance names */
2965 if (!unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
))
2968 instances
= strv_split(pattern
, WHITESPACE
);
2972 *out_instances
= TAKE_PTR(instances
);
2975 *out_unit_name
= TAKE_PTR(unit_name
);
2980 static int presets_find_config(UnitFileScope scope
, const char *root_dir
, char ***files
) {
2981 static const char* const system_dirs
[] = {CONF_PATHS("systemd/system-preset"), NULL
};
2982 static const char* const user_dirs
[] = {CONF_PATHS_USR("systemd/user-preset"), NULL
};
2983 const char* const* dirs
;
2986 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2988 if (scope
== UNIT_FILE_SYSTEM
)
2990 else if (IN_SET(scope
, UNIT_FILE_GLOBAL
, UNIT_FILE_USER
))
2993 assert_not_reached();
2995 return conf_files_list_strv(files
, ".preset", root_dir
, 0, dirs
);
2998 static int read_presets(UnitFileScope scope
, const char *root_dir
, UnitFilePresets
*presets
) {
2999 _cleanup_(unit_file_presets_freep
) UnitFilePresets ps
= {};
3000 _cleanup_strv_free_
char **files
= NULL
;
3005 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3008 r
= presets_find_config(scope
, root_dir
, &files
);
3012 STRV_FOREACH(p
, files
) {
3013 _cleanup_fclose_
FILE *f
= NULL
;
3016 f
= fopen(*p
, "re");
3018 if (errno
== ENOENT
)
3025 _cleanup_free_
char *line
= NULL
;
3026 UnitFilePresetRule rule
= {};
3027 const char *parameter
;
3030 r
= read_line(f
, LONG_LINE_MAX
, &line
);
3041 if (strchr(COMMENTS
, *l
))
3044 parameter
= first_word(l
, "enable");
3047 char **instances
= NULL
;
3049 /* Unit_name will remain the same as parameter when no instances are specified */
3050 r
= split_pattern_into_name_and_instances(parameter
, &unit_name
, &instances
);
3052 log_syntax(NULL
, LOG_WARNING
, *p
, n
, r
, "Couldn't parse line '%s'. Ignoring.", line
);
3056 rule
= (UnitFilePresetRule
) {
3057 .pattern
= unit_name
,
3058 .action
= PRESET_ENABLE
,
3059 .instances
= instances
,
3063 parameter
= first_word(l
, "disable");
3067 pattern
= strdup(parameter
);
3071 rule
= (UnitFilePresetRule
) {
3073 .action
= PRESET_DISABLE
,
3078 if (!GREEDY_REALLOC(ps
.rules
, ps
.n_rules
+ 1))
3081 ps
.rules
[ps
.n_rules
++] = rule
;
3085 log_syntax(NULL
, LOG_WARNING
, *p
, n
, 0, "Couldn't parse line '%s'. Ignoring.", line
);
3089 ps
.initialized
= true;
3091 ps
= (UnitFilePresets
){};
3096 static int pattern_match_multiple_instances(
3097 const UnitFilePresetRule rule
,
3098 const char *unit_name
,
3101 _cleanup_free_
char *templated_name
= NULL
;
3104 /* If no ret is needed or the rule itself does not have instances
3105 * initialized, we return not matching */
3106 if (!ret
|| !rule
.instances
)
3109 r
= unit_name_template(unit_name
, &templated_name
);
3112 if (!streq(rule
.pattern
, templated_name
))
3115 /* Compose a list of specified instances when unit name is a template */
3116 if (unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
3117 _cleanup_strv_free_
char **out_strv
= NULL
;
3120 STRV_FOREACH(iter
, rule
.instances
) {
3121 _cleanup_free_
char *name
= NULL
;
3123 r
= unit_name_replace_instance(unit_name
, *iter
, &name
);
3127 r
= strv_consume(&out_strv
, TAKE_PTR(name
));
3132 *ret
= TAKE_PTR(out_strv
);
3135 /* We now know the input unit name is an instance name */
3136 _cleanup_free_
char *instance_name
= NULL
;
3138 r
= unit_name_to_instance(unit_name
, &instance_name
);
3142 if (strv_find(rule
.instances
, instance_name
))
3148 static int query_presets(const char *name
, const UnitFilePresets
*presets
, char ***instance_name_list
) {
3149 PresetAction action
= PRESET_UNKNOWN
;
3151 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
3154 for (size_t i
= 0; i
< presets
->n_rules
; i
++)
3155 if (pattern_match_multiple_instances(presets
->rules
[i
], name
, instance_name_list
) > 0 ||
3156 fnmatch(presets
->rules
[i
].pattern
, name
, FNM_NOESCAPE
) == 0) {
3157 action
= presets
->rules
[i
].action
;
3162 case PRESET_UNKNOWN
:
3163 log_debug("Preset files don't specify rule for %s. Enabling.", name
);
3166 if (instance_name_list
&& *instance_name_list
) {
3168 STRV_FOREACH(s
, *instance_name_list
)
3169 log_debug("Preset files say enable %s.", *s
);
3171 log_debug("Preset files say enable %s.", name
);
3173 case PRESET_DISABLE
:
3174 log_debug("Preset files say disable %s.", name
);
3177 assert_not_reached();
3181 int unit_file_query_preset(UnitFileScope scope
, const char *root_dir
, const char *name
, UnitFilePresets
*cached
) {
3182 _cleanup_(unit_file_presets_freep
) UnitFilePresets tmp
= {};
3187 if (!cached
->initialized
) {
3188 r
= read_presets(scope
, root_dir
, cached
);
3193 return query_presets(name
, cached
, NULL
);
3196 static int execute_preset(
3197 UnitFileScope scope
,
3198 UnitFileFlags file_flags
,
3199 InstallContext
*plus
,
3200 InstallContext
*minus
,
3201 const LookupPaths
*paths
,
3202 const char *config_path
,
3204 UnitFilePresetMode mode
,
3205 UnitFileChange
**changes
,
3206 size_t *n_changes
) {
3213 assert(config_path
);
3215 if (mode
!= UNIT_FILE_PRESET_ENABLE_ONLY
) {
3216 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
3218 r
= install_context_mark_for_removal(scope
, minus
, paths
, &remove_symlinks_to
, config_path
, changes
, n_changes
);
3222 r
= remove_marked_symlinks(remove_symlinks_to
, config_path
, paths
, false, changes
, n_changes
);
3226 if (mode
!= UNIT_FILE_PRESET_DISABLE_ONLY
) {
3229 /* Returns number of symlinks that where supposed to be installed. */
3230 q
= install_context_apply(scope
,
3231 file_flags
| UNIT_FILE_IGNORE_AUXILIARY_FAILURE
,
3232 plus
, paths
, config_path
, SEARCH_LOAD
, changes
, n_changes
);
3244 static int preset_prepare_one(
3245 UnitFileScope scope
,
3246 InstallContext
*plus
,
3247 InstallContext
*minus
,
3250 const UnitFilePresets
*presets
,
3251 UnitFileChange
**changes
,
3252 size_t *n_changes
) {
3254 _cleanup_(install_context_done
) InstallContext tmp
= {};
3255 _cleanup_strv_free_
char **instance_name_list
= NULL
;
3256 UnitFileInstallInfo
*i
;
3259 if (install_info_find(plus
, name
) || install_info_find(minus
, name
))
3262 r
= install_info_discover(scope
, &tmp
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3263 &i
, changes
, n_changes
);
3266 if (!streq(name
, i
->name
)) {
3267 log_debug("Skipping %s because it is an alias for %s.", name
, i
->name
);
3271 r
= query_presets(name
, presets
, &instance_name_list
);
3276 if (instance_name_list
) {
3278 STRV_FOREACH(s
, instance_name_list
) {
3279 r
= install_info_discover_and_check(scope
, plus
, paths
, *s
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3280 &i
, changes
, n_changes
);
3285 r
= install_info_discover_and_check(scope
, plus
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3286 &i
, changes
, n_changes
);
3292 r
= install_info_discover(scope
, minus
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3293 &i
, changes
, n_changes
);
3298 int unit_file_preset(
3299 UnitFileScope scope
,
3300 UnitFileFlags file_flags
,
3301 const char *root_dir
,
3303 UnitFilePresetMode mode
,
3304 UnitFileChange
**changes
,
3305 size_t *n_changes
) {
3307 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
3308 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3309 _cleanup_(unit_file_presets_freep
) UnitFilePresets presets
= {};
3310 const char *config_path
;
3315 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3316 assert(mode
< _UNIT_FILE_PRESET_MAX
);
3318 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3322 config_path
= (file_flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
3326 r
= read_presets(scope
, root_dir
, &presets
);
3330 STRV_FOREACH(i
, files
) {
3331 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, *i
, &presets
, changes
, n_changes
);
3336 return execute_preset(scope
, file_flags
, &plus
, &minus
, &paths
, config_path
, files
, mode
, changes
, n_changes
);
3339 int unit_file_preset_all(
3340 UnitFileScope scope
,
3341 UnitFileFlags file_flags
,
3342 const char *root_dir
,
3343 UnitFilePresetMode mode
,
3344 UnitFileChange
**changes
,
3345 size_t *n_changes
) {
3347 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
3348 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3349 _cleanup_(unit_file_presets_freep
) UnitFilePresets presets
= {};
3350 const char *config_path
= NULL
;
3355 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3356 assert(mode
< _UNIT_FILE_PRESET_MAX
);
3358 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3362 config_path
= (file_flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
3366 r
= read_presets(scope
, root_dir
, &presets
);
3370 STRV_FOREACH(i
, paths
.search_path
) {
3371 _cleanup_closedir_
DIR *d
= NULL
;
3376 if (errno
== ENOENT
)
3382 FOREACH_DIRENT(de
, d
, return -errno
) {
3384 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
3387 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
3390 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, de
->d_name
, &presets
, changes
, n_changes
);
3392 !IN_SET(r
, -EEXIST
, -ERFKILL
, -EADDRNOTAVAIL
, -EIDRM
, -EUCLEAN
, -ELOOP
, -ENOENT
))
3393 /* Ignore generated/transient/missing/invalid units when applying preset, propagate other errors.
3394 * Coordinate with unit_file_dump_changes() above. */
3399 return execute_preset(scope
, file_flags
, &plus
, &minus
, &paths
, config_path
, NULL
, mode
, changes
, n_changes
);
3402 static UnitFileList
* unit_file_list_free_one(UnitFileList
*f
) {
3410 Hashmap
* unit_file_list_free(Hashmap
*h
) {
3411 return hashmap_free_with_destructor(h
, unit_file_list_free_one
);
3414 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList
*, unit_file_list_free_one
);
3416 int unit_file_get_list(
3417 UnitFileScope scope
,
3418 const char *root_dir
,
3423 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3428 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3431 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3435 STRV_FOREACH(dirname
, paths
.search_path
) {
3436 _cleanup_closedir_
DIR *d
= NULL
;
3439 d
= opendir(*dirname
);
3441 if (errno
== ENOENT
)
3443 if (IN_SET(errno
, ENOTDIR
, EACCES
)) {
3444 log_debug_errno(errno
, "Failed to open \"%s\": %m", *dirname
);
3451 FOREACH_DIRENT(de
, d
, return -errno
) {
3452 _cleanup_(unit_file_list_free_onep
) UnitFileList
*f
= NULL
;
3454 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
3457 if (!strv_fnmatch_or_empty(patterns
, de
->d_name
, FNM_NOESCAPE
))
3460 if (hashmap_get(h
, de
->d_name
))
3463 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
3466 f
= new0(UnitFileList
, 1);
3470 f
->path
= path_make_absolute(de
->d_name
, *dirname
);
3474 r
= unit_file_lookup_state(scope
, &paths
, de
->d_name
, &f
->state
);
3476 f
->state
= UNIT_FILE_BAD
;
3478 if (!strv_isempty(states
) &&
3479 !strv_contains(states
, unit_file_state_to_string(f
->state
)))
3482 r
= hashmap_put(h
, basename(f
->path
), f
);
3486 f
= NULL
; /* prevent cleanup */
3493 static const char* const unit_file_state_table
[_UNIT_FILE_STATE_MAX
] = {
3494 [UNIT_FILE_ENABLED
] = "enabled",
3495 [UNIT_FILE_ENABLED_RUNTIME
] = "enabled-runtime",
3496 [UNIT_FILE_LINKED
] = "linked",
3497 [UNIT_FILE_LINKED_RUNTIME
] = "linked-runtime",
3498 [UNIT_FILE_ALIAS
] = "alias",
3499 [UNIT_FILE_MASKED
] = "masked",
3500 [UNIT_FILE_MASKED_RUNTIME
] = "masked-runtime",
3501 [UNIT_FILE_STATIC
] = "static",
3502 [UNIT_FILE_DISABLED
] = "disabled",
3503 [UNIT_FILE_INDIRECT
] = "indirect",
3504 [UNIT_FILE_GENERATED
] = "generated",
3505 [UNIT_FILE_TRANSIENT
] = "transient",
3506 [UNIT_FILE_BAD
] = "bad",
3509 DEFINE_STRING_TABLE_LOOKUP(unit_file_state
, UnitFileState
);
3511 static const char* const unit_file_change_type_table
[_UNIT_FILE_CHANGE_TYPE_MAX
] = {
3512 [UNIT_FILE_SYMLINK
] = "symlink",
3513 [UNIT_FILE_UNLINK
] = "unlink",
3514 [UNIT_FILE_IS_MASKED
] = "masked",
3515 [UNIT_FILE_IS_DANGLING
] = "dangling",
3516 [UNIT_FILE_DESTINATION_NOT_PRESENT
] = "destination not present",
3517 [UNIT_FILE_AUXILIARY_FAILED
] = "auxiliary unit failed",
3520 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type
, int);
3522 static const char* const unit_file_preset_mode_table
[_UNIT_FILE_PRESET_MAX
] = {
3523 [UNIT_FILE_PRESET_FULL
] = "full",
3524 [UNIT_FILE_PRESET_ENABLE_ONLY
] = "enable-only",
3525 [UNIT_FILE_PRESET_DISABLE_ONLY
] = "disable-only",
3528 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode
, UnitFilePresetMode
);