1 /* SPDX-License-Identifier: LGPL-2.1+ */
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
) {
84 for (i
= 0; i
< p
->n_rules
; i
++) {
85 free(p
->rules
[i
].pattern
);
86 strv_free(p
->rules
[i
].instances
);
93 static const char *const unit_file_type_table
[_UNIT_FILE_TYPE_MAX
] = {
94 [UNIT_FILE_TYPE_REGULAR
] = "regular",
95 [UNIT_FILE_TYPE_SYMLINK
] = "symlink",
96 [UNIT_FILE_TYPE_MASKED
] = "masked",
99 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(unit_file_type
, UnitFileType
);
101 static int in_search_path(const LookupPaths
*p
, const char *path
) {
102 _cleanup_free_
char *parent
= NULL
;
106 parent
= dirname_malloc(path
);
110 return path_strv_contains(p
->search_path
, parent
);
113 static const char* skip_root(const LookupPaths
*p
, const char *path
) {
122 e
= path_startswith(path
, p
->root_dir
);
126 /* Make sure the returned path starts with a slash */
128 if (e
== path
|| e
[-1] != '/')
137 static int path_is_generator(const LookupPaths
*p
, const char *path
) {
138 _cleanup_free_
char *parent
= NULL
;
143 parent
= dirname_malloc(path
);
147 return path_equal_ptr(parent
, p
->generator
) ||
148 path_equal_ptr(parent
, p
->generator_early
) ||
149 path_equal_ptr(parent
, p
->generator_late
);
152 static int path_is_transient(const LookupPaths
*p
, const char *path
) {
153 _cleanup_free_
char *parent
= NULL
;
158 parent
= dirname_malloc(path
);
162 return path_equal_ptr(parent
, p
->transient
);
165 static int path_is_control(const LookupPaths
*p
, const char *path
) {
166 _cleanup_free_
char *parent
= NULL
;
171 parent
= dirname_malloc(path
);
175 return path_equal_ptr(parent
, p
->persistent_control
) ||
176 path_equal_ptr(parent
, p
->runtime_control
);
179 static int path_is_config(const LookupPaths
*p
, const char *path
, bool check_parent
) {
180 _cleanup_free_
char *parent
= NULL
;
185 /* Note that we do *not* have generic checks for /etc or /run in place, since with
186 * them we couldn't discern configuration from transient or generated units */
189 parent
= dirname_malloc(path
);
196 return path_equal_ptr(path
, p
->persistent_config
) ||
197 path_equal_ptr(path
, p
->runtime_config
);
200 static int path_is_runtime(const LookupPaths
*p
, const char *path
, bool check_parent
) {
201 _cleanup_free_
char *parent
= NULL
;
207 /* Everything in /run is considered runtime. On top of that we also add
208 * explicit checks for the various runtime directories, as safety net. */
210 rpath
= skip_root(p
, path
);
211 if (rpath
&& path_startswith(rpath
, "/run"))
215 parent
= dirname_malloc(path
);
222 return path_equal_ptr(path
, p
->runtime_config
) ||
223 path_equal_ptr(path
, p
->generator
) ||
224 path_equal_ptr(path
, p
->generator_early
) ||
225 path_equal_ptr(path
, p
->generator_late
) ||
226 path_equal_ptr(path
, p
->transient
) ||
227 path_equal_ptr(path
, p
->runtime_control
);
230 static int path_is_vendor(const LookupPaths
*p
, const char *path
) {
236 rpath
= skip_root(p
, path
);
240 if (path_startswith(rpath
, "/usr"))
244 if (path_startswith(rpath
, "/lib"))
248 return path_equal(rpath
, SYSTEM_DATA_UNIT_PATH
);
251 int unit_file_changes_add(
252 UnitFileChange
**changes
,
254 UnitFileChangeType type
,
256 const char *source
) {
258 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
262 assert(!changes
== !n_changes
);
267 c
= reallocarray(*changes
, *n_changes
+ 1, sizeof(UnitFileChange
));
276 if (!p
|| (source
&& !s
))
279 path_simplify(p
, false);
281 path_simplify(s
, false);
283 c
[*n_changes
] = (UnitFileChange
) { type
, p
, s
};
289 void unit_file_changes_free(UnitFileChange
*changes
, size_t n_changes
) {
292 assert(changes
|| n_changes
== 0);
294 for (i
= 0; i
< n_changes
; i
++) {
295 free(changes
[i
].path
);
296 free(changes
[i
].source
);
302 void unit_file_dump_changes(int r
, const char *verb
, const UnitFileChange
*changes
, size_t n_changes
, bool quiet
) {
306 assert(changes
|| n_changes
== 0);
307 /* If verb is not specified, errors are not allowed! */
308 assert(verb
|| r
>= 0);
310 for (i
= 0; i
< n_changes
; i
++) {
311 assert(verb
|| changes
[i
].type
>= 0);
313 switch(changes
[i
].type
) {
314 case UNIT_FILE_SYMLINK
:
316 log_info("Created symlink %s %s %s.",
318 special_glyph(SPECIAL_GLYPH_ARROW
),
321 case UNIT_FILE_UNLINK
:
323 log_info("Removed %s.", changes
[i
].path
);
325 case UNIT_FILE_IS_MASKED
:
327 log_info("Unit %s is masked, ignoring.", changes
[i
].path
);
329 case UNIT_FILE_IS_DANGLING
:
331 log_info("Unit %s is an alias to a unit that is not present, ignoring.",
335 if (changes
[i
].source
)
336 log_error_errno(changes
[i
].type
,
337 "Failed to %s unit, file %s already exists and is a symlink to %s.",
338 verb
, changes
[i
].path
, changes
[i
].source
);
340 log_error_errno(changes
[i
].type
,
341 "Failed to %s unit, file %s already exists.",
342 verb
, changes
[i
].path
);
346 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s is masked.",
347 verb
, changes
[i
].path
);
351 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s is transient or generated.",
352 verb
, changes
[i
].path
);
356 log_error_errno(changes
[i
].type
,
357 "Failed to %s unit, \"%s\" is not a valid unit name.",
358 verb
, changes
[i
].path
);
362 log_error_errno(changes
[i
].type
, "Failed to %s unit, refusing to operate on linked unit file %s",
363 verb
, changes
[i
].path
);
368 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s does not exist.", verb
, changes
[i
].path
);
373 assert(changes
[i
].type
< 0);
374 log_error_errno(changes
[i
].type
, "Failed to %s unit, file %s: %m.",
375 verb
, changes
[i
].path
);
380 if (r
< 0 && !logged
)
381 log_error_errno(r
, "Failed to %s: %m.", verb
);
385 * Checks if two paths or symlinks from wd are the same, when root is the root of the filesystem.
386 * wc should be the full path in the host file system.
388 static bool chroot_symlinks_same(const char *root
, const char *wd
, const char *a
, const char *b
) {
389 assert(path_is_absolute(wd
));
391 /* This will give incorrect results if the paths are relative and go outside
392 * of the chroot. False negatives are possible. */
397 a
= strjoina(path_is_absolute(a
) ? root
: wd
, "/", a
);
398 b
= strjoina(path_is_absolute(b
) ? root
: wd
, "/", b
);
399 return path_equal_or_files_same(a
, b
, 0);
402 static int create_symlink(
403 const LookupPaths
*paths
,
404 const char *old_path
,
405 const char *new_path
,
407 UnitFileChange
**changes
,
410 _cleanup_free_
char *dest
= NULL
, *dirname
= NULL
;
417 rp
= skip_root(paths
, old_path
);
421 /* Actually create a symlink, and remember that we did. Is
422 * smart enough to check if there's already a valid symlink in
425 * Returns 1 if a symlink was created or already exists and points to
426 * the right place, or negative on error.
429 mkdir_parents_label(new_path
, 0755);
431 if (symlink(old_path
, new_path
) >= 0) {
432 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
436 if (errno
!= EEXIST
) {
437 unit_file_changes_add(changes
, n_changes
, -errno
, new_path
, NULL
);
441 r
= readlink_malloc(new_path
, &dest
);
443 /* translate EINVAL (non-symlink exists) to EEXIST */
447 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
451 dirname
= dirname_malloc(new_path
);
455 if (chroot_symlinks_same(paths
->root_dir
, dirname
, dest
, old_path
)) {
456 log_debug("Symlink %s → %s already exists", new_path
, dest
);
461 unit_file_changes_add(changes
, n_changes
, -EEXIST
, new_path
, dest
);
465 r
= symlink_atomic(old_path
, new_path
);
467 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
471 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, new_path
, NULL
);
472 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
477 static int mark_symlink_for_removal(
478 Set
**remove_symlinks_to
,
486 r
= set_ensure_allocated(remove_symlinks_to
, &path_hash_ops
);
494 path_simplify(n
, false);
496 r
= set_consume(*remove_symlinks_to
, n
);
505 static int remove_marked_symlinks_fd(
506 Set
*remove_symlinks_to
,
509 const char *config_path
,
510 const LookupPaths
*lp
,
513 UnitFileChange
**changes
,
516 _cleanup_closedir_
DIR *d
= NULL
;
520 assert(remove_symlinks_to
);
535 FOREACH_DIRENT(de
, d
, return -errno
) {
537 dirent_ensure_type(d
, de
);
539 if (de
->d_type
== DT_DIR
) {
540 _cleanup_free_
char *p
= NULL
;
543 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
553 p
= path_make_absolute(de
->d_name
, path
);
559 /* This will close nfd, regardless whether it succeeds or not */
560 q
= remove_marked_symlinks_fd(remove_symlinks_to
, nfd
, p
, config_path
, lp
, dry_run
, restart
, changes
, n_changes
);
564 } else if (de
->d_type
== DT_LNK
) {
565 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
570 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
573 p
= path_make_absolute(de
->d_name
, path
);
576 path_simplify(p
, false);
578 q
= chase_symlinks(p
, NULL
, CHASE_NONEXISTENT
, &dest
, NULL
);
587 /* We remove all links pointing to a file or path that is marked, as well as all files sharing
588 * the same name as a file that is marked. */
590 found
= set_contains(remove_symlinks_to
, dest
) ||
591 set_contains(remove_symlinks_to
, basename(dest
)) ||
592 set_contains(remove_symlinks_to
, de
->d_name
);
598 if (unlinkat(fd
, de
->d_name
, 0) < 0 && errno
!= ENOENT
) {
601 unit_file_changes_add(changes
, n_changes
, -errno
, p
, NULL
);
605 (void) rmdir_parents(p
, config_path
);
608 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, p
, NULL
);
610 /* Now, remember the full path (but with the root prefix removed) of
611 * the symlink we just removed, and remove any symlinks to it, too. */
613 rp
= skip_root(lp
, p
);
614 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: p
);
617 if (q
> 0 && !dry_run
)
625 static int remove_marked_symlinks(
626 Set
*remove_symlinks_to
,
627 const char *config_path
,
628 const LookupPaths
*lp
,
630 UnitFileChange
**changes
,
633 _cleanup_close_
int fd
= -1;
640 if (set_size(remove_symlinks_to
) <= 0)
643 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
);
645 return errno
== ENOENT
? 0 : -errno
;
651 cfd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
655 /* This takes possession of cfd and closes it */
656 q
= remove_marked_symlinks_fd(remove_symlinks_to
, cfd
, config_path
, config_path
, lp
, dry_run
, &restart
, changes
, n_changes
);
664 static int is_symlink_with_known_name(const UnitFileInstallInfo
*i
, const char *name
) {
667 if (streq(name
, i
->name
))
670 if (strv_contains(i
->aliases
, name
))
673 /* Look for template symlink matching DefaultInstance */
674 if (i
->default_instance
&& unit_name_is_valid(i
->name
, UNIT_NAME_TEMPLATE
)) {
675 _cleanup_free_
char *s
= NULL
;
677 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &s
);
682 } else if (streq(name
, s
))
689 static int find_symlinks_fd(
690 const char *root_dir
,
691 const UnitFileInstallInfo
*i
,
693 bool ignore_same_name
,
696 const char *config_path
,
697 bool *same_name_link
) {
699 _cleanup_closedir_
DIR *d
= NULL
;
707 assert(same_name_link
);
715 FOREACH_DIRENT(de
, d
, return -errno
) {
717 dirent_ensure_type(d
, de
);
719 if (de
->d_type
== DT_DIR
) {
720 _cleanup_free_
char *p
= NULL
;
723 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
733 p
= path_make_absolute(de
->d_name
, path
);
739 /* This will close nfd, regardless whether it succeeds or not */
740 q
= find_symlinks_fd(root_dir
, i
, match_aliases
, ignore_same_name
, nfd
,
741 p
, config_path
, same_name_link
);
747 } else if (de
->d_type
== DT_LNK
) {
748 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
749 bool found_path
= false, found_dest
, b
= false;
752 /* Acquire symlink name */
753 p
= path_make_absolute(de
->d_name
, path
);
757 /* Acquire symlink destination */
758 q
= readlink_malloc(p
, &dest
);
768 if (!path_is_absolute(dest
)) {
771 x
= path_join(root_dir
, dest
);
775 free_and_replace(dest
, x
);
778 assert(unit_name_is_valid(i
->name
, UNIT_NAME_ANY
));
779 if (!ignore_same_name
)
780 /* Check if the symlink itself matches what we are looking for.
782 * If ignore_same_name is specified, we are in one of the directories which
783 * have lower priority than the unit file, and even if a file or symlink with
784 * this name was found, we should ignore it. */
785 found_path
= streq(de
->d_name
, i
->name
);
787 /* Check if what the symlink points to matches what we are looking for */
788 found_dest
= streq(basename(dest
), i
->name
);
790 if (found_path
&& found_dest
) {
791 _cleanup_free_
char *t
= NULL
;
793 /* Filter out same name links in the main
795 t
= path_make_absolute(i
->name
, config_path
);
799 b
= path_equal(t
, p
);
803 *same_name_link
= true;
804 else if (found_path
|| found_dest
) {
808 /* Check if symlink name is in the set of names used by [Install] */
809 q
= is_symlink_with_known_name(i
, de
->d_name
);
821 static int find_symlinks(
822 const char *root_dir
,
823 const UnitFileInstallInfo
*i
,
825 bool ignore_same_name
,
826 const char *config_path
,
827 bool *same_name_link
) {
833 assert(same_name_link
);
835 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
);
837 if (IN_SET(errno
, ENOENT
, ENOTDIR
, EACCES
))
842 /* This takes possession of fd and closes it */
843 return find_symlinks_fd(root_dir
, i
, match_name
, ignore_same_name
, fd
,
844 config_path
, config_path
, same_name_link
);
847 static int find_symlinks_in_scope(
849 const LookupPaths
*paths
,
850 const UnitFileInstallInfo
*i
,
852 UnitFileState
*state
) {
854 bool same_name_link_runtime
= false, same_name_link_config
= false;
855 bool enabled_in_runtime
= false, enabled_at_all
= false;
856 bool ignore_same_name
= false;
863 /* As we iterate over the list of search paths in paths->search_path, we may encounter "same name"
864 * symlinks. The ones which are "below" (i.e. have lower priority) than the unit file itself are
865 * effectively masked, so we should ignore them. */
867 STRV_FOREACH(p
, paths
->search_path
) {
868 bool same_name_link
= false;
870 r
= find_symlinks(paths
->root_dir
, i
, match_name
, ignore_same_name
, *p
, &same_name_link
);
874 /* We found symlinks in this dir? Yay! Let's see where precisely it is enabled. */
876 if (path_equal_ptr(*p
, paths
->persistent_config
)) {
877 /* This is the best outcome, let's return it immediately. */
878 *state
= UNIT_FILE_ENABLED
;
882 /* look for global enablement of user units */
883 if (scope
== UNIT_FILE_USER
&& path_is_user_config_dir(*p
)) {
884 *state
= UNIT_FILE_ENABLED
;
888 r
= path_is_runtime(paths
, *p
, false);
892 enabled_in_runtime
= true;
894 enabled_at_all
= true;
896 } else if (same_name_link
) {
897 if (path_equal_ptr(*p
, paths
->persistent_config
))
898 same_name_link_config
= true;
900 r
= path_is_runtime(paths
, *p
, false);
904 same_name_link_runtime
= true;
908 /* Check if next iteration will be "below" the unit file (either a regular file
909 * or a symlink), and hence should be ignored */
910 if (!ignore_same_name
&& path_startswith(i
->path
, *p
))
911 ignore_same_name
= true;
914 if (enabled_in_runtime
) {
915 *state
= UNIT_FILE_ENABLED_RUNTIME
;
919 /* Here's a special rule: if the unit we are looking for is an instance, and it symlinked in the search path
920 * outside of runtime and configuration directory, then we consider it statically enabled. Note we do that only
921 * for instance, not for regular names, as those are merely aliases, while instances explicitly instantiate
922 * something, and hence are a much stronger concept. */
923 if (enabled_at_all
&& unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
)) {
924 *state
= UNIT_FILE_STATIC
;
928 /* Hmm, we didn't find it, but maybe we found the same name
930 if (same_name_link_config
) {
931 *state
= UNIT_FILE_LINKED
;
934 if (same_name_link_runtime
) {
935 *state
= UNIT_FILE_LINKED_RUNTIME
;
942 static void install_info_free(UnitFileInstallInfo
*i
) {
949 strv_free(i
->aliases
);
950 strv_free(i
->wanted_by
);
951 strv_free(i
->required_by
);
953 free(i
->default_instance
);
954 free(i
->symlink_target
);
958 static void install_context_done(InstallContext
*c
) {
961 c
->will_process
= ordered_hashmap_free_with_destructor(c
->will_process
, install_info_free
);
962 c
->have_processed
= ordered_hashmap_free_with_destructor(c
->have_processed
, install_info_free
);
965 static UnitFileInstallInfo
*install_info_find(InstallContext
*c
, const char *name
) {
966 UnitFileInstallInfo
*i
;
968 i
= ordered_hashmap_get(c
->have_processed
, name
);
972 return ordered_hashmap_get(c
->will_process
, name
);
975 static int install_info_may_process(
976 const UnitFileInstallInfo
*i
,
977 const LookupPaths
*paths
,
978 UnitFileChange
**changes
,
983 /* Checks whether the loaded unit file is one we should process, or is masked,
984 * transient or generated and thus not subject to enable/disable operations. */
986 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
987 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, i
->path
, NULL
);
990 if (path_is_generator(paths
, i
->path
) ||
991 path_is_transient(paths
, i
->path
)) {
992 unit_file_changes_add(changes
, n_changes
, -EADDRNOTAVAIL
, i
->path
, NULL
);
993 return -EADDRNOTAVAIL
;
1000 * Adds a new UnitFileInstallInfo entry under name in the InstallContext.will_process
1001 * hashmap, or retrieves the existing one if already present.
1003 * Returns negative on error, 0 if the unit was already known, 1 otherwise.
1005 static int install_info_add(
1010 UnitFileInstallInfo
**ret
) {
1012 UnitFileInstallInfo
*i
= NULL
;
1018 /* 'name' and 'path' must not both be null. Check here 'path' using assert_se() to
1019 * workaround a bug in gcc that generates a -Wnonnull warning when calling basename(),
1020 * but this cannot be possible in any code path (See #6119). */
1022 name
= basename(path
);
1025 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
1028 i
= install_info_find(c
, name
);
1030 i
->auxiliary
= i
->auxiliary
&& auxiliary
;
1037 r
= ordered_hashmap_ensure_allocated(&c
->will_process
, &string_hash_ops
);
1041 i
= new(UnitFileInstallInfo
, 1);
1045 *i
= (UnitFileInstallInfo
) {
1046 .type
= _UNIT_FILE_TYPE_INVALID
,
1047 .auxiliary
= auxiliary
,
1050 i
->name
= strdup(name
);
1057 i
->path
= strdup(path
);
1064 r
= ordered_hashmap_put(c
->will_process
, i
->name
, i
);
1074 install_info_free(i
);
1078 static int config_parse_alias(
1080 const char *filename
,
1082 const char *section
,
1083 unsigned section_line
,
1097 type
= unit_name_to_type(unit
);
1098 if (!unit_type_may_alias(type
))
1099 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1100 "Alias= is not allowed for %s units, ignoring.",
1101 unit_type_to_string(type
));
1103 return config_parse_strv(unit
, filename
, line
, section
, section_line
,
1104 lvalue
, ltype
, rvalue
, data
, userdata
);
1107 static int config_parse_also(
1109 const char *filename
,
1111 const char *section
,
1112 unsigned section_line
,
1119 UnitFileInstallInfo
*info
= userdata
;
1120 InstallContext
*c
= data
;
1129 _cleanup_free_
char *word
= NULL
, *printed
= NULL
;
1131 r
= extract_first_word(&rvalue
, &word
, NULL
, 0);
1137 r
= install_full_printf(info
, word
, &printed
);
1141 r
= install_info_add(c
, printed
, NULL
, true, NULL
);
1145 r
= strv_push(&info
->also
, printed
);
1155 static int config_parse_default_instance(
1157 const char *filename
,
1159 const char *section
,
1160 unsigned section_line
,
1167 UnitFileInstallInfo
*i
= data
;
1168 _cleanup_free_
char *printed
= NULL
;
1176 if (unit_name_is_valid(unit
, UNIT_NAME_INSTANCE
))
1177 /* When enabling an instance, we might be using a template unit file,
1178 * but we should ignore DefaultInstance silently. */
1180 if (!unit_name_is_valid(unit
, UNIT_NAME_TEMPLATE
))
1181 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1182 "DefaultInstance= only makes sense for template units, ignoring.");
1184 r
= install_full_printf(i
, rvalue
, &printed
);
1188 if (isempty(printed
)) {
1189 i
->default_instance
= mfree(i
->default_instance
);
1193 if (!unit_instance_is_valid(printed
))
1194 return log_syntax(unit
, LOG_WARNING
, filename
, line
, SYNTHETIC_ERRNO(EINVAL
),
1195 "Invalid DefaultInstance= value \"%s\".", printed
);
1197 return free_and_replace(i
->default_instance
, printed
);
1200 static int unit_file_load(
1202 UnitFileInstallInfo
*info
,
1204 const char *root_dir
,
1205 SearchFlags flags
) {
1207 const ConfigTableItem items
[] = {
1208 { "Install", "Alias", config_parse_alias
, 0, &info
->aliases
},
1209 { "Install", "WantedBy", config_parse_strv
, 0, &info
->wanted_by
},
1210 { "Install", "RequiredBy", config_parse_strv
, 0, &info
->required_by
},
1211 { "Install", "DefaultInstance", config_parse_default_instance
, 0, info
},
1212 { "Install", "Also", config_parse_also
, 0, c
},
1217 _cleanup_fclose_
FILE *f
= NULL
;
1218 _cleanup_close_
int fd
= -1;
1225 if (!(flags
& SEARCH_DROPIN
)) {
1226 /* Loading or checking for the main unit file… */
1228 type
= unit_name_to_type(info
->name
);
1231 if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
|UNIT_NAME_INSTANCE
) && !unit_type_may_template(type
))
1232 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1233 "%s: unit type %s cannot be templated, ignoring.", path
, unit_type_to_string(type
));
1235 if (!(flags
& SEARCH_LOAD
)) {
1236 r
= lstat(path
, &st
);
1240 if (null_or_empty(&st
))
1241 info
->type
= UNIT_FILE_TYPE_MASKED
;
1242 else if (S_ISREG(st
.st_mode
))
1243 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1244 else if (S_ISLNK(st
.st_mode
))
1246 else if (S_ISDIR(st
.st_mode
))
1254 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
1258 /* 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. */
1260 if (!(flags
& SEARCH_LOAD
))
1263 fd
= chase_symlinks_and_open(path
, root_dir
, 0, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
, NULL
);
1268 if (fstat(fd
, &st
) < 0)
1271 if (null_or_empty(&st
)) {
1272 if ((flags
& SEARCH_DROPIN
) == 0)
1273 info
->type
= UNIT_FILE_TYPE_MASKED
;
1278 r
= stat_verify_regular(&st
);
1282 f
= take_fdopen(&fd
, "r");
1286 /* c is only needed if we actually load the file (it's referenced from items[] btw, in case you wonder.) */
1289 r
= config_parse(info
->name
, path
, f
,
1303 config_item_table_lookup
, items
,
1304 CONFIG_PARSE_ALLOW_INCLUDE
, info
);
1306 return log_debug_errno(r
, "Failed to parse %s: %m", info
->name
);
1308 if ((flags
& SEARCH_DROPIN
) == 0)
1309 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1312 (int) strv_length(info
->aliases
) +
1313 (int) strv_length(info
->wanted_by
) +
1314 (int) strv_length(info
->required_by
);
1317 static int unit_file_load_or_readlink(
1319 UnitFileInstallInfo
*info
,
1321 const char *root_dir
,
1322 SearchFlags flags
) {
1324 _cleanup_free_
char *target
= NULL
;
1327 r
= unit_file_load(c
, info
, path
, root_dir
, flags
);
1328 if (r
!= -ELOOP
|| (flags
& SEARCH_DROPIN
))
1331 /* This is a symlink, let's read it. */
1333 r
= readlink_malloc(path
, &target
);
1337 if (path_equal(target
, "/dev/null"))
1338 info
->type
= UNIT_FILE_TYPE_MASKED
;
1343 bn
= basename(target
);
1345 if (unit_name_is_valid(info
->name
, UNIT_NAME_PLAIN
)) {
1347 if (!unit_name_is_valid(bn
, UNIT_NAME_PLAIN
))
1350 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1352 if (!unit_name_is_valid(bn
, UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
))
1355 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
)) {
1357 if (!unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
))
1362 /* Enforce that the symlink destination does not
1363 * change the unit file type. */
1365 a
= unit_name_to_type(info
->name
);
1366 b
= unit_name_to_type(bn
);
1367 if (a
< 0 || b
< 0 || a
!= b
)
1370 if (path_is_absolute(target
))
1371 /* This is an absolute path, prefix the root so that we always deal with fully qualified paths */
1372 info
->symlink_target
= path_join(root_dir
, target
);
1374 /* This is a relative path, take it relative to the dir the symlink is located in. */
1375 info
->symlink_target
= file_in_same_dir(path
, target
);
1376 if (!info
->symlink_target
)
1379 info
->type
= UNIT_FILE_TYPE_SYMLINK
;
1385 static int unit_file_search(
1387 UnitFileInstallInfo
*info
,
1388 const LookupPaths
*paths
,
1389 SearchFlags flags
) {
1391 const char *dropin_dir_name
= NULL
, *dropin_template_dir_name
= NULL
;
1392 _cleanup_strv_free_
char **dirs
= NULL
, **files
= NULL
;
1393 _cleanup_free_
char *template = NULL
;
1394 bool found_unit
= false;
1401 /* Was this unit already loaded? */
1402 if (info
->type
!= _UNIT_FILE_TYPE_INVALID
)
1406 return unit_file_load_or_readlink(c
, info
, info
->path
, paths
->root_dir
, flags
);
1410 if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1411 r
= unit_name_template(info
->name
, &template);
1416 STRV_FOREACH(p
, paths
->search_path
) {
1417 _cleanup_free_
char *path
= NULL
;
1419 path
= path_join(*p
, info
->name
);
1423 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1425 info
->path
= TAKE_PTR(path
);
1429 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1433 if (!found_unit
&& template) {
1435 /* Unit file doesn't exist, however instance
1436 * enablement was requested. We will check if it is
1437 * possible to load template unit file. */
1439 STRV_FOREACH(p
, paths
->search_path
) {
1440 _cleanup_free_
char *path
= NULL
;
1442 path
= path_join(*p
, template);
1446 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1448 info
->path
= TAKE_PTR(path
);
1452 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1458 return log_debug_errno(SYNTHETIC_ERRNO(ENOENT
),
1459 "Cannot find unit %s%s%s.",
1460 info
->name
, template ? " or " : "", strempty(template));
1462 if (info
->type
== UNIT_FILE_TYPE_MASKED
)
1465 /* Search for drop-in directories */
1467 dropin_dir_name
= strjoina(info
->name
, ".d");
1468 STRV_FOREACH(p
, paths
->search_path
) {
1471 path
= path_join(*p
, dropin_dir_name
);
1475 r
= strv_consume(&dirs
, path
);
1481 dropin_template_dir_name
= strjoina(template, ".d");
1482 STRV_FOREACH(p
, paths
->search_path
) {
1485 path
= path_join(*p
, dropin_template_dir_name
);
1489 r
= strv_consume(&dirs
, path
);
1495 /* Load drop-in conf files */
1497 r
= conf_files_list_strv(&files
, ".conf", NULL
, 0, (const char**) dirs
);
1499 return log_debug_errno(r
, "Failed to get list of conf files: %m");
1501 STRV_FOREACH(p
, files
) {
1502 r
= unit_file_load_or_readlink(c
, info
, *p
, paths
->root_dir
, flags
| SEARCH_DROPIN
);
1504 return log_debug_errno(r
, "Failed to load conf file %s: %m", *p
);
1510 static int install_info_follow(
1512 UnitFileInstallInfo
*i
,
1513 const char *root_dir
,
1515 bool ignore_different_name
) {
1520 if (i
->type
!= UNIT_FILE_TYPE_SYMLINK
)
1522 if (!i
->symlink_target
)
1525 /* If the basename doesn't match, the caller should add a
1526 * complete new entry for this. */
1528 if (!ignore_different_name
&& !streq(basename(i
->symlink_target
), i
->name
))
1531 free_and_replace(i
->path
, i
->symlink_target
);
1532 i
->type
= _UNIT_FILE_TYPE_INVALID
;
1534 return unit_file_load_or_readlink(c
, i
, i
->path
, root_dir
, flags
);
1538 * Search for the unit file. If the unit name is a symlink, follow the symlink to the
1539 * target, maybe more than once. Propagate the instance name if present.
1541 static int install_info_traverse(
1542 UnitFileScope scope
,
1544 const LookupPaths
*paths
,
1545 UnitFileInstallInfo
*start
,
1547 UnitFileInstallInfo
**ret
) {
1549 UnitFileInstallInfo
*i
;
1557 r
= unit_file_search(c
, start
, paths
, flags
);
1562 while (i
->type
== UNIT_FILE_TYPE_SYMLINK
) {
1563 /* Follow the symlink */
1565 if (++k
> UNIT_FILE_FOLLOW_SYMLINK_MAX
)
1568 if (!(flags
& SEARCH_FOLLOW_CONFIG_SYMLINKS
)) {
1569 r
= path_is_config(paths
, i
->path
, true);
1576 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
, false);
1578 _cleanup_free_
char *buffer
= NULL
;
1581 /* Target has a different name, create a new
1582 * install info object for that, and continue
1585 bn
= basename(i
->symlink_target
);
1587 if (unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
) &&
1588 unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
)) {
1590 _cleanup_free_
char *instance
= NULL
;
1592 r
= unit_name_to_instance(i
->name
, &instance
);
1596 r
= unit_name_replace_instance(bn
, instance
, &buffer
);
1600 if (streq(buffer
, i
->name
)) {
1602 /* We filled in the instance, and the target stayed the same? If so, then let's
1603 * honour the link as it is. */
1605 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
, true);
1615 r
= install_info_add(c
, bn
, NULL
, false, &i
);
1619 /* Try again, with the new target we found. */
1620 r
= unit_file_search(c
, i
, paths
, flags
);
1622 /* Translate error code to highlight this specific case */
1637 * Call install_info_add() with name_or_path as the path (if name_or_path starts with "/")
1638 * or the name (otherwise). root_dir is prepended to the path.
1640 static int install_info_add_auto(
1642 const LookupPaths
*paths
,
1643 const char *name_or_path
,
1644 UnitFileInstallInfo
**ret
) {
1647 assert(name_or_path
);
1649 if (path_is_absolute(name_or_path
)) {
1652 pp
= prefix_roota(paths
->root_dir
, name_or_path
);
1654 return install_info_add(c
, NULL
, pp
, false, ret
);
1656 return install_info_add(c
, name_or_path
, NULL
, false, ret
);
1659 static int install_info_discover(
1660 UnitFileScope scope
,
1662 const LookupPaths
*paths
,
1665 UnitFileInstallInfo
**ret
,
1666 UnitFileChange
**changes
,
1667 size_t *n_changes
) {
1669 UnitFileInstallInfo
*i
;
1676 r
= install_info_add_auto(c
, paths
, name
, &i
);
1678 r
= install_info_traverse(scope
, c
, paths
, i
, flags
, ret
);
1681 unit_file_changes_add(changes
, n_changes
, r
, name
, NULL
);
1685 static int install_info_discover_and_check(
1686 UnitFileScope scope
,
1688 const LookupPaths
*paths
,
1691 UnitFileInstallInfo
**ret
,
1692 UnitFileChange
**changes
,
1693 size_t *n_changes
) {
1697 r
= install_info_discover(scope
, c
, paths
, name
, flags
, ret
, changes
, n_changes
);
1701 return install_info_may_process(ret
? *ret
: NULL
, paths
, changes
, n_changes
);
1704 int unit_file_verify_alias(const UnitFileInstallInfo
*i
, const char *dst
, char **ret_dst
) {
1705 _cleanup_free_
char *dst_updated
= NULL
;
1708 /* Verify that dst is a valid either a valid alias or a valid .wants/.requires symlink for the target
1709 * unit *i. Return negative on error or if not compatible, zero on success.
1711 * ret_dst is set in cases where "instance propagation" happens, i.e. when the instance part is
1712 * inserted into dst. It is not normally set, even on success, so that the caller can easily
1713 * distinguish the case where instance propagation occurred.
1716 const char *path_alias
= strrchr(dst
, '/');
1718 /* This branch covers legacy Alias= function of creating .wants and .requires symlinks. */
1719 _cleanup_free_
char *dir
= NULL
;
1722 path_alias
++; /* skip over slash */
1724 dir
= dirname_malloc(dst
);
1728 p
= endswith(dir
, ".wants");
1730 p
= endswith(dir
, ".requires");
1732 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV
),
1733 "Invalid path \"%s\" in alias.", dir
);
1734 *p
= '\0'; /* dir should now be a unit name */
1736 r
= unit_name_classify(dir
);
1738 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV
),
1739 "Invalid unit name component \"%s\" in alias.", dir
);
1741 const bool instance_propagation
= r
== UNIT_NAME_TEMPLATE
;
1743 /* That's the name we want to use for verification. */
1744 r
= unit_symlink_name_compatible(path_alias
, i
->name
, instance_propagation
);
1746 return log_error_errno(r
, "Failed to verify alias validity: %m");
1748 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV
),
1749 "Invalid unit %s symlink %s.",
1753 /* If the symlink target has an instance set and the symlink source doesn't, we "propagate
1754 * the instance", i.e. instantiate the symlink source with the target instance. */
1755 if (unit_name_is_valid(dst
, UNIT_NAME_TEMPLATE
)) {
1756 _cleanup_free_
char *inst
= NULL
;
1758 r
= unit_name_to_instance(i
->name
, &inst
);
1760 return log_error_errno(r
, "Failed to extract instance name from %s: %m", i
->name
);
1762 if (r
== UNIT_NAME_INSTANCE
) {
1763 r
= unit_name_replace_instance(dst
, inst
, &dst_updated
);
1765 return log_error_errno(r
, "Failed to build unit name from %s+%s: %m",
1770 r
= unit_validate_alias_symlink_and_warn(dst_updated
?: dst
, i
->name
);
1776 *ret_dst
= TAKE_PTR(dst_updated
);
1780 static int install_info_symlink_alias(
1781 UnitFileInstallInfo
*i
,
1782 const LookupPaths
*paths
,
1783 const char *config_path
,
1785 UnitFileChange
**changes
,
1786 size_t *n_changes
) {
1793 assert(config_path
);
1795 STRV_FOREACH(s
, i
->aliases
) {
1796 _cleanup_free_
char *alias_path
= NULL
, *dst
= NULL
, *dst_updated
= NULL
;
1798 q
= install_full_printf(i
, *s
, &dst
);
1802 q
= unit_file_verify_alias(i
, dst
, &dst_updated
);
1806 alias_path
= path_make_absolute(dst_updated
?: dst
, config_path
);
1810 q
= create_symlink(paths
, i
->path
, alias_path
, force
, changes
, n_changes
);
1818 static int install_info_symlink_wants(
1819 UnitFileInstallInfo
*i
,
1820 const LookupPaths
*paths
,
1821 const char *config_path
,
1824 UnitFileChange
**changes
,
1825 size_t *n_changes
) {
1827 _cleanup_free_
char *buf
= NULL
;
1834 assert(config_path
);
1836 if (strv_isempty(list
))
1839 if (unit_name_is_valid(i
->name
, UNIT_NAME_TEMPLATE
)) {
1840 UnitFileInstallInfo instance
= {
1841 .type
= _UNIT_FILE_TYPE_INVALID
,
1843 _cleanup_free_
char *path
= NULL
;
1845 /* If this is a template, and we have no instance, don't do anything */
1846 if (!i
->default_instance
)
1849 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &buf
);
1853 instance
.name
= buf
;
1854 r
= unit_file_search(NULL
, &instance
, paths
, SEARCH_FOLLOW_CONFIG_SYMLINKS
);
1858 path
= TAKE_PTR(instance
.path
);
1860 if (instance
.type
== UNIT_FILE_TYPE_MASKED
) {
1861 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, path
, NULL
);
1869 STRV_FOREACH(s
, list
) {
1870 _cleanup_free_
char *path
= NULL
, *dst
= NULL
;
1872 q
= install_full_printf(i
, *s
, &dst
);
1876 if (!unit_name_is_valid(dst
, UNIT_NAME_ANY
)) {
1877 unit_file_changes_add(changes
, n_changes
, -EUCLEAN
, dst
, NULL
);
1882 path
= strjoin(config_path
, "/", dst
, suffix
, n
);
1886 q
= create_symlink(paths
, i
->path
, path
, true, changes
, n_changes
);
1894 static int install_info_symlink_link(
1895 UnitFileInstallInfo
*i
,
1896 const LookupPaths
*paths
,
1897 const char *config_path
,
1899 UnitFileChange
**changes
,
1900 size_t *n_changes
) {
1902 _cleanup_free_
char *path
= NULL
;
1907 assert(config_path
);
1910 r
= in_search_path(paths
, i
->path
);
1916 path
= path_join(config_path
, i
->name
);
1920 return create_symlink(paths
, i
->path
, path
, force
, changes
, n_changes
);
1923 static int install_info_apply(
1924 UnitFileInstallInfo
*i
,
1925 const LookupPaths
*paths
,
1926 const char *config_path
,
1928 UnitFileChange
**changes
,
1929 size_t *n_changes
) {
1935 assert(config_path
);
1937 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
1940 r
= install_info_symlink_alias(i
, paths
, config_path
, force
, changes
, n_changes
);
1942 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->wanted_by
, ".wants/", changes
, n_changes
);
1946 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->required_by
, ".requires/", changes
, n_changes
);
1950 q
= install_info_symlink_link(i
, paths
, config_path
, force
, changes
, n_changes
);
1951 /* Do not count links to the unit file towards the "carries_install_info" count */
1952 if (r
== 0 && q
< 0)
1958 static int install_context_apply(
1959 UnitFileScope scope
,
1961 const LookupPaths
*paths
,
1962 const char *config_path
,
1965 UnitFileChange
**changes
,
1966 size_t *n_changes
) {
1968 UnitFileInstallInfo
*i
;
1973 assert(config_path
);
1975 if (ordered_hashmap_isempty(c
->will_process
))
1978 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
1983 while ((i
= ordered_hashmap_first(c
->will_process
))) {
1986 q
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
1990 q
= install_info_traverse(scope
, c
, paths
, i
, flags
, NULL
);
1992 unit_file_changes_add(changes
, n_changes
, q
, i
->name
, NULL
);
1996 /* We can attempt to process a masked unit when a different unit
1997 * that we were processing specifies it in Also=. */
1998 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
1999 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_MASKED
, i
->path
, NULL
);
2001 /* Assume that something *could* have been enabled here,
2002 * avoid "empty [Install] section" warning. */
2007 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
2010 q
= install_info_apply(i
, paths
, config_path
, force
, changes
, n_changes
);
2022 static int install_context_mark_for_removal(
2023 UnitFileScope scope
,
2025 const LookupPaths
*paths
,
2026 Set
**remove_symlinks_to
,
2027 const char *config_path
,
2028 UnitFileChange
**changes
,
2029 size_t *n_changes
) {
2031 UnitFileInstallInfo
*i
;
2036 assert(config_path
);
2038 /* Marks all items for removal */
2040 if (ordered_hashmap_isempty(c
->will_process
))
2043 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
2047 while ((i
= ordered_hashmap_first(c
->will_process
))) {
2049 r
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
2053 r
= install_info_traverse(scope
, c
, paths
, i
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, NULL
);
2054 if (r
== -ENOLINK
) {
2055 log_debug_errno(r
, "Name %s leads to a dangling symlink, removing name.", i
->name
);
2056 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_DANGLING
, i
->path
?: i
->name
, NULL
);
2057 } else if (r
== -ENOENT
) {
2059 if (i
->auxiliary
) /* some unit specified in Also= or similar is missing */
2060 log_debug_errno(r
, "Auxiliary unit of %s not found, removing name.", i
->name
);
2062 log_debug_errno(r
, "Unit %s not found, removing name.", i
->name
);
2063 unit_file_changes_add(changes
, n_changes
, r
, i
->path
?: i
->name
, NULL
);
2067 log_debug_errno(r
, "Failed to find unit %s, removing name: %m", i
->name
);
2068 unit_file_changes_add(changes
, n_changes
, r
, i
->path
?: i
->name
, NULL
);
2069 } else if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
2070 log_debug("Unit file %s is masked, ignoring.", i
->name
);
2071 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_MASKED
, i
->path
?: i
->name
, NULL
);
2073 } else if (i
->type
!= UNIT_FILE_TYPE_REGULAR
) {
2074 log_debug("Unit %s has type %s, ignoring.", i
->name
, unit_file_type_to_string(i
->type
) ?: "invalid");
2078 r
= mark_symlink_for_removal(remove_symlinks_to
, i
->name
);
2087 UnitFileScope scope
,
2088 UnitFileFlags flags
,
2089 const char *root_dir
,
2091 UnitFileChange
**changes
,
2092 size_t *n_changes
) {
2094 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2095 const char *config_path
;
2100 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2102 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2106 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2110 STRV_FOREACH(i
, files
) {
2111 _cleanup_free_
char *path
= NULL
;
2114 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
)) {
2120 path
= path_make_absolute(*i
, config_path
);
2124 q
= create_symlink(&paths
, "/dev/null", path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2125 if (q
< 0 && r
>= 0)
2132 int unit_file_unmask(
2133 UnitFileScope scope
,
2134 UnitFileFlags flags
,
2135 const char *root_dir
,
2137 UnitFileChange
**changes
,
2138 size_t *n_changes
) {
2140 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2141 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2142 _cleanup_strv_free_
char **todo
= NULL
;
2143 size_t n_todo
= 0, n_allocated
= 0;
2144 const char *config_path
;
2150 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2152 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2156 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2160 dry_run
= !!(flags
& UNIT_FILE_DRY_RUN
);
2162 STRV_FOREACH(i
, files
) {
2163 _cleanup_free_
char *path
= NULL
;
2165 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2168 path
= path_make_absolute(*i
, config_path
);
2172 r
= null_or_empty_path(path
);
2180 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2183 todo
[n_todo
] = strdup(*i
);
2193 STRV_FOREACH(i
, todo
) {
2194 _cleanup_free_
char *path
= NULL
;
2197 path
= path_make_absolute(*i
, config_path
);
2201 if (!dry_run
&& unlink(path
) < 0) {
2202 if (errno
!= ENOENT
) {
2205 unit_file_changes_add(changes
, n_changes
, -errno
, path
, NULL
);
2211 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
2213 rp
= skip_root(&paths
, path
);
2214 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: path
);
2219 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, dry_run
, changes
, n_changes
);
2227 UnitFileScope scope
,
2228 UnitFileFlags flags
,
2229 const char *root_dir
,
2231 UnitFileChange
**changes
,
2232 size_t *n_changes
) {
2234 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2235 _cleanup_strv_free_
char **todo
= NULL
;
2236 size_t n_todo
= 0, n_allocated
= 0;
2237 const char *config_path
;
2242 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2244 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2248 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2252 STRV_FOREACH(i
, files
) {
2253 _cleanup_free_
char *full
= NULL
;
2257 if (!path_is_absolute(*i
))
2261 if (!unit_name_is_valid(fn
, UNIT_NAME_ANY
))
2264 full
= path_join(paths
.root_dir
, *i
);
2268 if (lstat(full
, &st
) < 0)
2270 r
= stat_verify_regular(&st
);
2274 q
= in_search_path(&paths
, *i
);
2280 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2283 todo
[n_todo
] = strdup(*i
);
2293 STRV_FOREACH(i
, todo
) {
2294 _cleanup_free_
char *new_path
= NULL
;
2296 new_path
= path_make_absolute(basename(*i
), config_path
);
2300 q
= create_symlink(&paths
, *i
, new_path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2301 if (q
< 0 && r
>= 0)
2308 static int path_shall_revert(const LookupPaths
*paths
, const char *path
) {
2314 /* Checks whether the path is one where the drop-in directories shall be removed. */
2316 r
= path_is_config(paths
, path
, true);
2320 r
= path_is_control(paths
, path
);
2324 return path_is_transient(paths
, path
);
2327 int unit_file_revert(
2328 UnitFileScope scope
,
2329 const char *root_dir
,
2331 UnitFileChange
**changes
,
2332 size_t *n_changes
) {
2334 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2335 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2336 _cleanup_strv_free_
char **todo
= NULL
;
2337 size_t n_todo
= 0, n_allocated
= 0;
2341 /* Puts a unit file back into vendor state. This means:
2343 * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and
2344 * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated").
2346 * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in
2347 * "config", but not in "transient" or "control" or even "generated").
2349 * We remove all that in both the runtime and the persistent directories, if that applies.
2352 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2356 STRV_FOREACH(i
, files
) {
2357 bool has_vendor
= false;
2360 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2363 STRV_FOREACH(p
, paths
.search_path
) {
2364 _cleanup_free_
char *path
= NULL
, *dropin
= NULL
;
2367 path
= path_make_absolute(*i
, *p
);
2371 r
= lstat(path
, &st
);
2373 if (errno
!= ENOENT
)
2375 } else if (S_ISREG(st
.st_mode
)) {
2376 /* Check if there's a vendor version */
2377 r
= path_is_vendor(&paths
, path
);
2384 dropin
= strjoin(path
, ".d");
2388 r
= lstat(dropin
, &st
);
2390 if (errno
!= ENOENT
)
2392 } else if (S_ISDIR(st
.st_mode
)) {
2393 /* Remove the drop-ins */
2394 r
= path_shall_revert(&paths
, dropin
);
2398 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2401 todo
[n_todo
++] = TAKE_PTR(dropin
);
2409 /* OK, there's a vendor version, hence drop all configuration versions */
2410 STRV_FOREACH(p
, paths
.search_path
) {
2411 _cleanup_free_
char *path
= NULL
;
2414 path
= path_make_absolute(*i
, *p
);
2418 r
= lstat(path
, &st
);
2420 if (errno
!= ENOENT
)
2422 } else if (S_ISREG(st
.st_mode
) || S_ISLNK(st
.st_mode
)) {
2423 r
= path_is_config(&paths
, path
, true);
2427 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2430 todo
[n_todo
++] = TAKE_PTR(path
);
2439 STRV_FOREACH(i
, todo
) {
2440 _cleanup_strv_free_
char **fs
= NULL
;
2444 (void) get_files_in_directory(*i
, &fs
);
2446 q
= rm_rf(*i
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
2447 if (q
< 0 && q
!= -ENOENT
&& r
>= 0) {
2452 STRV_FOREACH(j
, fs
) {
2453 _cleanup_free_
char *t
= NULL
;
2455 t
= path_join(*i
, *j
);
2459 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, t
, NULL
);
2462 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, *i
, NULL
);
2464 rp
= skip_root(&paths
, *i
);
2465 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: *i
);
2470 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.runtime_config
, &paths
, false, changes
, n_changes
);
2474 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.persistent_config
, &paths
, false, changes
, n_changes
);
2481 int unit_file_add_dependency(
2482 UnitFileScope scope
,
2483 UnitFileFlags flags
,
2484 const char *root_dir
,
2488 UnitFileChange
**changes
,
2489 size_t *n_changes
) {
2491 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2492 _cleanup_(install_context_done
) InstallContext c
= {};
2493 UnitFileInstallInfo
*i
, *target_info
;
2494 const char *config_path
;
2499 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2502 if (!IN_SET(dep
, UNIT_WANTS
, UNIT_REQUIRES
))
2505 if (!unit_name_is_valid(target
, UNIT_NAME_ANY
))
2508 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2512 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2516 r
= install_info_discover_and_check(scope
, &c
, &paths
, target
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2517 &target_info
, changes
, n_changes
);
2521 assert(target_info
->type
== UNIT_FILE_TYPE_REGULAR
);
2523 STRV_FOREACH(f
, files
) {
2526 r
= install_info_discover_and_check(scope
, &c
, &paths
, *f
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2527 &i
, changes
, n_changes
);
2531 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2533 /* We didn't actually load anything from the unit
2534 * file, but instead just add in our new symlink to
2537 if (dep
== UNIT_WANTS
)
2540 l
= &i
->required_by
;
2543 *l
= strv_new(target_info
->name
);
2548 return install_context_apply(scope
, &c
, &paths
, config_path
, !!(flags
& UNIT_FILE_FORCE
), SEARCH_FOLLOW_CONFIG_SYMLINKS
, changes
, n_changes
);
2551 int unit_file_enable(
2552 UnitFileScope scope
,
2553 UnitFileFlags flags
,
2554 const char *root_dir
,
2556 UnitFileChange
**changes
,
2557 size_t *n_changes
) {
2559 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2560 _cleanup_(install_context_done
) InstallContext c
= {};
2561 const char *config_path
;
2562 UnitFileInstallInfo
*i
;
2567 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2569 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2573 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2577 STRV_FOREACH(f
, files
) {
2578 r
= install_info_discover_and_check(scope
, &c
, &paths
, *f
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2579 &i
, changes
, n_changes
);
2583 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2586 /* This will return the number of symlink rules that were
2587 supposed to be created, not the ones actually created. This
2588 is useful to determine whether the passed files had any
2589 installation data at all. */
2591 return install_context_apply(scope
, &c
, &paths
, config_path
, !!(flags
& UNIT_FILE_FORCE
), SEARCH_LOAD
, changes
, n_changes
);
2594 int unit_file_disable(
2595 UnitFileScope scope
,
2596 UnitFileFlags flags
,
2597 const char *root_dir
,
2599 UnitFileChange
**changes
,
2600 size_t *n_changes
) {
2602 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2603 _cleanup_(install_context_done
) InstallContext c
= {};
2604 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2605 const char *config_path
;
2610 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2612 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2616 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2620 STRV_FOREACH(i
, files
) {
2621 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2624 r
= install_info_add(&c
, *i
, NULL
, false, NULL
);
2629 r
= install_context_mark_for_removal(scope
, &c
, &paths
, &remove_symlinks_to
, config_path
, changes
, n_changes
);
2633 return remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, !!(flags
& UNIT_FILE_DRY_RUN
), changes
, n_changes
);
2636 int unit_file_reenable(
2637 UnitFileScope scope
,
2638 UnitFileFlags flags
,
2639 const char *root_dir
,
2641 UnitFileChange
**changes
,
2642 size_t *n_changes
) {
2648 /* First, we invoke the disable command with only the basename... */
2649 l
= strv_length(files
);
2650 n
= newa(char*, l
+1);
2651 for (i
= 0; i
< l
; i
++)
2652 n
[i
] = basename(files
[i
]);
2655 r
= unit_file_disable(scope
, flags
, root_dir
, n
, changes
, n_changes
);
2659 /* But the enable command with the full name */
2660 return unit_file_enable(scope
, flags
, root_dir
, files
, changes
, n_changes
);
2663 int unit_file_set_default(
2664 UnitFileScope scope
,
2665 UnitFileFlags flags
,
2666 const char *root_dir
,
2668 UnitFileChange
**changes
,
2669 size_t *n_changes
) {
2671 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2672 _cleanup_(install_context_done
) InstallContext c
= {};
2673 UnitFileInstallInfo
*i
;
2674 const char *new_path
;
2678 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2681 if (unit_name_to_type(name
) != UNIT_TARGET
) /* this also validates the name */
2683 if (streq(name
, SPECIAL_DEFAULT_TARGET
))
2686 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2690 r
= install_info_discover_and_check(scope
, &c
, &paths
, name
, 0, &i
, changes
, n_changes
);
2694 new_path
= strjoina(paths
.persistent_config
, "/" SPECIAL_DEFAULT_TARGET
);
2695 return create_symlink(&paths
, i
->path
, new_path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2698 int unit_file_get_default(
2699 UnitFileScope scope
,
2700 const char *root_dir
,
2703 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2704 _cleanup_(install_context_done
) InstallContext c
= {};
2705 UnitFileInstallInfo
*i
;
2710 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2713 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2717 r
= install_info_discover(scope
, &c
, &paths
, SPECIAL_DEFAULT_TARGET
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2721 r
= install_info_may_process(i
, &paths
, NULL
, 0);
2725 n
= strdup(i
->name
);
2733 int unit_file_lookup_state(
2734 UnitFileScope scope
,
2735 const LookupPaths
*paths
,
2737 UnitFileState
*ret
) {
2739 _cleanup_(install_context_done
) InstallContext c
= {};
2740 UnitFileInstallInfo
*i
;
2741 UnitFileState state
;
2747 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2750 r
= install_info_discover(scope
, &c
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2753 return log_debug_errno(r
, "Failed to discover unit %s: %m", name
);
2755 assert(IN_SET(i
->type
, UNIT_FILE_TYPE_REGULAR
, UNIT_FILE_TYPE_MASKED
));
2756 log_debug("Found unit %s at %s (%s)", name
, strna(i
->path
),
2757 i
->type
== UNIT_FILE_TYPE_REGULAR
? "regular file" : "mask");
2759 /* Shortcut things, if the caller just wants to know if this unit exists. */
2765 case UNIT_FILE_TYPE_MASKED
:
2766 r
= path_is_runtime(paths
, i
->path
, true);
2770 state
= r
> 0 ? UNIT_FILE_MASKED_RUNTIME
: UNIT_FILE_MASKED
;
2773 case UNIT_FILE_TYPE_REGULAR
:
2774 /* Check if the name we were querying is actually an alias */
2775 if (!streq(name
, basename(i
->path
)) && !unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
)) {
2776 state
= UNIT_FILE_ALIAS
;
2780 r
= path_is_generator(paths
, i
->path
);
2784 state
= UNIT_FILE_GENERATED
;
2788 r
= path_is_transient(paths
, i
->path
);
2792 state
= UNIT_FILE_TRANSIENT
;
2796 /* Check if any of the Alias= symlinks have been created.
2797 * We ignore other aliases, and only check those that would
2798 * be created by systemctl enable for this unit. */
2799 r
= find_symlinks_in_scope(scope
, paths
, i
, true, &state
);
2805 /* Check if the file is known under other names. If it is,
2806 * it might be in use. Report that as UNIT_FILE_INDIRECT. */
2807 r
= find_symlinks_in_scope(scope
, paths
, i
, false, &state
);
2811 state
= UNIT_FILE_INDIRECT
;
2813 if (unit_file_install_info_has_rules(i
))
2814 state
= UNIT_FILE_DISABLED
;
2815 else if (unit_file_install_info_has_also(i
))
2816 state
= UNIT_FILE_INDIRECT
;
2818 state
= UNIT_FILE_STATIC
;
2824 assert_not_reached("Unexpected unit file type.");
2831 int unit_file_get_state(
2832 UnitFileScope scope
,
2833 const char *root_dir
,
2835 UnitFileState
*ret
) {
2837 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2841 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2844 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2848 return unit_file_lookup_state(scope
, &paths
, name
, ret
);
2851 int unit_file_exists(UnitFileScope scope
, const LookupPaths
*paths
, const char *name
) {
2852 _cleanup_(install_context_done
) InstallContext c
= {};
2858 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2861 r
= install_info_discover(scope
, &c
, paths
, name
, 0, NULL
, NULL
, NULL
);
2870 static int split_pattern_into_name_and_instances(const char *pattern
, char **out_unit_name
, char ***out_instances
) {
2871 _cleanup_strv_free_
char **instances
= NULL
;
2872 _cleanup_free_
char *unit_name
= NULL
;
2876 assert(out_instances
);
2877 assert(out_unit_name
);
2879 r
= extract_first_word(&pattern
, &unit_name
, NULL
, EXTRACT_RETAIN_ESCAPE
);
2883 /* We handle the instances logic when unit name is extracted */
2885 /* We only create instances when a rule of templated unit
2886 * is seen. A rule like enable foo@.service a b c will
2887 * result in an array of (a, b, c) as instance names */
2888 if (!unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
))
2891 instances
= strv_split(pattern
, WHITESPACE
);
2895 *out_instances
= TAKE_PTR(instances
);
2898 *out_unit_name
= TAKE_PTR(unit_name
);
2903 static int presets_find_config(UnitFileScope scope
, const char *root_dir
, char ***files
) {
2904 static const char* const system_dirs
[] = {CONF_PATHS("systemd/system-preset"), NULL
};
2905 static const char* const user_dirs
[] = {CONF_PATHS_USR("systemd/user-preset"), NULL
};
2906 const char* const* dirs
;
2909 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2911 if (scope
== UNIT_FILE_SYSTEM
)
2913 else if (IN_SET(scope
, UNIT_FILE_GLOBAL
, UNIT_FILE_USER
))
2916 assert_not_reached("Invalid unit file scope");
2918 return conf_files_list_strv(files
, ".preset", root_dir
, 0, dirs
);
2921 static int read_presets(UnitFileScope scope
, const char *root_dir
, UnitFilePresets
*presets
) {
2922 _cleanup_(unit_file_presets_freep
) UnitFilePresets ps
= {};
2923 size_t n_allocated
= 0;
2924 _cleanup_strv_free_
char **files
= NULL
;
2929 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2932 r
= presets_find_config(scope
, root_dir
, &files
);
2936 STRV_FOREACH(p
, files
) {
2937 _cleanup_fclose_
FILE *f
;
2940 f
= fopen(*p
, "re");
2942 if (errno
== ENOENT
)
2949 _cleanup_free_
char *line
= NULL
;
2950 UnitFilePresetRule rule
= {};
2951 const char *parameter
;
2954 r
= read_line(f
, LONG_LINE_MAX
, &line
);
2965 if (strchr(COMMENTS
, *l
))
2968 parameter
= first_word(l
, "enable");
2971 char **instances
= NULL
;
2973 /* Unit_name will remain the same as parameter when no instances are specified */
2974 r
= split_pattern_into_name_and_instances(parameter
, &unit_name
, &instances
);
2976 log_syntax(NULL
, LOG_WARNING
, *p
, n
, r
, "Couldn't parse line '%s'. Ignoring.", line
);
2980 rule
= (UnitFilePresetRule
) {
2981 .pattern
= unit_name
,
2982 .action
= PRESET_ENABLE
,
2983 .instances
= instances
,
2987 parameter
= first_word(l
, "disable");
2991 pattern
= strdup(parameter
);
2995 rule
= (UnitFilePresetRule
) {
2997 .action
= PRESET_DISABLE
,
3002 if (!GREEDY_REALLOC(ps
.rules
, n_allocated
, ps
.n_rules
+ 1))
3005 ps
.rules
[ps
.n_rules
++] = rule
;
3009 log_syntax(NULL
, LOG_WARNING
, *p
, n
, 0, "Couldn't parse line '%s'. Ignoring.", line
);
3013 ps
.initialized
= true;
3015 ps
= (UnitFilePresets
){};
3020 static int pattern_match_multiple_instances(
3021 const UnitFilePresetRule rule
,
3022 const char *unit_name
,
3025 _cleanup_free_
char *templated_name
= NULL
;
3028 /* If no ret is needed or the rule itself does not have instances
3029 * initialized, we return not matching */
3030 if (!ret
|| !rule
.instances
)
3033 r
= unit_name_template(unit_name
, &templated_name
);
3036 if (!streq(rule
.pattern
, templated_name
))
3039 /* Compose a list of specified instances when unit name is a template */
3040 if (unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
3041 _cleanup_free_
char *prefix
= NULL
;
3042 _cleanup_strv_free_
char **out_strv
= NULL
;
3045 r
= unit_name_to_prefix(unit_name
, &prefix
);
3049 STRV_FOREACH(iter
, rule
.instances
) {
3050 _cleanup_free_
char *name
= NULL
;
3051 r
= unit_name_build(prefix
, *iter
, ".service", &name
);
3054 r
= strv_extend(&out_strv
, name
);
3059 *ret
= TAKE_PTR(out_strv
);
3062 /* We now know the input unit name is an instance name */
3063 _cleanup_free_
char *instance_name
= NULL
;
3065 r
= unit_name_to_instance(unit_name
, &instance_name
);
3069 if (strv_find(rule
.instances
, instance_name
))
3075 static int query_presets(const char *name
, const UnitFilePresets
*presets
, char ***instance_name_list
) {
3076 PresetAction action
= PRESET_UNKNOWN
;
3079 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
3082 for (i
= 0; i
< presets
->n_rules
; i
++)
3083 if (pattern_match_multiple_instances(presets
->rules
[i
], name
, instance_name_list
) > 0 ||
3084 fnmatch(presets
->rules
[i
].pattern
, name
, FNM_NOESCAPE
) == 0) {
3085 action
= presets
->rules
[i
].action
;
3090 case PRESET_UNKNOWN
:
3091 log_debug("Preset files don't specify rule for %s. Enabling.", name
);
3094 if (instance_name_list
&& *instance_name_list
)
3095 STRV_FOREACH(s
, *instance_name_list
)
3096 log_debug("Preset files say enable %s.", *s
);
3098 log_debug("Preset files say enable %s.", name
);
3100 case PRESET_DISABLE
:
3101 log_debug("Preset files say disable %s.", name
);
3104 assert_not_reached("invalid preset action");
3108 int unit_file_query_preset(UnitFileScope scope
, const char *root_dir
, const char *name
, UnitFilePresets
*cached
) {
3109 _cleanup_(unit_file_presets_freep
) UnitFilePresets tmp
= {};
3114 if (!cached
->initialized
) {
3115 r
= read_presets(scope
, root_dir
, cached
);
3120 return query_presets(name
, cached
, NULL
);
3123 static int execute_preset(
3124 UnitFileScope scope
,
3125 InstallContext
*plus
,
3126 InstallContext
*minus
,
3127 const LookupPaths
*paths
,
3128 const char *config_path
,
3130 UnitFilePresetMode mode
,
3132 UnitFileChange
**changes
,
3133 size_t *n_changes
) {
3140 assert(config_path
);
3142 if (mode
!= UNIT_FILE_PRESET_ENABLE_ONLY
) {
3143 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
3145 r
= install_context_mark_for_removal(scope
, minus
, paths
, &remove_symlinks_to
, config_path
, changes
, n_changes
);
3149 r
= remove_marked_symlinks(remove_symlinks_to
, config_path
, paths
, false, changes
, n_changes
);
3153 if (mode
!= UNIT_FILE_PRESET_DISABLE_ONLY
) {
3156 /* Returns number of symlinks that where supposed to be installed. */
3157 q
= install_context_apply(scope
, plus
, paths
, config_path
, force
, SEARCH_LOAD
, changes
, n_changes
);
3169 static int preset_prepare_one(
3170 UnitFileScope scope
,
3171 InstallContext
*plus
,
3172 InstallContext
*minus
,
3175 const UnitFilePresets
*presets
,
3176 UnitFileChange
**changes
,
3177 size_t *n_changes
) {
3179 _cleanup_(install_context_done
) InstallContext tmp
= {};
3180 _cleanup_strv_free_
char **instance_name_list
= NULL
;
3181 UnitFileInstallInfo
*i
;
3184 if (install_info_find(plus
, name
) || install_info_find(minus
, name
))
3187 r
= install_info_discover(scope
, &tmp
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3188 &i
, changes
, n_changes
);
3191 if (!streq(name
, i
->name
)) {
3192 log_debug("Skipping %s because it is an alias for %s.", name
, i
->name
);
3196 r
= query_presets(name
, presets
, &instance_name_list
);
3201 if (instance_name_list
) {
3203 STRV_FOREACH(s
, instance_name_list
) {
3204 r
= install_info_discover_and_check(scope
, plus
, paths
, *s
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3205 &i
, changes
, n_changes
);
3210 r
= install_info_discover_and_check(scope
, plus
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3211 &i
, changes
, n_changes
);
3217 r
= install_info_discover(scope
, minus
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3218 &i
, changes
, n_changes
);
3223 int unit_file_preset(
3224 UnitFileScope scope
,
3225 UnitFileFlags flags
,
3226 const char *root_dir
,
3228 UnitFilePresetMode mode
,
3229 UnitFileChange
**changes
,
3230 size_t *n_changes
) {
3232 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
3233 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3234 _cleanup_(unit_file_presets_freep
) UnitFilePresets presets
= {};
3235 const char *config_path
;
3240 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3241 assert(mode
< _UNIT_FILE_PRESET_MAX
);
3243 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3247 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
3251 r
= read_presets(scope
, root_dir
, &presets
);
3255 STRV_FOREACH(i
, files
) {
3256 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, *i
, &presets
, changes
, n_changes
);
3261 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, files
, mode
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
3264 int unit_file_preset_all(
3265 UnitFileScope scope
,
3266 UnitFileFlags flags
,
3267 const char *root_dir
,
3268 UnitFilePresetMode mode
,
3269 UnitFileChange
**changes
,
3270 size_t *n_changes
) {
3272 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
3273 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3274 _cleanup_(unit_file_presets_freep
) UnitFilePresets presets
= {};
3275 const char *config_path
= NULL
;
3280 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3281 assert(mode
< _UNIT_FILE_PRESET_MAX
);
3283 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3287 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
3291 r
= read_presets(scope
, root_dir
, &presets
);
3295 STRV_FOREACH(i
, paths
.search_path
) {
3296 _cleanup_closedir_
DIR *d
= NULL
;
3301 if (errno
== ENOENT
)
3307 FOREACH_DIRENT(de
, d
, return -errno
) {
3309 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
3312 dirent_ensure_type(d
, de
);
3314 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
3317 /* we don't pass changes[] in, because we want to handle errors on our own */
3318 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, de
->d_name
, &presets
, NULL
, 0);
3320 r
= unit_file_changes_add(changes
, n_changes
,
3321 UNIT_FILE_IS_MASKED
, de
->d_name
, NULL
);
3322 else if (r
== -ENOLINK
)
3323 r
= unit_file_changes_add(changes
, n_changes
,
3324 UNIT_FILE_IS_DANGLING
, de
->d_name
, NULL
);
3325 else if (r
== -EADDRNOTAVAIL
) /* Ignore generated/transient units when applying preset */
3332 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, NULL
, mode
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
3335 static void unit_file_list_free_one(UnitFileList
*f
) {
3343 Hashmap
* unit_file_list_free(Hashmap
*h
) {
3344 return hashmap_free_with_destructor(h
, unit_file_list_free_one
);
3347 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList
*, unit_file_list_free_one
);
3349 int unit_file_get_list(
3350 UnitFileScope scope
,
3351 const char *root_dir
,
3356 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3361 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3364 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3368 STRV_FOREACH(dirname
, paths
.search_path
) {
3369 _cleanup_closedir_
DIR *d
= NULL
;
3372 d
= opendir(*dirname
);
3374 if (errno
== ENOENT
)
3376 if (IN_SET(errno
, ENOTDIR
, EACCES
)) {
3377 log_debug_errno(errno
, "Failed to open \"%s\": %m", *dirname
);
3384 FOREACH_DIRENT(de
, d
, return -errno
) {
3385 _cleanup_(unit_file_list_free_onep
) UnitFileList
*f
= NULL
;
3387 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
3390 if (!strv_fnmatch_or_empty(patterns
, de
->d_name
, FNM_NOESCAPE
))
3393 if (hashmap_get(h
, de
->d_name
))
3396 dirent_ensure_type(d
, de
);
3398 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
3401 f
= new0(UnitFileList
, 1);
3405 f
->path
= path_make_absolute(de
->d_name
, *dirname
);
3409 r
= unit_file_lookup_state(scope
, &paths
, de
->d_name
, &f
->state
);
3411 f
->state
= UNIT_FILE_BAD
;
3413 if (!strv_isempty(states
) &&
3414 !strv_contains(states
, unit_file_state_to_string(f
->state
)))
3417 r
= hashmap_put(h
, basename(f
->path
), f
);
3421 f
= NULL
; /* prevent cleanup */
3428 static const char* const unit_file_state_table
[_UNIT_FILE_STATE_MAX
] = {
3429 [UNIT_FILE_ENABLED
] = "enabled",
3430 [UNIT_FILE_ENABLED_RUNTIME
] = "enabled-runtime",
3431 [UNIT_FILE_LINKED
] = "linked",
3432 [UNIT_FILE_LINKED_RUNTIME
] = "linked-runtime",
3433 [UNIT_FILE_ALIAS
] = "alias",
3434 [UNIT_FILE_MASKED
] = "masked",
3435 [UNIT_FILE_MASKED_RUNTIME
] = "masked-runtime",
3436 [UNIT_FILE_STATIC
] = "static",
3437 [UNIT_FILE_DISABLED
] = "disabled",
3438 [UNIT_FILE_INDIRECT
] = "indirect",
3439 [UNIT_FILE_GENERATED
] = "generated",
3440 [UNIT_FILE_TRANSIENT
] = "transient",
3441 [UNIT_FILE_BAD
] = "bad",
3444 DEFINE_STRING_TABLE_LOOKUP(unit_file_state
, UnitFileState
);
3446 static const char* const unit_file_change_type_table
[_UNIT_FILE_CHANGE_TYPE_MAX
] = {
3447 [UNIT_FILE_SYMLINK
] = "symlink",
3448 [UNIT_FILE_UNLINK
] = "unlink",
3449 [UNIT_FILE_IS_MASKED
] = "masked",
3450 [UNIT_FILE_IS_DANGLING
] = "dangling",
3453 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type
, UnitFileChangeType
);
3455 static const char* const unit_file_preset_mode_table
[_UNIT_FILE_PRESET_MAX
] = {
3456 [UNIT_FILE_PRESET_FULL
] = "full",
3457 [UNIT_FILE_PRESET_ENABLE_ONLY
] = "enable-only",
3458 [UNIT_FILE_PRESET_DISABLE_ONLY
] = "disable-only",
3461 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode
, UnitFilePresetMode
);