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_or_generator(const LookupPaths
*p
, const char *path
) {
236 rpath
= skip_root(p
, path
);
240 if (path_startswith(rpath
, "/usr"))
244 if (path_startswith(rpath
, "/lib"))
248 if (path_is_generator(p
, rpath
))
251 return path_equal(rpath
, SYSTEM_DATA_UNIT_PATH
);
254 int unit_file_changes_add(
255 UnitFileChange
**changes
,
257 UnitFileChangeType type
,
259 const char *source
) {
261 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
265 assert(!changes
== !n_changes
);
270 c
= reallocarray(*changes
, *n_changes
+ 1, sizeof(UnitFileChange
));
279 if (!p
|| (source
&& !s
))
282 path_simplify(p
, false);
284 path_simplify(s
, false);
286 c
[*n_changes
] = (UnitFileChange
) { type
, p
, s
};
292 void unit_file_changes_free(UnitFileChange
*changes
, size_t n_changes
) {
295 assert(changes
|| n_changes
== 0);
297 for (i
= 0; i
< n_changes
; i
++) {
298 free(changes
[i
].path
);
299 free(changes
[i
].source
);
305 void unit_file_dump_changes(int r
, const char *verb
, const UnitFileChange
*changes
, size_t n_changes
, bool quiet
) {
309 assert(changes
|| n_changes
== 0);
310 /* If verb is not specified, errors are not allowed! */
311 assert(verb
|| r
>= 0);
313 for (i
= 0; i
< n_changes
; i
++) {
314 assert(verb
|| changes
[i
].type
>= 0);
316 switch(changes
[i
].type
) {
317 case UNIT_FILE_SYMLINK
:
319 log_info("Created symlink %s %s %s.",
321 special_glyph(SPECIAL_GLYPH_ARROW
),
324 case UNIT_FILE_UNLINK
:
326 log_info("Removed %s.", changes
[i
].path
);
328 case UNIT_FILE_IS_MASKED
:
330 log_info("Unit %s is masked, ignoring.", changes
[i
].path
);
332 case UNIT_FILE_IS_DANGLING
:
334 log_info("Unit %s is an alias to a unit that is not present, ignoring.",
338 if (changes
[i
].source
)
339 log_error_errno(changes
[i
].type
,
340 "Failed to %s unit, file %s already exists and is a symlink to %s.",
341 verb
, changes
[i
].path
, changes
[i
].source
);
343 log_error_errno(changes
[i
].type
,
344 "Failed to %s unit, file %s already exists.",
345 verb
, changes
[i
].path
);
349 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s is masked.",
350 verb
, changes
[i
].path
);
354 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s is transient or generated.",
355 verb
, changes
[i
].path
);
359 log_error_errno(changes
[i
].type
,
360 "Failed to %s unit, \"%s\" is not a valid unit name.",
361 verb
, changes
[i
].path
);
365 log_error_errno(changes
[i
].type
, "Failed to %s unit, refusing to operate on linked unit file %s",
366 verb
, changes
[i
].path
);
371 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s does not exist.", verb
, changes
[i
].path
);
376 assert(changes
[i
].type
< 0);
377 log_error_errno(changes
[i
].type
, "Failed to %s unit, file %s: %m.",
378 verb
, changes
[i
].path
);
383 if (r
< 0 && !logged
)
384 log_error_errno(r
, "Failed to %s: %m.", verb
);
388 * Checks if two paths or symlinks from wd are the same, when root is the root of the filesystem.
389 * wc should be the full path in the host file system.
391 static bool chroot_symlinks_same(const char *root
, const char *wd
, const char *a
, const char *b
) {
392 assert(path_is_absolute(wd
));
394 /* This will give incorrect results if the paths are relative and go outside
395 * of the chroot. False negatives are possible. */
400 a
= strjoina(path_is_absolute(a
) ? root
: wd
, "/", a
);
401 b
= strjoina(path_is_absolute(b
) ? root
: wd
, "/", b
);
402 return path_equal_or_files_same(a
, b
, 0);
405 static int create_symlink(
406 const LookupPaths
*paths
,
407 const char *old_path
,
408 const char *new_path
,
410 UnitFileChange
**changes
,
413 _cleanup_free_
char *dest
= NULL
, *dirname
= NULL
;
420 rp
= skip_root(paths
, old_path
);
424 /* Actually create a symlink, and remember that we did. Is
425 * smart enough to check if there's already a valid symlink in
428 * Returns 1 if a symlink was created or already exists and points to
429 * the right place, or negative on error.
432 mkdir_parents_label(new_path
, 0755);
434 if (symlink(old_path
, new_path
) >= 0) {
435 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
439 if (errno
!= EEXIST
) {
440 unit_file_changes_add(changes
, n_changes
, -errno
, new_path
, NULL
);
444 r
= readlink_malloc(new_path
, &dest
);
446 /* translate EINVAL (non-symlink exists) to EEXIST */
450 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
454 dirname
= dirname_malloc(new_path
);
458 if (chroot_symlinks_same(paths
->root_dir
, dirname
, dest
, old_path
)) {
459 log_debug("Symlink %s → %s already exists", new_path
, dest
);
464 unit_file_changes_add(changes
, n_changes
, -EEXIST
, new_path
, dest
);
468 r
= symlink_atomic(old_path
, new_path
);
470 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
474 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, new_path
, NULL
);
475 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
480 static int mark_symlink_for_removal(
481 Set
**remove_symlinks_to
,
489 r
= set_ensure_allocated(remove_symlinks_to
, &path_hash_ops
);
497 path_simplify(n
, false);
499 r
= set_consume(*remove_symlinks_to
, n
);
508 static int remove_marked_symlinks_fd(
509 Set
*remove_symlinks_to
,
512 const char *config_path
,
513 const LookupPaths
*lp
,
516 UnitFileChange
**changes
,
519 _cleanup_closedir_
DIR *d
= NULL
;
523 assert(remove_symlinks_to
);
538 FOREACH_DIRENT(de
, d
, return -errno
) {
540 dirent_ensure_type(d
, de
);
542 if (de
->d_type
== DT_DIR
) {
543 _cleanup_free_
char *p
= NULL
;
546 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
556 p
= path_make_absolute(de
->d_name
, path
);
562 /* This will close nfd, regardless whether it succeeds or not */
563 q
= remove_marked_symlinks_fd(remove_symlinks_to
, nfd
, p
, config_path
, lp
, dry_run
, restart
, changes
, n_changes
);
567 } else if (de
->d_type
== DT_LNK
) {
568 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
573 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
576 p
= path_make_absolute(de
->d_name
, path
);
579 path_simplify(p
, false);
581 q
= chase_symlinks(p
, NULL
, CHASE_NONEXISTENT
, &dest
, NULL
);
590 /* We remove all links pointing to a file or path that is marked, as well as all files sharing
591 * the same name as a file that is marked. */
593 found
= set_contains(remove_symlinks_to
, dest
) ||
594 set_contains(remove_symlinks_to
, basename(dest
)) ||
595 set_contains(remove_symlinks_to
, de
->d_name
);
601 if (unlinkat(fd
, de
->d_name
, 0) < 0 && errno
!= ENOENT
) {
604 unit_file_changes_add(changes
, n_changes
, -errno
, p
, NULL
);
608 (void) rmdir_parents(p
, config_path
);
611 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, p
, NULL
);
613 /* Now, remember the full path (but with the root prefix removed) of
614 * the symlink we just removed, and remove any symlinks to it, too. */
616 rp
= skip_root(lp
, p
);
617 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: p
);
620 if (q
> 0 && !dry_run
)
628 static int remove_marked_symlinks(
629 Set
*remove_symlinks_to
,
630 const char *config_path
,
631 const LookupPaths
*lp
,
633 UnitFileChange
**changes
,
636 _cleanup_close_
int fd
= -1;
643 if (set_size(remove_symlinks_to
) <= 0)
646 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
);
648 return errno
== ENOENT
? 0 : -errno
;
654 cfd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
658 /* This takes possession of cfd and closes it */
659 q
= remove_marked_symlinks_fd(remove_symlinks_to
, cfd
, config_path
, config_path
, lp
, dry_run
, &restart
, changes
, n_changes
);
667 static int is_symlink_with_known_name(const UnitFileInstallInfo
*i
, const char *name
) {
670 if (streq(name
, i
->name
))
673 if (strv_contains(i
->aliases
, name
))
676 /* Look for template symlink matching DefaultInstance */
677 if (i
->default_instance
&& unit_name_is_valid(i
->name
, UNIT_NAME_TEMPLATE
)) {
678 _cleanup_free_
char *s
= NULL
;
680 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &s
);
685 } else if (streq(name
, s
))
692 static int find_symlinks_fd(
693 const char *root_dir
,
694 const UnitFileInstallInfo
*i
,
696 bool ignore_same_name
,
699 const char *config_path
,
700 bool *same_name_link
) {
702 _cleanup_closedir_
DIR *d
= NULL
;
710 assert(same_name_link
);
718 FOREACH_DIRENT(de
, d
, return -errno
) {
720 dirent_ensure_type(d
, de
);
722 if (de
->d_type
== DT_DIR
) {
723 _cleanup_free_
char *p
= NULL
;
726 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
736 p
= path_make_absolute(de
->d_name
, path
);
742 /* This will close nfd, regardless whether it succeeds or not */
743 q
= find_symlinks_fd(root_dir
, i
, match_aliases
, ignore_same_name
, nfd
,
744 p
, config_path
, same_name_link
);
750 } else if (de
->d_type
== DT_LNK
) {
751 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
752 bool found_path
= false, found_dest
, b
= false;
755 /* Acquire symlink name */
756 p
= path_make_absolute(de
->d_name
, path
);
760 /* Acquire symlink destination */
761 q
= readlink_malloc(p
, &dest
);
771 if (!path_is_absolute(dest
)) {
774 x
= path_join(root_dir
, dest
);
778 free_and_replace(dest
, x
);
781 assert(unit_name_is_valid(i
->name
, UNIT_NAME_ANY
));
782 if (!ignore_same_name
)
783 /* Check if the symlink itself matches what we are looking for.
785 * If ignore_same_name is specified, we are in one of the directories which
786 * have lower priority than the unit file, and even if a file or symlink with
787 * this name was found, we should ignore it. */
788 found_path
= streq(de
->d_name
, i
->name
);
790 /* Check if what the symlink points to matches what we are looking for */
791 found_dest
= streq(basename(dest
), i
->name
);
793 if (found_path
&& found_dest
) {
794 _cleanup_free_
char *t
= NULL
;
796 /* Filter out same name links in the main
798 t
= path_make_absolute(i
->name
, config_path
);
802 b
= path_equal(t
, p
);
806 *same_name_link
= true;
807 else if (found_path
|| found_dest
) {
811 /* Check if symlink name is in the set of names used by [Install] */
812 q
= is_symlink_with_known_name(i
, de
->d_name
);
824 static int find_symlinks(
825 const char *root_dir
,
826 const UnitFileInstallInfo
*i
,
828 bool ignore_same_name
,
829 const char *config_path
,
830 bool *same_name_link
) {
836 assert(same_name_link
);
838 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
);
840 if (IN_SET(errno
, ENOENT
, ENOTDIR
, EACCES
))
845 /* This takes possession of fd and closes it */
846 return find_symlinks_fd(root_dir
, i
, match_name
, ignore_same_name
, fd
,
847 config_path
, config_path
, same_name_link
);
850 static int find_symlinks_in_scope(
852 const LookupPaths
*paths
,
853 const UnitFileInstallInfo
*i
,
855 UnitFileState
*state
) {
857 bool same_name_link_runtime
= false, same_name_link_config
= false;
858 bool enabled_in_runtime
= false, enabled_at_all
= false;
859 bool ignore_same_name
= false;
866 /* As we iterate over the list of search paths in paths->search_path, we may encounter "same name"
867 * symlinks. The ones which are "below" (i.e. have lower priority) than the unit file itself are
868 * effectively masked, so we should ignore them. */
870 STRV_FOREACH(p
, paths
->search_path
) {
871 bool same_name_link
= false;
873 r
= find_symlinks(paths
->root_dir
, i
, match_name
, ignore_same_name
, *p
, &same_name_link
);
877 /* We found symlinks in this dir? Yay! Let's see where precisely it is enabled. */
879 if (path_equal_ptr(*p
, paths
->persistent_config
)) {
880 /* This is the best outcome, let's return it immediately. */
881 *state
= UNIT_FILE_ENABLED
;
885 /* look for global enablement of user units */
886 if (scope
== UNIT_FILE_USER
&& path_is_user_config_dir(*p
)) {
887 *state
= UNIT_FILE_ENABLED
;
891 r
= path_is_runtime(paths
, *p
, false);
895 enabled_in_runtime
= true;
897 enabled_at_all
= true;
899 } else if (same_name_link
) {
900 if (path_equal_ptr(*p
, paths
->persistent_config
))
901 same_name_link_config
= true;
903 r
= path_is_runtime(paths
, *p
, false);
907 same_name_link_runtime
= true;
911 /* Check if next iteration will be "below" the unit file (either a regular file
912 * or a symlink), and hence should be ignored */
913 if (!ignore_same_name
&& path_startswith(i
->path
, *p
))
914 ignore_same_name
= true;
917 if (enabled_in_runtime
) {
918 *state
= UNIT_FILE_ENABLED_RUNTIME
;
922 /* Here's a special rule: if the unit we are looking for is an instance, and it symlinked in the search path
923 * outside of runtime and configuration directory, then we consider it statically enabled. Note we do that only
924 * for instance, not for regular names, as those are merely aliases, while instances explicitly instantiate
925 * something, and hence are a much stronger concept. */
926 if (enabled_at_all
&& unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
)) {
927 *state
= UNIT_FILE_STATIC
;
931 /* Hmm, we didn't find it, but maybe we found the same name
933 if (same_name_link_config
) {
934 *state
= UNIT_FILE_LINKED
;
937 if (same_name_link_runtime
) {
938 *state
= UNIT_FILE_LINKED_RUNTIME
;
945 static void install_info_free(UnitFileInstallInfo
*i
) {
952 strv_free(i
->aliases
);
953 strv_free(i
->wanted_by
);
954 strv_free(i
->required_by
);
956 free(i
->default_instance
);
957 free(i
->symlink_target
);
961 static void install_context_done(InstallContext
*c
) {
964 c
->will_process
= ordered_hashmap_free_with_destructor(c
->will_process
, install_info_free
);
965 c
->have_processed
= ordered_hashmap_free_with_destructor(c
->have_processed
, install_info_free
);
968 static UnitFileInstallInfo
*install_info_find(InstallContext
*c
, const char *name
) {
969 UnitFileInstallInfo
*i
;
971 i
= ordered_hashmap_get(c
->have_processed
, name
);
975 return ordered_hashmap_get(c
->will_process
, name
);
978 static int install_info_may_process(
979 const UnitFileInstallInfo
*i
,
980 const LookupPaths
*paths
,
981 UnitFileChange
**changes
,
986 /* Checks whether the loaded unit file is one we should process, or is masked,
987 * transient or generated and thus not subject to enable/disable operations. */
989 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
990 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, i
->path
, NULL
);
993 if (path_is_generator(paths
, i
->path
) ||
994 path_is_transient(paths
, i
->path
)) {
995 unit_file_changes_add(changes
, n_changes
, -EADDRNOTAVAIL
, i
->path
, NULL
);
996 return -EADDRNOTAVAIL
;
1003 * Adds a new UnitFileInstallInfo entry under name in the InstallContext.will_process
1004 * hashmap, or retrieves the existing one if already present.
1006 * Returns negative on error, 0 if the unit was already known, 1 otherwise.
1008 static int install_info_add(
1013 UnitFileInstallInfo
**ret
) {
1015 UnitFileInstallInfo
*i
= NULL
;
1021 /* 'name' and 'path' must not both be null. Check here 'path' using assert_se() to
1022 * workaround a bug in gcc that generates a -Wnonnull warning when calling basename(),
1023 * but this cannot be possible in any code path (See #6119). */
1025 name
= basename(path
);
1028 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
1031 i
= install_info_find(c
, name
);
1033 i
->auxiliary
= i
->auxiliary
&& auxiliary
;
1040 r
= ordered_hashmap_ensure_allocated(&c
->will_process
, &string_hash_ops
);
1044 i
= new(UnitFileInstallInfo
, 1);
1048 *i
= (UnitFileInstallInfo
) {
1049 .type
= _UNIT_FILE_TYPE_INVALID
,
1050 .auxiliary
= auxiliary
,
1053 i
->name
= strdup(name
);
1060 i
->path
= strdup(path
);
1067 r
= ordered_hashmap_put(c
->will_process
, i
->name
, i
);
1077 install_info_free(i
);
1081 static int config_parse_alias(
1083 const char *filename
,
1085 const char *section
,
1086 unsigned section_line
,
1100 type
= unit_name_to_type(unit
);
1101 if (!unit_type_may_alias(type
))
1102 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1103 "Alias= is not allowed for %s units, ignoring.",
1104 unit_type_to_string(type
));
1106 return config_parse_strv(unit
, filename
, line
, section
, section_line
,
1107 lvalue
, ltype
, rvalue
, data
, userdata
);
1110 static int config_parse_also(
1112 const char *filename
,
1114 const char *section
,
1115 unsigned section_line
,
1122 UnitFileInstallInfo
*info
= userdata
;
1123 InstallContext
*c
= data
;
1132 _cleanup_free_
char *word
= NULL
, *printed
= NULL
;
1134 r
= extract_first_word(&rvalue
, &word
, NULL
, 0);
1140 r
= install_full_printf(info
, word
, &printed
);
1144 r
= install_info_add(c
, printed
, NULL
, true, NULL
);
1148 r
= strv_push(&info
->also
, printed
);
1158 static int config_parse_default_instance(
1160 const char *filename
,
1162 const char *section
,
1163 unsigned section_line
,
1170 UnitFileInstallInfo
*i
= data
;
1171 _cleanup_free_
char *printed
= NULL
;
1179 if (unit_name_is_valid(unit
, UNIT_NAME_INSTANCE
))
1180 /* When enabling an instance, we might be using a template unit file,
1181 * but we should ignore DefaultInstance silently. */
1183 if (!unit_name_is_valid(unit
, UNIT_NAME_TEMPLATE
))
1184 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1185 "DefaultInstance= only makes sense for template units, ignoring.");
1187 r
= install_full_printf(i
, rvalue
, &printed
);
1191 if (isempty(printed
)) {
1192 i
->default_instance
= mfree(i
->default_instance
);
1196 if (!unit_instance_is_valid(printed
))
1197 return log_syntax(unit
, LOG_WARNING
, filename
, line
, SYNTHETIC_ERRNO(EINVAL
),
1198 "Invalid DefaultInstance= value \"%s\".", printed
);
1200 return free_and_replace(i
->default_instance
, printed
);
1203 static int unit_file_load(
1205 UnitFileInstallInfo
*info
,
1207 const char *root_dir
,
1208 SearchFlags flags
) {
1210 const ConfigTableItem items
[] = {
1211 { "Install", "Alias", config_parse_alias
, 0, &info
->aliases
},
1212 { "Install", "WantedBy", config_parse_strv
, 0, &info
->wanted_by
},
1213 { "Install", "RequiredBy", config_parse_strv
, 0, &info
->required_by
},
1214 { "Install", "DefaultInstance", config_parse_default_instance
, 0, info
},
1215 { "Install", "Also", config_parse_also
, 0, c
},
1220 _cleanup_fclose_
FILE *f
= NULL
;
1221 _cleanup_close_
int fd
= -1;
1228 if (!(flags
& SEARCH_DROPIN
)) {
1229 /* Loading or checking for the main unit file… */
1231 type
= unit_name_to_type(info
->name
);
1234 if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
|UNIT_NAME_INSTANCE
) && !unit_type_may_template(type
))
1235 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1236 "%s: unit type %s cannot be templated, ignoring.", path
, unit_type_to_string(type
));
1238 if (!(flags
& SEARCH_LOAD
)) {
1239 r
= lstat(path
, &st
);
1243 if (null_or_empty(&st
))
1244 info
->type
= UNIT_FILE_TYPE_MASKED
;
1245 else if (S_ISREG(st
.st_mode
))
1246 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1247 else if (S_ISLNK(st
.st_mode
))
1249 else if (S_ISDIR(st
.st_mode
))
1257 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
1261 /* 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. */
1263 if (!(flags
& SEARCH_LOAD
))
1266 fd
= chase_symlinks_and_open(path
, root_dir
, 0, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
, NULL
);
1271 if (fstat(fd
, &st
) < 0)
1274 if (null_or_empty(&st
)) {
1275 if ((flags
& SEARCH_DROPIN
) == 0)
1276 info
->type
= UNIT_FILE_TYPE_MASKED
;
1281 r
= stat_verify_regular(&st
);
1285 f
= take_fdopen(&fd
, "r");
1289 /* c is only needed if we actually load the file (it's referenced from items[] btw, in case you wonder.) */
1292 r
= config_parse(info
->name
, path
, f
,
1306 config_item_table_lookup
, items
,
1310 return log_debug_errno(r
, "Failed to parse %s: %m", info
->name
);
1312 if ((flags
& SEARCH_DROPIN
) == 0)
1313 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1316 (int) strv_length(info
->aliases
) +
1317 (int) strv_length(info
->wanted_by
) +
1318 (int) strv_length(info
->required_by
);
1321 static int unit_file_load_or_readlink(
1323 UnitFileInstallInfo
*info
,
1325 const char *root_dir
,
1326 SearchFlags flags
) {
1328 _cleanup_free_
char *target
= NULL
;
1331 r
= unit_file_load(c
, info
, path
, root_dir
, flags
);
1332 if (r
!= -ELOOP
|| (flags
& SEARCH_DROPIN
))
1335 /* This is a symlink, let's read it. */
1337 r
= readlink_malloc(path
, &target
);
1341 if (path_equal(target
, "/dev/null"))
1342 info
->type
= UNIT_FILE_TYPE_MASKED
;
1347 bn
= basename(target
);
1349 if (unit_name_is_valid(info
->name
, UNIT_NAME_PLAIN
)) {
1351 if (!unit_name_is_valid(bn
, UNIT_NAME_PLAIN
))
1354 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1356 if (!unit_name_is_valid(bn
, UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
))
1359 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
)) {
1361 if (!unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
))
1366 /* Enforce that the symlink destination does not
1367 * change the unit file type. */
1369 a
= unit_name_to_type(info
->name
);
1370 b
= unit_name_to_type(bn
);
1371 if (a
< 0 || b
< 0 || a
!= b
)
1374 if (path_is_absolute(target
))
1375 /* This is an absolute path, prefix the root so that we always deal with fully qualified paths */
1376 info
->symlink_target
= path_join(root_dir
, target
);
1378 /* This is a relative path, take it relative to the dir the symlink is located in. */
1379 info
->symlink_target
= file_in_same_dir(path
, target
);
1380 if (!info
->symlink_target
)
1383 info
->type
= UNIT_FILE_TYPE_SYMLINK
;
1389 static int unit_file_search(
1391 UnitFileInstallInfo
*info
,
1392 const LookupPaths
*paths
,
1393 SearchFlags flags
) {
1395 const char *dropin_dir_name
= NULL
, *dropin_template_dir_name
= NULL
;
1396 _cleanup_strv_free_
char **dirs
= NULL
, **files
= NULL
;
1397 _cleanup_free_
char *template = NULL
;
1398 bool found_unit
= false;
1405 /* Was this unit already loaded? */
1406 if (info
->type
!= _UNIT_FILE_TYPE_INVALID
)
1410 return unit_file_load_or_readlink(c
, info
, info
->path
, paths
->root_dir
, flags
);
1414 if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1415 r
= unit_name_template(info
->name
, &template);
1420 STRV_FOREACH(p
, paths
->search_path
) {
1421 _cleanup_free_
char *path
= NULL
;
1423 path
= path_join(*p
, info
->name
);
1427 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1429 info
->path
= TAKE_PTR(path
);
1433 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1437 if (!found_unit
&& template) {
1439 /* Unit file doesn't exist, however instance
1440 * enablement was requested. We will check if it is
1441 * possible to load template unit file. */
1443 STRV_FOREACH(p
, paths
->search_path
) {
1444 _cleanup_free_
char *path
= NULL
;
1446 path
= path_join(*p
, template);
1450 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1452 info
->path
= TAKE_PTR(path
);
1456 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1462 return log_debug_errno(SYNTHETIC_ERRNO(ENOENT
),
1463 "Cannot find unit %s%s%s.",
1464 info
->name
, template ? " or " : "", strempty(template));
1466 if (info
->type
== UNIT_FILE_TYPE_MASKED
)
1469 /* Search for drop-in directories */
1471 dropin_dir_name
= strjoina(info
->name
, ".d");
1472 STRV_FOREACH(p
, paths
->search_path
) {
1475 path
= path_join(*p
, dropin_dir_name
);
1479 r
= strv_consume(&dirs
, path
);
1485 dropin_template_dir_name
= strjoina(template, ".d");
1486 STRV_FOREACH(p
, paths
->search_path
) {
1489 path
= path_join(*p
, dropin_template_dir_name
);
1493 r
= strv_consume(&dirs
, path
);
1499 /* Load drop-in conf files */
1501 r
= conf_files_list_strv(&files
, ".conf", NULL
, 0, (const char**) dirs
);
1503 return log_debug_errno(r
, "Failed to get list of conf files: %m");
1505 STRV_FOREACH(p
, files
) {
1506 r
= unit_file_load_or_readlink(c
, info
, *p
, paths
->root_dir
, flags
| SEARCH_DROPIN
);
1508 return log_debug_errno(r
, "Failed to load conf file %s: %m", *p
);
1514 static int install_info_follow(
1516 UnitFileInstallInfo
*i
,
1517 const char *root_dir
,
1519 bool ignore_different_name
) {
1524 if (i
->type
!= UNIT_FILE_TYPE_SYMLINK
)
1526 if (!i
->symlink_target
)
1529 /* If the basename doesn't match, the caller should add a
1530 * complete new entry for this. */
1532 if (!ignore_different_name
&& !streq(basename(i
->symlink_target
), i
->name
))
1535 free_and_replace(i
->path
, i
->symlink_target
);
1536 i
->type
= _UNIT_FILE_TYPE_INVALID
;
1538 return unit_file_load_or_readlink(c
, i
, i
->path
, root_dir
, flags
);
1542 * Search for the unit file. If the unit name is a symlink, follow the symlink to the
1543 * target, maybe more than once. Propagate the instance name if present.
1545 static int install_info_traverse(
1546 UnitFileScope scope
,
1548 const LookupPaths
*paths
,
1549 UnitFileInstallInfo
*start
,
1551 UnitFileInstallInfo
**ret
) {
1553 UnitFileInstallInfo
*i
;
1561 r
= unit_file_search(c
, start
, paths
, flags
);
1566 while (i
->type
== UNIT_FILE_TYPE_SYMLINK
) {
1567 /* Follow the symlink */
1569 if (++k
> UNIT_FILE_FOLLOW_SYMLINK_MAX
)
1572 if (!(flags
& SEARCH_FOLLOW_CONFIG_SYMLINKS
)) {
1573 r
= path_is_config(paths
, i
->path
, true);
1580 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
, false);
1582 _cleanup_free_
char *buffer
= NULL
;
1585 /* Target has a different name, create a new
1586 * install info object for that, and continue
1589 bn
= basename(i
->symlink_target
);
1591 if (unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
) &&
1592 unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
)) {
1594 _cleanup_free_
char *instance
= NULL
;
1596 r
= unit_name_to_instance(i
->name
, &instance
);
1600 r
= unit_name_replace_instance(bn
, instance
, &buffer
);
1604 if (streq(buffer
, i
->name
)) {
1606 /* We filled in the instance, and the target stayed the same? If so, then let's
1607 * honour the link as it is. */
1609 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
, true);
1619 r
= install_info_add(c
, bn
, NULL
, false, &i
);
1623 /* Try again, with the new target we found. */
1624 r
= unit_file_search(c
, i
, paths
, flags
);
1626 /* Translate error code to highlight this specific case */
1641 * Call install_info_add() with name_or_path as the path (if name_or_path starts with "/")
1642 * or the name (otherwise). root_dir is prepended to the path.
1644 static int install_info_add_auto(
1646 const LookupPaths
*paths
,
1647 const char *name_or_path
,
1648 UnitFileInstallInfo
**ret
) {
1651 assert(name_or_path
);
1653 if (path_is_absolute(name_or_path
)) {
1656 pp
= prefix_roota(paths
->root_dir
, name_or_path
);
1658 return install_info_add(c
, NULL
, pp
, false, ret
);
1660 return install_info_add(c
, name_or_path
, NULL
, false, ret
);
1663 static int install_info_discover(
1664 UnitFileScope scope
,
1666 const LookupPaths
*paths
,
1669 UnitFileInstallInfo
**ret
,
1670 UnitFileChange
**changes
,
1671 size_t *n_changes
) {
1673 UnitFileInstallInfo
*i
;
1680 r
= install_info_add_auto(c
, paths
, name
, &i
);
1682 r
= install_info_traverse(scope
, c
, paths
, i
, flags
, ret
);
1685 unit_file_changes_add(changes
, n_changes
, r
, name
, NULL
);
1689 static int install_info_discover_and_check(
1690 UnitFileScope scope
,
1692 const LookupPaths
*paths
,
1695 UnitFileInstallInfo
**ret
,
1696 UnitFileChange
**changes
,
1697 size_t *n_changes
) {
1701 r
= install_info_discover(scope
, c
, paths
, name
, flags
, ret
, changes
, n_changes
);
1705 return install_info_may_process(ret
? *ret
: NULL
, paths
, changes
, n_changes
);
1708 int unit_file_verify_alias(const UnitFileInstallInfo
*i
, const char *dst
, char **ret_dst
) {
1709 _cleanup_free_
char *dst_updated
= NULL
;
1712 /* Verify that dst is a valid either a valid alias or a valid .wants/.requires symlink for the target
1713 * unit *i. Return negative on error or if not compatible, zero on success.
1715 * ret_dst is set in cases where "instance propagation" happens, i.e. when the instance part is
1716 * inserted into dst. It is not normally set, even on success, so that the caller can easily
1717 * distinguish the case where instance propagation occurred.
1720 const char *path_alias
= strrchr(dst
, '/');
1722 /* This branch covers legacy Alias= function of creating .wants and .requires symlinks. */
1723 _cleanup_free_
char *dir
= NULL
;
1726 path_alias
++; /* skip over slash */
1728 dir
= dirname_malloc(dst
);
1732 p
= endswith(dir
, ".wants");
1734 p
= endswith(dir
, ".requires");
1736 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV
),
1737 "Invalid path \"%s\" in alias.", dir
);
1738 *p
= '\0'; /* dir should now be a unit name */
1740 r
= unit_name_classify(dir
);
1742 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV
),
1743 "Invalid unit name component \"%s\" in alias.", dir
);
1745 const bool instance_propagation
= r
== UNIT_NAME_TEMPLATE
;
1747 /* That's the name we want to use for verification. */
1748 r
= unit_symlink_name_compatible(path_alias
, i
->name
, instance_propagation
);
1750 return log_error_errno(r
, "Failed to verify alias validity: %m");
1752 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV
),
1753 "Invalid unit %s symlink %s.",
1757 /* If the symlink target has an instance set and the symlink source doesn't, we "propagate
1758 * the instance", i.e. instantiate the symlink source with the target instance. */
1759 if (unit_name_is_valid(dst
, UNIT_NAME_TEMPLATE
)) {
1760 _cleanup_free_
char *inst
= NULL
;
1762 r
= unit_name_to_instance(i
->name
, &inst
);
1764 return log_error_errno(r
, "Failed to extract instance name from %s: %m", i
->name
);
1766 if (r
== UNIT_NAME_INSTANCE
) {
1767 r
= unit_name_replace_instance(dst
, inst
, &dst_updated
);
1769 return log_error_errno(r
, "Failed to build unit name from %s+%s: %m",
1774 r
= unit_validate_alias_symlink_and_warn(dst_updated
?: dst
, i
->name
);
1780 *ret_dst
= TAKE_PTR(dst_updated
);
1784 static int install_info_symlink_alias(
1785 UnitFileInstallInfo
*i
,
1786 const LookupPaths
*paths
,
1787 const char *config_path
,
1789 UnitFileChange
**changes
,
1790 size_t *n_changes
) {
1797 assert(config_path
);
1799 STRV_FOREACH(s
, i
->aliases
) {
1800 _cleanup_free_
char *alias_path
= NULL
, *dst
= NULL
, *dst_updated
= NULL
;
1802 q
= install_full_printf(i
, *s
, &dst
);
1806 q
= unit_file_verify_alias(i
, dst
, &dst_updated
);
1810 alias_path
= path_make_absolute(dst_updated
?: dst
, config_path
);
1814 q
= create_symlink(paths
, i
->path
, alias_path
, force
, changes
, n_changes
);
1822 static int install_info_symlink_wants(
1823 UnitFileInstallInfo
*i
,
1824 const LookupPaths
*paths
,
1825 const char *config_path
,
1828 UnitFileChange
**changes
,
1829 size_t *n_changes
) {
1831 _cleanup_free_
char *buf
= NULL
;
1838 assert(config_path
);
1840 if (strv_isempty(list
))
1843 if (unit_name_is_valid(i
->name
, UNIT_NAME_TEMPLATE
)) {
1844 UnitFileInstallInfo instance
= {
1845 .type
= _UNIT_FILE_TYPE_INVALID
,
1847 _cleanup_free_
char *path
= NULL
;
1849 /* If this is a template, and we have no instance, don't do anything */
1850 if (!i
->default_instance
)
1853 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &buf
);
1857 instance
.name
= buf
;
1858 r
= unit_file_search(NULL
, &instance
, paths
, SEARCH_FOLLOW_CONFIG_SYMLINKS
);
1862 path
= TAKE_PTR(instance
.path
);
1864 if (instance
.type
== UNIT_FILE_TYPE_MASKED
) {
1865 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, path
, NULL
);
1873 STRV_FOREACH(s
, list
) {
1874 _cleanup_free_
char *path
= NULL
, *dst
= NULL
;
1876 q
= install_full_printf(i
, *s
, &dst
);
1880 if (!unit_name_is_valid(dst
, UNIT_NAME_ANY
)) {
1881 unit_file_changes_add(changes
, n_changes
, -EUCLEAN
, dst
, NULL
);
1886 path
= strjoin(config_path
, "/", dst
, suffix
, n
);
1890 q
= create_symlink(paths
, i
->path
, path
, true, changes
, n_changes
);
1898 static int install_info_symlink_link(
1899 UnitFileInstallInfo
*i
,
1900 const LookupPaths
*paths
,
1901 const char *config_path
,
1903 UnitFileChange
**changes
,
1904 size_t *n_changes
) {
1906 _cleanup_free_
char *path
= NULL
;
1911 assert(config_path
);
1914 r
= in_search_path(paths
, i
->path
);
1920 path
= path_join(config_path
, i
->name
);
1924 return create_symlink(paths
, i
->path
, path
, force
, changes
, n_changes
);
1927 static int install_info_apply(
1928 UnitFileInstallInfo
*i
,
1929 const LookupPaths
*paths
,
1930 const char *config_path
,
1932 UnitFileChange
**changes
,
1933 size_t *n_changes
) {
1939 assert(config_path
);
1941 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
1944 r
= install_info_symlink_alias(i
, paths
, config_path
, force
, changes
, n_changes
);
1946 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->wanted_by
, ".wants/", changes
, n_changes
);
1950 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->required_by
, ".requires/", changes
, n_changes
);
1954 q
= install_info_symlink_link(i
, paths
, config_path
, force
, changes
, n_changes
);
1955 /* Do not count links to the unit file towards the "carries_install_info" count */
1956 if (r
== 0 && q
< 0)
1962 static int install_context_apply(
1963 UnitFileScope scope
,
1965 const LookupPaths
*paths
,
1966 const char *config_path
,
1969 UnitFileChange
**changes
,
1970 size_t *n_changes
) {
1972 UnitFileInstallInfo
*i
;
1977 assert(config_path
);
1979 if (ordered_hashmap_isempty(c
->will_process
))
1982 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
1987 while ((i
= ordered_hashmap_first(c
->will_process
))) {
1990 q
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
1994 q
= install_info_traverse(scope
, c
, paths
, i
, flags
, NULL
);
1996 unit_file_changes_add(changes
, n_changes
, q
, i
->name
, NULL
);
2000 /* We can attempt to process a masked unit when a different unit
2001 * that we were processing specifies it in Also=. */
2002 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
2003 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_MASKED
, i
->path
, NULL
);
2005 /* Assume that something *could* have been enabled here,
2006 * avoid "empty [Install] section" warning. */
2011 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
2014 q
= install_info_apply(i
, paths
, config_path
, force
, changes
, n_changes
);
2026 static int install_context_mark_for_removal(
2027 UnitFileScope scope
,
2029 const LookupPaths
*paths
,
2030 Set
**remove_symlinks_to
,
2031 const char *config_path
,
2032 UnitFileChange
**changes
,
2033 size_t *n_changes
) {
2035 UnitFileInstallInfo
*i
;
2040 assert(config_path
);
2042 /* Marks all items for removal */
2044 if (ordered_hashmap_isempty(c
->will_process
))
2047 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
2051 while ((i
= ordered_hashmap_first(c
->will_process
))) {
2053 r
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
2057 r
= install_info_traverse(scope
, c
, paths
, i
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, NULL
);
2058 if (r
== -ENOLINK
) {
2059 log_debug_errno(r
, "Name %s leads to a dangling symlink, removing name.", i
->name
);
2060 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_DANGLING
, i
->path
?: i
->name
, NULL
);
2061 } else if (r
== -ENOENT
) {
2063 if (i
->auxiliary
) /* some unit specified in Also= or similar is missing */
2064 log_debug_errno(r
, "Auxiliary unit of %s not found, removing name.", i
->name
);
2066 log_debug_errno(r
, "Unit %s not found, removing name.", i
->name
);
2067 unit_file_changes_add(changes
, n_changes
, r
, i
->path
?: i
->name
, NULL
);
2071 log_debug_errno(r
, "Failed to find unit %s, removing name: %m", i
->name
);
2072 unit_file_changes_add(changes
, n_changes
, r
, i
->path
?: i
->name
, NULL
);
2073 } else if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
2074 log_debug("Unit file %s is masked, ignoring.", i
->name
);
2075 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_MASKED
, i
->path
?: i
->name
, NULL
);
2077 } else if (i
->type
!= UNIT_FILE_TYPE_REGULAR
) {
2078 log_debug("Unit %s has type %s, ignoring.", i
->name
, unit_file_type_to_string(i
->type
) ?: "invalid");
2082 r
= mark_symlink_for_removal(remove_symlinks_to
, i
->name
);
2091 UnitFileScope scope
,
2092 UnitFileFlags flags
,
2093 const char *root_dir
,
2095 UnitFileChange
**changes
,
2096 size_t *n_changes
) {
2098 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2099 const char *config_path
;
2104 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2106 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2110 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2114 STRV_FOREACH(i
, files
) {
2115 _cleanup_free_
char *path
= NULL
;
2118 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
)) {
2124 path
= path_make_absolute(*i
, config_path
);
2128 q
= create_symlink(&paths
, "/dev/null", path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2129 if (q
< 0 && r
>= 0)
2136 int unit_file_unmask(
2137 UnitFileScope scope
,
2138 UnitFileFlags flags
,
2139 const char *root_dir
,
2141 UnitFileChange
**changes
,
2142 size_t *n_changes
) {
2144 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2145 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2146 _cleanup_strv_free_
char **todo
= NULL
;
2147 size_t n_todo
= 0, n_allocated
= 0;
2148 const char *config_path
;
2154 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2156 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2160 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2164 dry_run
= !!(flags
& UNIT_FILE_DRY_RUN
);
2166 STRV_FOREACH(i
, files
) {
2167 _cleanup_free_
char *path
= NULL
;
2169 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2172 path
= path_make_absolute(*i
, config_path
);
2176 r
= null_or_empty_path(path
);
2184 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2187 todo
[n_todo
] = strdup(*i
);
2197 STRV_FOREACH(i
, todo
) {
2198 _cleanup_free_
char *path
= NULL
;
2201 path
= path_make_absolute(*i
, config_path
);
2205 if (!dry_run
&& unlink(path
) < 0) {
2206 if (errno
!= ENOENT
) {
2209 unit_file_changes_add(changes
, n_changes
, -errno
, path
, NULL
);
2215 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
2217 rp
= skip_root(&paths
, path
);
2218 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: path
);
2223 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, dry_run
, changes
, n_changes
);
2231 UnitFileScope scope
,
2232 UnitFileFlags flags
,
2233 const char *root_dir
,
2235 UnitFileChange
**changes
,
2236 size_t *n_changes
) {
2238 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2239 _cleanup_strv_free_
char **todo
= NULL
;
2240 size_t n_todo
= 0, n_allocated
= 0;
2241 const char *config_path
;
2246 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2248 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2252 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2256 STRV_FOREACH(i
, files
) {
2257 _cleanup_free_
char *full
= NULL
;
2261 if (!path_is_absolute(*i
))
2265 if (!unit_name_is_valid(fn
, UNIT_NAME_ANY
))
2268 full
= path_join(paths
.root_dir
, *i
);
2272 if (lstat(full
, &st
) < 0)
2274 r
= stat_verify_regular(&st
);
2278 q
= in_search_path(&paths
, *i
);
2284 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2287 todo
[n_todo
] = strdup(*i
);
2297 STRV_FOREACH(i
, todo
) {
2298 _cleanup_free_
char *new_path
= NULL
;
2300 new_path
= path_make_absolute(basename(*i
), config_path
);
2304 q
= create_symlink(&paths
, *i
, new_path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2305 if (q
< 0 && r
>= 0)
2312 static int path_shall_revert(const LookupPaths
*paths
, const char *path
) {
2318 /* Checks whether the path is one where the drop-in directories shall be removed. */
2320 r
= path_is_config(paths
, path
, true);
2324 r
= path_is_control(paths
, path
);
2328 return path_is_transient(paths
, path
);
2331 int unit_file_revert(
2332 UnitFileScope scope
,
2333 const char *root_dir
,
2335 UnitFileChange
**changes
,
2336 size_t *n_changes
) {
2338 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2339 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2340 _cleanup_strv_free_
char **todo
= NULL
;
2341 size_t n_todo
= 0, n_allocated
= 0;
2345 /* Puts a unit file back into vendor state. This means:
2347 * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and
2348 * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated").
2350 * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in
2351 * "config", but not in "transient" or "control" or even "generated").
2353 * We remove all that in both the runtime and the persistent directories, if that applies.
2356 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2360 STRV_FOREACH(i
, files
) {
2361 bool has_vendor
= false;
2364 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2367 STRV_FOREACH(p
, paths
.search_path
) {
2368 _cleanup_free_
char *path
= NULL
, *dropin
= NULL
;
2371 path
= path_make_absolute(*i
, *p
);
2375 r
= lstat(path
, &st
);
2377 if (errno
!= ENOENT
)
2379 } else if (S_ISREG(st
.st_mode
)) {
2380 /* Check if there's a vendor version */
2381 r
= path_is_vendor_or_generator(&paths
, path
);
2388 dropin
= strjoin(path
, ".d");
2392 r
= lstat(dropin
, &st
);
2394 if (errno
!= ENOENT
)
2396 } else if (S_ISDIR(st
.st_mode
)) {
2397 /* Remove the drop-ins */
2398 r
= path_shall_revert(&paths
, dropin
);
2402 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2405 todo
[n_todo
++] = TAKE_PTR(dropin
);
2413 /* OK, there's a vendor version, hence drop all configuration versions */
2414 STRV_FOREACH(p
, paths
.search_path
) {
2415 _cleanup_free_
char *path
= NULL
;
2418 path
= path_make_absolute(*i
, *p
);
2422 r
= lstat(path
, &st
);
2424 if (errno
!= ENOENT
)
2426 } else if (S_ISREG(st
.st_mode
) || S_ISLNK(st
.st_mode
)) {
2427 r
= path_is_config(&paths
, path
, true);
2431 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2434 todo
[n_todo
++] = TAKE_PTR(path
);
2443 STRV_FOREACH(i
, todo
) {
2444 _cleanup_strv_free_
char **fs
= NULL
;
2448 (void) get_files_in_directory(*i
, &fs
);
2450 q
= rm_rf(*i
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
2451 if (q
< 0 && q
!= -ENOENT
&& r
>= 0) {
2456 STRV_FOREACH(j
, fs
) {
2457 _cleanup_free_
char *t
= NULL
;
2459 t
= path_join(*i
, *j
);
2463 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, t
, NULL
);
2466 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, *i
, NULL
);
2468 rp
= skip_root(&paths
, *i
);
2469 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: *i
);
2474 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.runtime_config
, &paths
, false, changes
, n_changes
);
2478 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.persistent_config
, &paths
, false, changes
, n_changes
);
2485 int unit_file_add_dependency(
2486 UnitFileScope scope
,
2487 UnitFileFlags flags
,
2488 const char *root_dir
,
2492 UnitFileChange
**changes
,
2493 size_t *n_changes
) {
2495 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2496 _cleanup_(install_context_done
) InstallContext c
= {};
2497 UnitFileInstallInfo
*i
, *target_info
;
2498 const char *config_path
;
2503 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2506 if (!IN_SET(dep
, UNIT_WANTS
, UNIT_REQUIRES
))
2509 if (!unit_name_is_valid(target
, UNIT_NAME_ANY
))
2512 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2516 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2520 r
= install_info_discover_and_check(scope
, &c
, &paths
, target
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2521 &target_info
, changes
, n_changes
);
2525 assert(target_info
->type
== UNIT_FILE_TYPE_REGULAR
);
2527 STRV_FOREACH(f
, files
) {
2530 r
= install_info_discover_and_check(scope
, &c
, &paths
, *f
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2531 &i
, changes
, n_changes
);
2535 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2537 /* We didn't actually load anything from the unit
2538 * file, but instead just add in our new symlink to
2541 if (dep
== UNIT_WANTS
)
2544 l
= &i
->required_by
;
2547 *l
= strv_new(target_info
->name
);
2552 return install_context_apply(scope
, &c
, &paths
, config_path
, !!(flags
& UNIT_FILE_FORCE
), SEARCH_FOLLOW_CONFIG_SYMLINKS
, changes
, n_changes
);
2555 int unit_file_enable(
2556 UnitFileScope scope
,
2557 UnitFileFlags flags
,
2558 const char *root_dir
,
2560 UnitFileChange
**changes
,
2561 size_t *n_changes
) {
2563 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2564 _cleanup_(install_context_done
) InstallContext c
= {};
2565 const char *config_path
;
2566 UnitFileInstallInfo
*i
;
2571 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2573 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2577 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2581 STRV_FOREACH(f
, files
) {
2582 r
= install_info_discover_and_check(scope
, &c
, &paths
, *f
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2583 &i
, changes
, n_changes
);
2587 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2590 /* This will return the number of symlink rules that were
2591 supposed to be created, not the ones actually created. This
2592 is useful to determine whether the passed files had any
2593 installation data at all. */
2595 return install_context_apply(scope
, &c
, &paths
, config_path
, !!(flags
& UNIT_FILE_FORCE
), SEARCH_LOAD
, changes
, n_changes
);
2598 int unit_file_disable(
2599 UnitFileScope scope
,
2600 UnitFileFlags flags
,
2601 const char *root_dir
,
2603 UnitFileChange
**changes
,
2604 size_t *n_changes
) {
2606 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2607 _cleanup_(install_context_done
) InstallContext c
= {};
2608 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2609 const char *config_path
;
2614 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2616 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2620 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2624 STRV_FOREACH(i
, files
) {
2625 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2628 r
= install_info_add(&c
, *i
, NULL
, false, NULL
);
2633 r
= install_context_mark_for_removal(scope
, &c
, &paths
, &remove_symlinks_to
, config_path
, changes
, n_changes
);
2637 return remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, !!(flags
& UNIT_FILE_DRY_RUN
), changes
, n_changes
);
2640 int unit_file_reenable(
2641 UnitFileScope scope
,
2642 UnitFileFlags flags
,
2643 const char *root_dir
,
2645 UnitFileChange
**changes
,
2646 size_t *n_changes
) {
2652 /* First, we invoke the disable command with only the basename... */
2653 l
= strv_length(files
);
2654 n
= newa(char*, l
+1);
2655 for (i
= 0; i
< l
; i
++)
2656 n
[i
] = basename(files
[i
]);
2659 r
= unit_file_disable(scope
, flags
, root_dir
, n
, changes
, n_changes
);
2663 /* But the enable command with the full name */
2664 return unit_file_enable(scope
, flags
, root_dir
, files
, changes
, n_changes
);
2667 int unit_file_set_default(
2668 UnitFileScope scope
,
2669 UnitFileFlags flags
,
2670 const char *root_dir
,
2672 UnitFileChange
**changes
,
2673 size_t *n_changes
) {
2675 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2676 _cleanup_(install_context_done
) InstallContext c
= {};
2677 UnitFileInstallInfo
*i
;
2678 const char *new_path
;
2682 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2685 if (unit_name_to_type(name
) != UNIT_TARGET
) /* this also validates the name */
2687 if (streq(name
, SPECIAL_DEFAULT_TARGET
))
2690 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2694 r
= install_info_discover_and_check(scope
, &c
, &paths
, name
, 0, &i
, changes
, n_changes
);
2698 new_path
= strjoina(paths
.persistent_config
, "/" SPECIAL_DEFAULT_TARGET
);
2699 return create_symlink(&paths
, i
->path
, new_path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2702 int unit_file_get_default(
2703 UnitFileScope scope
,
2704 const char *root_dir
,
2707 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2708 _cleanup_(install_context_done
) InstallContext c
= {};
2709 UnitFileInstallInfo
*i
;
2714 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2717 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2721 r
= install_info_discover(scope
, &c
, &paths
, SPECIAL_DEFAULT_TARGET
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2725 r
= install_info_may_process(i
, &paths
, NULL
, 0);
2729 n
= strdup(i
->name
);
2737 int unit_file_lookup_state(
2738 UnitFileScope scope
,
2739 const LookupPaths
*paths
,
2741 UnitFileState
*ret
) {
2743 _cleanup_(install_context_done
) InstallContext c
= {};
2744 UnitFileInstallInfo
*i
;
2745 UnitFileState state
;
2751 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2754 r
= install_info_discover(scope
, &c
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2757 return log_debug_errno(r
, "Failed to discover unit %s: %m", name
);
2759 assert(IN_SET(i
->type
, UNIT_FILE_TYPE_REGULAR
, UNIT_FILE_TYPE_MASKED
));
2760 log_debug("Found unit %s at %s (%s)", name
, strna(i
->path
),
2761 i
->type
== UNIT_FILE_TYPE_REGULAR
? "regular file" : "mask");
2763 /* Shortcut things, if the caller just wants to know if this unit exists. */
2769 case UNIT_FILE_TYPE_MASKED
:
2770 r
= path_is_runtime(paths
, i
->path
, true);
2774 state
= r
> 0 ? UNIT_FILE_MASKED_RUNTIME
: UNIT_FILE_MASKED
;
2777 case UNIT_FILE_TYPE_REGULAR
:
2778 /* Check if the name we were querying is actually an alias */
2779 if (!streq(name
, basename(i
->path
)) && !unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
)) {
2780 state
= UNIT_FILE_ALIAS
;
2784 r
= path_is_generator(paths
, i
->path
);
2788 state
= UNIT_FILE_GENERATED
;
2792 r
= path_is_transient(paths
, i
->path
);
2796 state
= UNIT_FILE_TRANSIENT
;
2800 /* Check if any of the Alias= symlinks have been created.
2801 * We ignore other aliases, and only check those that would
2802 * be created by systemctl enable for this unit. */
2803 r
= find_symlinks_in_scope(scope
, paths
, i
, true, &state
);
2809 /* Check if the file is known under other names. If it is,
2810 * it might be in use. Report that as UNIT_FILE_INDIRECT. */
2811 r
= find_symlinks_in_scope(scope
, paths
, i
, false, &state
);
2815 state
= UNIT_FILE_INDIRECT
;
2817 if (unit_file_install_info_has_rules(i
))
2818 state
= UNIT_FILE_DISABLED
;
2819 else if (unit_file_install_info_has_also(i
))
2820 state
= UNIT_FILE_INDIRECT
;
2822 state
= UNIT_FILE_STATIC
;
2828 assert_not_reached("Unexpected unit file type.");
2835 int unit_file_get_state(
2836 UnitFileScope scope
,
2837 const char *root_dir
,
2839 UnitFileState
*ret
) {
2841 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2845 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2848 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2852 return unit_file_lookup_state(scope
, &paths
, name
, ret
);
2855 int unit_file_exists(UnitFileScope scope
, const LookupPaths
*paths
, const char *name
) {
2856 _cleanup_(install_context_done
) InstallContext c
= {};
2862 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2865 r
= install_info_discover(scope
, &c
, paths
, name
, 0, NULL
, NULL
, NULL
);
2874 static int split_pattern_into_name_and_instances(const char *pattern
, char **out_unit_name
, char ***out_instances
) {
2875 _cleanup_strv_free_
char **instances
= NULL
;
2876 _cleanup_free_
char *unit_name
= NULL
;
2880 assert(out_instances
);
2881 assert(out_unit_name
);
2883 r
= extract_first_word(&pattern
, &unit_name
, NULL
, EXTRACT_RETAIN_ESCAPE
);
2887 /* We handle the instances logic when unit name is extracted */
2889 /* We only create instances when a rule of templated unit
2890 * is seen. A rule like enable foo@.service a b c will
2891 * result in an array of (a, b, c) as instance names */
2892 if (!unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
))
2895 instances
= strv_split(pattern
, WHITESPACE
);
2899 *out_instances
= TAKE_PTR(instances
);
2902 *out_unit_name
= TAKE_PTR(unit_name
);
2907 static int presets_find_config(UnitFileScope scope
, const char *root_dir
, char ***files
) {
2908 static const char* const system_dirs
[] = {CONF_PATHS("systemd/system-preset"), NULL
};
2909 static const char* const user_dirs
[] = {CONF_PATHS_USR("systemd/user-preset"), NULL
};
2910 const char* const* dirs
;
2913 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2915 if (scope
== UNIT_FILE_SYSTEM
)
2917 else if (IN_SET(scope
, UNIT_FILE_GLOBAL
, UNIT_FILE_USER
))
2920 assert_not_reached("Invalid unit file scope");
2922 return conf_files_list_strv(files
, ".preset", root_dir
, 0, dirs
);
2925 static int read_presets(UnitFileScope scope
, const char *root_dir
, UnitFilePresets
*presets
) {
2926 _cleanup_(unit_file_presets_freep
) UnitFilePresets ps
= {};
2927 size_t n_allocated
= 0;
2928 _cleanup_strv_free_
char **files
= NULL
;
2933 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2936 r
= presets_find_config(scope
, root_dir
, &files
);
2940 STRV_FOREACH(p
, files
) {
2941 _cleanup_fclose_
FILE *f
;
2944 f
= fopen(*p
, "re");
2946 if (errno
== ENOENT
)
2953 _cleanup_free_
char *line
= NULL
;
2954 UnitFilePresetRule rule
= {};
2955 const char *parameter
;
2958 r
= read_line(f
, LONG_LINE_MAX
, &line
);
2969 if (strchr(COMMENTS
, *l
))
2972 parameter
= first_word(l
, "enable");
2975 char **instances
= NULL
;
2977 /* Unit_name will remain the same as parameter when no instances are specified */
2978 r
= split_pattern_into_name_and_instances(parameter
, &unit_name
, &instances
);
2980 log_syntax(NULL
, LOG_WARNING
, *p
, n
, r
, "Couldn't parse line '%s'. Ignoring.", line
);
2984 rule
= (UnitFilePresetRule
) {
2985 .pattern
= unit_name
,
2986 .action
= PRESET_ENABLE
,
2987 .instances
= instances
,
2991 parameter
= first_word(l
, "disable");
2995 pattern
= strdup(parameter
);
2999 rule
= (UnitFilePresetRule
) {
3001 .action
= PRESET_DISABLE
,
3006 if (!GREEDY_REALLOC(ps
.rules
, n_allocated
, ps
.n_rules
+ 1))
3009 ps
.rules
[ps
.n_rules
++] = rule
;
3013 log_syntax(NULL
, LOG_WARNING
, *p
, n
, 0, "Couldn't parse line '%s'. Ignoring.", line
);
3017 ps
.initialized
= true;
3019 ps
= (UnitFilePresets
){};
3024 static int pattern_match_multiple_instances(
3025 const UnitFilePresetRule rule
,
3026 const char *unit_name
,
3029 _cleanup_free_
char *templated_name
= NULL
;
3032 /* If no ret is needed or the rule itself does not have instances
3033 * initialized, we return not matching */
3034 if (!ret
|| !rule
.instances
)
3037 r
= unit_name_template(unit_name
, &templated_name
);
3040 if (!streq(rule
.pattern
, templated_name
))
3043 /* Compose a list of specified instances when unit name is a template */
3044 if (unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
3045 _cleanup_free_
char *prefix
= NULL
;
3046 _cleanup_strv_free_
char **out_strv
= NULL
;
3049 r
= unit_name_to_prefix(unit_name
, &prefix
);
3053 STRV_FOREACH(iter
, rule
.instances
) {
3054 _cleanup_free_
char *name
= NULL
;
3055 r
= unit_name_build(prefix
, *iter
, ".service", &name
);
3058 r
= strv_extend(&out_strv
, name
);
3063 *ret
= TAKE_PTR(out_strv
);
3066 /* We now know the input unit name is an instance name */
3067 _cleanup_free_
char *instance_name
= NULL
;
3069 r
= unit_name_to_instance(unit_name
, &instance_name
);
3073 if (strv_find(rule
.instances
, instance_name
))
3079 static int query_presets(const char *name
, const UnitFilePresets
*presets
, char ***instance_name_list
) {
3080 PresetAction action
= PRESET_UNKNOWN
;
3083 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
3086 for (i
= 0; i
< presets
->n_rules
; i
++)
3087 if (pattern_match_multiple_instances(presets
->rules
[i
], name
, instance_name_list
) > 0 ||
3088 fnmatch(presets
->rules
[i
].pattern
, name
, FNM_NOESCAPE
) == 0) {
3089 action
= presets
->rules
[i
].action
;
3094 case PRESET_UNKNOWN
:
3095 log_debug("Preset files don't specify rule for %s. Enabling.", name
);
3098 if (instance_name_list
&& *instance_name_list
)
3099 STRV_FOREACH(s
, *instance_name_list
)
3100 log_debug("Preset files say enable %s.", *s
);
3102 log_debug("Preset files say enable %s.", name
);
3104 case PRESET_DISABLE
:
3105 log_debug("Preset files say disable %s.", name
);
3108 assert_not_reached("invalid preset action");
3112 int unit_file_query_preset(UnitFileScope scope
, const char *root_dir
, const char *name
, UnitFilePresets
*cached
) {
3113 _cleanup_(unit_file_presets_freep
) UnitFilePresets tmp
= {};
3118 if (!cached
->initialized
) {
3119 r
= read_presets(scope
, root_dir
, cached
);
3124 return query_presets(name
, cached
, NULL
);
3127 static int execute_preset(
3128 UnitFileScope scope
,
3129 InstallContext
*plus
,
3130 InstallContext
*minus
,
3131 const LookupPaths
*paths
,
3132 const char *config_path
,
3134 UnitFilePresetMode mode
,
3136 UnitFileChange
**changes
,
3137 size_t *n_changes
) {
3144 assert(config_path
);
3146 if (mode
!= UNIT_FILE_PRESET_ENABLE_ONLY
) {
3147 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
3149 r
= install_context_mark_for_removal(scope
, minus
, paths
, &remove_symlinks_to
, config_path
, changes
, n_changes
);
3153 r
= remove_marked_symlinks(remove_symlinks_to
, config_path
, paths
, false, changes
, n_changes
);
3157 if (mode
!= UNIT_FILE_PRESET_DISABLE_ONLY
) {
3160 /* Returns number of symlinks that where supposed to be installed. */
3161 q
= install_context_apply(scope
, plus
, paths
, config_path
, force
, SEARCH_LOAD
, changes
, n_changes
);
3173 static int preset_prepare_one(
3174 UnitFileScope scope
,
3175 InstallContext
*plus
,
3176 InstallContext
*minus
,
3179 const UnitFilePresets
*presets
,
3180 UnitFileChange
**changes
,
3181 size_t *n_changes
) {
3183 _cleanup_(install_context_done
) InstallContext tmp
= {};
3184 _cleanup_strv_free_
char **instance_name_list
= NULL
;
3185 UnitFileInstallInfo
*i
;
3188 if (install_info_find(plus
, name
) || install_info_find(minus
, name
))
3191 r
= install_info_discover(scope
, &tmp
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3192 &i
, changes
, n_changes
);
3195 if (!streq(name
, i
->name
)) {
3196 log_debug("Skipping %s because it is an alias for %s.", name
, i
->name
);
3200 r
= query_presets(name
, presets
, &instance_name_list
);
3205 if (instance_name_list
) {
3207 STRV_FOREACH(s
, instance_name_list
) {
3208 r
= install_info_discover_and_check(scope
, plus
, paths
, *s
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3209 &i
, changes
, n_changes
);
3214 r
= install_info_discover_and_check(scope
, plus
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3215 &i
, changes
, n_changes
);
3221 r
= install_info_discover(scope
, minus
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3222 &i
, changes
, n_changes
);
3227 int unit_file_preset(
3228 UnitFileScope scope
,
3229 UnitFileFlags flags
,
3230 const char *root_dir
,
3232 UnitFilePresetMode mode
,
3233 UnitFileChange
**changes
,
3234 size_t *n_changes
) {
3236 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
3237 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3238 _cleanup_(unit_file_presets_freep
) UnitFilePresets presets
= {};
3239 const char *config_path
;
3244 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3245 assert(mode
< _UNIT_FILE_PRESET_MAX
);
3247 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3251 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
3255 r
= read_presets(scope
, root_dir
, &presets
);
3259 STRV_FOREACH(i
, files
) {
3260 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, *i
, &presets
, changes
, n_changes
);
3265 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, files
, mode
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
3268 int unit_file_preset_all(
3269 UnitFileScope scope
,
3270 UnitFileFlags flags
,
3271 const char *root_dir
,
3272 UnitFilePresetMode mode
,
3273 UnitFileChange
**changes
,
3274 size_t *n_changes
) {
3276 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
3277 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3278 _cleanup_(unit_file_presets_freep
) UnitFilePresets presets
= {};
3279 const char *config_path
= NULL
;
3284 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3285 assert(mode
< _UNIT_FILE_PRESET_MAX
);
3287 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3291 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
3295 r
= read_presets(scope
, root_dir
, &presets
);
3299 STRV_FOREACH(i
, paths
.search_path
) {
3300 _cleanup_closedir_
DIR *d
= NULL
;
3305 if (errno
== ENOENT
)
3311 FOREACH_DIRENT(de
, d
, return -errno
) {
3313 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
3316 dirent_ensure_type(d
, de
);
3318 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
3321 /* we don't pass changes[] in, because we want to handle errors on our own */
3322 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, de
->d_name
, &presets
, NULL
, 0);
3324 r
= unit_file_changes_add(changes
, n_changes
,
3325 UNIT_FILE_IS_MASKED
, de
->d_name
, NULL
);
3326 else if (r
== -ENOLINK
)
3327 r
= unit_file_changes_add(changes
, n_changes
,
3328 UNIT_FILE_IS_DANGLING
, de
->d_name
, NULL
);
3329 else if (r
== -EADDRNOTAVAIL
) /* Ignore generated/transient units when applying preset */
3336 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, NULL
, mode
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
3339 static void unit_file_list_free_one(UnitFileList
*f
) {
3347 Hashmap
* unit_file_list_free(Hashmap
*h
) {
3348 return hashmap_free_with_destructor(h
, unit_file_list_free_one
);
3351 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList
*, unit_file_list_free_one
);
3353 int unit_file_get_list(
3354 UnitFileScope scope
,
3355 const char *root_dir
,
3360 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3365 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3368 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3372 STRV_FOREACH(dirname
, paths
.search_path
) {
3373 _cleanup_closedir_
DIR *d
= NULL
;
3376 d
= opendir(*dirname
);
3378 if (errno
== ENOENT
)
3380 if (IN_SET(errno
, ENOTDIR
, EACCES
)) {
3381 log_debug_errno(errno
, "Failed to open \"%s\": %m", *dirname
);
3388 FOREACH_DIRENT(de
, d
, return -errno
) {
3389 _cleanup_(unit_file_list_free_onep
) UnitFileList
*f
= NULL
;
3391 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
3394 if (!strv_fnmatch_or_empty(patterns
, de
->d_name
, FNM_NOESCAPE
))
3397 if (hashmap_get(h
, de
->d_name
))
3400 dirent_ensure_type(d
, de
);
3402 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
3405 f
= new0(UnitFileList
, 1);
3409 f
->path
= path_make_absolute(de
->d_name
, *dirname
);
3413 r
= unit_file_lookup_state(scope
, &paths
, de
->d_name
, &f
->state
);
3415 f
->state
= UNIT_FILE_BAD
;
3417 if (!strv_isempty(states
) &&
3418 !strv_contains(states
, unit_file_state_to_string(f
->state
)))
3421 r
= hashmap_put(h
, basename(f
->path
), f
);
3425 f
= NULL
; /* prevent cleanup */
3432 static const char* const unit_file_state_table
[_UNIT_FILE_STATE_MAX
] = {
3433 [UNIT_FILE_ENABLED
] = "enabled",
3434 [UNIT_FILE_ENABLED_RUNTIME
] = "enabled-runtime",
3435 [UNIT_FILE_LINKED
] = "linked",
3436 [UNIT_FILE_LINKED_RUNTIME
] = "linked-runtime",
3437 [UNIT_FILE_ALIAS
] = "alias",
3438 [UNIT_FILE_MASKED
] = "masked",
3439 [UNIT_FILE_MASKED_RUNTIME
] = "masked-runtime",
3440 [UNIT_FILE_STATIC
] = "static",
3441 [UNIT_FILE_DISABLED
] = "disabled",
3442 [UNIT_FILE_INDIRECT
] = "indirect",
3443 [UNIT_FILE_GENERATED
] = "generated",
3444 [UNIT_FILE_TRANSIENT
] = "transient",
3445 [UNIT_FILE_BAD
] = "bad",
3448 DEFINE_STRING_TABLE_LOOKUP(unit_file_state
, UnitFileState
);
3450 static const char* const unit_file_change_type_table
[_UNIT_FILE_CHANGE_TYPE_MAX
] = {
3451 [UNIT_FILE_SYMLINK
] = "symlink",
3452 [UNIT_FILE_UNLINK
] = "unlink",
3453 [UNIT_FILE_IS_MASKED
] = "masked",
3454 [UNIT_FILE_IS_DANGLING
] = "dangling",
3457 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type
, UnitFileChangeType
);
3459 static const char* const unit_file_preset_mode_table
[_UNIT_FILE_PRESET_MAX
] = {
3460 [UNIT_FILE_PRESET_FULL
] = "full",
3461 [UNIT_FILE_PRESET_ENABLE_ONLY
] = "enable-only",
3462 [UNIT_FILE_PRESET_DISABLE_ONLY
] = "disable-only",
3465 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode
, UnitFilePresetMode
);