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 dirent_ensure_type(d
, de
);
573 if (de
->d_type
== DT_DIR
) {
574 _cleanup_free_
char *p
= NULL
;
577 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
587 p
= path_make_absolute(de
->d_name
, path
);
593 /* This will close nfd, regardless whether it succeeds or not */
594 q
= remove_marked_symlinks_fd(remove_symlinks_to
, nfd
, p
, config_path
, lp
, dry_run
, restart
, changes
, n_changes
);
598 } else if (de
->d_type
== DT_LNK
) {
599 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
604 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
607 p
= path_make_absolute(de
->d_name
, path
);
612 q
= chase_symlinks(p
, NULL
, CHASE_NONEXISTENT
, &dest
, NULL
);
621 /* We remove all links pointing to a file or path that is marked, as well as all files sharing
622 * the same name as a file that is marked. */
624 found
= set_contains(remove_symlinks_to
, dest
) ||
625 set_contains(remove_symlinks_to
, basename(dest
)) ||
626 set_contains(remove_symlinks_to
, de
->d_name
);
632 if (unlinkat(fd
, de
->d_name
, 0) < 0 && errno
!= ENOENT
) {
635 unit_file_changes_add(changes
, n_changes
, -errno
, p
, NULL
);
639 (void) rmdir_parents(p
, config_path
);
642 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, p
, NULL
);
644 /* Now, remember the full path (but with the root prefix removed) of
645 * the symlink we just removed, and remove any symlinks to it, too. */
647 rp
= skip_root(lp
, p
);
648 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: p
);
651 if (q
> 0 && !dry_run
)
659 static int remove_marked_symlinks(
660 Set
*remove_symlinks_to
,
661 const char *config_path
,
662 const LookupPaths
*lp
,
664 UnitFileChange
**changes
,
667 _cleanup_close_
int fd
= -1;
674 if (set_size(remove_symlinks_to
) <= 0)
677 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
);
679 return errno
== ENOENT
? 0 : -errno
;
685 cfd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
689 /* This takes possession of cfd and closes it */
690 q
= remove_marked_symlinks_fd(remove_symlinks_to
, cfd
, config_path
, config_path
, lp
, dry_run
, &restart
, changes
, n_changes
);
698 static int is_symlink_with_known_name(const UnitFileInstallInfo
*i
, const char *name
) {
701 if (streq(name
, i
->name
))
704 if (strv_contains(i
->aliases
, name
))
707 /* Look for template symlink matching DefaultInstance */
708 if (i
->default_instance
&& unit_name_is_valid(i
->name
, UNIT_NAME_TEMPLATE
)) {
709 _cleanup_free_
char *s
= NULL
;
711 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &s
);
716 } else if (streq(name
, s
))
723 static int find_symlinks_in_directory(
725 const char *dir_path
,
726 const char *root_dir
,
727 const UnitFileInstallInfo
*i
,
729 bool ignore_same_name
,
730 const char *config_path
,
731 bool *same_name_link
) {
736 FOREACH_DIRENT(de
, dir
, return -errno
) {
737 _cleanup_free_
char *dest
= NULL
;
738 bool found_path
= false, found_dest
, b
= false;
741 dirent_ensure_type(dir
, de
);
743 if (de
->d_type
!= DT_LNK
)
746 /* Acquire symlink destination */
747 q
= readlinkat_malloc(dirfd(dir
), de
->d_name
, &dest
);
757 if (!path_is_absolute(dest
)) {
760 x
= path_join(dir_path
, dest
);
764 free_and_replace(dest
, x
);
767 assert(unit_name_is_valid(i
->name
, UNIT_NAME_ANY
));
768 if (!ignore_same_name
)
769 /* Check if the symlink itself matches what we are looking for.
771 * If ignore_same_name is specified, we are in one of the directories which
772 * have lower priority than the unit file, and even if a file or symlink with
773 * this name was found, we should ignore it. */
774 found_path
= streq(de
->d_name
, i
->name
);
776 /* Check if what the symlink points to matches what we are looking for */
777 found_dest
= streq(basename(dest
), i
->name
);
779 if (found_path
&& found_dest
) {
780 _cleanup_free_
char *p
= NULL
, *t
= NULL
;
782 /* Filter out same name links in the main
784 p
= path_make_absolute(de
->d_name
, dir_path
);
785 t
= path_make_absolute(i
->name
, config_path
);
790 b
= path_equal(p
, t
);
794 *same_name_link
= true;
795 else if (found_path
|| found_dest
) {
799 /* Check if symlink name is in the set of names used by [Install] */
800 q
= is_symlink_with_known_name(i
, de
->d_name
);
811 static int find_symlinks(
812 const char *root_dir
,
813 const UnitFileInstallInfo
*i
,
815 bool ignore_same_name
,
816 const char *config_path
,
817 bool *same_name_link
) {
819 _cleanup_closedir_
DIR *config_dir
= NULL
;
825 assert(same_name_link
);
827 config_dir
= opendir(config_path
);
829 if (IN_SET(errno
, ENOENT
, ENOTDIR
, EACCES
))
834 FOREACH_DIRENT(de
, config_dir
, return -errno
) {
836 _cleanup_free_
const char *path
= NULL
;
837 _cleanup_closedir_
DIR *d
= NULL
;
839 dirent_ensure_type(config_dir
, de
);
841 if (de
->d_type
!= DT_DIR
)
844 suffix
= strrchr(de
->d_name
, '.');
845 if (!STRPTR_IN_SET(suffix
, ".wants", ".requires"))
848 path
= path_join(config_path
, de
->d_name
);
854 log_error_errno(errno
, "Failed to open directory '%s' while scanning for symlinks, ignoring: %m", path
);
858 r
= find_symlinks_in_directory(d
, path
, root_dir
, i
, match_name
, ignore_same_name
, config_path
, same_name_link
);
862 log_debug_errno(r
, "Failed to lookup for symlinks in '%s': %m", path
);
865 /* We didn't find any suitable symlinks in .wants or .requires directories, let's look for linked unit files in this directory. */
866 rewinddir(config_dir
);
867 return find_symlinks_in_directory(config_dir
, config_path
, root_dir
, i
, match_name
, ignore_same_name
, config_path
, same_name_link
);
870 static int find_symlinks_in_scope(
872 const LookupPaths
*paths
,
873 const UnitFileInstallInfo
*i
,
875 UnitFileState
*state
) {
877 bool same_name_link_runtime
= false, same_name_link_config
= false;
878 bool enabled_in_runtime
= false, enabled_at_all
= false;
879 bool ignore_same_name
= false;
886 /* As we iterate over the list of search paths in paths->search_path, we may encounter "same name"
887 * symlinks. The ones which are "below" (i.e. have lower priority) than the unit file itself are
888 * effectively masked, so we should ignore them. */
890 STRV_FOREACH(p
, paths
->search_path
) {
891 bool same_name_link
= false;
893 r
= find_symlinks(paths
->root_dir
, i
, match_name
, ignore_same_name
, *p
, &same_name_link
);
897 /* We found symlinks in this dir? Yay! Let's see where precisely it is enabled. */
899 if (path_equal_ptr(*p
, paths
->persistent_config
)) {
900 /* This is the best outcome, let's return it immediately. */
901 *state
= UNIT_FILE_ENABLED
;
905 /* look for global enablement of user units */
906 if (scope
== UNIT_FILE_USER
&& path_is_user_config_dir(*p
)) {
907 *state
= UNIT_FILE_ENABLED
;
911 r
= path_is_runtime(paths
, *p
, false);
915 enabled_in_runtime
= true;
917 enabled_at_all
= true;
919 } else if (same_name_link
) {
920 if (path_equal_ptr(*p
, paths
->persistent_config
))
921 same_name_link_config
= true;
923 r
= path_is_runtime(paths
, *p
, false);
927 same_name_link_runtime
= true;
931 /* Check if next iteration will be "below" the unit file (either a regular file
932 * or a symlink), and hence should be ignored */
933 if (!ignore_same_name
&& path_startswith(i
->path
, *p
))
934 ignore_same_name
= true;
937 if (enabled_in_runtime
) {
938 *state
= UNIT_FILE_ENABLED_RUNTIME
;
942 /* Here's a special rule: if the unit we are looking for is an instance, and it symlinked in the search path
943 * outside of runtime and configuration directory, then we consider it statically enabled. Note we do that only
944 * for instance, not for regular names, as those are merely aliases, while instances explicitly instantiate
945 * something, and hence are a much stronger concept. */
946 if (enabled_at_all
&& unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
)) {
947 *state
= UNIT_FILE_STATIC
;
951 /* Hmm, we didn't find it, but maybe we found the same name
953 if (same_name_link_config
) {
954 *state
= UNIT_FILE_LINKED
;
957 if (same_name_link_runtime
) {
958 *state
= UNIT_FILE_LINKED_RUNTIME
;
965 static void install_info_free(UnitFileInstallInfo
*i
) {
972 strv_free(i
->aliases
);
973 strv_free(i
->wanted_by
);
974 strv_free(i
->required_by
);
976 free(i
->default_instance
);
977 free(i
->symlink_target
);
981 static void install_context_done(InstallContext
*c
) {
984 c
->will_process
= ordered_hashmap_free_with_destructor(c
->will_process
, install_info_free
);
985 c
->have_processed
= ordered_hashmap_free_with_destructor(c
->have_processed
, install_info_free
);
988 static UnitFileInstallInfo
*install_info_find(InstallContext
*c
, const char *name
) {
989 UnitFileInstallInfo
*i
;
991 i
= ordered_hashmap_get(c
->have_processed
, name
);
995 return ordered_hashmap_get(c
->will_process
, name
);
998 static int install_info_may_process(
999 const UnitFileInstallInfo
*i
,
1000 const LookupPaths
*paths
,
1001 UnitFileChange
**changes
,
1002 size_t *n_changes
) {
1006 /* Checks whether the loaded unit file is one we should process, or is masked,
1007 * transient or generated and thus not subject to enable/disable operations. */
1009 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
1010 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, i
->path
, NULL
);
1013 if (path_is_generator(paths
, i
->path
) ||
1014 path_is_transient(paths
, i
->path
)) {
1015 unit_file_changes_add(changes
, n_changes
, -EADDRNOTAVAIL
, i
->path
, NULL
);
1016 return -EADDRNOTAVAIL
;
1023 * Adds a new UnitFileInstallInfo entry under name in the InstallContext.will_process
1024 * hashmap, or retrieves the existing one if already present.
1026 * Returns negative on error, 0 if the unit was already known, 1 otherwise.
1028 static int install_info_add(
1033 UnitFileInstallInfo
**ret
) {
1035 UnitFileInstallInfo
*i
= NULL
;
1041 /* 'name' and 'path' must not both be null. Check here 'path' using assert_se() to
1042 * workaround a bug in gcc that generates a -Wnonnull warning when calling basename(),
1043 * but this cannot be possible in any code path (See #6119). */
1045 name
= basename(path
);
1048 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
1051 i
= install_info_find(c
, name
);
1053 i
->auxiliary
= i
->auxiliary
&& auxiliary
;
1060 i
= new(UnitFileInstallInfo
, 1);
1064 *i
= (UnitFileInstallInfo
) {
1065 .type
= _UNIT_FILE_TYPE_INVALID
,
1066 .auxiliary
= auxiliary
,
1069 i
->name
= strdup(name
);
1076 i
->path
= strdup(path
);
1083 r
= ordered_hashmap_ensure_put(&c
->will_process
, &string_hash_ops
, i
->name
, i
);
1093 install_info_free(i
);
1097 static int config_parse_alias(
1099 const char *filename
,
1101 const char *section
,
1102 unsigned section_line
,
1116 type
= unit_name_to_type(unit
);
1117 if (!unit_type_may_alias(type
))
1118 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1119 "Alias= is not allowed for %s units, ignoring.",
1120 unit_type_to_string(type
));
1122 return config_parse_strv(unit
, filename
, line
, section
, section_line
,
1123 lvalue
, ltype
, rvalue
, data
, userdata
);
1126 static int config_parse_also(
1128 const char *filename
,
1130 const char *section
,
1131 unsigned section_line
,
1138 UnitFileInstallInfo
*info
= userdata
;
1139 InstallContext
*c
= data
;
1148 _cleanup_free_
char *word
= NULL
, *printed
= NULL
;
1150 r
= extract_first_word(&rvalue
, &word
, NULL
, 0);
1156 r
= install_name_printf(info
, word
, &printed
);
1160 r
= install_info_add(c
, printed
, NULL
, true, NULL
);
1164 r
= strv_push(&info
->also
, printed
);
1174 static int config_parse_default_instance(
1176 const char *filename
,
1178 const char *section
,
1179 unsigned section_line
,
1186 UnitFileInstallInfo
*i
= data
;
1187 _cleanup_free_
char *printed
= NULL
;
1195 if (unit_name_is_valid(unit
, UNIT_NAME_INSTANCE
))
1196 /* When enabling an instance, we might be using a template unit file,
1197 * but we should ignore DefaultInstance silently. */
1199 if (!unit_name_is_valid(unit
, UNIT_NAME_TEMPLATE
))
1200 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1201 "DefaultInstance= only makes sense for template units, ignoring.");
1203 r
= install_name_printf(i
, rvalue
, &printed
);
1207 if (isempty(printed
)) {
1208 i
->default_instance
= mfree(i
->default_instance
);
1212 if (!unit_instance_is_valid(printed
))
1213 return log_syntax(unit
, LOG_WARNING
, filename
, line
, SYNTHETIC_ERRNO(EINVAL
),
1214 "Invalid DefaultInstance= value \"%s\".", printed
);
1216 return free_and_replace(i
->default_instance
, printed
);
1219 static int unit_file_load(
1221 UnitFileInstallInfo
*info
,
1223 const char *root_dir
,
1224 SearchFlags flags
) {
1226 const ConfigTableItem items
[] = {
1227 { "Install", "Alias", config_parse_alias
, 0, &info
->aliases
},
1228 { "Install", "WantedBy", config_parse_strv
, 0, &info
->wanted_by
},
1229 { "Install", "RequiredBy", config_parse_strv
, 0, &info
->required_by
},
1230 { "Install", "DefaultInstance", config_parse_default_instance
, 0, info
},
1231 { "Install", "Also", config_parse_also
, 0, c
},
1236 _cleanup_fclose_
FILE *f
= NULL
;
1237 _cleanup_close_
int fd
= -1;
1244 if (!(flags
& SEARCH_DROPIN
)) {
1245 /* Loading or checking for the main unit file… */
1247 type
= unit_name_to_type(info
->name
);
1250 if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
|UNIT_NAME_INSTANCE
) && !unit_type_may_template(type
))
1251 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1252 "%s: unit type %s cannot be templated, ignoring.", path
, unit_type_to_string(type
));
1254 if (!(flags
& SEARCH_LOAD
)) {
1255 if (lstat(path
, &st
) < 0)
1258 if (null_or_empty(&st
))
1259 info
->type
= UNIT_FILE_TYPE_MASKED
;
1260 else if (S_ISREG(st
.st_mode
))
1261 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1262 else if (S_ISLNK(st
.st_mode
))
1264 else if (S_ISDIR(st
.st_mode
))
1272 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
1276 /* 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. */
1278 if (!(flags
& SEARCH_LOAD
))
1281 fd
= chase_symlinks_and_open(path
, root_dir
, 0, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
, NULL
);
1286 if (fstat(fd
, &st
) < 0)
1289 if (null_or_empty(&st
)) {
1290 if ((flags
& SEARCH_DROPIN
) == 0)
1291 info
->type
= UNIT_FILE_TYPE_MASKED
;
1296 r
= stat_verify_regular(&st
);
1300 f
= take_fdopen(&fd
, "r");
1304 /* c is only needed if we actually load the file (it's referenced from items[] btw, in case you wonder.) */
1307 r
= config_parse(info
->name
, path
, f
,
1321 config_item_table_lookup
, items
,
1325 return log_debug_errno(r
, "Failed to parse %s: %m", info
->name
);
1327 if ((flags
& SEARCH_DROPIN
) == 0)
1328 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1331 (int) strv_length(info
->aliases
) +
1332 (int) strv_length(info
->wanted_by
) +
1333 (int) strv_length(info
->required_by
);
1336 static int unit_file_load_or_readlink(
1338 UnitFileInstallInfo
*info
,
1340 const char *root_dir
,
1341 SearchFlags flags
) {
1343 _cleanup_free_
char *resolved
= NULL
;
1346 r
= unit_file_load(c
, info
, path
, root_dir
, flags
);
1347 if (r
!= -ELOOP
|| (flags
& SEARCH_DROPIN
))
1350 r
= chase_symlinks(path
, root_dir
, CHASE_WARN
| CHASE_NONEXISTENT
, &resolved
, NULL
);
1353 path_equal_ptr(path_startswith(resolved
, root_dir
), "dev/null"))
1354 /* When looking under root_dir, we can't expect /dev/ to be mounted,
1355 * so let's see if the path is a (possibly dangling) symlink to /dev/null. */
1356 info
->type
= UNIT_FILE_TYPE_MASKED
;
1358 else if (r
> 0 && null_or_empty_path(resolved
) > 0)
1360 info
->type
= UNIT_FILE_TYPE_MASKED
;
1363 _cleanup_free_
char *target
= NULL
;
1367 /* This is a symlink, let's read it. We read the link again, because last time
1368 * we followed the link until resolution, and here we need to do one step. */
1370 r
= readlink_malloc(path
, &target
);
1374 bn
= basename(target
);
1376 if (unit_name_is_valid(info
->name
, UNIT_NAME_PLAIN
)) {
1378 if (!unit_name_is_valid(bn
, UNIT_NAME_PLAIN
))
1381 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1383 if (!unit_name_is_valid(bn
, UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
))
1386 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
)) {
1388 if (!unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
))
1393 /* Enforce that the symlink destination does not
1394 * change the unit file type. */
1396 a
= unit_name_to_type(info
->name
);
1397 b
= unit_name_to_type(bn
);
1398 if (a
< 0 || b
< 0 || a
!= b
)
1401 if (path_is_absolute(target
))
1402 /* This is an absolute path, prefix the root so that we always deal with fully qualified paths */
1403 info
->symlink_target
= path_join(root_dir
, target
);
1405 /* This is a relative path, take it relative to the dir the symlink is located in. */
1406 info
->symlink_target
= file_in_same_dir(path
, target
);
1407 if (!info
->symlink_target
)
1410 info
->type
= UNIT_FILE_TYPE_SYMLINK
;
1416 static int unit_file_search(
1418 UnitFileInstallInfo
*info
,
1419 const LookupPaths
*paths
,
1420 SearchFlags flags
) {
1422 const char *dropin_dir_name
= NULL
, *dropin_template_dir_name
= NULL
;
1423 _cleanup_strv_free_
char **dirs
= NULL
, **files
= NULL
;
1424 _cleanup_free_
char *template = NULL
;
1425 bool found_unit
= false;
1432 /* Was this unit already loaded? */
1433 if (info
->type
!= _UNIT_FILE_TYPE_INVALID
)
1437 return unit_file_load_or_readlink(c
, info
, info
->path
, paths
->root_dir
, flags
);
1441 if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1442 r
= unit_name_template(info
->name
, &template);
1447 STRV_FOREACH(p
, paths
->search_path
) {
1448 _cleanup_free_
char *path
= NULL
;
1450 path
= path_join(*p
, info
->name
);
1454 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1456 info
->path
= TAKE_PTR(path
);
1460 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1464 if (!found_unit
&& template) {
1466 /* Unit file doesn't exist, however instance
1467 * enablement was requested. We will check if it is
1468 * possible to load template unit file. */
1470 STRV_FOREACH(p
, paths
->search_path
) {
1471 _cleanup_free_
char *path
= NULL
;
1473 path
= path_join(*p
, template);
1477 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1479 info
->path
= TAKE_PTR(path
);
1483 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1489 return log_debug_errno(SYNTHETIC_ERRNO(ENOENT
),
1490 "Cannot find unit %s%s%s.",
1491 info
->name
, template ? " or " : "", strempty(template));
1493 if (info
->type
== UNIT_FILE_TYPE_MASKED
)
1496 /* Search for drop-in directories */
1498 dropin_dir_name
= strjoina(info
->name
, ".d");
1499 STRV_FOREACH(p
, paths
->search_path
) {
1502 path
= path_join(*p
, dropin_dir_name
);
1506 r
= strv_consume(&dirs
, path
);
1512 dropin_template_dir_name
= strjoina(template, ".d");
1513 STRV_FOREACH(p
, paths
->search_path
) {
1516 path
= path_join(*p
, dropin_template_dir_name
);
1520 r
= strv_consume(&dirs
, path
);
1526 /* Load drop-in conf files */
1528 r
= conf_files_list_strv(&files
, ".conf", NULL
, 0, (const char**) dirs
);
1530 return log_debug_errno(r
, "Failed to get list of conf files: %m");
1532 STRV_FOREACH(p
, files
) {
1533 r
= unit_file_load_or_readlink(c
, info
, *p
, paths
->root_dir
, flags
| SEARCH_DROPIN
);
1535 return log_debug_errno(r
, "Failed to load conf file %s: %m", *p
);
1541 static int install_info_follow(
1543 UnitFileInstallInfo
*i
,
1544 const char *root_dir
,
1546 bool ignore_different_name
) {
1551 if (i
->type
!= UNIT_FILE_TYPE_SYMLINK
)
1553 if (!i
->symlink_target
)
1556 /* If the basename doesn't match, the caller should add a
1557 * complete new entry for this. */
1559 if (!ignore_different_name
&& !streq(basename(i
->symlink_target
), i
->name
))
1562 free_and_replace(i
->path
, i
->symlink_target
);
1563 i
->type
= _UNIT_FILE_TYPE_INVALID
;
1565 return unit_file_load_or_readlink(c
, i
, i
->path
, root_dir
, flags
);
1569 * Search for the unit file. If the unit name is a symlink, follow the symlink to the
1570 * target, maybe more than once. Propagate the instance name if present.
1572 static int install_info_traverse(
1573 UnitFileScope scope
,
1575 const LookupPaths
*paths
,
1576 UnitFileInstallInfo
*start
,
1578 UnitFileInstallInfo
**ret
) {
1580 UnitFileInstallInfo
*i
;
1588 r
= unit_file_search(c
, start
, paths
, flags
);
1593 while (i
->type
== UNIT_FILE_TYPE_SYMLINK
) {
1594 /* Follow the symlink */
1596 if (++k
> UNIT_FILE_FOLLOW_SYMLINK_MAX
)
1599 if (!(flags
& SEARCH_FOLLOW_CONFIG_SYMLINKS
)) {
1600 r
= path_is_config(paths
, i
->path
, true);
1607 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
, false);
1609 _cleanup_free_
char *buffer
= NULL
;
1612 /* Target has a different name, create a new
1613 * install info object for that, and continue
1616 bn
= basename(i
->symlink_target
);
1618 if (unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
) &&
1619 unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
)) {
1621 _cleanup_free_
char *instance
= NULL
;
1623 r
= unit_name_to_instance(i
->name
, &instance
);
1627 r
= unit_name_replace_instance(bn
, instance
, &buffer
);
1631 if (streq(buffer
, i
->name
)) {
1633 /* We filled in the instance, and the target stayed the same? If so, then let's
1634 * honour the link as it is. */
1636 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
, true);
1646 r
= install_info_add(c
, bn
, NULL
, false, &i
);
1650 /* Try again, with the new target we found. */
1651 r
= unit_file_search(c
, i
, paths
, flags
);
1653 /* Translate error code to highlight this specific case */
1668 * Call install_info_add() with name_or_path as the path (if name_or_path starts with "/")
1669 * or the name (otherwise). root_dir is prepended to the path.
1671 static int install_info_add_auto(
1673 const LookupPaths
*paths
,
1674 const char *name_or_path
,
1675 UnitFileInstallInfo
**ret
) {
1678 assert(name_or_path
);
1680 if (path_is_absolute(name_or_path
)) {
1683 pp
= prefix_roota(paths
->root_dir
, name_or_path
);
1685 return install_info_add(c
, NULL
, pp
, false, ret
);
1687 return install_info_add(c
, name_or_path
, NULL
, false, ret
);
1690 static int install_info_discover(
1691 UnitFileScope scope
,
1693 const LookupPaths
*paths
,
1696 UnitFileInstallInfo
**ret
,
1697 UnitFileChange
**changes
,
1698 size_t *n_changes
) {
1700 UnitFileInstallInfo
*i
;
1707 r
= install_info_add_auto(c
, paths
, name
, &i
);
1709 r
= install_info_traverse(scope
, c
, paths
, i
, flags
, ret
);
1712 unit_file_changes_add(changes
, n_changes
, r
, name
, NULL
);
1716 static int install_info_discover_and_check(
1717 UnitFileScope scope
,
1719 const LookupPaths
*paths
,
1722 UnitFileInstallInfo
**ret
,
1723 UnitFileChange
**changes
,
1724 size_t *n_changes
) {
1728 r
= install_info_discover(scope
, c
, paths
, name
, flags
, ret
, changes
, n_changes
);
1732 return install_info_may_process(ret
? *ret
: NULL
, paths
, changes
, n_changes
);
1735 int unit_file_verify_alias(const UnitFileInstallInfo
*i
, const char *dst
, char **ret_dst
) {
1736 _cleanup_free_
char *dst_updated
= NULL
;
1739 /* Verify that dst is a valid either a valid alias or a valid .wants/.requires symlink for the target
1740 * unit *i. Return negative on error or if not compatible, zero on success.
1742 * ret_dst is set in cases where "instance propagation" happens, i.e. when the instance part is
1743 * inserted into dst. It is not normally set, even on success, so that the caller can easily
1744 * distinguish the case where instance propagation occurred.
1747 const char *path_alias
= strrchr(dst
, '/');
1749 /* This branch covers legacy Alias= function of creating .wants and .requires symlinks. */
1750 _cleanup_free_
char *dir
= NULL
;
1753 path_alias
++; /* skip over slash */
1755 dir
= dirname_malloc(dst
);
1759 p
= endswith(dir
, ".wants");
1761 p
= endswith(dir
, ".requires");
1763 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV
),
1764 "Invalid path \"%s\" in alias.", dir
);
1765 *p
= '\0'; /* dir should now be a unit name */
1767 UnitNameFlags type
= unit_name_classify(dir
);
1769 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV
),
1770 "Invalid unit name component \"%s\" in alias.", dir
);
1772 const bool instance_propagation
= type
== UNIT_NAME_TEMPLATE
;
1774 /* That's the name we want to use for verification. */
1775 r
= unit_symlink_name_compatible(path_alias
, i
->name
, instance_propagation
);
1777 return log_error_errno(r
, "Failed to verify alias validity: %m");
1779 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV
),
1780 "Invalid unit %s symlink %s.",
1784 /* If the symlink target has an instance set and the symlink source doesn't, we "propagate
1785 * the instance", i.e. instantiate the symlink source with the target instance. */
1786 if (unit_name_is_valid(dst
, UNIT_NAME_TEMPLATE
)) {
1787 _cleanup_free_
char *inst
= NULL
;
1789 UnitNameFlags type
= unit_name_to_instance(i
->name
, &inst
);
1791 return log_error_errno(type
, "Failed to extract instance name from %s: %m", i
->name
);
1793 if (type
== UNIT_NAME_INSTANCE
) {
1794 r
= unit_name_replace_instance(dst
, inst
, &dst_updated
);
1796 return log_error_errno(r
, "Failed to build unit name from %s+%s: %m",
1801 r
= unit_validate_alias_symlink_and_warn(dst_updated
?: dst
, i
->name
);
1807 *ret_dst
= TAKE_PTR(dst_updated
);
1811 static int install_info_symlink_alias(
1812 UnitFileInstallInfo
*i
,
1813 const LookupPaths
*paths
,
1814 const char *config_path
,
1816 UnitFileChange
**changes
,
1817 size_t *n_changes
) {
1824 assert(config_path
);
1826 STRV_FOREACH(s
, i
->aliases
) {
1827 _cleanup_free_
char *alias_path
= NULL
, *dst
= NULL
, *dst_updated
= NULL
;
1829 q
= install_path_printf(i
, *s
, &dst
);
1833 q
= unit_file_verify_alias(i
, dst
, &dst_updated
);
1837 alias_path
= path_make_absolute(dst_updated
?: dst
, config_path
);
1841 q
= create_symlink(paths
, i
->path
, alias_path
, force
, changes
, n_changes
);
1849 static int install_info_symlink_wants(
1850 UnitFileScope scope
,
1851 UnitFileFlags file_flags
,
1852 UnitFileInstallInfo
*i
,
1853 const LookupPaths
*paths
,
1854 const char *config_path
,
1857 UnitFileChange
**changes
,
1858 size_t *n_changes
) {
1860 _cleanup_free_
char *buf
= NULL
;
1861 UnitNameFlags valid_dst_type
= UNIT_NAME_ANY
;
1868 assert(config_path
);
1870 if (strv_isempty(list
))
1873 if (unit_name_is_valid(i
->name
, UNIT_NAME_PLAIN
| UNIT_NAME_INSTANCE
))
1874 /* Not a template unit. Use the name directly. */
1877 else if (i
->default_instance
) {
1878 UnitFileInstallInfo instance
= {
1879 .type
= _UNIT_FILE_TYPE_INVALID
,
1881 _cleanup_free_
char *path
= NULL
;
1883 /* If this is a template, and we have a default instance, use it. */
1885 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &buf
);
1889 instance
.name
= buf
;
1890 r
= unit_file_search(NULL
, &instance
, paths
, SEARCH_FOLLOW_CONFIG_SYMLINKS
);
1894 path
= TAKE_PTR(instance
.path
);
1896 if (instance
.type
== UNIT_FILE_TYPE_MASKED
) {
1897 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, path
, NULL
);
1904 /* We have a template, but no instance yet. When used with an instantiated unit, we will get
1905 * the instance from that unit. Cannot be used with non-instance units. */
1907 valid_dst_type
= UNIT_NAME_INSTANCE
| UNIT_NAME_TEMPLATE
;
1911 STRV_FOREACH(s
, list
) {
1912 _cleanup_free_
char *path
= NULL
, *dst
= NULL
;
1914 q
= install_name_printf(i
, *s
, &dst
);
1918 if (!unit_name_is_valid(dst
, valid_dst_type
)) {
1919 /* Generate a proper error here: EUCLEAN if the name is generally bad, EIDRM if the
1920 * template status doesn't match. If we are doing presets don't bother reporting the
1921 * error. This also covers cases like 'systemctl preset serial-getty@.service', which
1922 * has no DefaultInstance, so there is nothing we can do. At the same time,
1923 * 'systemctl enable serial-getty@.service' should fail, the user should specify an
1924 * instance like in 'systemctl enable serial-getty@ttyS0.service'.
1926 if (file_flags
& UNIT_FILE_IGNORE_AUXILIARY_FAILURE
)
1929 if (unit_name_is_valid(dst
, UNIT_NAME_ANY
)) {
1930 unit_file_changes_add(changes
, n_changes
, -EIDRM
, dst
, n
);
1933 unit_file_changes_add(changes
, n_changes
, -EUCLEAN
, dst
, NULL
);
1940 path
= strjoin(config_path
, "/", dst
, suffix
, n
);
1944 q
= create_symlink(paths
, i
->path
, path
, true, changes
, n_changes
);
1948 if (unit_file_exists(scope
, paths
, dst
) == 0)
1949 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_DESTINATION_NOT_PRESENT
, dst
, i
->path
);
1955 static int install_info_symlink_link(
1956 UnitFileInstallInfo
*i
,
1957 const LookupPaths
*paths
,
1958 const char *config_path
,
1960 UnitFileChange
**changes
,
1961 size_t *n_changes
) {
1963 _cleanup_free_
char *path
= NULL
;
1968 assert(config_path
);
1971 r
= in_search_path(paths
, i
->path
);
1977 path
= path_join(config_path
, i
->name
);
1981 return create_symlink(paths
, i
->path
, path
, force
, changes
, n_changes
);
1984 static int install_info_apply(
1985 UnitFileScope scope
,
1986 UnitFileFlags file_flags
,
1987 UnitFileInstallInfo
*i
,
1988 const LookupPaths
*paths
,
1989 const char *config_path
,
1990 UnitFileChange
**changes
,
1991 size_t *n_changes
) {
1997 assert(config_path
);
1999 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
2002 bool force
= file_flags
& UNIT_FILE_FORCE
;
2004 r
= install_info_symlink_alias(i
, paths
, config_path
, force
, changes
, n_changes
);
2006 q
= install_info_symlink_wants(scope
, file_flags
, i
, paths
, config_path
, i
->wanted_by
, ".wants/", changes
, n_changes
);
2010 q
= install_info_symlink_wants(scope
, file_flags
, i
, paths
, config_path
, i
->required_by
, ".requires/", changes
, n_changes
);
2014 q
= install_info_symlink_link(i
, paths
, config_path
, force
, changes
, n_changes
);
2015 /* Do not count links to the unit file towards the "carries_install_info" count */
2016 if (r
== 0 && q
< 0)
2022 static int install_context_apply(
2023 UnitFileScope scope
,
2024 UnitFileFlags file_flags
,
2026 const LookupPaths
*paths
,
2027 const char *config_path
,
2029 UnitFileChange
**changes
,
2030 size_t *n_changes
) {
2032 UnitFileInstallInfo
*i
;
2037 assert(config_path
);
2039 if (ordered_hashmap_isempty(c
->will_process
))
2042 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
2047 while ((i
= ordered_hashmap_first(c
->will_process
))) {
2050 q
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
2054 q
= install_info_traverse(scope
, c
, paths
, i
, flags
, NULL
);
2057 q
= unit_file_changes_add(changes
, n_changes
, UNIT_FILE_AUXILIARY_FAILED
, NULL
, i
->name
);
2063 unit_file_changes_add(changes
, n_changes
, q
, i
->name
, NULL
);
2067 /* We can attempt to process a masked unit when a different unit
2068 * that we were processing specifies it in Also=. */
2069 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
2070 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_MASKED
, i
->path
, NULL
);
2072 /* Assume that something *could* have been enabled here,
2073 * avoid "empty [Install] section" warning. */
2078 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
2081 q
= install_info_apply(scope
, file_flags
, i
, paths
, config_path
, changes
, n_changes
);
2093 static int install_context_mark_for_removal(
2094 UnitFileScope scope
,
2096 const LookupPaths
*paths
,
2097 Set
**remove_symlinks_to
,
2098 const char *config_path
,
2099 UnitFileChange
**changes
,
2100 size_t *n_changes
) {
2102 UnitFileInstallInfo
*i
;
2107 assert(config_path
);
2109 /* Marks all items for removal */
2111 if (ordered_hashmap_isempty(c
->will_process
))
2114 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
2118 while ((i
= ordered_hashmap_first(c
->will_process
))) {
2120 r
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
2124 r
= install_info_traverse(scope
, c
, paths
, i
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, NULL
);
2125 if (r
== -ENOLINK
) {
2126 log_debug_errno(r
, "Name %s leads to a dangling symlink, removing name.", i
->name
);
2127 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_DANGLING
, i
->path
?: i
->name
, NULL
);
2128 } else if (r
== -ENOENT
) {
2130 if (i
->auxiliary
) /* some unit specified in Also= or similar is missing */
2131 log_debug_errno(r
, "Auxiliary unit of %s not found, removing name.", i
->name
);
2133 log_debug_errno(r
, "Unit %s not found, removing name.", i
->name
);
2134 unit_file_changes_add(changes
, n_changes
, r
, i
->path
?: i
->name
, NULL
);
2138 log_debug_errno(r
, "Failed to find unit %s, removing name: %m", i
->name
);
2139 unit_file_changes_add(changes
, n_changes
, r
, i
->path
?: i
->name
, NULL
);
2140 } else if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
2141 log_debug("Unit file %s is masked, ignoring.", i
->name
);
2142 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_MASKED
, i
->path
?: i
->name
, NULL
);
2144 } else if (i
->type
!= UNIT_FILE_TYPE_REGULAR
) {
2145 log_debug("Unit %s has type %s, ignoring.", i
->name
, unit_file_type_to_string(i
->type
) ?: "invalid");
2149 r
= mark_symlink_for_removal(remove_symlinks_to
, i
->name
);
2158 UnitFileScope scope
,
2159 UnitFileFlags flags
,
2160 const char *root_dir
,
2162 UnitFileChange
**changes
,
2163 size_t *n_changes
) {
2165 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2166 const char *config_path
;
2171 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2173 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2177 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2181 STRV_FOREACH(i
, files
) {
2182 _cleanup_free_
char *path
= NULL
;
2185 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
)) {
2191 path
= path_make_absolute(*i
, config_path
);
2195 q
= create_symlink(&paths
, "/dev/null", path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2196 if (q
< 0 && r
>= 0)
2203 int unit_file_unmask(
2204 UnitFileScope scope
,
2205 UnitFileFlags flags
,
2206 const char *root_dir
,
2208 UnitFileChange
**changes
,
2209 size_t *n_changes
) {
2211 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2212 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2213 _cleanup_strv_free_
char **todo
= NULL
;
2214 const char *config_path
;
2221 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2223 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2227 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2231 dry_run
= !!(flags
& UNIT_FILE_DRY_RUN
);
2233 STRV_FOREACH(i
, files
) {
2234 _cleanup_free_
char *path
= NULL
;
2236 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2239 path
= path_make_absolute(*i
, config_path
);
2243 r
= null_or_empty_path(path
);
2251 if (!GREEDY_REALLOC0(todo
, n_todo
+ 2))
2254 todo
[n_todo
] = strdup(*i
);
2264 STRV_FOREACH(i
, todo
) {
2265 _cleanup_free_
char *path
= NULL
;
2268 path
= path_make_absolute(*i
, config_path
);
2272 if (!dry_run
&& unlink(path
) < 0) {
2273 if (errno
!= ENOENT
) {
2276 unit_file_changes_add(changes
, n_changes
, -errno
, path
, NULL
);
2282 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
2284 rp
= skip_root(&paths
, path
);
2285 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: path
);
2290 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, dry_run
, changes
, n_changes
);
2298 UnitFileScope scope
,
2299 UnitFileFlags flags
,
2300 const char *root_dir
,
2302 UnitFileChange
**changes
,
2303 size_t *n_changes
) {
2305 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2306 _cleanup_strv_free_
char **todo
= NULL
;
2307 const char *config_path
;
2313 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2315 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2319 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2323 STRV_FOREACH(i
, files
) {
2324 _cleanup_free_
char *full
= NULL
;
2328 if (!path_is_absolute(*i
))
2332 if (!unit_name_is_valid(fn
, UNIT_NAME_ANY
))
2335 full
= path_join(paths
.root_dir
, *i
);
2339 if (lstat(full
, &st
) < 0)
2341 r
= stat_verify_regular(&st
);
2345 q
= in_search_path(&paths
, *i
);
2351 if (!GREEDY_REALLOC0(todo
, n_todo
+ 2))
2354 todo
[n_todo
] = strdup(*i
);
2364 STRV_FOREACH(i
, todo
) {
2365 _cleanup_free_
char *new_path
= NULL
;
2367 new_path
= path_make_absolute(basename(*i
), config_path
);
2371 q
= create_symlink(&paths
, *i
, new_path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2372 if (q
< 0 && r
>= 0)
2379 static int path_shall_revert(const LookupPaths
*paths
, const char *path
) {
2385 /* Checks whether the path is one where the drop-in directories shall be removed. */
2387 r
= path_is_config(paths
, path
, true);
2391 r
= path_is_control(paths
, path
);
2395 return path_is_transient(paths
, path
);
2398 int unit_file_revert(
2399 UnitFileScope scope
,
2400 const char *root_dir
,
2402 UnitFileChange
**changes
,
2403 size_t *n_changes
) {
2405 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2406 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2407 _cleanup_strv_free_
char **todo
= NULL
;
2412 /* Puts a unit file back into vendor state. This means:
2414 * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and
2415 * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated").
2417 * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in
2418 * "config", but not in "transient" or "control" or even "generated").
2420 * We remove all that in both the runtime and the persistent directories, if that applies.
2423 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2427 STRV_FOREACH(i
, files
) {
2428 bool has_vendor
= false;
2431 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2434 STRV_FOREACH(p
, paths
.search_path
) {
2435 _cleanup_free_
char *path
= NULL
, *dropin
= NULL
;
2438 path
= path_make_absolute(*i
, *p
);
2442 r
= lstat(path
, &st
);
2444 if (errno
!= ENOENT
)
2446 } else if (S_ISREG(st
.st_mode
)) {
2447 /* Check if there's a vendor version */
2448 r
= path_is_vendor_or_generator(&paths
, path
);
2455 dropin
= strjoin(path
, ".d");
2459 r
= lstat(dropin
, &st
);
2461 if (errno
!= ENOENT
)
2463 } else if (S_ISDIR(st
.st_mode
)) {
2464 /* Remove the drop-ins */
2465 r
= path_shall_revert(&paths
, dropin
);
2469 if (!GREEDY_REALLOC0(todo
, n_todo
+ 2))
2472 todo
[n_todo
++] = TAKE_PTR(dropin
);
2480 /* OK, there's a vendor version, hence drop all configuration versions */
2481 STRV_FOREACH(p
, paths
.search_path
) {
2482 _cleanup_free_
char *path
= NULL
;
2485 path
= path_make_absolute(*i
, *p
);
2489 r
= lstat(path
, &st
);
2491 if (errno
!= ENOENT
)
2493 } else if (S_ISREG(st
.st_mode
) || S_ISLNK(st
.st_mode
)) {
2494 r
= path_is_config(&paths
, path
, true);
2498 if (!GREEDY_REALLOC0(todo
, n_todo
+ 2))
2501 todo
[n_todo
++] = TAKE_PTR(path
);
2510 STRV_FOREACH(i
, todo
) {
2511 _cleanup_strv_free_
char **fs
= NULL
;
2515 (void) get_files_in_directory(*i
, &fs
);
2517 q
= rm_rf(*i
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
2518 if (q
< 0 && q
!= -ENOENT
&& r
>= 0) {
2523 STRV_FOREACH(j
, fs
) {
2524 _cleanup_free_
char *t
= NULL
;
2526 t
= path_join(*i
, *j
);
2530 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, t
, NULL
);
2533 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, *i
, NULL
);
2535 rp
= skip_root(&paths
, *i
);
2536 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: *i
);
2541 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.runtime_config
, &paths
, false, changes
, n_changes
);
2545 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.persistent_config
, &paths
, false, changes
, n_changes
);
2552 int unit_file_add_dependency(
2553 UnitFileScope scope
,
2554 UnitFileFlags file_flags
,
2555 const char *root_dir
,
2559 UnitFileChange
**changes
,
2560 size_t *n_changes
) {
2562 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2563 _cleanup_(install_context_done
) InstallContext c
= {};
2564 UnitFileInstallInfo
*i
, *target_info
;
2565 const char *config_path
;
2570 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2573 if (!IN_SET(dep
, UNIT_WANTS
, UNIT_REQUIRES
))
2576 if (!unit_name_is_valid(target
, UNIT_NAME_ANY
))
2579 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2583 config_path
= (file_flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2587 r
= install_info_discover_and_check(scope
, &c
, &paths
, target
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2588 &target_info
, changes
, n_changes
);
2592 assert(target_info
->type
== UNIT_FILE_TYPE_REGULAR
);
2594 STRV_FOREACH(f
, files
) {
2597 r
= install_info_discover_and_check(scope
, &c
, &paths
, *f
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2598 &i
, changes
, n_changes
);
2602 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2604 /* We didn't actually load anything from the unit
2605 * file, but instead just add in our new symlink to
2608 if (dep
== UNIT_WANTS
)
2611 l
= &i
->required_by
;
2614 *l
= strv_new(target_info
->name
);
2619 return install_context_apply(scope
, file_flags
, &c
, &paths
, config_path
,
2620 SEARCH_FOLLOW_CONFIG_SYMLINKS
, changes
, n_changes
);
2623 int unit_file_enable(
2624 UnitFileScope scope
,
2625 UnitFileFlags file_flags
,
2626 const char *root_dir
,
2628 UnitFileChange
**changes
,
2629 size_t *n_changes
) {
2631 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2632 _cleanup_(install_context_done
) InstallContext c
= {};
2633 const char *config_path
;
2634 UnitFileInstallInfo
*i
;
2639 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2641 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2645 config_path
= config_path_from_flags(&paths
, file_flags
);
2649 STRV_FOREACH(f
, files
) {
2650 r
= install_info_discover_and_check(scope
, &c
, &paths
, *f
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2651 &i
, changes
, n_changes
);
2655 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2658 /* This will return the number of symlink rules that were
2659 supposed to be created, not the ones actually created. This
2660 is useful to determine whether the passed files had any
2661 installation data at all. */
2663 return install_context_apply(scope
, file_flags
, &c
, &paths
, config_path
, SEARCH_LOAD
, changes
, n_changes
);
2666 int unit_file_disable(
2667 UnitFileScope scope
,
2668 UnitFileFlags flags
,
2669 const char *root_dir
,
2671 UnitFileChange
**changes
,
2672 size_t *n_changes
) {
2674 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2675 _cleanup_(install_context_done
) InstallContext c
= {};
2676 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2677 const char *config_path
;
2682 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2684 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2688 config_path
= config_path_from_flags(&paths
, flags
);
2692 STRV_FOREACH(i
, files
) {
2693 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2696 r
= install_info_add(&c
, *i
, NULL
, false, NULL
);
2701 r
= install_context_mark_for_removal(scope
, &c
, &paths
, &remove_symlinks_to
, config_path
, changes
, n_changes
);
2705 return remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, !!(flags
& UNIT_FILE_DRY_RUN
), changes
, n_changes
);
2708 int unit_file_reenable(
2709 UnitFileScope scope
,
2710 UnitFileFlags flags
,
2711 const char *root_dir
,
2713 UnitFileChange
**changes
,
2714 size_t *n_changes
) {
2720 /* First, we invoke the disable command with only the basename... */
2721 l
= strv_length(files
);
2722 n
= newa(char*, l
+1);
2723 for (i
= 0; i
< l
; i
++)
2724 n
[i
] = basename(files
[i
]);
2727 r
= unit_file_disable(scope
, flags
, root_dir
, n
, changes
, n_changes
);
2731 /* But the enable command with the full name */
2732 return unit_file_enable(scope
, flags
, root_dir
, files
, changes
, n_changes
);
2735 int unit_file_set_default(
2736 UnitFileScope scope
,
2737 UnitFileFlags flags
,
2738 const char *root_dir
,
2740 UnitFileChange
**changes
,
2741 size_t *n_changes
) {
2743 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2744 _cleanup_(install_context_done
) InstallContext c
= {};
2745 UnitFileInstallInfo
*i
;
2746 const char *new_path
;
2750 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2753 if (unit_name_to_type(name
) != UNIT_TARGET
) /* this also validates the name */
2755 if (streq(name
, SPECIAL_DEFAULT_TARGET
))
2758 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2762 r
= install_info_discover_and_check(scope
, &c
, &paths
, name
, 0, &i
, changes
, n_changes
);
2766 new_path
= strjoina(paths
.persistent_config
, "/" SPECIAL_DEFAULT_TARGET
);
2767 return create_symlink(&paths
, i
->path
, new_path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2770 int unit_file_get_default(
2771 UnitFileScope scope
,
2772 const char *root_dir
,
2775 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2776 _cleanup_(install_context_done
) InstallContext c
= {};
2777 UnitFileInstallInfo
*i
;
2782 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2785 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2789 r
= install_info_discover(scope
, &c
, &paths
, SPECIAL_DEFAULT_TARGET
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2793 r
= install_info_may_process(i
, &paths
, NULL
, 0);
2797 n
= strdup(i
->name
);
2805 int unit_file_lookup_state(
2806 UnitFileScope scope
,
2807 const LookupPaths
*paths
,
2809 UnitFileState
*ret
) {
2811 _cleanup_(install_context_done
) InstallContext c
= {};
2812 UnitFileInstallInfo
*i
;
2813 UnitFileState state
;
2819 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2822 r
= install_info_discover(scope
, &c
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2825 return log_debug_errno(r
, "Failed to discover unit %s: %m", name
);
2827 assert(IN_SET(i
->type
, UNIT_FILE_TYPE_REGULAR
, UNIT_FILE_TYPE_MASKED
));
2828 log_debug("Found unit %s at %s (%s)", name
, strna(i
->path
),
2829 i
->type
== UNIT_FILE_TYPE_REGULAR
? "regular file" : "mask");
2831 /* Shortcut things, if the caller just wants to know if this unit exists. */
2837 case UNIT_FILE_TYPE_MASKED
:
2838 r
= path_is_runtime(paths
, i
->path
, true);
2842 state
= r
> 0 ? UNIT_FILE_MASKED_RUNTIME
: UNIT_FILE_MASKED
;
2845 case UNIT_FILE_TYPE_REGULAR
:
2846 /* Check if the name we were querying is actually an alias */
2847 if (!streq(name
, basename(i
->path
)) && !unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
)) {
2848 state
= UNIT_FILE_ALIAS
;
2852 r
= path_is_generator(paths
, i
->path
);
2856 state
= UNIT_FILE_GENERATED
;
2860 r
= path_is_transient(paths
, i
->path
);
2864 state
= UNIT_FILE_TRANSIENT
;
2868 /* Check if any of the Alias= symlinks have been created.
2869 * We ignore other aliases, and only check those that would
2870 * be created by systemctl enable for this unit. */
2871 r
= find_symlinks_in_scope(scope
, paths
, i
, true, &state
);
2877 /* Check if the file is known under other names. If it is,
2878 * it might be in use. Report that as UNIT_FILE_INDIRECT. */
2879 r
= find_symlinks_in_scope(scope
, paths
, i
, false, &state
);
2883 state
= UNIT_FILE_INDIRECT
;
2885 if (unit_file_install_info_has_rules(i
))
2886 state
= UNIT_FILE_DISABLED
;
2887 else if (unit_file_install_info_has_also(i
))
2888 state
= UNIT_FILE_INDIRECT
;
2890 state
= UNIT_FILE_STATIC
;
2896 assert_not_reached("Unexpected unit file type.");
2903 int unit_file_get_state(
2904 UnitFileScope scope
,
2905 const char *root_dir
,
2907 UnitFileState
*ret
) {
2909 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2913 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2916 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2920 return unit_file_lookup_state(scope
, &paths
, name
, ret
);
2923 int unit_file_exists(UnitFileScope scope
, const LookupPaths
*paths
, const char *name
) {
2924 _cleanup_(install_context_done
) InstallContext c
= {};
2930 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2933 r
= install_info_discover(scope
, &c
, paths
, name
, 0, NULL
, NULL
, NULL
);
2942 static int split_pattern_into_name_and_instances(const char *pattern
, char **out_unit_name
, char ***out_instances
) {
2943 _cleanup_strv_free_
char **instances
= NULL
;
2944 _cleanup_free_
char *unit_name
= NULL
;
2948 assert(out_instances
);
2949 assert(out_unit_name
);
2951 r
= extract_first_word(&pattern
, &unit_name
, NULL
, EXTRACT_RETAIN_ESCAPE
);
2955 /* We handle the instances logic when unit name is extracted */
2957 /* We only create instances when a rule of templated unit
2958 * is seen. A rule like enable foo@.service a b c will
2959 * result in an array of (a, b, c) as instance names */
2960 if (!unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
))
2963 instances
= strv_split(pattern
, WHITESPACE
);
2967 *out_instances
= TAKE_PTR(instances
);
2970 *out_unit_name
= TAKE_PTR(unit_name
);
2975 static int presets_find_config(UnitFileScope scope
, const char *root_dir
, char ***files
) {
2976 static const char* const system_dirs
[] = {CONF_PATHS("systemd/system-preset"), NULL
};
2977 static const char* const user_dirs
[] = {CONF_PATHS_USR("systemd/user-preset"), NULL
};
2978 const char* const* dirs
;
2981 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2983 if (scope
== UNIT_FILE_SYSTEM
)
2985 else if (IN_SET(scope
, UNIT_FILE_GLOBAL
, UNIT_FILE_USER
))
2988 assert_not_reached("Invalid unit file scope");
2990 return conf_files_list_strv(files
, ".preset", root_dir
, 0, dirs
);
2993 static int read_presets(UnitFileScope scope
, const char *root_dir
, UnitFilePresets
*presets
) {
2994 _cleanup_(unit_file_presets_freep
) UnitFilePresets ps
= {};
2995 _cleanup_strv_free_
char **files
= NULL
;
3000 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3003 r
= presets_find_config(scope
, root_dir
, &files
);
3007 STRV_FOREACH(p
, files
) {
3008 _cleanup_fclose_
FILE *f
= NULL
;
3011 f
= fopen(*p
, "re");
3013 if (errno
== ENOENT
)
3020 _cleanup_free_
char *line
= NULL
;
3021 UnitFilePresetRule rule
= {};
3022 const char *parameter
;
3025 r
= read_line(f
, LONG_LINE_MAX
, &line
);
3036 if (strchr(COMMENTS
, *l
))
3039 parameter
= first_word(l
, "enable");
3042 char **instances
= NULL
;
3044 /* Unit_name will remain the same as parameter when no instances are specified */
3045 r
= split_pattern_into_name_and_instances(parameter
, &unit_name
, &instances
);
3047 log_syntax(NULL
, LOG_WARNING
, *p
, n
, r
, "Couldn't parse line '%s'. Ignoring.", line
);
3051 rule
= (UnitFilePresetRule
) {
3052 .pattern
= unit_name
,
3053 .action
= PRESET_ENABLE
,
3054 .instances
= instances
,
3058 parameter
= first_word(l
, "disable");
3062 pattern
= strdup(parameter
);
3066 rule
= (UnitFilePresetRule
) {
3068 .action
= PRESET_DISABLE
,
3073 if (!GREEDY_REALLOC(ps
.rules
, ps
.n_rules
+ 1))
3076 ps
.rules
[ps
.n_rules
++] = rule
;
3080 log_syntax(NULL
, LOG_WARNING
, *p
, n
, 0, "Couldn't parse line '%s'. Ignoring.", line
);
3084 ps
.initialized
= true;
3086 ps
= (UnitFilePresets
){};
3091 static int pattern_match_multiple_instances(
3092 const UnitFilePresetRule rule
,
3093 const char *unit_name
,
3096 _cleanup_free_
char *templated_name
= NULL
;
3099 /* If no ret is needed or the rule itself does not have instances
3100 * initialized, we return not matching */
3101 if (!ret
|| !rule
.instances
)
3104 r
= unit_name_template(unit_name
, &templated_name
);
3107 if (!streq(rule
.pattern
, templated_name
))
3110 /* Compose a list of specified instances when unit name is a template */
3111 if (unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
3112 _cleanup_strv_free_
char **out_strv
= NULL
;
3115 STRV_FOREACH(iter
, rule
.instances
) {
3116 _cleanup_free_
char *name
= NULL
;
3118 r
= unit_name_replace_instance(unit_name
, *iter
, &name
);
3122 r
= strv_consume(&out_strv
, TAKE_PTR(name
));
3127 *ret
= TAKE_PTR(out_strv
);
3130 /* We now know the input unit name is an instance name */
3131 _cleanup_free_
char *instance_name
= NULL
;
3133 r
= unit_name_to_instance(unit_name
, &instance_name
);
3137 if (strv_find(rule
.instances
, instance_name
))
3143 static int query_presets(const char *name
, const UnitFilePresets
*presets
, char ***instance_name_list
) {
3144 PresetAction action
= PRESET_UNKNOWN
;
3146 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
3149 for (size_t i
= 0; i
< presets
->n_rules
; i
++)
3150 if (pattern_match_multiple_instances(presets
->rules
[i
], name
, instance_name_list
) > 0 ||
3151 fnmatch(presets
->rules
[i
].pattern
, name
, FNM_NOESCAPE
) == 0) {
3152 action
= presets
->rules
[i
].action
;
3157 case PRESET_UNKNOWN
:
3158 log_debug("Preset files don't specify rule for %s. Enabling.", name
);
3161 if (instance_name_list
&& *instance_name_list
) {
3163 STRV_FOREACH(s
, *instance_name_list
)
3164 log_debug("Preset files say enable %s.", *s
);
3166 log_debug("Preset files say enable %s.", name
);
3168 case PRESET_DISABLE
:
3169 log_debug("Preset files say disable %s.", name
);
3172 assert_not_reached("invalid preset action");
3176 int unit_file_query_preset(UnitFileScope scope
, const char *root_dir
, const char *name
, UnitFilePresets
*cached
) {
3177 _cleanup_(unit_file_presets_freep
) UnitFilePresets tmp
= {};
3182 if (!cached
->initialized
) {
3183 r
= read_presets(scope
, root_dir
, cached
);
3188 return query_presets(name
, cached
, NULL
);
3191 static int execute_preset(
3192 UnitFileScope scope
,
3193 UnitFileFlags file_flags
,
3194 InstallContext
*plus
,
3195 InstallContext
*minus
,
3196 const LookupPaths
*paths
,
3197 const char *config_path
,
3199 UnitFilePresetMode mode
,
3200 UnitFileChange
**changes
,
3201 size_t *n_changes
) {
3208 assert(config_path
);
3210 if (mode
!= UNIT_FILE_PRESET_ENABLE_ONLY
) {
3211 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
3213 r
= install_context_mark_for_removal(scope
, minus
, paths
, &remove_symlinks_to
, config_path
, changes
, n_changes
);
3217 r
= remove_marked_symlinks(remove_symlinks_to
, config_path
, paths
, false, changes
, n_changes
);
3221 if (mode
!= UNIT_FILE_PRESET_DISABLE_ONLY
) {
3224 /* Returns number of symlinks that where supposed to be installed. */
3225 q
= install_context_apply(scope
,
3226 file_flags
| UNIT_FILE_IGNORE_AUXILIARY_FAILURE
,
3227 plus
, paths
, config_path
, SEARCH_LOAD
, changes
, n_changes
);
3239 static int preset_prepare_one(
3240 UnitFileScope scope
,
3241 InstallContext
*plus
,
3242 InstallContext
*minus
,
3245 const UnitFilePresets
*presets
,
3246 UnitFileChange
**changes
,
3247 size_t *n_changes
) {
3249 _cleanup_(install_context_done
) InstallContext tmp
= {};
3250 _cleanup_strv_free_
char **instance_name_list
= NULL
;
3251 UnitFileInstallInfo
*i
;
3254 if (install_info_find(plus
, name
) || install_info_find(minus
, name
))
3257 r
= install_info_discover(scope
, &tmp
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3258 &i
, changes
, n_changes
);
3261 if (!streq(name
, i
->name
)) {
3262 log_debug("Skipping %s because it is an alias for %s.", name
, i
->name
);
3266 r
= query_presets(name
, presets
, &instance_name_list
);
3271 if (instance_name_list
) {
3273 STRV_FOREACH(s
, instance_name_list
) {
3274 r
= install_info_discover_and_check(scope
, plus
, paths
, *s
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3275 &i
, changes
, n_changes
);
3280 r
= install_info_discover_and_check(scope
, plus
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3281 &i
, changes
, n_changes
);
3287 r
= install_info_discover(scope
, minus
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3288 &i
, changes
, n_changes
);
3293 int unit_file_preset(
3294 UnitFileScope scope
,
3295 UnitFileFlags file_flags
,
3296 const char *root_dir
,
3298 UnitFilePresetMode mode
,
3299 UnitFileChange
**changes
,
3300 size_t *n_changes
) {
3302 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
3303 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3304 _cleanup_(unit_file_presets_freep
) UnitFilePresets presets
= {};
3305 const char *config_path
;
3310 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3311 assert(mode
< _UNIT_FILE_PRESET_MAX
);
3313 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3317 config_path
= (file_flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
3321 r
= read_presets(scope
, root_dir
, &presets
);
3325 STRV_FOREACH(i
, files
) {
3326 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, *i
, &presets
, changes
, n_changes
);
3331 return execute_preset(scope
, file_flags
, &plus
, &minus
, &paths
, config_path
, files
, mode
, changes
, n_changes
);
3334 int unit_file_preset_all(
3335 UnitFileScope scope
,
3336 UnitFileFlags file_flags
,
3337 const char *root_dir
,
3338 UnitFilePresetMode mode
,
3339 UnitFileChange
**changes
,
3340 size_t *n_changes
) {
3342 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
3343 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3344 _cleanup_(unit_file_presets_freep
) UnitFilePresets presets
= {};
3345 const char *config_path
= NULL
;
3350 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3351 assert(mode
< _UNIT_FILE_PRESET_MAX
);
3353 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3357 config_path
= (file_flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
3361 r
= read_presets(scope
, root_dir
, &presets
);
3365 STRV_FOREACH(i
, paths
.search_path
) {
3366 _cleanup_closedir_
DIR *d
= NULL
;
3371 if (errno
== ENOENT
)
3377 FOREACH_DIRENT(de
, d
, return -errno
) {
3379 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
3382 dirent_ensure_type(d
, de
);
3384 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
3387 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, de
->d_name
, &presets
, changes
, n_changes
);
3389 !IN_SET(r
, -EEXIST
, -ERFKILL
, -EADDRNOTAVAIL
, -EIDRM
, -EUCLEAN
, -ELOOP
, -ENOENT
))
3390 /* Ignore generated/transient/missing/invalid units when applying preset, propagate other errors.
3391 * Coordinate with unit_file_dump_changes() above. */
3396 return execute_preset(scope
, file_flags
, &plus
, &minus
, &paths
, config_path
, NULL
, mode
, changes
, n_changes
);
3399 static UnitFileList
* unit_file_list_free_one(UnitFileList
*f
) {
3407 Hashmap
* unit_file_list_free(Hashmap
*h
) {
3408 return hashmap_free_with_destructor(h
, unit_file_list_free_one
);
3411 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList
*, unit_file_list_free_one
);
3413 int unit_file_get_list(
3414 UnitFileScope scope
,
3415 const char *root_dir
,
3420 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3425 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3428 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3432 STRV_FOREACH(dirname
, paths
.search_path
) {
3433 _cleanup_closedir_
DIR *d
= NULL
;
3436 d
= opendir(*dirname
);
3438 if (errno
== ENOENT
)
3440 if (IN_SET(errno
, ENOTDIR
, EACCES
)) {
3441 log_debug_errno(errno
, "Failed to open \"%s\": %m", *dirname
);
3448 FOREACH_DIRENT(de
, d
, return -errno
) {
3449 _cleanup_(unit_file_list_free_onep
) UnitFileList
*f
= NULL
;
3451 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
3454 if (!strv_fnmatch_or_empty(patterns
, de
->d_name
, FNM_NOESCAPE
))
3457 if (hashmap_get(h
, de
->d_name
))
3460 dirent_ensure_type(d
, de
);
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
);