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 "extract-word.h"
22 #include "install-printf.h"
24 #include "locale-util.h"
28 #include "path-lookup.h"
29 #include "path-util.h"
33 #include "stat-util.h"
34 #include "string-table.h"
35 #include "string-util.h"
37 #include "unit-file.h"
39 #define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
41 typedef enum SearchFlags
{
43 SEARCH_FOLLOW_CONFIG_SYMLINKS
= 1 << 1,
44 SEARCH_DROPIN
= 1 << 2,
48 OrderedHashmap
*will_process
;
49 OrderedHashmap
*have_processed
;
58 struct UnitFilePresetRule
{
64 static bool unit_file_install_info_has_rules(const UnitFileInstallInfo
*i
) {
67 return !strv_isempty(i
->aliases
) ||
68 !strv_isempty(i
->wanted_by
) ||
69 !strv_isempty(i
->required_by
);
72 static bool unit_file_install_info_has_also(const UnitFileInstallInfo
*i
) {
75 return !strv_isempty(i
->also
);
78 void unit_file_presets_freep(UnitFilePresets
*p
) {
82 for (size_t i
= 0; i
< p
->n_rules
; i
++) {
83 free(p
->rules
[i
].pattern
);
84 strv_free(p
->rules
[i
].instances
);
91 static const char *const unit_file_type_table
[_UNIT_FILE_TYPE_MAX
] = {
92 [UNIT_FILE_TYPE_REGULAR
] = "regular",
93 [UNIT_FILE_TYPE_SYMLINK
] = "symlink",
94 [UNIT_FILE_TYPE_MASKED
] = "masked",
97 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(unit_file_type
, UnitFileType
);
99 static int in_search_path(const LookupPaths
*p
, const char *path
) {
100 _cleanup_free_
char *parent
= NULL
;
104 parent
= dirname_malloc(path
);
108 return path_strv_contains(p
->search_path
, parent
);
111 static const char* skip_root(const LookupPaths
*p
, const char *path
) {
120 e
= path_startswith(path
, p
->root_dir
);
124 /* Make sure the returned path starts with a slash */
126 if (e
== path
|| e
[-1] != '/')
135 static int path_is_generator(const LookupPaths
*p
, const char *path
) {
136 _cleanup_free_
char *parent
= NULL
;
141 parent
= dirname_malloc(path
);
145 return path_equal_ptr(parent
, p
->generator
) ||
146 path_equal_ptr(parent
, p
->generator_early
) ||
147 path_equal_ptr(parent
, p
->generator_late
);
150 static int path_is_transient(const LookupPaths
*p
, const char *path
) {
151 _cleanup_free_
char *parent
= NULL
;
156 parent
= dirname_malloc(path
);
160 return path_equal_ptr(parent
, p
->transient
);
163 static int path_is_control(const LookupPaths
*p
, const char *path
) {
164 _cleanup_free_
char *parent
= NULL
;
169 parent
= dirname_malloc(path
);
173 return path_equal_ptr(parent
, p
->persistent_control
) ||
174 path_equal_ptr(parent
, p
->runtime_control
);
177 static int path_is_config(const LookupPaths
*p
, const char *path
, bool check_parent
) {
178 _cleanup_free_
char *parent
= NULL
;
183 /* Note that we do *not* have generic checks for /etc or /run in place, since with
184 * them we couldn't discern configuration from transient or generated units */
187 parent
= dirname_malloc(path
);
194 return path_equal_ptr(path
, p
->persistent_config
) ||
195 path_equal_ptr(path
, p
->runtime_config
);
198 static int path_is_runtime(const LookupPaths
*p
, const char *path
, bool check_parent
) {
199 _cleanup_free_
char *parent
= NULL
;
205 /* Everything in /run is considered runtime. On top of that we also add
206 * explicit checks for the various runtime directories, as safety net. */
208 rpath
= skip_root(p
, path
);
209 if (rpath
&& path_startswith(rpath
, "/run"))
213 parent
= dirname_malloc(path
);
220 return path_equal_ptr(path
, p
->runtime_config
) ||
221 path_equal_ptr(path
, p
->generator
) ||
222 path_equal_ptr(path
, p
->generator_early
) ||
223 path_equal_ptr(path
, p
->generator_late
) ||
224 path_equal_ptr(path
, p
->transient
) ||
225 path_equal_ptr(path
, p
->runtime_control
);
228 static int path_is_vendor_or_generator(const LookupPaths
*p
, const char *path
) {
234 rpath
= skip_root(p
, path
);
238 if (path_startswith(rpath
, "/usr"))
242 if (path_startswith(rpath
, "/lib"))
246 if (path_is_generator(p
, rpath
))
249 return path_equal(rpath
, SYSTEM_DATA_UNIT_PATH
);
252 static const char* config_path_from_flags(const LookupPaths
*paths
, UnitFileFlags flags
) {
255 if (FLAGS_SET(flags
, UNIT_FILE_PORTABLE
))
256 return FLAGS_SET(flags
, UNIT_FILE_RUNTIME
) ? paths
->runtime_attached
: paths
->persistent_attached
;
258 return FLAGS_SET(flags
, UNIT_FILE_RUNTIME
) ? paths
->runtime_config
: paths
->persistent_config
;
261 int unit_file_changes_add(
262 UnitFileChange
**changes
,
266 const char *source
) {
268 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
272 assert(!changes
== !n_changes
);
277 c
= reallocarray(*changes
, *n_changes
+ 1, sizeof(UnitFileChange
));
286 if (!p
|| (source
&& !s
))
289 path_simplify(p
, false);
291 path_simplify(s
, false);
293 c
[*n_changes
] = (UnitFileChange
) { type
, p
, s
};
299 void unit_file_changes_free(UnitFileChange
*changes
, size_t n_changes
) {
300 assert(changes
|| n_changes
== 0);
302 for (size_t i
= 0; i
< n_changes
; i
++) {
303 free(changes
[i
].path
);
304 free(changes
[i
].source
);
310 void unit_file_dump_changes(int r
, const char *verb
, const UnitFileChange
*changes
, size_t n_changes
, bool quiet
) {
313 assert(changes
|| n_changes
== 0);
314 /* If verb is not specified, errors are not allowed! */
315 assert(verb
|| r
>= 0);
317 for (size_t i
= 0; i
< n_changes
; i
++) {
318 assert(verb
|| changes
[i
].type
>= 0);
320 switch(changes
[i
].type
) {
321 case UNIT_FILE_SYMLINK
:
323 log_info("Created symlink %s %s %s.",
325 special_glyph(SPECIAL_GLYPH_ARROW
),
328 case UNIT_FILE_UNLINK
:
330 log_info("Removed %s.", changes
[i
].path
);
332 case UNIT_FILE_IS_MASKED
:
334 log_info("Unit %s is masked, ignoring.", changes
[i
].path
);
336 case UNIT_FILE_IS_DANGLING
:
338 log_info("Unit %s is an alias to a unit that is not present, ignoring.",
342 if (changes
[i
].source
)
343 log_error_errno(changes
[i
].type
,
344 "Failed to %s unit, file %s already exists and is a symlink to %s.",
345 verb
, changes
[i
].path
, changes
[i
].source
);
347 log_error_errno(changes
[i
].type
,
348 "Failed to %s unit, file %s already exists.",
349 verb
, changes
[i
].path
);
353 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s is masked.",
354 verb
, changes
[i
].path
);
358 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s is transient or generated.",
359 verb
, changes
[i
].path
);
363 log_error_errno(changes
[i
].type
,
364 "Failed to %s unit, \"%s\" is not a valid unit name.",
365 verb
, changes
[i
].path
);
369 log_error_errno(changes
[i
].type
, "Failed to %s unit, refusing to operate on linked unit file %s",
370 verb
, changes
[i
].path
);
375 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s does not exist.", verb
, changes
[i
].path
);
380 assert(changes
[i
].type
< 0);
381 log_error_errno(changes
[i
].type
, "Failed to %s unit, file %s: %m.",
382 verb
, changes
[i
].path
);
387 if (r
< 0 && !logged
)
388 log_error_errno(r
, "Failed to %s: %m.", verb
);
392 * Checks if two paths or symlinks from wd are the same, when root is the root of the filesystem.
393 * wc should be the full path in the host file system.
395 static bool chroot_symlinks_same(const char *root
, const char *wd
, const char *a
, const char *b
) {
396 assert(path_is_absolute(wd
));
398 /* This will give incorrect results if the paths are relative and go outside
399 * of the chroot. False negatives are possible. */
404 a
= strjoina(path_is_absolute(a
) ? root
: wd
, "/", a
);
405 b
= strjoina(path_is_absolute(b
) ? root
: wd
, "/", b
);
406 return path_equal_or_files_same(a
, b
, 0);
409 static int create_symlink(
410 const LookupPaths
*paths
,
411 const char *old_path
,
412 const char *new_path
,
414 UnitFileChange
**changes
,
417 _cleanup_free_
char *dest
= NULL
, *dirname
= NULL
;
424 rp
= skip_root(paths
, old_path
);
428 /* Actually create a symlink, and remember that we did. Is
429 * smart enough to check if there's already a valid symlink in
432 * Returns 1 if a symlink was created or already exists and points to
433 * the right place, or negative on error.
436 mkdir_parents_label(new_path
, 0755);
438 if (symlink(old_path
, new_path
) >= 0) {
439 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
443 if (errno
!= EEXIST
) {
444 unit_file_changes_add(changes
, n_changes
, -errno
, new_path
, NULL
);
448 r
= readlink_malloc(new_path
, &dest
);
450 /* translate EINVAL (non-symlink exists) to EEXIST */
454 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
458 dirname
= dirname_malloc(new_path
);
462 if (chroot_symlinks_same(paths
->root_dir
, dirname
, dest
, old_path
)) {
463 log_debug("Symlink %s → %s already exists", new_path
, dest
);
468 unit_file_changes_add(changes
, n_changes
, -EEXIST
, new_path
, dest
);
472 r
= symlink_atomic(old_path
, new_path
);
474 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
478 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, new_path
, NULL
);
479 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
484 static int mark_symlink_for_removal(
485 Set
**remove_symlinks_to
,
493 r
= set_ensure_allocated(remove_symlinks_to
, &path_hash_ops
);
501 path_simplify(n
, false);
503 r
= set_consume(*remove_symlinks_to
, n
);
512 static int remove_marked_symlinks_fd(
513 Set
*remove_symlinks_to
,
516 const char *config_path
,
517 const LookupPaths
*lp
,
520 UnitFileChange
**changes
,
523 _cleanup_closedir_
DIR *d
= NULL
;
527 assert(remove_symlinks_to
);
542 FOREACH_DIRENT(de
, d
, return -errno
) {
544 dirent_ensure_type(d
, de
);
546 if (de
->d_type
== DT_DIR
) {
547 _cleanup_free_
char *p
= NULL
;
550 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
560 p
= path_make_absolute(de
->d_name
, path
);
566 /* This will close nfd, regardless whether it succeeds or not */
567 q
= remove_marked_symlinks_fd(remove_symlinks_to
, nfd
, p
, config_path
, lp
, dry_run
, restart
, changes
, n_changes
);
571 } else if (de
->d_type
== DT_LNK
) {
572 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
577 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
580 p
= path_make_absolute(de
->d_name
, path
);
583 path_simplify(p
, false);
585 q
= chase_symlinks(p
, NULL
, CHASE_NONEXISTENT
, &dest
, NULL
);
594 /* We remove all links pointing to a file or path that is marked, as well as all files sharing
595 * the same name as a file that is marked. */
597 found
= set_contains(remove_symlinks_to
, dest
) ||
598 set_contains(remove_symlinks_to
, basename(dest
)) ||
599 set_contains(remove_symlinks_to
, de
->d_name
);
605 if (unlinkat(fd
, de
->d_name
, 0) < 0 && errno
!= ENOENT
) {
608 unit_file_changes_add(changes
, n_changes
, -errno
, p
, NULL
);
612 (void) rmdir_parents(p
, config_path
);
615 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, p
, NULL
);
617 /* Now, remember the full path (but with the root prefix removed) of
618 * the symlink we just removed, and remove any symlinks to it, too. */
620 rp
= skip_root(lp
, p
);
621 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: p
);
624 if (q
> 0 && !dry_run
)
632 static int remove_marked_symlinks(
633 Set
*remove_symlinks_to
,
634 const char *config_path
,
635 const LookupPaths
*lp
,
637 UnitFileChange
**changes
,
640 _cleanup_close_
int fd
= -1;
647 if (set_size(remove_symlinks_to
) <= 0)
650 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
);
652 return errno
== ENOENT
? 0 : -errno
;
658 cfd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
662 /* This takes possession of cfd and closes it */
663 q
= remove_marked_symlinks_fd(remove_symlinks_to
, cfd
, config_path
, config_path
, lp
, dry_run
, &restart
, changes
, n_changes
);
671 static int is_symlink_with_known_name(const UnitFileInstallInfo
*i
, const char *name
) {
674 if (streq(name
, i
->name
))
677 if (strv_contains(i
->aliases
, name
))
680 /* Look for template symlink matching DefaultInstance */
681 if (i
->default_instance
&& unit_name_is_valid(i
->name
, UNIT_NAME_TEMPLATE
)) {
682 _cleanup_free_
char *s
= NULL
;
684 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &s
);
689 } else if (streq(name
, s
))
696 static int find_symlinks_fd(
697 const char *root_dir
,
698 const UnitFileInstallInfo
*i
,
700 bool ignore_same_name
,
703 const char *config_path
,
704 bool *same_name_link
) {
706 _cleanup_closedir_
DIR *d
= NULL
;
714 assert(same_name_link
);
722 FOREACH_DIRENT(de
, d
, return -errno
) {
724 dirent_ensure_type(d
, de
);
726 if (de
->d_type
== DT_DIR
) {
727 _cleanup_free_
char *p
= NULL
;
730 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
740 p
= path_make_absolute(de
->d_name
, path
);
746 /* This will close nfd, regardless whether it succeeds or not */
747 q
= find_symlinks_fd(root_dir
, i
, match_aliases
, ignore_same_name
, nfd
,
748 p
, config_path
, same_name_link
);
754 } else if (de
->d_type
== DT_LNK
) {
755 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
756 bool found_path
= false, found_dest
, b
= false;
759 /* Acquire symlink name */
760 p
= path_make_absolute(de
->d_name
, path
);
764 /* Acquire symlink destination */
765 q
= readlink_malloc(p
, &dest
);
775 if (!path_is_absolute(dest
)) {
778 x
= path_join(root_dir
, dest
);
782 free_and_replace(dest
, x
);
785 assert(unit_name_is_valid(i
->name
, UNIT_NAME_ANY
));
786 if (!ignore_same_name
)
787 /* Check if the symlink itself matches what we are looking for.
789 * If ignore_same_name is specified, we are in one of the directories which
790 * have lower priority than the unit file, and even if a file or symlink with
791 * this name was found, we should ignore it. */
792 found_path
= streq(de
->d_name
, i
->name
);
794 /* Check if what the symlink points to matches what we are looking for */
795 found_dest
= streq(basename(dest
), i
->name
);
797 if (found_path
&& found_dest
) {
798 _cleanup_free_
char *t
= NULL
;
800 /* Filter out same name links in the main
802 t
= path_make_absolute(i
->name
, config_path
);
806 b
= path_equal(t
, p
);
810 *same_name_link
= true;
811 else if (found_path
|| found_dest
) {
815 /* Check if symlink name is in the set of names used by [Install] */
816 q
= is_symlink_with_known_name(i
, de
->d_name
);
828 static int find_symlinks(
829 const char *root_dir
,
830 const UnitFileInstallInfo
*i
,
832 bool ignore_same_name
,
833 const char *config_path
,
834 bool *same_name_link
) {
840 assert(same_name_link
);
842 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
);
844 if (IN_SET(errno
, ENOENT
, ENOTDIR
, EACCES
))
849 /* This takes possession of fd and closes it */
850 return find_symlinks_fd(root_dir
, i
, match_name
, ignore_same_name
, fd
,
851 config_path
, config_path
, same_name_link
);
854 static int find_symlinks_in_scope(
856 const LookupPaths
*paths
,
857 const UnitFileInstallInfo
*i
,
859 UnitFileState
*state
) {
861 bool same_name_link_runtime
= false, same_name_link_config
= false;
862 bool enabled_in_runtime
= false, enabled_at_all
= false;
863 bool ignore_same_name
= false;
870 /* As we iterate over the list of search paths in paths->search_path, we may encounter "same name"
871 * symlinks. The ones which are "below" (i.e. have lower priority) than the unit file itself are
872 * effectively masked, so we should ignore them. */
874 STRV_FOREACH(p
, paths
->search_path
) {
875 bool same_name_link
= false;
877 r
= find_symlinks(paths
->root_dir
, i
, match_name
, ignore_same_name
, *p
, &same_name_link
);
881 /* We found symlinks in this dir? Yay! Let's see where precisely it is enabled. */
883 if (path_equal_ptr(*p
, paths
->persistent_config
)) {
884 /* This is the best outcome, let's return it immediately. */
885 *state
= UNIT_FILE_ENABLED
;
889 /* look for global enablement of user units */
890 if (scope
== UNIT_FILE_USER
&& path_is_user_config_dir(*p
)) {
891 *state
= UNIT_FILE_ENABLED
;
895 r
= path_is_runtime(paths
, *p
, false);
899 enabled_in_runtime
= true;
901 enabled_at_all
= true;
903 } else if (same_name_link
) {
904 if (path_equal_ptr(*p
, paths
->persistent_config
))
905 same_name_link_config
= true;
907 r
= path_is_runtime(paths
, *p
, false);
911 same_name_link_runtime
= true;
915 /* Check if next iteration will be "below" the unit file (either a regular file
916 * or a symlink), and hence should be ignored */
917 if (!ignore_same_name
&& path_startswith(i
->path
, *p
))
918 ignore_same_name
= true;
921 if (enabled_in_runtime
) {
922 *state
= UNIT_FILE_ENABLED_RUNTIME
;
926 /* Here's a special rule: if the unit we are looking for is an instance, and it symlinked in the search path
927 * outside of runtime and configuration directory, then we consider it statically enabled. Note we do that only
928 * for instance, not for regular names, as those are merely aliases, while instances explicitly instantiate
929 * something, and hence are a much stronger concept. */
930 if (enabled_at_all
&& unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
)) {
931 *state
= UNIT_FILE_STATIC
;
935 /* Hmm, we didn't find it, but maybe we found the same name
937 if (same_name_link_config
) {
938 *state
= UNIT_FILE_LINKED
;
941 if (same_name_link_runtime
) {
942 *state
= UNIT_FILE_LINKED_RUNTIME
;
949 static void install_info_free(UnitFileInstallInfo
*i
) {
956 strv_free(i
->aliases
);
957 strv_free(i
->wanted_by
);
958 strv_free(i
->required_by
);
960 free(i
->default_instance
);
961 free(i
->symlink_target
);
965 static void install_context_done(InstallContext
*c
) {
968 c
->will_process
= ordered_hashmap_free_with_destructor(c
->will_process
, install_info_free
);
969 c
->have_processed
= ordered_hashmap_free_with_destructor(c
->have_processed
, install_info_free
);
972 static UnitFileInstallInfo
*install_info_find(InstallContext
*c
, const char *name
) {
973 UnitFileInstallInfo
*i
;
975 i
= ordered_hashmap_get(c
->have_processed
, name
);
979 return ordered_hashmap_get(c
->will_process
, name
);
982 static int install_info_may_process(
983 const UnitFileInstallInfo
*i
,
984 const LookupPaths
*paths
,
985 UnitFileChange
**changes
,
990 /* Checks whether the loaded unit file is one we should process, or is masked,
991 * transient or generated and thus not subject to enable/disable operations. */
993 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
994 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, i
->path
, NULL
);
997 if (path_is_generator(paths
, i
->path
) ||
998 path_is_transient(paths
, i
->path
)) {
999 unit_file_changes_add(changes
, n_changes
, -EADDRNOTAVAIL
, i
->path
, NULL
);
1000 return -EADDRNOTAVAIL
;
1007 * Adds a new UnitFileInstallInfo entry under name in the InstallContext.will_process
1008 * hashmap, or retrieves the existing one if already present.
1010 * Returns negative on error, 0 if the unit was already known, 1 otherwise.
1012 static int install_info_add(
1017 UnitFileInstallInfo
**ret
) {
1019 UnitFileInstallInfo
*i
= NULL
;
1025 /* 'name' and 'path' must not both be null. Check here 'path' using assert_se() to
1026 * workaround a bug in gcc that generates a -Wnonnull warning when calling basename(),
1027 * but this cannot be possible in any code path (See #6119). */
1029 name
= basename(path
);
1032 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
1035 i
= install_info_find(c
, name
);
1037 i
->auxiliary
= i
->auxiliary
&& auxiliary
;
1044 r
= ordered_hashmap_ensure_allocated(&c
->will_process
, &string_hash_ops
);
1048 i
= new(UnitFileInstallInfo
, 1);
1052 *i
= (UnitFileInstallInfo
) {
1053 .type
= _UNIT_FILE_TYPE_INVALID
,
1054 .auxiliary
= auxiliary
,
1057 i
->name
= strdup(name
);
1064 i
->path
= strdup(path
);
1071 r
= ordered_hashmap_put(c
->will_process
, i
->name
, i
);
1081 install_info_free(i
);
1085 static int config_parse_alias(
1087 const char *filename
,
1089 const char *section
,
1090 unsigned section_line
,
1104 type
= unit_name_to_type(unit
);
1105 if (!unit_type_may_alias(type
))
1106 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1107 "Alias= is not allowed for %s units, ignoring.",
1108 unit_type_to_string(type
));
1110 return config_parse_strv(unit
, filename
, line
, section
, section_line
,
1111 lvalue
, ltype
, rvalue
, data
, userdata
);
1114 static int config_parse_also(
1116 const char *filename
,
1118 const char *section
,
1119 unsigned section_line
,
1126 UnitFileInstallInfo
*info
= userdata
;
1127 InstallContext
*c
= data
;
1136 _cleanup_free_
char *word
= NULL
, *printed
= NULL
;
1138 r
= extract_first_word(&rvalue
, &word
, NULL
, 0);
1144 r
= install_full_printf(info
, word
, &printed
);
1148 r
= install_info_add(c
, printed
, NULL
, true, NULL
);
1152 r
= strv_push(&info
->also
, printed
);
1162 static int config_parse_default_instance(
1164 const char *filename
,
1166 const char *section
,
1167 unsigned section_line
,
1174 UnitFileInstallInfo
*i
= data
;
1175 _cleanup_free_
char *printed
= NULL
;
1183 if (unit_name_is_valid(unit
, UNIT_NAME_INSTANCE
))
1184 /* When enabling an instance, we might be using a template unit file,
1185 * but we should ignore DefaultInstance silently. */
1187 if (!unit_name_is_valid(unit
, UNIT_NAME_TEMPLATE
))
1188 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1189 "DefaultInstance= only makes sense for template units, ignoring.");
1191 r
= install_full_printf(i
, rvalue
, &printed
);
1195 if (isempty(printed
)) {
1196 i
->default_instance
= mfree(i
->default_instance
);
1200 if (!unit_instance_is_valid(printed
))
1201 return log_syntax(unit
, LOG_WARNING
, filename
, line
, SYNTHETIC_ERRNO(EINVAL
),
1202 "Invalid DefaultInstance= value \"%s\".", printed
);
1204 return free_and_replace(i
->default_instance
, printed
);
1207 static int unit_file_load(
1209 UnitFileInstallInfo
*info
,
1211 const char *root_dir
,
1212 SearchFlags flags
) {
1214 const ConfigTableItem items
[] = {
1215 { "Install", "Alias", config_parse_alias
, 0, &info
->aliases
},
1216 { "Install", "WantedBy", config_parse_strv
, 0, &info
->wanted_by
},
1217 { "Install", "RequiredBy", config_parse_strv
, 0, &info
->required_by
},
1218 { "Install", "DefaultInstance", config_parse_default_instance
, 0, info
},
1219 { "Install", "Also", config_parse_also
, 0, c
},
1224 _cleanup_fclose_
FILE *f
= NULL
;
1225 _cleanup_close_
int fd
= -1;
1232 if (!(flags
& SEARCH_DROPIN
)) {
1233 /* Loading or checking for the main unit file… */
1235 type
= unit_name_to_type(info
->name
);
1238 if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
|UNIT_NAME_INSTANCE
) && !unit_type_may_template(type
))
1239 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1240 "%s: unit type %s cannot be templated, ignoring.", path
, unit_type_to_string(type
));
1242 if (!(flags
& SEARCH_LOAD
)) {
1243 if (lstat(path
, &st
) < 0)
1246 if (null_or_empty(&st
))
1247 info
->type
= UNIT_FILE_TYPE_MASKED
;
1248 else if (S_ISREG(st
.st_mode
))
1249 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1250 else if (S_ISLNK(st
.st_mode
))
1252 else if (S_ISDIR(st
.st_mode
))
1260 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
1264 /* 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. */
1266 if (!(flags
& SEARCH_LOAD
))
1269 fd
= chase_symlinks_and_open(path
, root_dir
, 0, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
, NULL
);
1274 if (fstat(fd
, &st
) < 0)
1277 if (null_or_empty(&st
)) {
1278 if ((flags
& SEARCH_DROPIN
) == 0)
1279 info
->type
= UNIT_FILE_TYPE_MASKED
;
1284 r
= stat_verify_regular(&st
);
1288 f
= take_fdopen(&fd
, "r");
1292 /* c is only needed if we actually load the file (it's referenced from items[] btw, in case you wonder.) */
1295 r
= config_parse(info
->name
, path
, f
,
1309 config_item_table_lookup
, items
,
1313 return log_debug_errno(r
, "Failed to parse %s: %m", info
->name
);
1315 if ((flags
& SEARCH_DROPIN
) == 0)
1316 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1319 (int) strv_length(info
->aliases
) +
1320 (int) strv_length(info
->wanted_by
) +
1321 (int) strv_length(info
->required_by
);
1324 static int unit_file_load_or_readlink(
1326 UnitFileInstallInfo
*info
,
1328 const char *root_dir
,
1329 SearchFlags flags
) {
1330 _cleanup_free_
char *resolved
= NULL
;
1334 r
= unit_file_load(c
, info
, path
, root_dir
, flags
);
1335 if (r
!= -ELOOP
|| (flags
& SEARCH_DROPIN
))
1338 r
= chase_symlinks(path
, root_dir
, CHASE_WARN
| CHASE_NONEXISTENT
, &resolved
, NULL
);
1341 path_equal_ptr(path_startswith(resolved
, root_dir
), "dev/null"))
1342 /* When looking under root_dir, we can't expect /dev/ to be mounted,
1343 * so let's see if the path is a (possibly dangling) symlink to /dev/null. */
1344 info
->type
= UNIT_FILE_TYPE_MASKED
;
1347 stat(resolved
, &st
) >= 0 &&
1350 info
->type
= UNIT_FILE_TYPE_MASKED
;
1353 _cleanup_free_
char *target
= NULL
;
1357 /* This is a symlink, let's read it. We read the link again, because last time
1358 * we followed the link until resolution, and here we need to do one step. */
1360 r
= readlink_malloc(path
, &target
);
1364 bn
= basename(target
);
1366 if (unit_name_is_valid(info
->name
, UNIT_NAME_PLAIN
)) {
1368 if (!unit_name_is_valid(bn
, UNIT_NAME_PLAIN
))
1371 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1373 if (!unit_name_is_valid(bn
, UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
))
1376 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
)) {
1378 if (!unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
))
1383 /* Enforce that the symlink destination does not
1384 * change the unit file type. */
1386 a
= unit_name_to_type(info
->name
);
1387 b
= unit_name_to_type(bn
);
1388 if (a
< 0 || b
< 0 || a
!= b
)
1391 if (path_is_absolute(target
))
1392 /* This is an absolute path, prefix the root so that we always deal with fully qualified paths */
1393 info
->symlink_target
= path_join(root_dir
, target
);
1395 /* This is a relative path, take it relative to the dir the symlink is located in. */
1396 info
->symlink_target
= file_in_same_dir(path
, target
);
1397 if (!info
->symlink_target
)
1400 info
->type
= UNIT_FILE_TYPE_SYMLINK
;
1406 static int unit_file_search(
1408 UnitFileInstallInfo
*info
,
1409 const LookupPaths
*paths
,
1410 SearchFlags flags
) {
1412 const char *dropin_dir_name
= NULL
, *dropin_template_dir_name
= NULL
;
1413 _cleanup_strv_free_
char **dirs
= NULL
, **files
= NULL
;
1414 _cleanup_free_
char *template = NULL
;
1415 bool found_unit
= false;
1422 /* Was this unit already loaded? */
1423 if (info
->type
!= _UNIT_FILE_TYPE_INVALID
)
1427 return unit_file_load_or_readlink(c
, info
, info
->path
, paths
->root_dir
, flags
);
1431 if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1432 r
= unit_name_template(info
->name
, &template);
1437 STRV_FOREACH(p
, paths
->search_path
) {
1438 _cleanup_free_
char *path
= NULL
;
1440 path
= path_join(*p
, info
->name
);
1444 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1446 info
->path
= TAKE_PTR(path
);
1450 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1454 if (!found_unit
&& template) {
1456 /* Unit file doesn't exist, however instance
1457 * enablement was requested. We will check if it is
1458 * possible to load template unit file. */
1460 STRV_FOREACH(p
, paths
->search_path
) {
1461 _cleanup_free_
char *path
= NULL
;
1463 path
= path_join(*p
, template);
1467 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1469 info
->path
= TAKE_PTR(path
);
1473 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1479 return log_debug_errno(SYNTHETIC_ERRNO(ENOENT
),
1480 "Cannot find unit %s%s%s.",
1481 info
->name
, template ? " or " : "", strempty(template));
1483 if (info
->type
== UNIT_FILE_TYPE_MASKED
)
1486 /* Search for drop-in directories */
1488 dropin_dir_name
= strjoina(info
->name
, ".d");
1489 STRV_FOREACH(p
, paths
->search_path
) {
1492 path
= path_join(*p
, dropin_dir_name
);
1496 r
= strv_consume(&dirs
, path
);
1502 dropin_template_dir_name
= strjoina(template, ".d");
1503 STRV_FOREACH(p
, paths
->search_path
) {
1506 path
= path_join(*p
, dropin_template_dir_name
);
1510 r
= strv_consume(&dirs
, path
);
1516 /* Load drop-in conf files */
1518 r
= conf_files_list_strv(&files
, ".conf", NULL
, 0, (const char**) dirs
);
1520 return log_debug_errno(r
, "Failed to get list of conf files: %m");
1522 STRV_FOREACH(p
, files
) {
1523 r
= unit_file_load_or_readlink(c
, info
, *p
, paths
->root_dir
, flags
| SEARCH_DROPIN
);
1525 return log_debug_errno(r
, "Failed to load conf file %s: %m", *p
);
1531 static int install_info_follow(
1533 UnitFileInstallInfo
*i
,
1534 const char *root_dir
,
1536 bool ignore_different_name
) {
1541 if (i
->type
!= UNIT_FILE_TYPE_SYMLINK
)
1543 if (!i
->symlink_target
)
1546 /* If the basename doesn't match, the caller should add a
1547 * complete new entry for this. */
1549 if (!ignore_different_name
&& !streq(basename(i
->symlink_target
), i
->name
))
1552 free_and_replace(i
->path
, i
->symlink_target
);
1553 i
->type
= _UNIT_FILE_TYPE_INVALID
;
1555 return unit_file_load_or_readlink(c
, i
, i
->path
, root_dir
, flags
);
1559 * Search for the unit file. If the unit name is a symlink, follow the symlink to the
1560 * target, maybe more than once. Propagate the instance name if present.
1562 static int install_info_traverse(
1563 UnitFileScope scope
,
1565 const LookupPaths
*paths
,
1566 UnitFileInstallInfo
*start
,
1568 UnitFileInstallInfo
**ret
) {
1570 UnitFileInstallInfo
*i
;
1578 r
= unit_file_search(c
, start
, paths
, flags
);
1583 while (i
->type
== UNIT_FILE_TYPE_SYMLINK
) {
1584 /* Follow the symlink */
1586 if (++k
> UNIT_FILE_FOLLOW_SYMLINK_MAX
)
1589 if (!(flags
& SEARCH_FOLLOW_CONFIG_SYMLINKS
)) {
1590 r
= path_is_config(paths
, i
->path
, true);
1597 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
, false);
1599 _cleanup_free_
char *buffer
= NULL
;
1602 /* Target has a different name, create a new
1603 * install info object for that, and continue
1606 bn
= basename(i
->symlink_target
);
1608 if (unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
) &&
1609 unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
)) {
1611 _cleanup_free_
char *instance
= NULL
;
1613 r
= unit_name_to_instance(i
->name
, &instance
);
1617 r
= unit_name_replace_instance(bn
, instance
, &buffer
);
1621 if (streq(buffer
, i
->name
)) {
1623 /* We filled in the instance, and the target stayed the same? If so, then let's
1624 * honour the link as it is. */
1626 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
, true);
1636 r
= install_info_add(c
, bn
, NULL
, false, &i
);
1640 /* Try again, with the new target we found. */
1641 r
= unit_file_search(c
, i
, paths
, flags
);
1643 /* Translate error code to highlight this specific case */
1658 * Call install_info_add() with name_or_path as the path (if name_or_path starts with "/")
1659 * or the name (otherwise). root_dir is prepended to the path.
1661 static int install_info_add_auto(
1663 const LookupPaths
*paths
,
1664 const char *name_or_path
,
1665 UnitFileInstallInfo
**ret
) {
1668 assert(name_or_path
);
1670 if (path_is_absolute(name_or_path
)) {
1673 pp
= prefix_roota(paths
->root_dir
, name_or_path
);
1675 return install_info_add(c
, NULL
, pp
, false, ret
);
1677 return install_info_add(c
, name_or_path
, NULL
, false, ret
);
1680 static int install_info_discover(
1681 UnitFileScope scope
,
1683 const LookupPaths
*paths
,
1686 UnitFileInstallInfo
**ret
,
1687 UnitFileChange
**changes
,
1688 size_t *n_changes
) {
1690 UnitFileInstallInfo
*i
;
1697 r
= install_info_add_auto(c
, paths
, name
, &i
);
1699 r
= install_info_traverse(scope
, c
, paths
, i
, flags
, ret
);
1702 unit_file_changes_add(changes
, n_changes
, r
, name
, NULL
);
1706 static int install_info_discover_and_check(
1707 UnitFileScope scope
,
1709 const LookupPaths
*paths
,
1712 UnitFileInstallInfo
**ret
,
1713 UnitFileChange
**changes
,
1714 size_t *n_changes
) {
1718 r
= install_info_discover(scope
, c
, paths
, name
, flags
, ret
, changes
, n_changes
);
1722 return install_info_may_process(ret
? *ret
: NULL
, paths
, changes
, n_changes
);
1725 int unit_file_verify_alias(const UnitFileInstallInfo
*i
, const char *dst
, char **ret_dst
) {
1726 _cleanup_free_
char *dst_updated
= NULL
;
1729 /* Verify that dst is a valid either a valid alias or a valid .wants/.requires symlink for the target
1730 * unit *i. Return negative on error or if not compatible, zero on success.
1732 * ret_dst is set in cases where "instance propagation" happens, i.e. when the instance part is
1733 * inserted into dst. It is not normally set, even on success, so that the caller can easily
1734 * distinguish the case where instance propagation occurred.
1737 const char *path_alias
= strrchr(dst
, '/');
1739 /* This branch covers legacy Alias= function of creating .wants and .requires symlinks. */
1740 _cleanup_free_
char *dir
= NULL
;
1743 path_alias
++; /* skip over slash */
1745 dir
= dirname_malloc(dst
);
1749 p
= endswith(dir
, ".wants");
1751 p
= endswith(dir
, ".requires");
1753 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV
),
1754 "Invalid path \"%s\" in alias.", dir
);
1755 *p
= '\0'; /* dir should now be a unit name */
1757 r
= unit_name_classify(dir
);
1759 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV
),
1760 "Invalid unit name component \"%s\" in alias.", dir
);
1762 const bool instance_propagation
= r
== UNIT_NAME_TEMPLATE
;
1764 /* That's the name we want to use for verification. */
1765 r
= unit_symlink_name_compatible(path_alias
, i
->name
, instance_propagation
);
1767 return log_error_errno(r
, "Failed to verify alias validity: %m");
1769 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV
),
1770 "Invalid unit %s symlink %s.",
1774 /* If the symlink target has an instance set and the symlink source doesn't, we "propagate
1775 * the instance", i.e. instantiate the symlink source with the target instance. */
1776 if (unit_name_is_valid(dst
, UNIT_NAME_TEMPLATE
)) {
1777 _cleanup_free_
char *inst
= NULL
;
1779 r
= unit_name_to_instance(i
->name
, &inst
);
1781 return log_error_errno(r
, "Failed to extract instance name from %s: %m", i
->name
);
1783 if (r
== UNIT_NAME_INSTANCE
) {
1784 r
= unit_name_replace_instance(dst
, inst
, &dst_updated
);
1786 return log_error_errno(r
, "Failed to build unit name from %s+%s: %m",
1791 r
= unit_validate_alias_symlink_and_warn(dst_updated
?: dst
, i
->name
);
1797 *ret_dst
= TAKE_PTR(dst_updated
);
1801 static int install_info_symlink_alias(
1802 UnitFileInstallInfo
*i
,
1803 const LookupPaths
*paths
,
1804 const char *config_path
,
1806 UnitFileChange
**changes
,
1807 size_t *n_changes
) {
1814 assert(config_path
);
1816 STRV_FOREACH(s
, i
->aliases
) {
1817 _cleanup_free_
char *alias_path
= NULL
, *dst
= NULL
, *dst_updated
= NULL
;
1819 q
= install_full_printf(i
, *s
, &dst
);
1823 q
= unit_file_verify_alias(i
, dst
, &dst_updated
);
1827 alias_path
= path_make_absolute(dst_updated
?: dst
, config_path
);
1831 q
= create_symlink(paths
, i
->path
, alias_path
, force
, changes
, n_changes
);
1839 static int install_info_symlink_wants(
1840 UnitFileInstallInfo
*i
,
1841 const LookupPaths
*paths
,
1842 const char *config_path
,
1845 UnitFileChange
**changes
,
1846 size_t *n_changes
) {
1848 _cleanup_free_
char *buf
= NULL
;
1855 assert(config_path
);
1857 if (strv_isempty(list
))
1860 if (unit_name_is_valid(i
->name
, UNIT_NAME_TEMPLATE
)) {
1861 UnitFileInstallInfo instance
= {
1862 .type
= _UNIT_FILE_TYPE_INVALID
,
1864 _cleanup_free_
char *path
= NULL
;
1866 /* If this is a template, and we have no instance, don't do anything */
1867 if (!i
->default_instance
)
1870 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &buf
);
1874 instance
.name
= buf
;
1875 r
= unit_file_search(NULL
, &instance
, paths
, SEARCH_FOLLOW_CONFIG_SYMLINKS
);
1879 path
= TAKE_PTR(instance
.path
);
1881 if (instance
.type
== UNIT_FILE_TYPE_MASKED
) {
1882 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, path
, NULL
);
1890 STRV_FOREACH(s
, list
) {
1891 _cleanup_free_
char *path
= NULL
, *dst
= NULL
;
1893 q
= install_full_printf(i
, *s
, &dst
);
1897 if (!unit_name_is_valid(dst
, UNIT_NAME_ANY
)) {
1898 unit_file_changes_add(changes
, n_changes
, -EUCLEAN
, dst
, NULL
);
1903 path
= strjoin(config_path
, "/", dst
, suffix
, n
);
1907 q
= create_symlink(paths
, i
->path
, path
, true, changes
, n_changes
);
1915 static int install_info_symlink_link(
1916 UnitFileInstallInfo
*i
,
1917 const LookupPaths
*paths
,
1918 const char *config_path
,
1920 UnitFileChange
**changes
,
1921 size_t *n_changes
) {
1923 _cleanup_free_
char *path
= NULL
;
1928 assert(config_path
);
1931 r
= in_search_path(paths
, i
->path
);
1937 path
= path_join(config_path
, i
->name
);
1941 return create_symlink(paths
, i
->path
, path
, force
, changes
, n_changes
);
1944 static int install_info_apply(
1945 UnitFileInstallInfo
*i
,
1946 const LookupPaths
*paths
,
1947 const char *config_path
,
1949 UnitFileChange
**changes
,
1950 size_t *n_changes
) {
1956 assert(config_path
);
1958 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
1961 r
= install_info_symlink_alias(i
, paths
, config_path
, force
, changes
, n_changes
);
1963 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->wanted_by
, ".wants/", changes
, n_changes
);
1967 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->required_by
, ".requires/", changes
, n_changes
);
1971 q
= install_info_symlink_link(i
, paths
, config_path
, force
, changes
, n_changes
);
1972 /* Do not count links to the unit file towards the "carries_install_info" count */
1973 if (r
== 0 && q
< 0)
1979 static int install_context_apply(
1980 UnitFileScope scope
,
1982 const LookupPaths
*paths
,
1983 const char *config_path
,
1986 UnitFileChange
**changes
,
1987 size_t *n_changes
) {
1989 UnitFileInstallInfo
*i
;
1994 assert(config_path
);
1996 if (ordered_hashmap_isempty(c
->will_process
))
1999 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
2004 while ((i
= ordered_hashmap_first(c
->will_process
))) {
2007 q
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
2011 q
= install_info_traverse(scope
, c
, paths
, i
, flags
, NULL
);
2013 unit_file_changes_add(changes
, n_changes
, q
, i
->name
, NULL
);
2017 /* We can attempt to process a masked unit when a different unit
2018 * that we were processing specifies it in Also=. */
2019 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
2020 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_MASKED
, i
->path
, NULL
);
2022 /* Assume that something *could* have been enabled here,
2023 * avoid "empty [Install] section" warning. */
2028 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
2031 q
= install_info_apply(i
, paths
, config_path
, force
, changes
, n_changes
);
2043 static int install_context_mark_for_removal(
2044 UnitFileScope scope
,
2046 const LookupPaths
*paths
,
2047 Set
**remove_symlinks_to
,
2048 const char *config_path
,
2049 UnitFileChange
**changes
,
2050 size_t *n_changes
) {
2052 UnitFileInstallInfo
*i
;
2057 assert(config_path
);
2059 /* Marks all items for removal */
2061 if (ordered_hashmap_isempty(c
->will_process
))
2064 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
2068 while ((i
= ordered_hashmap_first(c
->will_process
))) {
2070 r
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
2074 r
= install_info_traverse(scope
, c
, paths
, i
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, NULL
);
2075 if (r
== -ENOLINK
) {
2076 log_debug_errno(r
, "Name %s leads to a dangling symlink, removing name.", i
->name
);
2077 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_DANGLING
, i
->path
?: i
->name
, NULL
);
2078 } else if (r
== -ENOENT
) {
2080 if (i
->auxiliary
) /* some unit specified in Also= or similar is missing */
2081 log_debug_errno(r
, "Auxiliary unit of %s not found, removing name.", i
->name
);
2083 log_debug_errno(r
, "Unit %s not found, removing name.", i
->name
);
2084 unit_file_changes_add(changes
, n_changes
, r
, i
->path
?: i
->name
, NULL
);
2088 log_debug_errno(r
, "Failed to find unit %s, removing name: %m", i
->name
);
2089 unit_file_changes_add(changes
, n_changes
, r
, i
->path
?: i
->name
, NULL
);
2090 } else if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
2091 log_debug("Unit file %s is masked, ignoring.", i
->name
);
2092 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_MASKED
, i
->path
?: i
->name
, NULL
);
2094 } else if (i
->type
!= UNIT_FILE_TYPE_REGULAR
) {
2095 log_debug("Unit %s has type %s, ignoring.", i
->name
, unit_file_type_to_string(i
->type
) ?: "invalid");
2099 r
= mark_symlink_for_removal(remove_symlinks_to
, i
->name
);
2108 UnitFileScope scope
,
2109 UnitFileFlags flags
,
2110 const char *root_dir
,
2112 UnitFileChange
**changes
,
2113 size_t *n_changes
) {
2115 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2116 const char *config_path
;
2121 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2123 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2127 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2131 STRV_FOREACH(i
, files
) {
2132 _cleanup_free_
char *path
= NULL
;
2135 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
)) {
2141 path
= path_make_absolute(*i
, config_path
);
2145 q
= create_symlink(&paths
, "/dev/null", path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2146 if (q
< 0 && r
>= 0)
2153 int unit_file_unmask(
2154 UnitFileScope scope
,
2155 UnitFileFlags flags
,
2156 const char *root_dir
,
2158 UnitFileChange
**changes
,
2159 size_t *n_changes
) {
2161 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2162 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2163 _cleanup_strv_free_
char **todo
= NULL
;
2164 size_t n_todo
= 0, n_allocated
= 0;
2165 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 dry_run
= !!(flags
& UNIT_FILE_DRY_RUN
);
2183 STRV_FOREACH(i
, files
) {
2184 _cleanup_free_
char *path
= NULL
;
2186 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2189 path
= path_make_absolute(*i
, config_path
);
2193 r
= null_or_empty_path(path
);
2201 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2204 todo
[n_todo
] = strdup(*i
);
2214 STRV_FOREACH(i
, todo
) {
2215 _cleanup_free_
char *path
= NULL
;
2218 path
= path_make_absolute(*i
, config_path
);
2222 if (!dry_run
&& unlink(path
) < 0) {
2223 if (errno
!= ENOENT
) {
2226 unit_file_changes_add(changes
, n_changes
, -errno
, path
, NULL
);
2232 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
2234 rp
= skip_root(&paths
, path
);
2235 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: path
);
2240 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, dry_run
, changes
, n_changes
);
2248 UnitFileScope scope
,
2249 UnitFileFlags flags
,
2250 const char *root_dir
,
2252 UnitFileChange
**changes
,
2253 size_t *n_changes
) {
2255 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2256 _cleanup_strv_free_
char **todo
= NULL
;
2257 size_t n_todo
= 0, n_allocated
= 0;
2258 const char *config_path
;
2263 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2265 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2269 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2273 STRV_FOREACH(i
, files
) {
2274 _cleanup_free_
char *full
= NULL
;
2278 if (!path_is_absolute(*i
))
2282 if (!unit_name_is_valid(fn
, UNIT_NAME_ANY
))
2285 full
= path_join(paths
.root_dir
, *i
);
2289 if (lstat(full
, &st
) < 0)
2291 r
= stat_verify_regular(&st
);
2295 q
= in_search_path(&paths
, *i
);
2301 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2304 todo
[n_todo
] = strdup(*i
);
2314 STRV_FOREACH(i
, todo
) {
2315 _cleanup_free_
char *new_path
= NULL
;
2317 new_path
= path_make_absolute(basename(*i
), config_path
);
2321 q
= create_symlink(&paths
, *i
, new_path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2322 if (q
< 0 && r
>= 0)
2329 static int path_shall_revert(const LookupPaths
*paths
, const char *path
) {
2335 /* Checks whether the path is one where the drop-in directories shall be removed. */
2337 r
= path_is_config(paths
, path
, true);
2341 r
= path_is_control(paths
, path
);
2345 return path_is_transient(paths
, path
);
2348 int unit_file_revert(
2349 UnitFileScope scope
,
2350 const char *root_dir
,
2352 UnitFileChange
**changes
,
2353 size_t *n_changes
) {
2355 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2356 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2357 _cleanup_strv_free_
char **todo
= NULL
;
2358 size_t n_todo
= 0, n_allocated
= 0;
2362 /* Puts a unit file back into vendor state. This means:
2364 * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and
2365 * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated").
2367 * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in
2368 * "config", but not in "transient" or "control" or even "generated").
2370 * We remove all that in both the runtime and the persistent directories, if that applies.
2373 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2377 STRV_FOREACH(i
, files
) {
2378 bool has_vendor
= false;
2381 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2384 STRV_FOREACH(p
, paths
.search_path
) {
2385 _cleanup_free_
char *path
= NULL
, *dropin
= NULL
;
2388 path
= path_make_absolute(*i
, *p
);
2392 r
= lstat(path
, &st
);
2394 if (errno
!= ENOENT
)
2396 } else if (S_ISREG(st
.st_mode
)) {
2397 /* Check if there's a vendor version */
2398 r
= path_is_vendor_or_generator(&paths
, path
);
2405 dropin
= strjoin(path
, ".d");
2409 r
= lstat(dropin
, &st
);
2411 if (errno
!= ENOENT
)
2413 } else if (S_ISDIR(st
.st_mode
)) {
2414 /* Remove the drop-ins */
2415 r
= path_shall_revert(&paths
, dropin
);
2419 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2422 todo
[n_todo
++] = TAKE_PTR(dropin
);
2430 /* OK, there's a vendor version, hence drop all configuration versions */
2431 STRV_FOREACH(p
, paths
.search_path
) {
2432 _cleanup_free_
char *path
= NULL
;
2435 path
= path_make_absolute(*i
, *p
);
2439 r
= lstat(path
, &st
);
2441 if (errno
!= ENOENT
)
2443 } else if (S_ISREG(st
.st_mode
) || S_ISLNK(st
.st_mode
)) {
2444 r
= path_is_config(&paths
, path
, true);
2448 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2451 todo
[n_todo
++] = TAKE_PTR(path
);
2460 STRV_FOREACH(i
, todo
) {
2461 _cleanup_strv_free_
char **fs
= NULL
;
2465 (void) get_files_in_directory(*i
, &fs
);
2467 q
= rm_rf(*i
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
2468 if (q
< 0 && q
!= -ENOENT
&& r
>= 0) {
2473 STRV_FOREACH(j
, fs
) {
2474 _cleanup_free_
char *t
= NULL
;
2476 t
= path_join(*i
, *j
);
2480 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, t
, NULL
);
2483 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, *i
, NULL
);
2485 rp
= skip_root(&paths
, *i
);
2486 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: *i
);
2491 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.runtime_config
, &paths
, false, changes
, n_changes
);
2495 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.persistent_config
, &paths
, false, changes
, n_changes
);
2502 int unit_file_add_dependency(
2503 UnitFileScope scope
,
2504 UnitFileFlags flags
,
2505 const char *root_dir
,
2509 UnitFileChange
**changes
,
2510 size_t *n_changes
) {
2512 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2513 _cleanup_(install_context_done
) InstallContext c
= {};
2514 UnitFileInstallInfo
*i
, *target_info
;
2515 const char *config_path
;
2520 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2523 if (!IN_SET(dep
, UNIT_WANTS
, UNIT_REQUIRES
))
2526 if (!unit_name_is_valid(target
, UNIT_NAME_ANY
))
2529 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2533 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2537 r
= install_info_discover_and_check(scope
, &c
, &paths
, target
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2538 &target_info
, changes
, n_changes
);
2542 assert(target_info
->type
== UNIT_FILE_TYPE_REGULAR
);
2544 STRV_FOREACH(f
, files
) {
2547 r
= install_info_discover_and_check(scope
, &c
, &paths
, *f
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2548 &i
, changes
, n_changes
);
2552 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2554 /* We didn't actually load anything from the unit
2555 * file, but instead just add in our new symlink to
2558 if (dep
== UNIT_WANTS
)
2561 l
= &i
->required_by
;
2564 *l
= strv_new(target_info
->name
);
2569 return install_context_apply(scope
, &c
, &paths
, config_path
, !!(flags
& UNIT_FILE_FORCE
), SEARCH_FOLLOW_CONFIG_SYMLINKS
, changes
, n_changes
);
2572 int unit_file_enable(
2573 UnitFileScope scope
,
2574 UnitFileFlags flags
,
2575 const char *root_dir
,
2577 UnitFileChange
**changes
,
2578 size_t *n_changes
) {
2580 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2581 _cleanup_(install_context_done
) InstallContext c
= {};
2582 const char *config_path
;
2583 UnitFileInstallInfo
*i
;
2588 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2590 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2594 config_path
= config_path_from_flags(&paths
, flags
);
2598 STRV_FOREACH(f
, files
) {
2599 r
= install_info_discover_and_check(scope
, &c
, &paths
, *f
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2600 &i
, changes
, n_changes
);
2604 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2607 /* This will return the number of symlink rules that were
2608 supposed to be created, not the ones actually created. This
2609 is useful to determine whether the passed files had any
2610 installation data at all. */
2612 return install_context_apply(scope
, &c
, &paths
, config_path
, !!(flags
& UNIT_FILE_FORCE
), SEARCH_LOAD
, changes
, n_changes
);
2615 int unit_file_disable(
2616 UnitFileScope scope
,
2617 UnitFileFlags flags
,
2618 const char *root_dir
,
2620 UnitFileChange
**changes
,
2621 size_t *n_changes
) {
2623 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2624 _cleanup_(install_context_done
) InstallContext c
= {};
2625 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2626 const char *config_path
;
2631 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2633 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2637 config_path
= config_path_from_flags(&paths
, flags
);
2641 STRV_FOREACH(i
, files
) {
2642 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2645 r
= install_info_add(&c
, *i
, NULL
, false, NULL
);
2650 r
= install_context_mark_for_removal(scope
, &c
, &paths
, &remove_symlinks_to
, config_path
, changes
, n_changes
);
2654 return remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, !!(flags
& UNIT_FILE_DRY_RUN
), changes
, n_changes
);
2657 int unit_file_reenable(
2658 UnitFileScope scope
,
2659 UnitFileFlags flags
,
2660 const char *root_dir
,
2662 UnitFileChange
**changes
,
2663 size_t *n_changes
) {
2669 /* First, we invoke the disable command with only the basename... */
2670 l
= strv_length(files
);
2671 n
= newa(char*, l
+1);
2672 for (i
= 0; i
< l
; i
++)
2673 n
[i
] = basename(files
[i
]);
2676 r
= unit_file_disable(scope
, flags
, root_dir
, n
, changes
, n_changes
);
2680 /* But the enable command with the full name */
2681 return unit_file_enable(scope
, flags
, root_dir
, files
, changes
, n_changes
);
2684 int unit_file_set_default(
2685 UnitFileScope scope
,
2686 UnitFileFlags flags
,
2687 const char *root_dir
,
2689 UnitFileChange
**changes
,
2690 size_t *n_changes
) {
2692 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2693 _cleanup_(install_context_done
) InstallContext c
= {};
2694 UnitFileInstallInfo
*i
;
2695 const char *new_path
;
2699 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2702 if (unit_name_to_type(name
) != UNIT_TARGET
) /* this also validates the name */
2704 if (streq(name
, SPECIAL_DEFAULT_TARGET
))
2707 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2711 r
= install_info_discover_and_check(scope
, &c
, &paths
, name
, 0, &i
, changes
, n_changes
);
2715 new_path
= strjoina(paths
.persistent_config
, "/" SPECIAL_DEFAULT_TARGET
);
2716 return create_symlink(&paths
, i
->path
, new_path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2719 int unit_file_get_default(
2720 UnitFileScope scope
,
2721 const char *root_dir
,
2724 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2725 _cleanup_(install_context_done
) InstallContext c
= {};
2726 UnitFileInstallInfo
*i
;
2731 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2734 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2738 r
= install_info_discover(scope
, &c
, &paths
, SPECIAL_DEFAULT_TARGET
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2742 r
= install_info_may_process(i
, &paths
, NULL
, 0);
2746 n
= strdup(i
->name
);
2754 int unit_file_lookup_state(
2755 UnitFileScope scope
,
2756 const LookupPaths
*paths
,
2758 UnitFileState
*ret
) {
2760 _cleanup_(install_context_done
) InstallContext c
= {};
2761 UnitFileInstallInfo
*i
;
2762 UnitFileState state
;
2768 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2771 r
= install_info_discover(scope
, &c
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2774 return log_debug_errno(r
, "Failed to discover unit %s: %m", name
);
2776 assert(IN_SET(i
->type
, UNIT_FILE_TYPE_REGULAR
, UNIT_FILE_TYPE_MASKED
));
2777 log_debug("Found unit %s at %s (%s)", name
, strna(i
->path
),
2778 i
->type
== UNIT_FILE_TYPE_REGULAR
? "regular file" : "mask");
2780 /* Shortcut things, if the caller just wants to know if this unit exists. */
2786 case UNIT_FILE_TYPE_MASKED
:
2787 r
= path_is_runtime(paths
, i
->path
, true);
2791 state
= r
> 0 ? UNIT_FILE_MASKED_RUNTIME
: UNIT_FILE_MASKED
;
2794 case UNIT_FILE_TYPE_REGULAR
:
2795 /* Check if the name we were querying is actually an alias */
2796 if (!streq(name
, basename(i
->path
)) && !unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
)) {
2797 state
= UNIT_FILE_ALIAS
;
2801 r
= path_is_generator(paths
, i
->path
);
2805 state
= UNIT_FILE_GENERATED
;
2809 r
= path_is_transient(paths
, i
->path
);
2813 state
= UNIT_FILE_TRANSIENT
;
2817 /* Check if any of the Alias= symlinks have been created.
2818 * We ignore other aliases, and only check those that would
2819 * be created by systemctl enable for this unit. */
2820 r
= find_symlinks_in_scope(scope
, paths
, i
, true, &state
);
2826 /* Check if the file is known under other names. If it is,
2827 * it might be in use. Report that as UNIT_FILE_INDIRECT. */
2828 r
= find_symlinks_in_scope(scope
, paths
, i
, false, &state
);
2832 state
= UNIT_FILE_INDIRECT
;
2834 if (unit_file_install_info_has_rules(i
))
2835 state
= UNIT_FILE_DISABLED
;
2836 else if (unit_file_install_info_has_also(i
))
2837 state
= UNIT_FILE_INDIRECT
;
2839 state
= UNIT_FILE_STATIC
;
2845 assert_not_reached("Unexpected unit file type.");
2852 int unit_file_get_state(
2853 UnitFileScope scope
,
2854 const char *root_dir
,
2856 UnitFileState
*ret
) {
2858 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2862 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2865 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2869 return unit_file_lookup_state(scope
, &paths
, name
, ret
);
2872 int unit_file_exists(UnitFileScope scope
, const LookupPaths
*paths
, const char *name
) {
2873 _cleanup_(install_context_done
) InstallContext c
= {};
2879 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2882 r
= install_info_discover(scope
, &c
, paths
, name
, 0, NULL
, NULL
, NULL
);
2891 static int split_pattern_into_name_and_instances(const char *pattern
, char **out_unit_name
, char ***out_instances
) {
2892 _cleanup_strv_free_
char **instances
= NULL
;
2893 _cleanup_free_
char *unit_name
= NULL
;
2897 assert(out_instances
);
2898 assert(out_unit_name
);
2900 r
= extract_first_word(&pattern
, &unit_name
, NULL
, EXTRACT_RETAIN_ESCAPE
);
2904 /* We handle the instances logic when unit name is extracted */
2906 /* We only create instances when a rule of templated unit
2907 * is seen. A rule like enable foo@.service a b c will
2908 * result in an array of (a, b, c) as instance names */
2909 if (!unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
))
2912 instances
= strv_split(pattern
, WHITESPACE
);
2916 *out_instances
= TAKE_PTR(instances
);
2919 *out_unit_name
= TAKE_PTR(unit_name
);
2924 static int presets_find_config(UnitFileScope scope
, const char *root_dir
, char ***files
) {
2925 static const char* const system_dirs
[] = {CONF_PATHS("systemd/system-preset"), NULL
};
2926 static const char* const user_dirs
[] = {CONF_PATHS_USR("systemd/user-preset"), NULL
};
2927 const char* const* dirs
;
2930 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2932 if (scope
== UNIT_FILE_SYSTEM
)
2934 else if (IN_SET(scope
, UNIT_FILE_GLOBAL
, UNIT_FILE_USER
))
2937 assert_not_reached("Invalid unit file scope");
2939 return conf_files_list_strv(files
, ".preset", root_dir
, 0, dirs
);
2942 static int read_presets(UnitFileScope scope
, const char *root_dir
, UnitFilePresets
*presets
) {
2943 _cleanup_(unit_file_presets_freep
) UnitFilePresets ps
= {};
2944 size_t n_allocated
= 0;
2945 _cleanup_strv_free_
char **files
= NULL
;
2950 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2953 r
= presets_find_config(scope
, root_dir
, &files
);
2957 STRV_FOREACH(p
, files
) {
2958 _cleanup_fclose_
FILE *f
;
2961 f
= fopen(*p
, "re");
2963 if (errno
== ENOENT
)
2970 _cleanup_free_
char *line
= NULL
;
2971 UnitFilePresetRule rule
= {};
2972 const char *parameter
;
2975 r
= read_line(f
, LONG_LINE_MAX
, &line
);
2986 if (strchr(COMMENTS
, *l
))
2989 parameter
= first_word(l
, "enable");
2992 char **instances
= NULL
;
2994 /* Unit_name will remain the same as parameter when no instances are specified */
2995 r
= split_pattern_into_name_and_instances(parameter
, &unit_name
, &instances
);
2997 log_syntax(NULL
, LOG_WARNING
, *p
, n
, r
, "Couldn't parse line '%s'. Ignoring.", line
);
3001 rule
= (UnitFilePresetRule
) {
3002 .pattern
= unit_name
,
3003 .action
= PRESET_ENABLE
,
3004 .instances
= instances
,
3008 parameter
= first_word(l
, "disable");
3012 pattern
= strdup(parameter
);
3016 rule
= (UnitFilePresetRule
) {
3018 .action
= PRESET_DISABLE
,
3023 if (!GREEDY_REALLOC(ps
.rules
, n_allocated
, ps
.n_rules
+ 1))
3026 ps
.rules
[ps
.n_rules
++] = rule
;
3030 log_syntax(NULL
, LOG_WARNING
, *p
, n
, 0, "Couldn't parse line '%s'. Ignoring.", line
);
3034 ps
.initialized
= true;
3036 ps
= (UnitFilePresets
){};
3041 static int pattern_match_multiple_instances(
3042 const UnitFilePresetRule rule
,
3043 const char *unit_name
,
3046 _cleanup_free_
char *templated_name
= NULL
;
3049 /* If no ret is needed or the rule itself does not have instances
3050 * initialized, we return not matching */
3051 if (!ret
|| !rule
.instances
)
3054 r
= unit_name_template(unit_name
, &templated_name
);
3057 if (!streq(rule
.pattern
, templated_name
))
3060 /* Compose a list of specified instances when unit name is a template */
3061 if (unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
3062 _cleanup_strv_free_
char **out_strv
= NULL
;
3065 STRV_FOREACH(iter
, rule
.instances
) {
3066 _cleanup_free_
char *name
= NULL
;
3068 r
= unit_name_replace_instance(unit_name
, *iter
, &name
);
3072 r
= strv_consume(&out_strv
, TAKE_PTR(name
));
3077 *ret
= TAKE_PTR(out_strv
);
3080 /* We now know the input unit name is an instance name */
3081 _cleanup_free_
char *instance_name
= NULL
;
3083 r
= unit_name_to_instance(unit_name
, &instance_name
);
3087 if (strv_find(rule
.instances
, instance_name
))
3093 static int query_presets(const char *name
, const UnitFilePresets
*presets
, char ***instance_name_list
) {
3094 PresetAction action
= PRESET_UNKNOWN
;
3096 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
3099 for (size_t i
= 0; i
< presets
->n_rules
; i
++)
3100 if (pattern_match_multiple_instances(presets
->rules
[i
], name
, instance_name_list
) > 0 ||
3101 fnmatch(presets
->rules
[i
].pattern
, name
, FNM_NOESCAPE
) == 0) {
3102 action
= presets
->rules
[i
].action
;
3107 case PRESET_UNKNOWN
:
3108 log_debug("Preset files don't specify rule for %s. Enabling.", name
);
3111 if (instance_name_list
&& *instance_name_list
) {
3113 STRV_FOREACH(s
, *instance_name_list
)
3114 log_debug("Preset files say enable %s.", *s
);
3116 log_debug("Preset files say enable %s.", name
);
3118 case PRESET_DISABLE
:
3119 log_debug("Preset files say disable %s.", name
);
3122 assert_not_reached("invalid preset action");
3126 int unit_file_query_preset(UnitFileScope scope
, const char *root_dir
, const char *name
, UnitFilePresets
*cached
) {
3127 _cleanup_(unit_file_presets_freep
) UnitFilePresets tmp
= {};
3132 if (!cached
->initialized
) {
3133 r
= read_presets(scope
, root_dir
, cached
);
3138 return query_presets(name
, cached
, NULL
);
3141 static int execute_preset(
3142 UnitFileScope scope
,
3143 InstallContext
*plus
,
3144 InstallContext
*minus
,
3145 const LookupPaths
*paths
,
3146 const char *config_path
,
3148 UnitFilePresetMode mode
,
3150 UnitFileChange
**changes
,
3151 size_t *n_changes
) {
3158 assert(config_path
);
3160 if (mode
!= UNIT_FILE_PRESET_ENABLE_ONLY
) {
3161 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
3163 r
= install_context_mark_for_removal(scope
, minus
, paths
, &remove_symlinks_to
, config_path
, changes
, n_changes
);
3167 r
= remove_marked_symlinks(remove_symlinks_to
, config_path
, paths
, false, changes
, n_changes
);
3171 if (mode
!= UNIT_FILE_PRESET_DISABLE_ONLY
) {
3174 /* Returns number of symlinks that where supposed to be installed. */
3175 q
= install_context_apply(scope
, plus
, paths
, config_path
, force
, SEARCH_LOAD
, changes
, n_changes
);
3187 static int preset_prepare_one(
3188 UnitFileScope scope
,
3189 InstallContext
*plus
,
3190 InstallContext
*minus
,
3193 const UnitFilePresets
*presets
,
3194 UnitFileChange
**changes
,
3195 size_t *n_changes
) {
3197 _cleanup_(install_context_done
) InstallContext tmp
= {};
3198 _cleanup_strv_free_
char **instance_name_list
= NULL
;
3199 UnitFileInstallInfo
*i
;
3202 if (install_info_find(plus
, name
) || install_info_find(minus
, name
))
3205 r
= install_info_discover(scope
, &tmp
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3206 &i
, changes
, n_changes
);
3209 if (!streq(name
, i
->name
)) {
3210 log_debug("Skipping %s because it is an alias for %s.", name
, i
->name
);
3214 r
= query_presets(name
, presets
, &instance_name_list
);
3219 if (instance_name_list
) {
3221 STRV_FOREACH(s
, instance_name_list
) {
3222 r
= install_info_discover_and_check(scope
, plus
, paths
, *s
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3223 &i
, changes
, n_changes
);
3228 r
= install_info_discover_and_check(scope
, plus
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3229 &i
, changes
, n_changes
);
3235 r
= install_info_discover(scope
, minus
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3236 &i
, changes
, n_changes
);
3241 int unit_file_preset(
3242 UnitFileScope scope
,
3243 UnitFileFlags flags
,
3244 const char *root_dir
,
3246 UnitFilePresetMode mode
,
3247 UnitFileChange
**changes
,
3248 size_t *n_changes
) {
3250 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
3251 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3252 _cleanup_(unit_file_presets_freep
) UnitFilePresets presets
= {};
3253 const char *config_path
;
3258 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3259 assert(mode
< _UNIT_FILE_PRESET_MAX
);
3261 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3265 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
3269 r
= read_presets(scope
, root_dir
, &presets
);
3273 STRV_FOREACH(i
, files
) {
3274 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, *i
, &presets
, changes
, n_changes
);
3279 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, files
, mode
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
3282 int unit_file_preset_all(
3283 UnitFileScope scope
,
3284 UnitFileFlags flags
,
3285 const char *root_dir
,
3286 UnitFilePresetMode mode
,
3287 UnitFileChange
**changes
,
3288 size_t *n_changes
) {
3290 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
3291 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3292 _cleanup_(unit_file_presets_freep
) UnitFilePresets presets
= {};
3293 const char *config_path
= NULL
;
3298 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3299 assert(mode
< _UNIT_FILE_PRESET_MAX
);
3301 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3305 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
3309 r
= read_presets(scope
, root_dir
, &presets
);
3313 STRV_FOREACH(i
, paths
.search_path
) {
3314 _cleanup_closedir_
DIR *d
= NULL
;
3319 if (errno
== ENOENT
)
3325 FOREACH_DIRENT(de
, d
, return -errno
) {
3327 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
3330 dirent_ensure_type(d
, de
);
3332 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
3335 /* we don't pass changes[] in, because we want to handle errors on our own */
3336 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, de
->d_name
, &presets
, NULL
, 0);
3338 r
= unit_file_changes_add(changes
, n_changes
,
3339 UNIT_FILE_IS_MASKED
, de
->d_name
, NULL
);
3340 else if (r
== -ENOLINK
)
3341 r
= unit_file_changes_add(changes
, n_changes
,
3342 UNIT_FILE_IS_DANGLING
, de
->d_name
, NULL
);
3343 else if (r
== -EADDRNOTAVAIL
) /* Ignore generated/transient units when applying preset */
3350 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, NULL
, mode
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
3353 static void unit_file_list_free_one(UnitFileList
*f
) {
3361 Hashmap
* unit_file_list_free(Hashmap
*h
) {
3362 return hashmap_free_with_destructor(h
, unit_file_list_free_one
);
3365 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList
*, unit_file_list_free_one
);
3367 int unit_file_get_list(
3368 UnitFileScope scope
,
3369 const char *root_dir
,
3374 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3379 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3382 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3386 STRV_FOREACH(dirname
, paths
.search_path
) {
3387 _cleanup_closedir_
DIR *d
= NULL
;
3390 d
= opendir(*dirname
);
3392 if (errno
== ENOENT
)
3394 if (IN_SET(errno
, ENOTDIR
, EACCES
)) {
3395 log_debug_errno(errno
, "Failed to open \"%s\": %m", *dirname
);
3402 FOREACH_DIRENT(de
, d
, return -errno
) {
3403 _cleanup_(unit_file_list_free_onep
) UnitFileList
*f
= NULL
;
3405 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
3408 if (!strv_fnmatch_or_empty(patterns
, de
->d_name
, FNM_NOESCAPE
))
3411 if (hashmap_get(h
, de
->d_name
))
3414 dirent_ensure_type(d
, de
);
3416 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
3419 f
= new0(UnitFileList
, 1);
3423 f
->path
= path_make_absolute(de
->d_name
, *dirname
);
3427 r
= unit_file_lookup_state(scope
, &paths
, de
->d_name
, &f
->state
);
3429 f
->state
= UNIT_FILE_BAD
;
3431 if (!strv_isempty(states
) &&
3432 !strv_contains(states
, unit_file_state_to_string(f
->state
)))
3435 r
= hashmap_put(h
, basename(f
->path
), f
);
3439 f
= NULL
; /* prevent cleanup */
3446 static const char* const unit_file_state_table
[_UNIT_FILE_STATE_MAX
] = {
3447 [UNIT_FILE_ENABLED
] = "enabled",
3448 [UNIT_FILE_ENABLED_RUNTIME
] = "enabled-runtime",
3449 [UNIT_FILE_LINKED
] = "linked",
3450 [UNIT_FILE_LINKED_RUNTIME
] = "linked-runtime",
3451 [UNIT_FILE_ALIAS
] = "alias",
3452 [UNIT_FILE_MASKED
] = "masked",
3453 [UNIT_FILE_MASKED_RUNTIME
] = "masked-runtime",
3454 [UNIT_FILE_STATIC
] = "static",
3455 [UNIT_FILE_DISABLED
] = "disabled",
3456 [UNIT_FILE_INDIRECT
] = "indirect",
3457 [UNIT_FILE_GENERATED
] = "generated",
3458 [UNIT_FILE_TRANSIENT
] = "transient",
3459 [UNIT_FILE_BAD
] = "bad",
3462 DEFINE_STRING_TABLE_LOOKUP(unit_file_state
, UnitFileState
);
3464 static const char* const unit_file_change_type_table
[_UNIT_FILE_CHANGE_TYPE_MAX
] = {
3465 [UNIT_FILE_SYMLINK
] = "symlink",
3466 [UNIT_FILE_UNLINK
] = "unlink",
3467 [UNIT_FILE_IS_MASKED
] = "masked",
3468 [UNIT_FILE_IS_DANGLING
] = "dangling",
3471 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type
, UnitFileChangeType
);
3473 static const char* const unit_file_preset_mode_table
[_UNIT_FILE_PRESET_MAX
] = {
3474 [UNIT_FILE_PRESET_FULL
] = "full",
3475 [UNIT_FILE_PRESET_ENABLE_ONLY
] = "enable-only",
3476 [UNIT_FILE_PRESET_DISABLE_ONLY
] = "disable-only",
3479 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode
, UnitFilePresetMode
);