1 /* SPDX-License-Identifier: LGPL-2.1+ */
15 #include "alloc-util.h"
16 #include "conf-files.h"
17 #include "conf-parser.h"
19 #include "dirent-util.h"
20 #include "extract-word.h"
25 #include "install-printf.h"
27 #include "locale-util.h"
31 #include "path-lookup.h"
32 #include "path-util.h"
36 #include "stat-util.h"
37 #include "string-table.h"
38 #include "string-util.h"
40 #include "unit-name.h"
42 #define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
44 typedef enum SearchFlags
{
46 SEARCH_FOLLOW_CONFIG_SYMLINKS
= 1 << 1,
47 SEARCH_DROPIN
= 1 << 2,
51 OrderedHashmap
*will_process
;
52 OrderedHashmap
*have_processed
;
72 static bool unit_file_install_info_has_rules(const UnitFileInstallInfo
*i
) {
75 return !strv_isempty(i
->aliases
) ||
76 !strv_isempty(i
->wanted_by
) ||
77 !strv_isempty(i
->required_by
);
80 static bool unit_file_install_info_has_also(const UnitFileInstallInfo
*i
) {
83 return !strv_isempty(i
->also
);
86 static void presets_freep(Presets
*p
) {
92 for (i
= 0; i
< p
->n_rules
; i
++) {
93 free(p
->rules
[i
].pattern
);
94 strv_free(p
->rules
[i
].instances
);
101 bool unit_type_may_alias(UnitType type
) {
111 bool unit_type_may_template(UnitType type
) {
120 static const char *const unit_file_type_table
[_UNIT_FILE_TYPE_MAX
] = {
121 [UNIT_FILE_TYPE_REGULAR
] = "regular",
122 [UNIT_FILE_TYPE_SYMLINK
] = "symlink",
123 [UNIT_FILE_TYPE_MASKED
] = "masked",
126 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(unit_file_type
, UnitFileType
);
128 static int in_search_path(const LookupPaths
*p
, const char *path
) {
129 _cleanup_free_
char *parent
= NULL
;
134 parent
= dirname_malloc(path
);
138 STRV_FOREACH(i
, p
->search_path
)
139 if (path_equal(parent
, *i
))
145 static const char* skip_root(const LookupPaths
*p
, const char *path
) {
154 e
= path_startswith(path
, p
->root_dir
);
158 /* Make sure the returned path starts with a slash */
160 if (e
== path
|| e
[-1] != '/')
169 static int path_is_generator(const LookupPaths
*p
, const char *path
) {
170 _cleanup_free_
char *parent
= NULL
;
175 parent
= dirname_malloc(path
);
179 return path_equal_ptr(parent
, p
->generator
) ||
180 path_equal_ptr(parent
, p
->generator_early
) ||
181 path_equal_ptr(parent
, p
->generator_late
);
184 static int path_is_transient(const LookupPaths
*p
, const char *path
) {
185 _cleanup_free_
char *parent
= NULL
;
190 parent
= dirname_malloc(path
);
194 return path_equal_ptr(parent
, p
->transient
);
197 static int path_is_control(const LookupPaths
*p
, const char *path
) {
198 _cleanup_free_
char *parent
= NULL
;
203 parent
= dirname_malloc(path
);
207 return path_equal_ptr(parent
, p
->persistent_control
) ||
208 path_equal_ptr(parent
, p
->runtime_control
);
211 static int path_is_config(const LookupPaths
*p
, const char *path
, bool check_parent
) {
212 _cleanup_free_
char *parent
= NULL
;
217 /* Note that we do *not* have generic checks for /etc or /run in place, since with
218 * them we couldn't discern configuration from transient or generated units */
221 parent
= dirname_malloc(path
);
228 return path_equal_ptr(path
, p
->persistent_config
) ||
229 path_equal_ptr(path
, p
->runtime_config
);
232 static int path_is_runtime(const LookupPaths
*p
, const char *path
, bool check_parent
) {
233 _cleanup_free_
char *parent
= NULL
;
239 /* Everything in /run is considered runtime. On top of that we also add
240 * explicit checks for the various runtime directories, as safety net. */
242 rpath
= skip_root(p
, path
);
243 if (rpath
&& path_startswith(rpath
, "/run"))
247 parent
= dirname_malloc(path
);
254 return path_equal_ptr(path
, p
->runtime_config
) ||
255 path_equal_ptr(path
, p
->generator
) ||
256 path_equal_ptr(path
, p
->generator_early
) ||
257 path_equal_ptr(path
, p
->generator_late
) ||
258 path_equal_ptr(path
, p
->transient
) ||
259 path_equal_ptr(path
, p
->runtime_control
);
262 static int path_is_vendor(const LookupPaths
*p
, const char *path
) {
268 rpath
= skip_root(p
, path
);
272 if (path_startswith(rpath
, "/usr"))
276 if (path_startswith(rpath
, "/lib"))
280 return path_equal(rpath
, SYSTEM_DATA_UNIT_PATH
);
283 int unit_file_changes_add(
284 UnitFileChange
**changes
,
286 UnitFileChangeType type
,
288 const char *source
) {
290 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
294 assert(!changes
== !n_changes
);
299 c
= reallocarray(*changes
, *n_changes
+ 1, sizeof(UnitFileChange
));
308 if (!p
|| (source
&& !s
))
311 path_simplify(p
, false);
313 path_simplify(s
, false);
315 c
[*n_changes
] = (UnitFileChange
) { type
, p
, s
};
321 void unit_file_changes_free(UnitFileChange
*changes
, size_t n_changes
) {
324 assert(changes
|| n_changes
== 0);
326 for (i
= 0; i
< n_changes
; i
++) {
327 free(changes
[i
].path
);
328 free(changes
[i
].source
);
334 void unit_file_dump_changes(int r
, const char *verb
, const UnitFileChange
*changes
, size_t n_changes
, bool quiet
) {
338 assert(changes
|| n_changes
== 0);
339 /* If verb is not specified, errors are not allowed! */
340 assert(verb
|| r
>= 0);
342 for (i
= 0; i
< n_changes
; i
++) {
343 assert(verb
|| changes
[i
].type
>= 0);
345 switch(changes
[i
].type
) {
346 case UNIT_FILE_SYMLINK
:
348 log_info("Created symlink %s %s %s.",
350 special_glyph(SPECIAL_GLYPH_ARROW
),
353 case UNIT_FILE_UNLINK
:
355 log_info("Removed %s.", changes
[i
].path
);
357 case UNIT_FILE_IS_MASKED
:
359 log_info("Unit %s is masked, ignoring.", changes
[i
].path
);
361 case UNIT_FILE_IS_DANGLING
:
363 log_info("Unit %s is an alias to a unit that is not present, ignoring.",
367 if (changes
[i
].source
)
368 log_error_errno(changes
[i
].type
,
369 "Failed to %s unit, file %s already exists and is a symlink to %s.",
370 verb
, changes
[i
].path
, changes
[i
].source
);
372 log_error_errno(changes
[i
].type
,
373 "Failed to %s unit, file %s already exists.",
374 verb
, changes
[i
].path
);
378 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s is masked.",
379 verb
, changes
[i
].path
);
383 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s is transient or generated.",
384 verb
, changes
[i
].path
);
388 log_error_errno(changes
[i
].type
, "Failed to %s unit, refusing to operate on linked unit file %s",
389 verb
, changes
[i
].path
);
394 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s does not exist.", verb
, changes
[i
].path
);
399 assert(changes
[i
].type
< 0);
400 log_error_errno(changes
[i
].type
, "Failed to %s unit, file %s: %m.",
401 verb
, changes
[i
].path
);
406 if (r
< 0 && !logged
)
407 log_error_errno(r
, "Failed to %s: %m.", verb
);
411 * Checks if two paths or symlinks from wd are the same, when root is the root of the filesystem.
412 * wc should be the full path in the host file system.
414 static bool chroot_symlinks_same(const char *root
, const char *wd
, const char *a
, const char *b
) {
415 assert(path_is_absolute(wd
));
417 /* This will give incorrect results if the paths are relative and go outside
418 * of the chroot. False negatives are possible. */
423 a
= strjoina(path_is_absolute(a
) ? root
: wd
, "/", a
);
424 b
= strjoina(path_is_absolute(b
) ? root
: wd
, "/", b
);
425 return path_equal_or_files_same(a
, b
, 0);
428 static int create_symlink(
429 const LookupPaths
*paths
,
430 const char *old_path
,
431 const char *new_path
,
433 UnitFileChange
**changes
,
436 _cleanup_free_
char *dest
= NULL
, *dirname
= NULL
;
443 rp
= skip_root(paths
, old_path
);
447 /* Actually create a symlink, and remember that we did. Is
448 * smart enough to check if there's already a valid symlink in
451 * Returns 1 if a symlink was created or already exists and points to
452 * the right place, or negative on error.
455 mkdir_parents_label(new_path
, 0755);
457 if (symlink(old_path
, new_path
) >= 0) {
458 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
462 if (errno
!= EEXIST
) {
463 unit_file_changes_add(changes
, n_changes
, -errno
, new_path
, NULL
);
467 r
= readlink_malloc(new_path
, &dest
);
469 /* translate EINVAL (non-symlink exists) to EEXIST */
473 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
477 dirname
= dirname_malloc(new_path
);
481 if (chroot_symlinks_same(paths
->root_dir
, dirname
, dest
, old_path
)) {
482 log_debug("Symlink %s → %s already exists", new_path
, dest
);
487 unit_file_changes_add(changes
, n_changes
, -EEXIST
, new_path
, dest
);
491 r
= symlink_atomic(old_path
, new_path
);
493 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
497 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, new_path
, NULL
);
498 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
503 static int mark_symlink_for_removal(
504 Set
**remove_symlinks_to
,
512 r
= set_ensure_allocated(remove_symlinks_to
, &path_hash_ops
);
520 path_simplify(n
, false);
522 r
= set_consume(*remove_symlinks_to
, n
);
531 static int remove_marked_symlinks_fd(
532 Set
*remove_symlinks_to
,
535 const char *config_path
,
536 const LookupPaths
*lp
,
539 UnitFileChange
**changes
,
542 _cleanup_closedir_
DIR *d
= NULL
;
546 assert(remove_symlinks_to
);
561 FOREACH_DIRENT(de
, d
, return -errno
) {
563 dirent_ensure_type(d
, de
);
565 if (de
->d_type
== DT_DIR
) {
566 _cleanup_free_
char *p
= NULL
;
569 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
579 p
= path_make_absolute(de
->d_name
, path
);
585 /* This will close nfd, regardless whether it succeeds or not */
586 q
= remove_marked_symlinks_fd(remove_symlinks_to
, nfd
, p
, config_path
, lp
, dry_run
, restart
, changes
, n_changes
);
590 } else if (de
->d_type
== DT_LNK
) {
591 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
596 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
599 p
= path_make_absolute(de
->d_name
, path
);
602 path_simplify(p
, false);
604 q
= readlink_malloc(p
, &dest
);
613 /* We remove all links pointing to a file or path that is marked, as well as all files sharing
614 * the same name as a file that is marked. */
616 found
= set_contains(remove_symlinks_to
, dest
) ||
617 set_contains(remove_symlinks_to
, basename(dest
)) ||
618 set_contains(remove_symlinks_to
, de
->d_name
);
624 if (unlinkat(fd
, de
->d_name
, 0) < 0 && errno
!= ENOENT
) {
627 unit_file_changes_add(changes
, n_changes
, -errno
, p
, NULL
);
631 (void) rmdir_parents(p
, config_path
);
634 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, p
, NULL
);
636 /* Now, remember the full path (but with the root prefix removed) of
637 * the symlink we just removed, and remove any symlinks to it, too. */
639 rp
= skip_root(lp
, p
);
640 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: p
);
643 if (q
> 0 && !dry_run
)
651 static int remove_marked_symlinks(
652 Set
*remove_symlinks_to
,
653 const char *config_path
,
654 const LookupPaths
*lp
,
656 UnitFileChange
**changes
,
659 _cleanup_close_
int fd
= -1;
666 if (set_size(remove_symlinks_to
) <= 0)
669 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
);
671 return errno
== ENOENT
? 0 : -errno
;
677 cfd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
681 /* This takes possession of cfd and closes it */
682 q
= remove_marked_symlinks_fd(remove_symlinks_to
, cfd
, config_path
, config_path
, lp
, dry_run
, &restart
, changes
, n_changes
);
690 static int is_symlink_with_known_name(const UnitFileInstallInfo
*i
, const char *name
) {
693 if (streq(name
, i
->name
))
696 if (strv_contains(i
->aliases
, name
))
699 /* Look for template symlink matching DefaultInstance */
700 if (i
->default_instance
&& unit_name_is_valid(i
->name
, UNIT_NAME_TEMPLATE
)) {
701 _cleanup_free_
char *s
= NULL
;
703 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &s
);
708 } else if (streq(name
, s
))
715 static int find_symlinks_fd(
716 const char *root_dir
,
717 const UnitFileInstallInfo
*i
,
719 bool ignore_same_name
,
722 const char *config_path
,
723 bool *same_name_link
) {
725 _cleanup_closedir_
DIR *d
= NULL
;
733 assert(same_name_link
);
741 FOREACH_DIRENT(de
, d
, return -errno
) {
743 dirent_ensure_type(d
, de
);
745 if (de
->d_type
== DT_DIR
) {
746 _cleanup_free_
char *p
= NULL
;
749 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
759 p
= path_make_absolute(de
->d_name
, path
);
765 /* This will close nfd, regardless whether it succeeds or not */
766 q
= find_symlinks_fd(root_dir
, i
, match_aliases
, ignore_same_name
, nfd
,
767 p
, config_path
, same_name_link
);
773 } else if (de
->d_type
== DT_LNK
) {
774 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
775 bool found_path
= false, found_dest
, b
= false;
778 /* Acquire symlink name */
779 p
= path_make_absolute(de
->d_name
, path
);
783 /* Acquire symlink destination */
784 q
= readlink_malloc(p
, &dest
);
794 if (!path_is_absolute(dest
)) {
797 x
= prefix_root(root_dir
, dest
);
801 free_and_replace(dest
, x
);
804 assert(unit_name_is_valid(i
->name
, UNIT_NAME_ANY
));
805 if (!ignore_same_name
)
806 /* Check if the symlink itself matches what we are looking for.
808 * If ignore_same_name is specified, we are in one of the directories which
809 * have lower priority than the unit file, and even if a file or symlink with
810 * this name was found, we should ignore it. */
811 found_path
= streq(de
->d_name
, i
->name
);
813 /* Check if what the symlink points to matches what we are looking for */
814 found_dest
= streq(basename(dest
), i
->name
);
816 if (found_path
&& found_dest
) {
817 _cleanup_free_
char *t
= NULL
;
819 /* Filter out same name links in the main
821 t
= path_make_absolute(i
->name
, config_path
);
825 b
= path_equal(t
, p
);
829 *same_name_link
= true;
830 else if (found_path
|| found_dest
) {
834 /* Check if symlink name is in the set of names used by [Install] */
835 q
= is_symlink_with_known_name(i
, de
->d_name
);
847 static int find_symlinks(
848 const char *root_dir
,
849 const UnitFileInstallInfo
*i
,
851 bool ignore_same_name
,
852 const char *config_path
,
853 bool *same_name_link
) {
859 assert(same_name_link
);
861 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
);
863 if (IN_SET(errno
, ENOENT
, ENOTDIR
, EACCES
))
868 /* This takes possession of fd and closes it */
869 return find_symlinks_fd(root_dir
, i
, match_name
, ignore_same_name
, fd
,
870 config_path
, config_path
, same_name_link
);
873 static int find_symlinks_in_scope(
875 const LookupPaths
*paths
,
876 const UnitFileInstallInfo
*i
,
878 UnitFileState
*state
) {
880 bool same_name_link_runtime
= false, same_name_link_config
= false;
881 bool enabled_in_runtime
= false, enabled_at_all
= false;
882 bool ignore_same_name
= false;
889 /* As we iterate over the list of search paths in paths->search_path, we may encounter "same name"
890 * symlinks. The ones which are "below" (i.e. have lower priority) than the unit file itself are
891 * efectively masked, so we should ignore them. */
893 STRV_FOREACH(p
, paths
->search_path
) {
894 bool same_name_link
= false;
896 r
= find_symlinks(paths
->root_dir
, i
, match_name
, ignore_same_name
, *p
, &same_name_link
);
900 /* We found symlinks in this dir? Yay! Let's see where precisely it is enabled. */
902 if (path_equal_ptr(*p
, paths
->persistent_config
)) {
903 /* This is the best outcome, let's return it immediately. */
904 *state
= UNIT_FILE_ENABLED
;
908 /* look for global enablement of user units */
909 if (scope
== UNIT_FILE_USER
&& path_is_user_config_dir(*p
)) {
910 *state
= UNIT_FILE_ENABLED
;
914 r
= path_is_runtime(paths
, *p
, false);
918 enabled_in_runtime
= true;
920 enabled_at_all
= true;
922 } else if (same_name_link
) {
923 if (path_equal_ptr(*p
, paths
->persistent_config
))
924 same_name_link_config
= true;
926 r
= path_is_runtime(paths
, *p
, false);
930 same_name_link_runtime
= true;
934 /* Check if next iteration will be "below" the unit file (either a regular file
935 * or a symlink), and hence should be ignored */
936 if (!ignore_same_name
&& path_startswith(i
->path
, *p
))
937 ignore_same_name
= true;
940 if (enabled_in_runtime
) {
941 *state
= UNIT_FILE_ENABLED_RUNTIME
;
945 /* Here's a special rule: if the unit we are looking for is an instance, and it symlinked in the search path
946 * outside of runtime and configuration directory, then we consider it statically enabled. Note we do that only
947 * for instance, not for regular names, as those are merely aliases, while instances explicitly instantiate
948 * something, and hence are a much stronger concept. */
949 if (enabled_at_all
&& unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
)) {
950 *state
= UNIT_FILE_STATIC
;
954 /* Hmm, we didn't find it, but maybe we found the same name
956 if (same_name_link_config
) {
957 *state
= UNIT_FILE_LINKED
;
960 if (same_name_link_runtime
) {
961 *state
= UNIT_FILE_LINKED_RUNTIME
;
968 static void install_info_free(UnitFileInstallInfo
*i
) {
975 strv_free(i
->aliases
);
976 strv_free(i
->wanted_by
);
977 strv_free(i
->required_by
);
979 free(i
->default_instance
);
980 free(i
->symlink_target
);
984 static void install_context_done(InstallContext
*c
) {
987 c
->will_process
= ordered_hashmap_free_with_destructor(c
->will_process
, install_info_free
);
988 c
->have_processed
= ordered_hashmap_free_with_destructor(c
->have_processed
, install_info_free
);
991 static UnitFileInstallInfo
*install_info_find(InstallContext
*c
, const char *name
) {
992 UnitFileInstallInfo
*i
;
994 i
= ordered_hashmap_get(c
->have_processed
, name
);
998 return ordered_hashmap_get(c
->will_process
, name
);
1001 static int install_info_may_process(
1002 const UnitFileInstallInfo
*i
,
1003 const LookupPaths
*paths
,
1004 UnitFileChange
**changes
,
1005 size_t *n_changes
) {
1009 /* Checks whether the loaded unit file is one we should process, or is masked,
1010 * transient or generated and thus not subject to enable/disable operations. */
1012 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
1013 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, i
->path
, NULL
);
1016 if (path_is_generator(paths
, i
->path
) ||
1017 path_is_transient(paths
, i
->path
)) {
1018 unit_file_changes_add(changes
, n_changes
, -EADDRNOTAVAIL
, i
->path
, NULL
);
1019 return -EADDRNOTAVAIL
;
1026 * Adds a new UnitFileInstallInfo entry under name in the InstallContext.will_process
1027 * hashmap, or retrieves the existing one if already present.
1029 * Returns negative on error, 0 if the unit was already known, 1 otherwise.
1031 static int install_info_add(
1036 UnitFileInstallInfo
**ret
) {
1038 UnitFileInstallInfo
*i
= NULL
;
1042 assert(name
|| path
);
1045 name
= basename(path
);
1047 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
1050 i
= install_info_find(c
, name
);
1052 i
->auxiliary
= i
->auxiliary
&& auxiliary
;
1059 r
= ordered_hashmap_ensure_allocated(&c
->will_process
, &string_hash_ops
);
1063 i
= new(UnitFileInstallInfo
, 1);
1067 *i
= (UnitFileInstallInfo
) {
1068 .type
= _UNIT_FILE_TYPE_INVALID
,
1069 .auxiliary
= auxiliary
,
1072 i
->name
= strdup(name
);
1079 i
->path
= strdup(path
);
1086 r
= ordered_hashmap_put(c
->will_process
, i
->name
, i
);
1096 install_info_free(i
);
1100 static int config_parse_alias(
1102 const char *filename
,
1104 const char *section
,
1105 unsigned section_line
,
1119 type
= unit_name_to_type(unit
);
1120 if (!unit_type_may_alias(type
))
1121 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1122 "Alias= is not allowed for %s units, ignoring.",
1123 unit_type_to_string(type
));
1125 return config_parse_strv(unit
, filename
, line
, section
, section_line
,
1126 lvalue
, ltype
, rvalue
, data
, userdata
);
1129 static int config_parse_also(
1131 const char *filename
,
1133 const char *section
,
1134 unsigned section_line
,
1141 UnitFileInstallInfo
*info
= userdata
, *alsoinfo
= NULL
;
1142 InstallContext
*c
= data
;
1151 _cleanup_free_
char *word
= NULL
, *printed
= NULL
;
1153 r
= extract_first_word(&rvalue
, &word
, NULL
, 0);
1159 r
= install_full_printf(info
, word
, &printed
);
1163 if (!unit_name_is_valid(printed
, UNIT_NAME_ANY
))
1166 r
= install_info_add(c
, printed
, NULL
, true, &alsoinfo
);
1170 r
= strv_push(&info
->also
, printed
);
1180 static int config_parse_default_instance(
1182 const char *filename
,
1184 const char *section
,
1185 unsigned section_line
,
1192 UnitFileInstallInfo
*i
= data
;
1193 _cleanup_free_
char *printed
= NULL
;
1201 if (unit_name_is_valid(unit
, UNIT_NAME_INSTANCE
))
1202 /* When enabling an instance, we might be using a template unit file,
1203 * but we should ignore DefaultInstance silently. */
1205 if (!unit_name_is_valid(unit
, UNIT_NAME_TEMPLATE
))
1206 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1207 "DefaultInstance= only makes sense for template units, ignoring.");
1209 r
= install_full_printf(i
, rvalue
, &printed
);
1213 if (!unit_instance_is_valid(printed
))
1216 return free_and_replace(i
->default_instance
, printed
);
1219 static int unit_file_load(
1221 UnitFileInstallInfo
*info
,
1223 const char *root_dir
,
1224 SearchFlags flags
) {
1226 const ConfigTableItem items
[] = {
1227 { "Install", "Alias", config_parse_alias
, 0, &info
->aliases
},
1228 { "Install", "WantedBy", config_parse_strv
, 0, &info
->wanted_by
},
1229 { "Install", "RequiredBy", config_parse_strv
, 0, &info
->required_by
},
1230 { "Install", "DefaultInstance", config_parse_default_instance
, 0, info
},
1231 { "Install", "Also", config_parse_also
, 0, c
},
1236 _cleanup_fclose_
FILE *f
= NULL
;
1237 _cleanup_close_
int fd
= -1;
1244 if (!(flags
& SEARCH_DROPIN
)) {
1245 /* Loading or checking for the main unit file… */
1247 type
= unit_name_to_type(info
->name
);
1250 if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
|UNIT_NAME_INSTANCE
) && !unit_type_may_template(type
))
1251 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1252 "Unit type %s cannot be templated.", unit_type_to_string(type
));
1254 if (!(flags
& SEARCH_LOAD
)) {
1255 r
= lstat(path
, &st
);
1259 if (null_or_empty(&st
))
1260 info
->type
= UNIT_FILE_TYPE_MASKED
;
1261 else if (S_ISREG(st
.st_mode
))
1262 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1263 else if (S_ISLNK(st
.st_mode
))
1265 else if (S_ISDIR(st
.st_mode
))
1273 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
1277 /* 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. */
1279 if (!(flags
& SEARCH_LOAD
))
1282 fd
= chase_symlinks_and_open(path
, root_dir
, 0, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
, NULL
);
1287 if (fstat(fd
, &st
) < 0)
1290 if (null_or_empty(&st
)) {
1291 if ((flags
& SEARCH_DROPIN
) == 0)
1292 info
->type
= UNIT_FILE_TYPE_MASKED
;
1297 r
= stat_verify_regular(&st
);
1301 f
= fdopen(fd
, "r");
1306 /* c is only needed if we actually load the file (it's referenced from items[] btw, in case you wonder.) */
1309 r
= config_parse(info
->name
, path
, f
,
1311 config_item_table_lookup
, items
,
1312 CONFIG_PARSE_RELAXED
|CONFIG_PARSE_ALLOW_INCLUDE
, info
);
1314 return log_debug_errno(r
, "Failed to parse %s: %m", info
->name
);
1316 if ((flags
& SEARCH_DROPIN
) == 0)
1317 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1320 (int) strv_length(info
->aliases
) +
1321 (int) strv_length(info
->wanted_by
) +
1322 (int) strv_length(info
->required_by
);
1325 static int unit_file_load_or_readlink(
1327 UnitFileInstallInfo
*info
,
1329 const char *root_dir
,
1330 SearchFlags flags
) {
1332 _cleanup_free_
char *target
= NULL
;
1335 r
= unit_file_load(c
, info
, path
, root_dir
, flags
);
1336 if (r
!= -ELOOP
|| (flags
& SEARCH_DROPIN
))
1339 /* This is a symlink, let's read it. */
1341 r
= readlink_malloc(path
, &target
);
1345 if (path_equal(target
, "/dev/null"))
1346 info
->type
= UNIT_FILE_TYPE_MASKED
;
1351 bn
= basename(target
);
1353 if (unit_name_is_valid(info
->name
, UNIT_NAME_PLAIN
)) {
1355 if (!unit_name_is_valid(bn
, UNIT_NAME_PLAIN
))
1358 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1360 if (!unit_name_is_valid(bn
, UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
))
1363 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
)) {
1365 if (!unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
))
1370 /* Enforce that the symlink destination does not
1371 * change the unit file type. */
1373 a
= unit_name_to_type(info
->name
);
1374 b
= unit_name_to_type(bn
);
1375 if (a
< 0 || b
< 0 || a
!= b
)
1378 if (path_is_absolute(target
))
1379 /* This is an absolute path, prefix the root so that we always deal with fully qualified paths */
1380 info
->symlink_target
= prefix_root(root_dir
, target
);
1382 /* This is a relative path, take it relative to the dir the symlink is located in. */
1383 info
->symlink_target
= file_in_same_dir(path
, target
);
1384 if (!info
->symlink_target
)
1387 info
->type
= UNIT_FILE_TYPE_SYMLINK
;
1393 static int unit_file_search(
1395 UnitFileInstallInfo
*info
,
1396 const LookupPaths
*paths
,
1397 SearchFlags flags
) {
1399 const char *dropin_dir_name
= NULL
, *dropin_template_dir_name
= NULL
;
1400 _cleanup_strv_free_
char **dirs
= NULL
, **files
= NULL
;
1401 _cleanup_free_
char *template = NULL
;
1402 bool found_unit
= false;
1409 /* Was this unit already loaded? */
1410 if (info
->type
!= _UNIT_FILE_TYPE_INVALID
)
1414 return unit_file_load_or_readlink(c
, info
, info
->path
, paths
->root_dir
, flags
);
1418 if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1419 r
= unit_name_template(info
->name
, &template);
1424 STRV_FOREACH(p
, paths
->search_path
) {
1425 _cleanup_free_
char *path
= NULL
;
1427 path
= strjoin(*p
, "/", info
->name
);
1431 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1433 info
->path
= TAKE_PTR(path
);
1437 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1441 if (!found_unit
&& template) {
1443 /* Unit file doesn't exist, however instance
1444 * enablement was requested. We will check if it is
1445 * possible to load template unit file. */
1447 STRV_FOREACH(p
, paths
->search_path
) {
1448 _cleanup_free_
char *path
= NULL
;
1450 path
= strjoin(*p
, "/", template);
1454 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1456 info
->path
= TAKE_PTR(path
);
1460 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1466 return log_debug_errno(SYNTHETIC_ERRNO(ENOENT
),
1467 "Cannot find unit %s%s%s.",
1468 info
->name
, template ? " or " : "", strempty(template));
1470 if (info
->type
== UNIT_FILE_TYPE_MASKED
)
1473 /* Search for drop-in directories */
1475 dropin_dir_name
= strjoina(info
->name
, ".d");
1476 STRV_FOREACH(p
, paths
->search_path
) {
1479 path
= path_join(*p
, dropin_dir_name
);
1483 r
= strv_consume(&dirs
, path
);
1489 dropin_template_dir_name
= strjoina(template, ".d");
1490 STRV_FOREACH(p
, paths
->search_path
) {
1493 path
= path_join(*p
, dropin_template_dir_name
);
1497 r
= strv_consume(&dirs
, path
);
1503 /* Load drop-in conf files */
1505 r
= conf_files_list_strv(&files
, ".conf", NULL
, 0, (const char**) dirs
);
1507 return log_debug_errno(r
, "Failed to get list of conf files: %m");
1509 STRV_FOREACH(p
, files
) {
1510 r
= unit_file_load_or_readlink(c
, info
, *p
, paths
->root_dir
, flags
| SEARCH_DROPIN
);
1512 return log_debug_errno(r
, "Failed to load conf file %s: %m", *p
);
1518 static int install_info_follow(
1520 UnitFileInstallInfo
*i
,
1521 const char *root_dir
,
1523 bool ignore_different_name
) {
1528 if (i
->type
!= UNIT_FILE_TYPE_SYMLINK
)
1530 if (!i
->symlink_target
)
1533 /* If the basename doesn't match, the caller should add a
1534 * complete new entry for this. */
1536 if (!ignore_different_name
&& !streq(basename(i
->symlink_target
), i
->name
))
1539 free_and_replace(i
->path
, i
->symlink_target
);
1540 i
->type
= _UNIT_FILE_TYPE_INVALID
;
1542 return unit_file_load_or_readlink(c
, i
, i
->path
, root_dir
, flags
);
1546 * Search for the unit file. If the unit name is a symlink, follow the symlink to the
1547 * target, maybe more than once. Propagate the instance name if present.
1549 static int install_info_traverse(
1550 UnitFileScope scope
,
1552 const LookupPaths
*paths
,
1553 UnitFileInstallInfo
*start
,
1555 UnitFileInstallInfo
**ret
) {
1557 UnitFileInstallInfo
*i
;
1565 r
= unit_file_search(c
, start
, paths
, flags
);
1570 while (i
->type
== UNIT_FILE_TYPE_SYMLINK
) {
1571 /* Follow the symlink */
1573 if (++k
> UNIT_FILE_FOLLOW_SYMLINK_MAX
)
1576 if (!(flags
& SEARCH_FOLLOW_CONFIG_SYMLINKS
)) {
1577 r
= path_is_config(paths
, i
->path
, true);
1584 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
, false);
1586 _cleanup_free_
char *buffer
= NULL
;
1589 /* Target has a different name, create a new
1590 * install info object for that, and continue
1593 bn
= basename(i
->symlink_target
);
1595 if (unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
) &&
1596 unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
)) {
1598 _cleanup_free_
char *instance
= NULL
;
1600 r
= unit_name_to_instance(i
->name
, &instance
);
1604 r
= unit_name_replace_instance(bn
, instance
, &buffer
);
1608 if (streq(buffer
, i
->name
)) {
1610 /* We filled in the instance, and the target stayed the same? If so, then let's
1611 * honour the link as it is. */
1613 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
, true);
1623 r
= install_info_add(c
, bn
, NULL
, false, &i
);
1627 /* Try again, with the new target we found. */
1628 r
= unit_file_search(c
, i
, paths
, flags
);
1630 /* Translate error code to highlight this specific case */
1645 * Call install_info_add() with name_or_path as the path (if name_or_path starts with "/")
1646 * or the name (otherwise). root_dir is prepended to the path.
1648 static int install_info_add_auto(
1650 const LookupPaths
*paths
,
1651 const char *name_or_path
,
1652 UnitFileInstallInfo
**ret
) {
1655 assert(name_or_path
);
1657 if (path_is_absolute(name_or_path
)) {
1660 pp
= prefix_roota(paths
->root_dir
, name_or_path
);
1662 return install_info_add(c
, NULL
, pp
, false, ret
);
1664 return install_info_add(c
, name_or_path
, NULL
, false, ret
);
1667 static int install_info_discover(
1668 UnitFileScope scope
,
1670 const LookupPaths
*paths
,
1673 UnitFileInstallInfo
**ret
,
1674 UnitFileChange
**changes
,
1675 size_t *n_changes
) {
1677 UnitFileInstallInfo
*i
;
1684 r
= install_info_add_auto(c
, paths
, name
, &i
);
1686 r
= install_info_traverse(scope
, c
, paths
, i
, flags
, ret
);
1689 unit_file_changes_add(changes
, n_changes
, r
, name
, NULL
);
1693 static int install_info_discover_and_check(
1694 UnitFileScope scope
,
1696 const LookupPaths
*paths
,
1699 UnitFileInstallInfo
**ret
,
1700 UnitFileChange
**changes
,
1701 size_t *n_changes
) {
1705 r
= install_info_discover(scope
, c
, paths
, name
, flags
, ret
, changes
, n_changes
);
1709 return install_info_may_process(ret
? *ret
: NULL
, paths
, changes
, n_changes
);
1712 static int install_info_symlink_alias(
1713 UnitFileInstallInfo
*i
,
1714 const LookupPaths
*paths
,
1715 const char *config_path
,
1717 UnitFileChange
**changes
,
1718 size_t *n_changes
) {
1725 assert(config_path
);
1727 STRV_FOREACH(s
, i
->aliases
) {
1728 _cleanup_free_
char *alias_path
= NULL
, *dst
= NULL
;
1730 q
= install_full_printf(i
, *s
, &dst
);
1734 alias_path
= path_make_absolute(dst
, config_path
);
1738 q
= create_symlink(paths
, i
->path
, alias_path
, force
, changes
, n_changes
);
1746 static int install_info_symlink_wants(
1747 UnitFileInstallInfo
*i
,
1748 const LookupPaths
*paths
,
1749 const char *config_path
,
1752 UnitFileChange
**changes
,
1753 size_t *n_changes
) {
1755 _cleanup_free_
char *buf
= NULL
;
1762 assert(config_path
);
1764 if (strv_isempty(list
))
1767 if (unit_name_is_valid(i
->name
, UNIT_NAME_TEMPLATE
)) {
1768 UnitFileInstallInfo instance
= {
1769 .type
= _UNIT_FILE_TYPE_INVALID
,
1771 _cleanup_free_
char *path
= NULL
;
1773 /* If this is a template, and we have no instance, don't do anything */
1774 if (!i
->default_instance
)
1777 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &buf
);
1781 instance
.name
= buf
;
1782 r
= unit_file_search(NULL
, &instance
, paths
, SEARCH_FOLLOW_CONFIG_SYMLINKS
);
1786 path
= TAKE_PTR(instance
.path
);
1788 if (instance
.type
== UNIT_FILE_TYPE_MASKED
) {
1789 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, path
, NULL
);
1797 STRV_FOREACH(s
, list
) {
1798 _cleanup_free_
char *path
= NULL
, *dst
= NULL
;
1800 q
= install_full_printf(i
, *s
, &dst
);
1804 if (!unit_name_is_valid(dst
, UNIT_NAME_ANY
)) {
1809 path
= strjoin(config_path
, "/", dst
, suffix
, n
);
1813 q
= create_symlink(paths
, i
->path
, path
, true, changes
, n_changes
);
1821 static int install_info_symlink_link(
1822 UnitFileInstallInfo
*i
,
1823 const LookupPaths
*paths
,
1824 const char *config_path
,
1826 UnitFileChange
**changes
,
1827 size_t *n_changes
) {
1829 _cleanup_free_
char *path
= NULL
;
1834 assert(config_path
);
1837 r
= in_search_path(paths
, i
->path
);
1843 path
= strjoin(config_path
, "/", i
->name
);
1847 return create_symlink(paths
, i
->path
, path
, force
, changes
, n_changes
);
1850 static int install_info_apply(
1851 UnitFileInstallInfo
*i
,
1852 const LookupPaths
*paths
,
1853 const char *config_path
,
1855 UnitFileChange
**changes
,
1856 size_t *n_changes
) {
1862 assert(config_path
);
1864 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
1867 r
= install_info_symlink_alias(i
, paths
, config_path
, force
, changes
, n_changes
);
1869 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->wanted_by
, ".wants/", changes
, n_changes
);
1873 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->required_by
, ".requires/", changes
, n_changes
);
1877 q
= install_info_symlink_link(i
, paths
, config_path
, force
, changes
, n_changes
);
1878 /* Do not count links to the unit file towards the "carries_install_info" count */
1879 if (r
== 0 && q
< 0)
1885 static int install_context_apply(
1886 UnitFileScope scope
,
1888 const LookupPaths
*paths
,
1889 const char *config_path
,
1892 UnitFileChange
**changes
,
1893 size_t *n_changes
) {
1895 UnitFileInstallInfo
*i
;
1900 assert(config_path
);
1902 if (ordered_hashmap_isempty(c
->will_process
))
1905 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
1910 while ((i
= ordered_hashmap_first(c
->will_process
))) {
1913 q
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
1917 q
= install_info_traverse(scope
, c
, paths
, i
, flags
, NULL
);
1919 unit_file_changes_add(changes
, n_changes
, r
, i
->name
, NULL
);
1923 /* We can attempt to process a masked unit when a different unit
1924 * that we were processing specifies it in Also=. */
1925 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
1926 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_MASKED
, i
->path
, NULL
);
1928 /* Assume that something *could* have been enabled here,
1929 * avoid "empty [Install] section" warning. */
1934 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
1937 q
= install_info_apply(i
, paths
, config_path
, force
, changes
, n_changes
);
1949 static int install_context_mark_for_removal(
1950 UnitFileScope scope
,
1952 const LookupPaths
*paths
,
1953 Set
**remove_symlinks_to
,
1954 const char *config_path
,
1955 UnitFileChange
**changes
,
1956 size_t *n_changes
) {
1958 UnitFileInstallInfo
*i
;
1963 assert(config_path
);
1965 /* Marks all items for removal */
1967 if (ordered_hashmap_isempty(c
->will_process
))
1970 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
1974 while ((i
= ordered_hashmap_first(c
->will_process
))) {
1976 r
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
1980 r
= install_info_traverse(scope
, c
, paths
, i
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, NULL
);
1981 if (r
== -ENOLINK
) {
1982 log_debug_errno(r
, "Name %s leads to a dangling symlink, removing name.", i
->name
);
1983 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_DANGLING
, i
->path
?: i
->name
, NULL
);
1984 } else if (r
== -ENOENT
) {
1986 if (i
->auxiliary
) /* some unit specified in Also= or similar is missing */
1987 log_debug_errno(r
, "Auxiliary unit of %s not found, removing name.", i
->name
);
1989 log_debug_errno(r
, "Unit %s not found, removing name.", i
->name
);
1990 unit_file_changes_add(changes
, n_changes
, r
, i
->path
?: i
->name
, NULL
);
1994 log_debug_errno(r
, "Failed to find unit %s, removing name: %m", i
->name
);
1995 unit_file_changes_add(changes
, n_changes
, r
, i
->path
?: i
->name
, NULL
);
1996 } else if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
1997 log_debug("Unit file %s is masked, ignoring.", i
->name
);
1998 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_MASKED
, i
->path
?: i
->name
, NULL
);
2000 } else if (i
->type
!= UNIT_FILE_TYPE_REGULAR
) {
2001 log_debug("Unit %s has type %s, ignoring.", i
->name
, unit_file_type_to_string(i
->type
) ?: "invalid");
2005 r
= mark_symlink_for_removal(remove_symlinks_to
, i
->name
);
2014 UnitFileScope scope
,
2015 UnitFileFlags flags
,
2016 const char *root_dir
,
2018 UnitFileChange
**changes
,
2019 size_t *n_changes
) {
2021 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2022 const char *config_path
;
2027 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2029 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2033 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2037 STRV_FOREACH(i
, files
) {
2038 _cleanup_free_
char *path
= NULL
;
2041 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
)) {
2047 path
= path_make_absolute(*i
, config_path
);
2051 q
= create_symlink(&paths
, "/dev/null", path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2052 if (q
< 0 && r
>= 0)
2059 int unit_file_unmask(
2060 UnitFileScope scope
,
2061 UnitFileFlags flags
,
2062 const char *root_dir
,
2064 UnitFileChange
**changes
,
2065 size_t *n_changes
) {
2067 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2068 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2069 _cleanup_strv_free_
char **todo
= NULL
;
2070 size_t n_todo
= 0, n_allocated
= 0;
2071 const char *config_path
;
2077 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2079 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2083 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2087 dry_run
= !!(flags
& UNIT_FILE_DRY_RUN
);
2089 STRV_FOREACH(i
, files
) {
2090 _cleanup_free_
char *path
= NULL
;
2092 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2095 path
= path_make_absolute(*i
, config_path
);
2099 r
= null_or_empty_path(path
);
2107 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2110 todo
[n_todo
] = strdup(*i
);
2120 STRV_FOREACH(i
, todo
) {
2121 _cleanup_free_
char *path
= NULL
;
2124 path
= path_make_absolute(*i
, config_path
);
2128 if (!dry_run
&& unlink(path
) < 0) {
2129 if (errno
!= ENOENT
) {
2132 unit_file_changes_add(changes
, n_changes
, -errno
, path
, NULL
);
2138 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
2140 rp
= skip_root(&paths
, path
);
2141 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: path
);
2146 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, dry_run
, changes
, n_changes
);
2154 UnitFileScope scope
,
2155 UnitFileFlags flags
,
2156 const char *root_dir
,
2158 UnitFileChange
**changes
,
2159 size_t *n_changes
) {
2161 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2162 _cleanup_strv_free_
char **todo
= NULL
;
2163 size_t n_todo
= 0, n_allocated
= 0;
2164 const char *config_path
;
2169 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2171 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2175 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2179 STRV_FOREACH(i
, files
) {
2180 _cleanup_free_
char *full
= NULL
;
2184 if (!path_is_absolute(*i
))
2188 if (!unit_name_is_valid(fn
, UNIT_NAME_ANY
))
2191 full
= prefix_root(paths
.root_dir
, *i
);
2195 if (lstat(full
, &st
) < 0)
2197 r
= stat_verify_regular(&st
);
2201 q
= in_search_path(&paths
, *i
);
2207 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2210 todo
[n_todo
] = strdup(*i
);
2220 STRV_FOREACH(i
, todo
) {
2221 _cleanup_free_
char *new_path
= NULL
;
2223 new_path
= path_make_absolute(basename(*i
), config_path
);
2227 q
= create_symlink(&paths
, *i
, new_path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2228 if (q
< 0 && r
>= 0)
2235 static int path_shall_revert(const LookupPaths
*paths
, const char *path
) {
2241 /* Checks whether the path is one where the drop-in directories shall be removed. */
2243 r
= path_is_config(paths
, path
, true);
2247 r
= path_is_control(paths
, path
);
2251 return path_is_transient(paths
, path
);
2254 int unit_file_revert(
2255 UnitFileScope scope
,
2256 const char *root_dir
,
2258 UnitFileChange
**changes
,
2259 size_t *n_changes
) {
2261 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2262 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2263 _cleanup_strv_free_
char **todo
= NULL
;
2264 size_t n_todo
= 0, n_allocated
= 0;
2268 /* Puts a unit file back into vendor state. This means:
2270 * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and
2271 * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated").
2273 * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in
2274 * "config", but not in "transient" or "control" or even "generated").
2276 * We remove all that in both the runtime and the persistent directories, if that applies.
2279 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2283 STRV_FOREACH(i
, files
) {
2284 bool has_vendor
= false;
2287 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2290 STRV_FOREACH(p
, paths
.search_path
) {
2291 _cleanup_free_
char *path
= NULL
, *dropin
= NULL
;
2294 path
= path_make_absolute(*i
, *p
);
2298 r
= lstat(path
, &st
);
2300 if (errno
!= ENOENT
)
2302 } else if (S_ISREG(st
.st_mode
)) {
2303 /* Check if there's a vendor version */
2304 r
= path_is_vendor(&paths
, path
);
2311 dropin
= strappend(path
, ".d");
2315 r
= lstat(dropin
, &st
);
2317 if (errno
!= ENOENT
)
2319 } else if (S_ISDIR(st
.st_mode
)) {
2320 /* Remove the drop-ins */
2321 r
= path_shall_revert(&paths
, dropin
);
2325 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2328 todo
[n_todo
++] = TAKE_PTR(dropin
);
2336 /* OK, there's a vendor version, hence drop all configuration versions */
2337 STRV_FOREACH(p
, paths
.search_path
) {
2338 _cleanup_free_
char *path
= NULL
;
2341 path
= path_make_absolute(*i
, *p
);
2345 r
= lstat(path
, &st
);
2347 if (errno
!= ENOENT
)
2349 } else if (S_ISREG(st
.st_mode
) || S_ISLNK(st
.st_mode
)) {
2350 r
= path_is_config(&paths
, path
, true);
2354 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2357 todo
[n_todo
++] = TAKE_PTR(path
);
2366 STRV_FOREACH(i
, todo
) {
2367 _cleanup_strv_free_
char **fs
= NULL
;
2371 (void) get_files_in_directory(*i
, &fs
);
2373 q
= rm_rf(*i
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
2374 if (q
< 0 && q
!= -ENOENT
&& r
>= 0) {
2379 STRV_FOREACH(j
, fs
) {
2380 _cleanup_free_
char *t
= NULL
;
2382 t
= strjoin(*i
, "/", *j
);
2386 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, t
, NULL
);
2389 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, *i
, NULL
);
2391 rp
= skip_root(&paths
, *i
);
2392 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: *i
);
2397 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.runtime_config
, &paths
, false, changes
, n_changes
);
2401 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.persistent_config
, &paths
, false, changes
, n_changes
);
2408 int unit_file_add_dependency(
2409 UnitFileScope scope
,
2410 UnitFileFlags flags
,
2411 const char *root_dir
,
2415 UnitFileChange
**changes
,
2416 size_t *n_changes
) {
2418 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2419 _cleanup_(install_context_done
) InstallContext c
= {};
2420 UnitFileInstallInfo
*i
, *target_info
;
2421 const char *config_path
;
2426 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2429 if (!IN_SET(dep
, UNIT_WANTS
, UNIT_REQUIRES
))
2432 if (!unit_name_is_valid(target
, UNIT_NAME_ANY
))
2435 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2439 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2443 r
= install_info_discover_and_check(scope
, &c
, &paths
, target
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2444 &target_info
, changes
, n_changes
);
2448 assert(target_info
->type
== UNIT_FILE_TYPE_REGULAR
);
2450 STRV_FOREACH(f
, files
) {
2453 r
= install_info_discover_and_check(scope
, &c
, &paths
, *f
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2454 &i
, changes
, n_changes
);
2458 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2460 /* We didn't actually load anything from the unit
2461 * file, but instead just add in our new symlink to
2464 if (dep
== UNIT_WANTS
)
2467 l
= &i
->required_by
;
2470 *l
= strv_new(target_info
->name
);
2475 return install_context_apply(scope
, &c
, &paths
, config_path
, !!(flags
& UNIT_FILE_FORCE
), SEARCH_FOLLOW_CONFIG_SYMLINKS
, changes
, n_changes
);
2478 int unit_file_enable(
2479 UnitFileScope scope
,
2480 UnitFileFlags flags
,
2481 const char *root_dir
,
2483 UnitFileChange
**changes
,
2484 size_t *n_changes
) {
2486 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2487 _cleanup_(install_context_done
) InstallContext c
= {};
2488 const char *config_path
;
2489 UnitFileInstallInfo
*i
;
2494 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2496 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2500 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2504 STRV_FOREACH(f
, files
) {
2505 r
= install_info_discover_and_check(scope
, &c
, &paths
, *f
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2506 &i
, changes
, n_changes
);
2510 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2513 /* This will return the number of symlink rules that were
2514 supposed to be created, not the ones actually created. This
2515 is useful to determine whether the passed files had any
2516 installation data at all. */
2518 return install_context_apply(scope
, &c
, &paths
, config_path
, !!(flags
& UNIT_FILE_FORCE
), SEARCH_LOAD
, changes
, n_changes
);
2521 int unit_file_disable(
2522 UnitFileScope scope
,
2523 UnitFileFlags flags
,
2524 const char *root_dir
,
2526 UnitFileChange
**changes
,
2527 size_t *n_changes
) {
2529 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2530 _cleanup_(install_context_done
) InstallContext c
= {};
2531 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2532 const char *config_path
;
2537 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2539 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2543 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2547 STRV_FOREACH(i
, files
) {
2548 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2551 r
= install_info_add(&c
, *i
, NULL
, false, NULL
);
2556 r
= install_context_mark_for_removal(scope
, &c
, &paths
, &remove_symlinks_to
, config_path
, changes
, n_changes
);
2560 return remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, !!(flags
& UNIT_FILE_DRY_RUN
), changes
, n_changes
);
2563 int unit_file_reenable(
2564 UnitFileScope scope
,
2565 UnitFileFlags flags
,
2566 const char *root_dir
,
2568 UnitFileChange
**changes
,
2569 size_t *n_changes
) {
2575 /* First, we invoke the disable command with only the basename... */
2576 l
= strv_length(files
);
2577 n
= newa(char*, l
+1);
2578 for (i
= 0; i
< l
; i
++)
2579 n
[i
] = basename(files
[i
]);
2582 r
= unit_file_disable(scope
, flags
, root_dir
, n
, changes
, n_changes
);
2586 /* But the enable command with the full name */
2587 return unit_file_enable(scope
, flags
, root_dir
, files
, changes
, n_changes
);
2590 int unit_file_set_default(
2591 UnitFileScope scope
,
2592 UnitFileFlags flags
,
2593 const char *root_dir
,
2595 UnitFileChange
**changes
,
2596 size_t *n_changes
) {
2598 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2599 _cleanup_(install_context_done
) InstallContext c
= {};
2600 UnitFileInstallInfo
*i
;
2601 const char *new_path
;
2605 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2608 if (unit_name_to_type(name
) != UNIT_TARGET
) /* this also validates the name */
2610 if (streq(name
, SPECIAL_DEFAULT_TARGET
))
2613 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2617 r
= install_info_discover_and_check(scope
, &c
, &paths
, name
, 0, &i
, changes
, n_changes
);
2621 new_path
= strjoina(paths
.persistent_config
, "/" SPECIAL_DEFAULT_TARGET
);
2622 return create_symlink(&paths
, i
->path
, new_path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2625 int unit_file_get_default(
2626 UnitFileScope scope
,
2627 const char *root_dir
,
2630 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2631 _cleanup_(install_context_done
) InstallContext c
= {};
2632 UnitFileInstallInfo
*i
;
2637 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2640 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2644 r
= install_info_discover(scope
, &c
, &paths
, SPECIAL_DEFAULT_TARGET
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2648 r
= install_info_may_process(i
, &paths
, NULL
, 0);
2652 n
= strdup(i
->name
);
2660 int unit_file_lookup_state(
2661 UnitFileScope scope
,
2662 const LookupPaths
*paths
,
2664 UnitFileState
*ret
) {
2666 _cleanup_(install_context_done
) InstallContext c
= {};
2667 UnitFileInstallInfo
*i
;
2668 UnitFileState state
;
2674 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2677 r
= install_info_discover(scope
, &c
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2680 return log_debug_errno(r
, "Failed to discover unit %s: %m", name
);
2682 assert(IN_SET(i
->type
, UNIT_FILE_TYPE_REGULAR
, UNIT_FILE_TYPE_MASKED
));
2683 log_debug("Found unit %s at %s (%s)", name
, strna(i
->path
),
2684 i
->type
== UNIT_FILE_TYPE_REGULAR
? "regular file" : "mask");
2686 /* Shortcut things, if the caller just wants to know if this unit exists. */
2692 case UNIT_FILE_TYPE_MASKED
:
2693 r
= path_is_runtime(paths
, i
->path
, true);
2697 state
= r
> 0 ? UNIT_FILE_MASKED_RUNTIME
: UNIT_FILE_MASKED
;
2700 case UNIT_FILE_TYPE_REGULAR
:
2701 r
= path_is_generator(paths
, i
->path
);
2705 state
= UNIT_FILE_GENERATED
;
2709 r
= path_is_transient(paths
, i
->path
);
2713 state
= UNIT_FILE_TRANSIENT
;
2717 /* Check if any of the Alias= symlinks have been created.
2718 * We ignore other aliases, and only check those that would
2719 * be created by systemctl enable for this unit. */
2720 r
= find_symlinks_in_scope(scope
, paths
, i
, true, &state
);
2726 /* Check if the file is known under other names. If it is,
2727 * it might be in use. Report that as UNIT_FILE_INDIRECT. */
2728 r
= find_symlinks_in_scope(scope
, paths
, i
, false, &state
);
2732 state
= UNIT_FILE_INDIRECT
;
2734 if (unit_file_install_info_has_rules(i
))
2735 state
= UNIT_FILE_DISABLED
;
2736 else if (unit_file_install_info_has_also(i
))
2737 state
= UNIT_FILE_INDIRECT
;
2739 state
= UNIT_FILE_STATIC
;
2745 assert_not_reached("Unexpect unit file type.");
2752 int unit_file_get_state(
2753 UnitFileScope scope
,
2754 const char *root_dir
,
2756 UnitFileState
*ret
) {
2758 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
2762 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2765 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2769 return unit_file_lookup_state(scope
, &paths
, name
, ret
);
2772 int unit_file_exists(UnitFileScope scope
, const LookupPaths
*paths
, const char *name
) {
2773 _cleanup_(install_context_done
) InstallContext c
= {};
2779 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2782 r
= install_info_discover(scope
, &c
, paths
, name
, 0, NULL
, NULL
, NULL
);
2791 static int split_pattern_into_name_and_instances(const char *pattern
, char **out_unit_name
, char ***out_instances
) {
2792 _cleanup_strv_free_
char **instances
= NULL
;
2793 _cleanup_free_
char *unit_name
= NULL
;
2797 assert(out_instances
);
2798 assert(out_unit_name
);
2800 r
= extract_first_word(&pattern
, &unit_name
, NULL
, EXTRACT_RETAIN_ESCAPE
);
2804 /* We handle the instances logic when unit name is extracted */
2806 /* We only create instances when a rule of templated unit
2807 * is seen. A rule like enable foo@.service a b c will
2808 * result in an array of (a, b, c) as instance names */
2809 if (!unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
))
2812 instances
= strv_split(pattern
, WHITESPACE
);
2816 *out_instances
= TAKE_PTR(instances
);
2819 *out_unit_name
= TAKE_PTR(unit_name
);
2824 static int presets_find_config(UnitFileScope scope
, const char *root_dir
, char ***files
) {
2825 const char* const* dirs
;
2828 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2830 if (scope
== UNIT_FILE_SYSTEM
)
2831 dirs
= (const char* const*) CONF_PATHS_STRV("systemd/system-preset");
2833 else if (IN_SET(scope
, UNIT_FILE_GLOBAL
, UNIT_FILE_USER
))
2834 dirs
= (const char* const*) CONF_PATHS_USR_STRV("systemd/user-preset");
2837 assert_not_reached("Invalid unit file scope");
2839 return conf_files_list_strv(files
, ".preset", root_dir
, 0, dirs
);
2842 static int read_presets(UnitFileScope scope
, const char *root_dir
, Presets
*presets
) {
2843 _cleanup_(presets_freep
) Presets ps
= {};
2844 size_t n_allocated
= 0;
2845 _cleanup_strv_free_
char **files
= NULL
;
2850 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2853 r
= presets_find_config(scope
, root_dir
, &files
);
2857 STRV_FOREACH(p
, files
) {
2858 _cleanup_fclose_
FILE *f
;
2861 f
= fopen(*p
, "re");
2863 if (errno
== ENOENT
)
2870 _cleanup_free_
char *line
= NULL
;
2871 PresetRule rule
= {};
2872 const char *parameter
;
2875 r
= read_line(f
, LONG_LINE_MAX
, &line
);
2886 if (strchr(COMMENTS
, *l
))
2889 parameter
= first_word(l
, "enable");
2892 char **instances
= NULL
;
2894 /* Unit_name will remain the same as parameter when no instances are specified */
2895 r
= split_pattern_into_name_and_instances(parameter
, &unit_name
, &instances
);
2897 log_syntax(NULL
, LOG_WARNING
, *p
, n
, r
, "Couldn't parse line '%s'. Ignoring.", line
);
2901 rule
= (PresetRule
) {
2902 .pattern
= unit_name
,
2903 .action
= PRESET_ENABLE
,
2904 .instances
= instances
,
2908 parameter
= first_word(l
, "disable");
2912 pattern
= strdup(parameter
);
2916 rule
= (PresetRule
) {
2918 .action
= PRESET_DISABLE
,
2923 if (!GREEDY_REALLOC(ps
.rules
, n_allocated
, ps
.n_rules
+ 1))
2926 ps
.rules
[ps
.n_rules
++] = rule
;
2930 log_syntax(NULL
, LOG_WARNING
, *p
, n
, 0, "Couldn't parse line '%s'. Ignoring.", line
);
2940 static int pattern_match_multiple_instances(
2941 const PresetRule rule
,
2942 const char *unit_name
,
2945 _cleanup_free_
char *templated_name
= NULL
;
2948 /* If no ret is needed or the rule itself does not have instances
2949 * initalized, we return not matching */
2950 if (!ret
|| !rule
.instances
)
2953 r
= unit_name_template(unit_name
, &templated_name
);
2956 if (!streq(rule
.pattern
, templated_name
))
2959 /* Compose a list of specified instances when unit name is a template */
2960 if (unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2961 _cleanup_free_
char *prefix
= NULL
;
2962 _cleanup_strv_free_
char **out_strv
= NULL
;
2965 r
= unit_name_to_prefix(unit_name
, &prefix
);
2969 STRV_FOREACH(iter
, rule
.instances
) {
2970 _cleanup_free_
char *name
= NULL
;
2971 r
= unit_name_build(prefix
, *iter
, ".service", &name
);
2974 r
= strv_extend(&out_strv
, name
);
2979 *ret
= TAKE_PTR(out_strv
);
2982 /* We now know the input unit name is an instance name */
2983 _cleanup_free_
char *instance_name
= NULL
;
2985 r
= unit_name_to_instance(unit_name
, &instance_name
);
2989 if (strv_find(rule
.instances
, instance_name
))
2995 static int query_presets(const char *name
, const Presets presets
, char ***instance_name_list
) {
2996 PresetAction action
= PRESET_UNKNOWN
;
2999 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
3002 for (i
= 0; i
< presets
.n_rules
; i
++)
3003 if (pattern_match_multiple_instances(presets
.rules
[i
], name
, instance_name_list
) > 0 ||
3004 fnmatch(presets
.rules
[i
].pattern
, name
, FNM_NOESCAPE
) == 0) {
3005 action
= presets
.rules
[i
].action
;
3010 case PRESET_UNKNOWN
:
3011 log_debug("Preset files don't specify rule for %s. Enabling.", name
);
3014 if (instance_name_list
&& *instance_name_list
)
3015 STRV_FOREACH(s
, *instance_name_list
)
3016 log_debug("Preset files say enable %s.", *s
);
3018 log_debug("Preset files say enable %s.", name
);
3020 case PRESET_DISABLE
:
3021 log_debug("Preset files say disable %s.", name
);
3024 assert_not_reached("invalid preset action");
3028 int unit_file_query_preset(UnitFileScope scope
, const char *root_dir
, const char *name
) {
3029 _cleanup_(presets_freep
) Presets presets
= {};
3032 r
= read_presets(scope
, root_dir
, &presets
);
3036 return query_presets(name
, presets
, NULL
);
3039 static int execute_preset(
3040 UnitFileScope scope
,
3041 InstallContext
*plus
,
3042 InstallContext
*minus
,
3043 const LookupPaths
*paths
,
3044 const char *config_path
,
3046 UnitFilePresetMode mode
,
3048 UnitFileChange
**changes
,
3049 size_t *n_changes
) {
3056 assert(config_path
);
3058 if (mode
!= UNIT_FILE_PRESET_ENABLE_ONLY
) {
3059 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
3061 r
= install_context_mark_for_removal(scope
, minus
, paths
, &remove_symlinks_to
, config_path
, changes
, n_changes
);
3065 r
= remove_marked_symlinks(remove_symlinks_to
, config_path
, paths
, false, changes
, n_changes
);
3069 if (mode
!= UNIT_FILE_PRESET_DISABLE_ONLY
) {
3072 /* Returns number of symlinks that where supposed to be installed. */
3073 q
= install_context_apply(scope
, plus
, paths
, config_path
, force
, SEARCH_LOAD
, changes
, n_changes
);
3085 static int preset_prepare_one(
3086 UnitFileScope scope
,
3087 InstallContext
*plus
,
3088 InstallContext
*minus
,
3092 UnitFileChange
**changes
,
3093 size_t *n_changes
) {
3095 _cleanup_(install_context_done
) InstallContext tmp
= {};
3096 _cleanup_strv_free_
char **instance_name_list
= NULL
;
3097 UnitFileInstallInfo
*i
;
3100 if (install_info_find(plus
, name
) || install_info_find(minus
, name
))
3103 r
= install_info_discover(scope
, &tmp
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3104 &i
, changes
, n_changes
);
3107 if (!streq(name
, i
->name
)) {
3108 log_debug("Skipping %s because it is an alias for %s.", name
, i
->name
);
3112 r
= query_presets(name
, presets
, &instance_name_list
);
3117 if (instance_name_list
) {
3119 STRV_FOREACH(s
, instance_name_list
) {
3120 r
= install_info_discover_and_check(scope
, plus
, paths
, *s
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3121 &i
, changes
, n_changes
);
3126 r
= install_info_discover_and_check(scope
, plus
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3127 &i
, changes
, n_changes
);
3133 r
= install_info_discover(scope
, minus
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3134 &i
, changes
, n_changes
);
3139 int unit_file_preset(
3140 UnitFileScope scope
,
3141 UnitFileFlags flags
,
3142 const char *root_dir
,
3144 UnitFilePresetMode mode
,
3145 UnitFileChange
**changes
,
3146 size_t *n_changes
) {
3148 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
3149 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3150 _cleanup_(presets_freep
) Presets presets
= {};
3151 const char *config_path
;
3156 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3157 assert(mode
< _UNIT_FILE_PRESET_MAX
);
3159 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3163 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
3167 r
= read_presets(scope
, root_dir
, &presets
);
3171 STRV_FOREACH(i
, files
) {
3172 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, *i
, presets
, changes
, n_changes
);
3177 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, files
, mode
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
3180 int unit_file_preset_all(
3181 UnitFileScope scope
,
3182 UnitFileFlags flags
,
3183 const char *root_dir
,
3184 UnitFilePresetMode mode
,
3185 UnitFileChange
**changes
,
3186 size_t *n_changes
) {
3188 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
3189 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3190 _cleanup_(presets_freep
) Presets presets
= {};
3191 const char *config_path
= NULL
;
3196 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3197 assert(mode
< _UNIT_FILE_PRESET_MAX
);
3199 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3203 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
3207 r
= read_presets(scope
, root_dir
, &presets
);
3211 STRV_FOREACH(i
, paths
.search_path
) {
3212 _cleanup_closedir_
DIR *d
= NULL
;
3217 if (errno
== ENOENT
)
3223 FOREACH_DIRENT(de
, d
, return -errno
) {
3225 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
3228 dirent_ensure_type(d
, de
);
3230 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
3233 /* we don't pass changes[] in, because we want to handle errors on our own */
3234 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, de
->d_name
, presets
, NULL
, 0);
3236 r
= unit_file_changes_add(changes
, n_changes
,
3237 UNIT_FILE_IS_MASKED
, de
->d_name
, NULL
);
3238 else if (r
== -ENOLINK
)
3239 r
= unit_file_changes_add(changes
, n_changes
,
3240 UNIT_FILE_IS_DANGLING
, de
->d_name
, NULL
);
3241 else if (r
== -EADDRNOTAVAIL
) /* Ignore generated/transient units when applying preset */
3248 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, NULL
, mode
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
3251 static void unit_file_list_free_one(UnitFileList
*f
) {
3259 Hashmap
* unit_file_list_free(Hashmap
*h
) {
3260 return hashmap_free_with_destructor(h
, unit_file_list_free_one
);
3263 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList
*, unit_file_list_free_one
);
3265 int unit_file_get_list(
3266 UnitFileScope scope
,
3267 const char *root_dir
,
3272 _cleanup_(lookup_paths_free
) LookupPaths paths
= {};
3277 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3280 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3284 STRV_FOREACH(i
, paths
.search_path
) {
3285 _cleanup_closedir_
DIR *d
= NULL
;
3290 if (errno
== ENOENT
)
3292 if (IN_SET(errno
, ENOTDIR
, EACCES
)) {
3293 log_debug_errno(errno
, "Failed to open \"%s\": %m", *i
);
3300 FOREACH_DIRENT(de
, d
, return -errno
) {
3301 _cleanup_(unit_file_list_free_onep
) UnitFileList
*f
= NULL
;
3303 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
3306 if (!strv_fnmatch_or_empty(patterns
, de
->d_name
, FNM_NOESCAPE
))
3309 if (hashmap_get(h
, de
->d_name
))
3312 dirent_ensure_type(d
, de
);
3314 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
3317 f
= new0(UnitFileList
, 1);
3321 f
->path
= path_make_absolute(de
->d_name
, *i
);
3325 r
= unit_file_lookup_state(scope
, &paths
, de
->d_name
, &f
->state
);
3327 f
->state
= UNIT_FILE_BAD
;
3329 if (!strv_isempty(states
) &&
3330 !strv_contains(states
, unit_file_state_to_string(f
->state
)))
3333 r
= hashmap_put(h
, basename(f
->path
), f
);
3337 f
= NULL
; /* prevent cleanup */
3344 static const char* const unit_file_state_table
[_UNIT_FILE_STATE_MAX
] = {
3345 [UNIT_FILE_ENABLED
] = "enabled",
3346 [UNIT_FILE_ENABLED_RUNTIME
] = "enabled-runtime",
3347 [UNIT_FILE_LINKED
] = "linked",
3348 [UNIT_FILE_LINKED_RUNTIME
] = "linked-runtime",
3349 [UNIT_FILE_MASKED
] = "masked",
3350 [UNIT_FILE_MASKED_RUNTIME
] = "masked-runtime",
3351 [UNIT_FILE_STATIC
] = "static",
3352 [UNIT_FILE_DISABLED
] = "disabled",
3353 [UNIT_FILE_INDIRECT
] = "indirect",
3354 [UNIT_FILE_GENERATED
] = "generated",
3355 [UNIT_FILE_TRANSIENT
] = "transient",
3356 [UNIT_FILE_BAD
] = "bad",
3359 DEFINE_STRING_TABLE_LOOKUP(unit_file_state
, UnitFileState
);
3361 static const char* const unit_file_change_type_table
[_UNIT_FILE_CHANGE_TYPE_MAX
] = {
3362 [UNIT_FILE_SYMLINK
] = "symlink",
3363 [UNIT_FILE_UNLINK
] = "unlink",
3364 [UNIT_FILE_IS_MASKED
] = "masked",
3365 [UNIT_FILE_IS_DANGLING
] = "dangling",
3368 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type
, UnitFileChangeType
);
3370 static const char* const unit_file_preset_mode_table
[_UNIT_FILE_PRESET_MAX
] = {
3371 [UNIT_FILE_PRESET_FULL
] = "full",
3372 [UNIT_FILE_PRESET_ENABLE_ONLY
] = "enable-only",
3373 [UNIT_FILE_PRESET_DISABLE_ONLY
] = "disable-only",
3376 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode
, UnitFilePresetMode
);