1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2011 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty <of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
33 #include "alloc-util.h"
34 #include "conf-files.h"
35 #include "conf-parser.h"
36 #include "dirent-util.h"
37 #include "extract-word.h"
42 #include "install-printf.h"
44 #include "locale-util.h"
48 #include "path-lookup.h"
49 #include "path-util.h"
53 #include "stat-util.h"
54 #include "string-table.h"
55 #include "string-util.h"
57 #include "unit-name.h"
59 #define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
61 typedef enum SearchFlags
{
62 SEARCH_LOAD
= 1U << 0,
63 SEARCH_FOLLOW_CONFIG_SYMLINKS
= 1U << 1,
64 SEARCH_DROPIN
= 1U << 2,
68 OrderedHashmap
*will_process
;
69 OrderedHashmap
*have_processed
;
88 static inline bool unit_file_install_info_has_rules(UnitFileInstallInfo
*i
) {
91 return !strv_isempty(i
->aliases
) ||
92 !strv_isempty(i
->wanted_by
) ||
93 !strv_isempty(i
->required_by
);
96 static inline bool unit_file_install_info_has_also(UnitFileInstallInfo
*i
) {
99 return !strv_isempty(i
->also
);
102 static inline void presets_freep(Presets
*p
) {
108 for (i
= 0; i
< p
->n_rules
; i
++)
109 free(p
->rules
[i
].pattern
);
115 static int unit_file_lookup_state(UnitFileScope scope
, const LookupPaths
*paths
, const char *name
, UnitFileState
*ret
);
117 bool unit_type_may_alias(UnitType type
) {
127 bool unit_type_may_template(UnitType type
) {
136 static const char *unit_file_type_table
[_UNIT_FILE_TYPE_MAX
] = {
137 [UNIT_FILE_TYPE_REGULAR
] = "regular",
138 [UNIT_FILE_TYPE_SYMLINK
] = "symlink",
139 [UNIT_FILE_TYPE_MASKED
] = "masked",
142 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(unit_file_type
, UnitFileType
);
144 static int in_search_path(const LookupPaths
*p
, const char *path
) {
145 _cleanup_free_
char *parent
= NULL
;
150 parent
= dirname_malloc(path
);
154 STRV_FOREACH(i
, p
->search_path
)
155 if (path_equal(parent
, *i
))
161 static const char* skip_root(const LookupPaths
*p
, const char *path
) {
170 e
= path_startswith(path
, p
->root_dir
);
174 /* Make sure the returned path starts with a slash */
176 if (e
== path
|| e
[-1] != '/')
185 static int path_is_generator(const LookupPaths
*p
, const char *path
) {
186 _cleanup_free_
char *parent
= NULL
;
191 parent
= dirname_malloc(path
);
195 return path_equal_ptr(parent
, p
->generator
) ||
196 path_equal_ptr(parent
, p
->generator_early
) ||
197 path_equal_ptr(parent
, p
->generator_late
);
200 static int path_is_transient(const LookupPaths
*p
, const char *path
) {
201 _cleanup_free_
char *parent
= NULL
;
206 parent
= dirname_malloc(path
);
210 return path_equal_ptr(parent
, p
->transient
);
213 static int path_is_control(const LookupPaths
*p
, const char *path
) {
214 _cleanup_free_
char *parent
= NULL
;
219 parent
= dirname_malloc(path
);
223 return path_equal_ptr(parent
, p
->persistent_control
) ||
224 path_equal_ptr(parent
, p
->runtime_control
);
227 static int path_is_config(const LookupPaths
*p
, const char *path
, bool check_parent
) {
228 _cleanup_free_
char *parent
= NULL
;
233 /* Note that we do *not* have generic checks for /etc or /run in place, since with
234 * them we couldn't discern configuration from transient or generated units */
237 parent
= dirname_malloc(path
);
244 return path_equal_ptr(path
, p
->persistent_config
) ||
245 path_equal_ptr(path
, p
->runtime_config
);
248 static int path_is_runtime(const LookupPaths
*p
, const char *path
, bool check_parent
) {
249 _cleanup_free_
char *parent
= NULL
;
255 /* Everything in /run is considered runtime. On top of that we also add
256 * explicit checks for the various runtime directories, as safety net. */
258 rpath
= skip_root(p
, path
);
259 if (rpath
&& path_startswith(rpath
, "/run"))
263 parent
= dirname_malloc(path
);
270 return path_equal_ptr(path
, p
->runtime_config
) ||
271 path_equal_ptr(path
, p
->generator
) ||
272 path_equal_ptr(path
, p
->generator_early
) ||
273 path_equal_ptr(path
, p
->generator_late
) ||
274 path_equal_ptr(path
, p
->transient
) ||
275 path_equal_ptr(path
, p
->runtime_control
);
278 static int path_is_vendor(const LookupPaths
*p
, const char *path
) {
284 rpath
= skip_root(p
, path
);
288 if (path_startswith(rpath
, "/usr"))
292 if (path_startswith(rpath
, "/lib"))
296 return path_equal(rpath
, SYSTEM_DATA_UNIT_PATH
);
299 int unit_file_changes_add(
300 UnitFileChange
**changes
,
302 UnitFileChangeType type
,
304 const char *source
) {
306 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
310 assert(!changes
== !n_changes
);
315 c
= reallocarray(*changes
, *n_changes
+ 1, sizeof(UnitFileChange
));
324 if (!p
|| (source
&& !s
))
327 path_kill_slashes(p
);
329 path_kill_slashes(s
);
331 c
[*n_changes
] = (UnitFileChange
) { type
, p
, s
};
337 void unit_file_changes_free(UnitFileChange
*changes
, unsigned n_changes
) {
340 assert(changes
|| n_changes
== 0);
342 for (i
= 0; i
< n_changes
; i
++) {
343 free(changes
[i
].path
);
344 free(changes
[i
].source
);
350 void unit_file_dump_changes(int r
, const char *verb
, const UnitFileChange
*changes
, unsigned n_changes
, bool quiet
) {
354 assert(changes
|| n_changes
== 0);
355 /* If verb is not specified, errors are not allowed! */
356 assert(verb
|| r
>= 0);
358 for (i
= 0; i
< n_changes
; i
++) {
359 assert(verb
|| changes
[i
].type
>= 0);
361 switch(changes
[i
].type
) {
362 case UNIT_FILE_SYMLINK
:
364 log_info("Created symlink %s %s %s.",
366 special_glyph(ARROW
),
369 case UNIT_FILE_UNLINK
:
371 log_info("Removed %s.", changes
[i
].path
);
373 case UNIT_FILE_IS_MASKED
:
375 log_info("Unit %s is masked, ignoring.", changes
[i
].path
);
377 case UNIT_FILE_IS_DANGLING
:
379 log_info("Unit %s is an alias to a unit that is not present, ignoring.",
383 if (changes
[i
].source
)
384 log_error_errno(changes
[i
].type
,
385 "Failed to %s unit, file %s already exists and is a symlink to %s.",
386 verb
, changes
[i
].path
, changes
[i
].source
);
388 log_error_errno(changes
[i
].type
,
389 "Failed to %s unit, file %s already exists.",
390 verb
, changes
[i
].path
);
394 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s is masked.",
395 verb
, changes
[i
].path
);
399 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s is transient or generated.",
400 verb
, changes
[i
].path
);
404 log_error_errno(changes
[i
].type
, "Failed to %s unit, refusing to operate on linked unit file %s",
405 verb
, changes
[i
].path
);
410 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s does not exist.", verb
, changes
[i
].path
);
415 assert(changes
[i
].type
< 0);
416 log_error_errno(changes
[i
].type
, "Failed to %s unit, file %s: %m.",
417 verb
, changes
[i
].path
);
422 if (r
< 0 && !logged
)
423 log_error_errno(r
, "Failed to %s: %m.", verb
);
427 * Checks if two paths or symlinks from wd are the same, when root is the root of the filesystem.
428 * wc should be the full path in the host file system.
430 static bool chroot_symlinks_same(const char *root
, const char *wd
, const char *a
, const char *b
) {
431 assert(path_is_absolute(wd
));
433 /* This will give incorrect results if the paths are relative and go outside
434 * of the chroot. False negatives are possible. */
439 a
= strjoina(path_is_absolute(a
) ? root
: wd
, "/", a
);
440 b
= strjoina(path_is_absolute(b
) ? root
: wd
, "/", b
);
441 return path_equal_or_files_same(a
, b
, 0);
444 static int create_symlink(
445 const LookupPaths
*paths
,
446 const char *old_path
,
447 const char *new_path
,
449 UnitFileChange
**changes
,
450 unsigned *n_changes
) {
452 _cleanup_free_
char *dest
= NULL
, *dirname
= NULL
;
459 rp
= skip_root(paths
, old_path
);
463 /* Actually create a symlink, and remember that we did. Is
464 * smart enough to check if there's already a valid symlink in
467 * Returns 1 if a symlink was created or already exists and points to
468 * the right place, or negative on error.
471 mkdir_parents_label(new_path
, 0755);
473 if (symlink(old_path
, new_path
) >= 0) {
474 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
478 if (errno
!= EEXIST
) {
479 unit_file_changes_add(changes
, n_changes
, -errno
, new_path
, NULL
);
483 r
= readlink_malloc(new_path
, &dest
);
485 /* translate EINVAL (non-symlink exists) to EEXIST */
489 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
493 dirname
= dirname_malloc(new_path
);
497 if (chroot_symlinks_same(paths
->root_dir
, dirname
, dest
, old_path
))
501 unit_file_changes_add(changes
, n_changes
, -EEXIST
, new_path
, dest
);
505 r
= symlink_atomic(old_path
, new_path
);
507 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
511 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, new_path
, NULL
);
512 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
517 static int mark_symlink_for_removal(
518 Set
**remove_symlinks_to
,
526 r
= set_ensure_allocated(remove_symlinks_to
, &path_hash_ops
);
534 path_kill_slashes(n
);
536 r
= set_consume(*remove_symlinks_to
, n
);
545 static int remove_marked_symlinks_fd(
546 Set
*remove_symlinks_to
,
549 const char *config_path
,
550 const LookupPaths
*lp
,
553 UnitFileChange
**changes
,
554 unsigned *n_changes
) {
556 _cleanup_closedir_
DIR *d
= NULL
;
560 assert(remove_symlinks_to
);
575 FOREACH_DIRENT(de
, d
, return -errno
) {
577 dirent_ensure_type(d
, de
);
579 if (de
->d_type
== DT_DIR
) {
580 _cleanup_free_
char *p
= NULL
;
583 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
593 p
= path_make_absolute(de
->d_name
, path
);
599 /* This will close nfd, regardless whether it succeeds or not */
600 q
= remove_marked_symlinks_fd(remove_symlinks_to
, nfd
, p
, config_path
, lp
, dry_run
, restart
, changes
, n_changes
);
604 } else if (de
->d_type
== DT_LNK
) {
605 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
610 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
613 p
= path_make_absolute(de
->d_name
, path
);
616 path_kill_slashes(p
);
618 q
= readlink_malloc(p
, &dest
);
627 /* We remove all links pointing to a file or path that is marked, as well as all files sharing
628 * the same name as a file that is marked. */
630 found
= set_contains(remove_symlinks_to
, dest
) ||
631 set_contains(remove_symlinks_to
, basename(dest
)) ||
632 set_contains(remove_symlinks_to
, de
->d_name
);
638 if (unlinkat(fd
, de
->d_name
, 0) < 0 && errno
!= ENOENT
) {
641 unit_file_changes_add(changes
, n_changes
, -errno
, p
, NULL
);
645 (void) rmdir_parents(p
, config_path
);
648 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, p
, NULL
);
650 /* Now, remember the full path (but with the root prefix removed) of
651 * the symlink we just removed, and remove any symlinks to it, too. */
653 rp
= skip_root(lp
, p
);
654 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: p
);
657 if (q
> 0 && !dry_run
)
665 static int remove_marked_symlinks(
666 Set
*remove_symlinks_to
,
667 const char *config_path
,
668 const LookupPaths
*lp
,
670 UnitFileChange
**changes
,
671 unsigned *n_changes
) {
673 _cleanup_close_
int fd
= -1;
680 if (set_size(remove_symlinks_to
) <= 0)
683 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
);
685 return errno
== ENOENT
? 0 : -errno
;
691 cfd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
695 /* This takes possession of cfd and closes it */
696 q
= remove_marked_symlinks_fd(remove_symlinks_to
, cfd
, config_path
, config_path
, lp
, dry_run
, &restart
, changes
, n_changes
);
704 static bool is_symlink_with_known_name(const UnitFileInstallInfo
*i
, const char *name
) {
707 if (streq(name
, i
->name
))
710 if (strv_contains(i
->aliases
, name
))
713 /* Look for template symlink matching DefaultInstance */
714 if (i
->default_instance
&& unit_name_is_valid(i
->name
, UNIT_NAME_TEMPLATE
)) {
715 _cleanup_free_
char *s
= NULL
;
717 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &s
);
722 } else if (streq(name
, s
))
729 static int find_symlinks_fd(
730 const char *root_dir
,
731 UnitFileInstallInfo
*i
,
735 const char *config_path
,
736 bool *same_name_link
) {
738 _cleanup_closedir_
DIR *d
= NULL
;
746 assert(same_name_link
);
754 FOREACH_DIRENT(de
, d
, return -errno
) {
756 dirent_ensure_type(d
, de
);
758 if (de
->d_type
== DT_DIR
) {
759 _cleanup_free_
char *p
= NULL
;
762 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
772 p
= path_make_absolute(de
->d_name
, path
);
778 /* This will close nfd, regardless whether it succeeds or not */
779 q
= find_symlinks_fd(root_dir
, i
, match_aliases
, nfd
,
780 p
, config_path
, same_name_link
);
786 } else if (de
->d_type
== DT_LNK
) {
787 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
788 bool found_path
, found_dest
, b
= false;
791 /* Acquire symlink name */
792 p
= path_make_absolute(de
->d_name
, path
);
796 /* Acquire symlink destination */
797 q
= readlink_malloc(p
, &dest
);
807 if (!path_is_absolute(dest
)) {
810 x
= prefix_root(root_dir
, dest
);
818 /* Check if the symlink itself matches what we
820 if (path_is_absolute(i
->name
))
821 found_path
= path_equal(p
, i
->name
);
823 found_path
= streq(de
->d_name
, i
->name
);
825 /* Check if what the symlink points to
826 * matches what we are looking for */
827 if (path_is_absolute(i
->name
))
828 found_dest
= path_equal(dest
, i
->name
);
830 found_dest
= streq(basename(dest
), i
->name
);
832 if (found_path
&& found_dest
) {
833 _cleanup_free_
char *t
= NULL
;
835 /* Filter out same name links in the main
837 t
= path_make_absolute(i
->name
, config_path
);
841 b
= path_equal(t
, p
);
845 *same_name_link
= true;
846 else if (found_path
|| found_dest
) {
850 /* Check if symlink name is in the set of names used by [Install] */
851 q
= is_symlink_with_known_name(i
, de
->d_name
);
863 static int find_symlinks(
864 const char *root_dir
,
865 UnitFileInstallInfo
*i
,
867 const char *config_path
,
868 bool *same_name_link
) {
874 assert(same_name_link
);
876 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
);
878 if (IN_SET(errno
, ENOENT
, ENOTDIR
, EACCES
))
883 /* This takes possession of fd and closes it */
884 return find_symlinks_fd(root_dir
, i
, match_name
, fd
,
885 config_path
, config_path
, same_name_link
);
888 static int find_symlinks_in_scope(
890 const LookupPaths
*paths
,
891 UnitFileInstallInfo
*i
,
893 UnitFileState
*state
) {
895 bool same_name_link_runtime
= false, same_name_link_config
= false;
896 bool enabled_in_runtime
= false, enabled_at_all
= false;
903 STRV_FOREACH(p
, paths
->search_path
) {
904 bool same_name_link
= false;
906 r
= find_symlinks(paths
->root_dir
, i
, match_name
, *p
, &same_name_link
);
910 /* We found symlinks in this dir? Yay! Let's see where precisely it is enabled. */
912 r
= path_is_config(paths
, *p
, false);
916 /* This is the best outcome, let's return it immediately. */
917 *state
= UNIT_FILE_ENABLED
;
921 /* look for globally enablement of user units */
922 if (scope
== UNIT_FILE_USER
&& path_is_user_config_dir(*p
)) {
923 *state
= UNIT_FILE_ENABLED
;
927 r
= path_is_runtime(paths
, *p
, false);
931 enabled_in_runtime
= true;
933 enabled_at_all
= true;
935 } else if (same_name_link
) {
937 r
= path_is_config(paths
, *p
, false);
941 same_name_link_config
= true;
943 r
= path_is_runtime(paths
, *p
, false);
947 same_name_link_runtime
= true;
952 if (enabled_in_runtime
) {
953 *state
= UNIT_FILE_ENABLED_RUNTIME
;
957 /* Here's a special rule: if the unit we are looking for is an instance, and it symlinked in the search path
958 * outside of runtime and configuration directory, then we consider it statically enabled. Note we do that only
959 * for instance, not for regular names, as those are merely aliases, while instances explicitly instantiate
960 * something, and hence are a much stronger concept. */
961 if (enabled_at_all
&& unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
)) {
962 *state
= UNIT_FILE_STATIC
;
966 /* Hmm, we didn't find it, but maybe we found the same name
968 if (same_name_link_config
) {
969 *state
= UNIT_FILE_LINKED
;
972 if (same_name_link_runtime
) {
973 *state
= UNIT_FILE_LINKED_RUNTIME
;
980 static void install_info_free(UnitFileInstallInfo
*i
) {
987 strv_free(i
->aliases
);
988 strv_free(i
->wanted_by
);
989 strv_free(i
->required_by
);
991 free(i
->default_instance
);
992 free(i
->symlink_target
);
996 static void install_context_done(InstallContext
*c
) {
999 c
->will_process
= ordered_hashmap_free_with_destructor(c
->will_process
, install_info_free
);
1000 c
->have_processed
= ordered_hashmap_free_with_destructor(c
->have_processed
, install_info_free
);
1003 static UnitFileInstallInfo
*install_info_find(InstallContext
*c
, const char *name
) {
1004 UnitFileInstallInfo
*i
;
1006 i
= ordered_hashmap_get(c
->have_processed
, name
);
1010 return ordered_hashmap_get(c
->will_process
, name
);
1013 static int install_info_may_process(
1014 UnitFileInstallInfo
*i
,
1015 const LookupPaths
*paths
,
1016 UnitFileChange
**changes
,
1017 unsigned *n_changes
) {
1021 /* Checks whether the loaded unit file is one we should process, or is masked,
1022 * transient or generated and thus not subject to enable/disable operations. */
1024 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
1025 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, i
->path
, NULL
);
1028 if (path_is_generator(paths
, i
->path
) ||
1029 path_is_transient(paths
, i
->path
)) {
1030 unit_file_changes_add(changes
, n_changes
, -EADDRNOTAVAIL
, i
->path
, NULL
);
1031 return -EADDRNOTAVAIL
;
1038 * Adds a new UnitFileInstallInfo entry under name in the InstallContext.will_process
1039 * hashmap, or retrieves the existing one if already present.
1041 * Returns negative on error, 0 if the unit was already known, 1 otherwise.
1043 static int install_info_add(
1048 UnitFileInstallInfo
**ret
) {
1050 UnitFileInstallInfo
*i
= NULL
;
1054 assert(name
|| path
);
1057 name
= basename(path
);
1059 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
1062 i
= install_info_find(c
, name
);
1064 i
->auxiliary
= i
->auxiliary
&& auxiliary
;
1071 r
= ordered_hashmap_ensure_allocated(&c
->will_process
, &string_hash_ops
);
1075 i
= new0(UnitFileInstallInfo
, 1);
1078 i
->type
= _UNIT_FILE_TYPE_INVALID
;
1079 i
->auxiliary
= auxiliary
;
1081 i
->name
= strdup(name
);
1088 i
->path
= strdup(path
);
1095 r
= ordered_hashmap_put(c
->will_process
, i
->name
, i
);
1105 install_info_free(i
);
1109 static int config_parse_alias(
1111 const char *filename
,
1113 const char *section
,
1114 unsigned section_line
,
1128 type
= unit_name_to_type(unit
);
1129 if (!unit_type_may_alias(type
))
1130 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1131 "Alias= is not allowed for %s units, ignoring.",
1132 unit_type_to_string(type
));
1134 return config_parse_strv(unit
, filename
, line
, section
, section_line
,
1135 lvalue
, ltype
, rvalue
, data
, userdata
);
1138 static int config_parse_also(
1140 const char *filename
,
1142 const char *section
,
1143 unsigned section_line
,
1150 UnitFileInstallInfo
*info
= userdata
, *alsoinfo
= NULL
;
1151 InstallContext
*c
= data
;
1160 _cleanup_free_
char *word
= NULL
, *printed
= NULL
;
1162 r
= extract_first_word(&rvalue
, &word
, NULL
, 0);
1168 r
= install_full_printf(info
, word
, &printed
);
1172 if (!unit_name_is_valid(printed
, UNIT_NAME_ANY
))
1175 r
= install_info_add(c
, printed
, NULL
, true, &alsoinfo
);
1179 r
= strv_push(&info
->also
, printed
);
1189 static int config_parse_default_instance(
1191 const char *filename
,
1193 const char *section
,
1194 unsigned section_line
,
1201 UnitFileInstallInfo
*i
= data
;
1202 _cleanup_free_
char *printed
= NULL
;
1210 if (unit_name_is_valid(unit
, UNIT_NAME_INSTANCE
))
1211 /* When enabling an instance, we might be using a template unit file,
1212 * but we should ignore DefaultInstance silently. */
1214 if (!unit_name_is_valid(unit
, UNIT_NAME_TEMPLATE
))
1215 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1216 "DefaultInstance= only makes sense for template units, ignoring.");
1218 r
= install_full_printf(i
, rvalue
, &printed
);
1222 if (!unit_instance_is_valid(printed
))
1225 return free_and_replace(i
->default_instance
, printed
);
1228 static int unit_file_load(
1230 UnitFileInstallInfo
*info
,
1232 const char *root_dir
,
1233 SearchFlags flags
) {
1235 const ConfigTableItem items
[] = {
1236 { "Install", "Alias", config_parse_alias
, 0, &info
->aliases
},
1237 { "Install", "WantedBy", config_parse_strv
, 0, &info
->wanted_by
},
1238 { "Install", "RequiredBy", config_parse_strv
, 0, &info
->required_by
},
1239 { "Install", "DefaultInstance", config_parse_default_instance
, 0, info
},
1240 { "Install", "Also", config_parse_also
, 0, c
},
1245 _cleanup_fclose_
FILE *f
= NULL
;
1246 _cleanup_close_
int fd
= -1;
1253 if (!(flags
& SEARCH_DROPIN
)) {
1254 /* Loading or checking for the main unit file… */
1256 type
= unit_name_to_type(info
->name
);
1259 if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
|UNIT_NAME_INSTANCE
) && !unit_type_may_template(type
)) {
1260 log_error("Unit type %s cannot be templated.", unit_type_to_string(type
));
1264 if (!(flags
& SEARCH_LOAD
)) {
1265 r
= lstat(path
, &st
);
1269 if (null_or_empty(&st
))
1270 info
->type
= UNIT_FILE_TYPE_MASKED
;
1271 else if (S_ISREG(st
.st_mode
))
1272 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1273 else if (S_ISLNK(st
.st_mode
))
1275 else if (S_ISDIR(st
.st_mode
))
1283 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
1287 /* 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. */
1289 if (!(flags
& SEARCH_LOAD
))
1292 fd
= chase_symlinks_and_open(path
, root_dir
, 0, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
, NULL
);
1297 if (fstat(fd
, &st
) < 0)
1300 if (null_or_empty(&st
)) {
1301 if ((flags
& SEARCH_DROPIN
) == 0)
1302 info
->type
= UNIT_FILE_TYPE_MASKED
;
1307 r
= stat_verify_regular(&st
);
1311 f
= fdopen(fd
, "re");
1316 /* c is only needed if we actually load the file (it's referenced from items[] btw, in case you wonder.) */
1319 r
= config_parse(info
->name
, path
, f
,
1321 config_item_table_lookup
, items
,
1322 CONFIG_PARSE_RELAXED
|CONFIG_PARSE_ALLOW_INCLUDE
, info
);
1324 return log_debug_errno(r
, "Failed to parse %s: %m", info
->name
);
1326 if ((flags
& SEARCH_DROPIN
) == 0)
1327 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1330 (int) strv_length(info
->aliases
) +
1331 (int) strv_length(info
->wanted_by
) +
1332 (int) strv_length(info
->required_by
);
1335 static int unit_file_load_or_readlink(
1337 UnitFileInstallInfo
*info
,
1339 const char *root_dir
,
1340 SearchFlags flags
) {
1342 _cleanup_free_
char *target
= NULL
;
1345 r
= unit_file_load(c
, info
, path
, root_dir
, flags
);
1346 if (r
!= -ELOOP
|| (flags
& SEARCH_DROPIN
))
1349 /* This is a symlink, let's read it. */
1351 r
= readlink_malloc(path
, &target
);
1355 if (path_equal(target
, "/dev/null"))
1356 info
->type
= UNIT_FILE_TYPE_MASKED
;
1361 bn
= basename(target
);
1363 if (unit_name_is_valid(info
->name
, UNIT_NAME_PLAIN
)) {
1365 if (!unit_name_is_valid(bn
, UNIT_NAME_PLAIN
))
1368 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1370 if (!unit_name_is_valid(bn
, UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
))
1373 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
)) {
1375 if (!unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
))
1380 /* Enforce that the symlink destination does not
1381 * change the unit file type. */
1383 a
= unit_name_to_type(info
->name
);
1384 b
= unit_name_to_type(bn
);
1385 if (a
< 0 || b
< 0 || a
!= b
)
1388 if (path_is_absolute(target
))
1389 /* This is an absolute path, prefix the root so that we always deal with fully qualified paths */
1390 info
->symlink_target
= prefix_root(root_dir
, target
);
1392 /* This is a relative path, take it relative to the dir the symlink is located in. */
1393 info
->symlink_target
= file_in_same_dir(path
, target
);
1394 if (!info
->symlink_target
)
1397 info
->type
= UNIT_FILE_TYPE_SYMLINK
;
1403 static int unit_file_search(
1405 UnitFileInstallInfo
*info
,
1406 const LookupPaths
*paths
,
1407 SearchFlags flags
) {
1409 const char *dropin_dir_name
= NULL
, *dropin_template_dir_name
= NULL
;
1410 _cleanup_strv_free_
char **dirs
= NULL
, **files
= NULL
;
1411 _cleanup_free_
char *template = NULL
;
1412 bool found_unit
= false;
1419 /* Was this unit already loaded? */
1420 if (info
->type
!= _UNIT_FILE_TYPE_INVALID
)
1424 return unit_file_load_or_readlink(c
, info
, info
->path
, paths
->root_dir
, flags
);
1428 if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1429 r
= unit_name_template(info
->name
, &template);
1434 STRV_FOREACH(p
, paths
->search_path
) {
1435 _cleanup_free_
char *path
= NULL
;
1437 path
= strjoin(*p
, "/", info
->name
);
1441 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1443 info
->path
= TAKE_PTR(path
);
1447 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1451 if (!found_unit
&& template) {
1453 /* Unit file doesn't exist, however instance
1454 * enablement was requested. We will check if it is
1455 * possible to load template unit file. */
1457 STRV_FOREACH(p
, paths
->search_path
) {
1458 _cleanup_free_
char *path
= NULL
;
1460 path
= strjoin(*p
, "/", template);
1464 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1466 info
->path
= TAKE_PTR(path
);
1470 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1476 log_debug("Cannot find unit %s%s%s.", info
->name
, template ? " or " : "", strempty(template));
1480 if (info
->type
== UNIT_FILE_TYPE_MASKED
)
1483 /* Search for drop-in directories */
1485 dropin_dir_name
= strjoina(info
->name
, ".d");
1486 STRV_FOREACH(p
, paths
->search_path
) {
1489 path
= path_join(NULL
, *p
, dropin_dir_name
);
1493 r
= strv_consume(&dirs
, path
);
1499 dropin_template_dir_name
= strjoina(template, ".d");
1500 STRV_FOREACH(p
, paths
->search_path
) {
1503 path
= path_join(NULL
, *p
, dropin_template_dir_name
);
1507 r
= strv_consume(&dirs
, path
);
1513 /* Load drop-in conf files */
1515 r
= conf_files_list_strv(&files
, ".conf", NULL
, 0, (const char**) dirs
);
1517 return log_debug_errno(r
, "Failed to get list of conf files: %m");
1519 STRV_FOREACH(p
, files
) {
1520 r
= unit_file_load_or_readlink(c
, info
, *p
, paths
->root_dir
, flags
| SEARCH_DROPIN
);
1522 return log_debug_errno(r
, "Failed to load conf file %s: %m", *p
);
1528 static int install_info_follow(
1530 UnitFileInstallInfo
*i
,
1531 const char *root_dir
,
1533 bool ignore_different_name
) {
1538 if (i
->type
!= UNIT_FILE_TYPE_SYMLINK
)
1540 if (!i
->symlink_target
)
1543 /* If the basename doesn't match, the caller should add a
1544 * complete new entry for this. */
1546 if (!ignore_different_name
&& !streq(basename(i
->symlink_target
), i
->name
))
1549 free_and_replace(i
->path
, i
->symlink_target
);
1550 i
->type
= _UNIT_FILE_TYPE_INVALID
;
1552 return unit_file_load_or_readlink(c
, i
, i
->path
, root_dir
, flags
);
1556 * Search for the unit file. If the unit name is a symlink, follow the symlink to the
1557 * target, maybe more than once. Propagate the instance name if present.
1559 static int install_info_traverse(
1560 UnitFileScope scope
,
1562 const LookupPaths
*paths
,
1563 UnitFileInstallInfo
*start
,
1565 UnitFileInstallInfo
**ret
) {
1567 UnitFileInstallInfo
*i
;
1575 r
= unit_file_search(c
, start
, paths
, flags
);
1580 while (i
->type
== UNIT_FILE_TYPE_SYMLINK
) {
1581 /* Follow the symlink */
1583 if (++k
> UNIT_FILE_FOLLOW_SYMLINK_MAX
)
1586 if (!(flags
& SEARCH_FOLLOW_CONFIG_SYMLINKS
)) {
1587 r
= path_is_config(paths
, i
->path
, true);
1594 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
, false);
1596 _cleanup_free_
char *buffer
= NULL
;
1599 /* Target has a different name, create a new
1600 * install info object for that, and continue
1603 bn
= basename(i
->symlink_target
);
1605 if (unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
) &&
1606 unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
)) {
1608 _cleanup_free_
char *instance
= NULL
;
1610 r
= unit_name_to_instance(i
->name
, &instance
);
1614 r
= unit_name_replace_instance(bn
, instance
, &buffer
);
1618 if (streq(buffer
, i
->name
)) {
1620 /* We filled in the instance, and the target stayed the same? If so, then let's
1621 * honour the link as it is. */
1623 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
, true);
1633 r
= install_info_add(c
, bn
, NULL
, false, &i
);
1637 /* Try again, with the new target we found. */
1638 r
= unit_file_search(c
, i
, paths
, flags
);
1640 /* Translate error code to highlight this specific case */
1655 * Call install_info_add() with name_or_path as the path (if name_or_path starts with "/")
1656 * or the name (otherwise). root_dir is prepended to the path.
1658 static int install_info_add_auto(
1660 const LookupPaths
*paths
,
1661 const char *name_or_path
,
1662 UnitFileInstallInfo
**ret
) {
1665 assert(name_or_path
);
1667 if (path_is_absolute(name_or_path
)) {
1670 pp
= prefix_roota(paths
->root_dir
, name_or_path
);
1672 return install_info_add(c
, NULL
, pp
, false, ret
);
1674 return install_info_add(c
, name_or_path
, NULL
, false, ret
);
1677 static int install_info_discover(
1678 UnitFileScope scope
,
1680 const LookupPaths
*paths
,
1683 UnitFileInstallInfo
**ret
,
1684 UnitFileChange
**changes
,
1685 unsigned *n_changes
) {
1687 UnitFileInstallInfo
*i
;
1694 r
= install_info_add_auto(c
, paths
, name
, &i
);
1696 r
= install_info_traverse(scope
, c
, paths
, i
, flags
, ret
);
1699 unit_file_changes_add(changes
, n_changes
, r
, name
, NULL
);
1703 static int install_info_symlink_alias(
1704 UnitFileInstallInfo
*i
,
1705 const LookupPaths
*paths
,
1706 const char *config_path
,
1708 UnitFileChange
**changes
,
1709 unsigned *n_changes
) {
1716 assert(config_path
);
1718 STRV_FOREACH(s
, i
->aliases
) {
1719 _cleanup_free_
char *alias_path
= NULL
, *dst
= NULL
;
1721 q
= install_full_printf(i
, *s
, &dst
);
1725 alias_path
= path_make_absolute(dst
, config_path
);
1729 q
= create_symlink(paths
, i
->path
, alias_path
, force
, changes
, n_changes
);
1737 static int install_info_symlink_wants(
1738 UnitFileInstallInfo
*i
,
1739 const LookupPaths
*paths
,
1740 const char *config_path
,
1743 UnitFileChange
**changes
,
1744 unsigned *n_changes
) {
1746 _cleanup_free_
char *buf
= NULL
;
1753 assert(config_path
);
1755 if (strv_isempty(list
))
1758 if (unit_name_is_valid(i
->name
, UNIT_NAME_TEMPLATE
) && i
->default_instance
) {
1759 UnitFileInstallInfo instance
= {
1760 .type
= _UNIT_FILE_TYPE_INVALID
,
1762 _cleanup_free_
char *path
= NULL
;
1764 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &buf
);
1768 instance
.name
= buf
;
1769 r
= unit_file_search(NULL
, &instance
, paths
, SEARCH_FOLLOW_CONFIG_SYMLINKS
);
1773 path
= TAKE_PTR(instance
.path
);
1775 if (instance
.type
== UNIT_FILE_TYPE_MASKED
) {
1776 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, path
, NULL
);
1784 STRV_FOREACH(s
, list
) {
1785 _cleanup_free_
char *path
= NULL
, *dst
= NULL
;
1787 q
= install_full_printf(i
, *s
, &dst
);
1791 if (!unit_name_is_valid(dst
, UNIT_NAME_ANY
)) {
1796 path
= strjoin(config_path
, "/", dst
, suffix
, n
);
1800 q
= create_symlink(paths
, i
->path
, path
, true, changes
, n_changes
);
1808 static int install_info_symlink_link(
1809 UnitFileInstallInfo
*i
,
1810 const LookupPaths
*paths
,
1811 const char *config_path
,
1813 UnitFileChange
**changes
,
1814 unsigned *n_changes
) {
1816 _cleanup_free_
char *path
= NULL
;
1821 assert(config_path
);
1824 r
= in_search_path(paths
, i
->path
);
1830 path
= strjoin(config_path
, "/", i
->name
);
1834 return create_symlink(paths
, i
->path
, path
, force
, changes
, n_changes
);
1837 static int install_info_apply(
1838 UnitFileInstallInfo
*i
,
1839 const LookupPaths
*paths
,
1840 const char *config_path
,
1842 UnitFileChange
**changes
,
1843 unsigned *n_changes
) {
1849 assert(config_path
);
1851 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
1854 r
= install_info_symlink_alias(i
, paths
, config_path
, force
, changes
, n_changes
);
1856 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->wanted_by
, ".wants/", changes
, n_changes
);
1860 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->required_by
, ".requires/", changes
, n_changes
);
1864 q
= install_info_symlink_link(i
, paths
, config_path
, force
, changes
, n_changes
);
1865 /* Do not count links to the unit file towards the "carries_install_info" count */
1866 if (r
== 0 && q
< 0)
1872 static int install_context_apply(
1873 UnitFileScope scope
,
1875 const LookupPaths
*paths
,
1876 const char *config_path
,
1879 UnitFileChange
**changes
,
1880 unsigned *n_changes
) {
1882 UnitFileInstallInfo
*i
;
1887 assert(config_path
);
1889 if (ordered_hashmap_isempty(c
->will_process
))
1892 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
1897 while ((i
= ordered_hashmap_first(c
->will_process
))) {
1900 q
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
1904 r
= install_info_traverse(scope
, c
, paths
, i
, flags
, NULL
);
1906 unit_file_changes_add(changes
, n_changes
, r
, i
->name
, NULL
);
1910 /* We can attempt to process a masked unit when a different unit
1911 * that we were processing specifies it in Also=. */
1912 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
1913 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_MASKED
, i
->path
, NULL
);
1915 /* Assume that something *could* have been enabled here,
1916 * avoid "empty [Install] section" warning. */
1921 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
1924 q
= install_info_apply(i
, paths
, config_path
, force
, changes
, n_changes
);
1936 static int install_context_mark_for_removal(
1937 UnitFileScope scope
,
1939 const LookupPaths
*paths
,
1940 Set
**remove_symlinks_to
,
1941 const char *config_path
,
1942 UnitFileChange
**changes
,
1943 unsigned *n_changes
) {
1945 UnitFileInstallInfo
*i
;
1950 assert(config_path
);
1952 /* Marks all items for removal */
1954 if (ordered_hashmap_isempty(c
->will_process
))
1957 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
1961 while ((i
= ordered_hashmap_first(c
->will_process
))) {
1963 r
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
1967 r
= install_info_traverse(scope
, c
, paths
, i
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, NULL
);
1968 if (r
== -ENOLINK
) {
1969 log_debug_errno(r
, "Name %s leads to a dangling symlink, removing name.", i
->name
);
1970 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_DANGLING
, i
->path
?: i
->name
, NULL
);
1971 } else if (r
== -ENOENT
) {
1973 if (i
->auxiliary
) /* some unit specified in Also= or similar is missing */
1974 log_debug_errno(r
, "Auxiliary unit of %s not found, removing name.", i
->name
);
1976 log_debug_errno(r
, "Unit %s not found, removing name.", i
->name
);
1977 unit_file_changes_add(changes
, n_changes
, r
, i
->path
?: i
->name
, NULL
);
1981 log_debug_errno(r
, "Failed to find unit %s, removing name: %m", i
->name
);
1982 unit_file_changes_add(changes
, n_changes
, r
, i
->path
?: i
->name
, NULL
);
1983 } else if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
1984 log_debug("Unit file %s is masked, ignoring.", i
->name
);
1985 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_MASKED
, i
->path
?: i
->name
, NULL
);
1987 } else if (i
->type
!= UNIT_FILE_TYPE_REGULAR
) {
1988 log_debug("Unit %s has type %s, ignoring.", i
->name
, unit_file_type_to_string(i
->type
) ?: "invalid");
1992 r
= mark_symlink_for_removal(remove_symlinks_to
, i
->name
);
2001 UnitFileScope scope
,
2002 UnitFileFlags flags
,
2003 const char *root_dir
,
2005 UnitFileChange
**changes
,
2006 unsigned *n_changes
) {
2008 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2009 const char *config_path
;
2014 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2016 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2020 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2024 STRV_FOREACH(i
, files
) {
2025 _cleanup_free_
char *path
= NULL
;
2028 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
)) {
2034 path
= path_make_absolute(*i
, config_path
);
2038 q
= create_symlink(&paths
, "/dev/null", path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2039 if (q
< 0 && r
>= 0)
2046 int unit_file_unmask(
2047 UnitFileScope scope
,
2048 UnitFileFlags flags
,
2049 const char *root_dir
,
2051 UnitFileChange
**changes
,
2052 unsigned *n_changes
) {
2054 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2055 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2056 _cleanup_strv_free_
char **todo
= NULL
;
2057 size_t n_todo
= 0, n_allocated
= 0;
2058 const char *config_path
;
2064 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2066 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2070 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2074 dry_run
= !!(flags
& UNIT_FILE_DRY_RUN
);
2076 STRV_FOREACH(i
, files
) {
2077 _cleanup_free_
char *path
= NULL
;
2079 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2082 path
= path_make_absolute(*i
, config_path
);
2086 r
= null_or_empty_path(path
);
2094 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2097 todo
[n_todo
] = strdup(*i
);
2107 STRV_FOREACH(i
, todo
) {
2108 _cleanup_free_
char *path
= NULL
;
2111 path
= path_make_absolute(*i
, config_path
);
2115 if (!dry_run
&& unlink(path
) < 0) {
2116 if (errno
!= ENOENT
) {
2119 unit_file_changes_add(changes
, n_changes
, -errno
, path
, NULL
);
2125 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
2127 rp
= skip_root(&paths
, path
);
2128 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: path
);
2133 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, dry_run
, changes
, n_changes
);
2141 UnitFileScope scope
,
2142 UnitFileFlags flags
,
2143 const char *root_dir
,
2145 UnitFileChange
**changes
,
2146 unsigned *n_changes
) {
2148 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2149 _cleanup_strv_free_
char **todo
= NULL
;
2150 size_t n_todo
= 0, n_allocated
= 0;
2151 const char *config_path
;
2156 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2158 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2162 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2166 STRV_FOREACH(i
, files
) {
2167 _cleanup_free_
char *full
= NULL
;
2171 if (!path_is_absolute(*i
))
2175 if (!unit_name_is_valid(fn
, UNIT_NAME_ANY
))
2178 full
= prefix_root(paths
.root_dir
, *i
);
2182 if (lstat(full
, &st
) < 0)
2184 r
= stat_verify_regular(&st
);
2188 q
= in_search_path(&paths
, *i
);
2194 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2197 todo
[n_todo
] = strdup(*i
);
2207 STRV_FOREACH(i
, todo
) {
2208 _cleanup_free_
char *new_path
= NULL
;
2210 new_path
= path_make_absolute(basename(*i
), config_path
);
2214 q
= create_symlink(&paths
, *i
, new_path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2215 if (q
< 0 && r
>= 0)
2222 static int path_shall_revert(const LookupPaths
*paths
, const char *path
) {
2228 /* Checks whether the path is one where the drop-in directories shall be removed. */
2230 r
= path_is_config(paths
, path
, true);
2234 r
= path_is_control(paths
, path
);
2238 return path_is_transient(paths
, path
);
2241 int unit_file_revert(
2242 UnitFileScope scope
,
2243 const char *root_dir
,
2245 UnitFileChange
**changes
,
2246 unsigned *n_changes
) {
2248 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2249 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2250 _cleanup_strv_free_
char **todo
= NULL
;
2251 size_t n_todo
= 0, n_allocated
= 0;
2255 /* Puts a unit file back into vendor state. This means:
2257 * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and
2258 * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated").
2260 * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in
2261 * "config", but not in "transient" or "control" or even "generated").
2263 * We remove all that in both the runtime and the persistent directories, if that applies.
2266 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2270 STRV_FOREACH(i
, files
) {
2271 bool has_vendor
= false;
2274 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2277 STRV_FOREACH(p
, paths
.search_path
) {
2278 _cleanup_free_
char *path
= NULL
, *dropin
= NULL
;
2281 path
= path_make_absolute(*i
, *p
);
2285 r
= lstat(path
, &st
);
2287 if (errno
!= ENOENT
)
2289 } else if (S_ISREG(st
.st_mode
)) {
2290 /* Check if there's a vendor version */
2291 r
= path_is_vendor(&paths
, path
);
2298 dropin
= strappend(path
, ".d");
2302 r
= lstat(dropin
, &st
);
2304 if (errno
!= ENOENT
)
2306 } else if (S_ISDIR(st
.st_mode
)) {
2307 /* Remove the drop-ins */
2308 r
= path_shall_revert(&paths
, dropin
);
2312 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2315 todo
[n_todo
++] = TAKE_PTR(dropin
);
2323 /* OK, there's a vendor version, hence drop all configuration versions */
2324 STRV_FOREACH(p
, paths
.search_path
) {
2325 _cleanup_free_
char *path
= NULL
;
2328 path
= path_make_absolute(*i
, *p
);
2332 r
= lstat(path
, &st
);
2334 if (errno
!= ENOENT
)
2336 } else if (S_ISREG(st
.st_mode
) || S_ISLNK(st
.st_mode
)) {
2337 r
= path_is_config(&paths
, path
, true);
2341 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2344 todo
[n_todo
++] = TAKE_PTR(path
);
2353 STRV_FOREACH(i
, todo
) {
2354 _cleanup_strv_free_
char **fs
= NULL
;
2358 (void) get_files_in_directory(*i
, &fs
);
2360 q
= rm_rf(*i
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
2361 if (q
< 0 && q
!= -ENOENT
&& r
>= 0) {
2366 STRV_FOREACH(j
, fs
) {
2367 _cleanup_free_
char *t
= NULL
;
2369 t
= strjoin(*i
, "/", *j
);
2373 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, t
, NULL
);
2376 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, *i
, NULL
);
2378 rp
= skip_root(&paths
, *i
);
2379 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: *i
);
2384 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.runtime_config
, &paths
, false, changes
, n_changes
);
2388 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.persistent_config
, &paths
, false, changes
, n_changes
);
2395 int unit_file_add_dependency(
2396 UnitFileScope scope
,
2397 UnitFileFlags flags
,
2398 const char *root_dir
,
2402 UnitFileChange
**changes
,
2403 unsigned *n_changes
) {
2405 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2406 _cleanup_(install_context_done
) InstallContext c
= {};
2407 UnitFileInstallInfo
*i
, *target_info
;
2408 const char *config_path
;
2413 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2416 if (!IN_SET(dep
, UNIT_WANTS
, UNIT_REQUIRES
))
2419 if (!unit_name_is_valid(target
, UNIT_NAME_ANY
))
2422 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2426 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2430 r
= install_info_discover(scope
, &c
, &paths
, target
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2431 &target_info
, changes
, n_changes
);
2434 r
= install_info_may_process(target_info
, &paths
, changes
, n_changes
);
2438 assert(target_info
->type
== UNIT_FILE_TYPE_REGULAR
);
2440 STRV_FOREACH(f
, files
) {
2443 r
= install_info_discover(scope
, &c
, &paths
, *f
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2444 &i
, changes
, n_changes
);
2447 r
= install_info_may_process(i
, &paths
, changes
, n_changes
);
2451 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2453 /* We didn't actually load anything from the unit
2454 * file, but instead just add in our new symlink to
2457 if (dep
== UNIT_WANTS
)
2460 l
= &i
->required_by
;
2463 *l
= strv_new(target_info
->name
, NULL
);
2468 return install_context_apply(scope
, &c
, &paths
, config_path
, !!(flags
& UNIT_FILE_FORCE
), SEARCH_FOLLOW_CONFIG_SYMLINKS
, changes
, n_changes
);
2471 int unit_file_enable(
2472 UnitFileScope scope
,
2473 UnitFileFlags flags
,
2474 const char *root_dir
,
2476 UnitFileChange
**changes
,
2477 unsigned *n_changes
) {
2479 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2480 _cleanup_(install_context_done
) InstallContext c
= {};
2481 const char *config_path
;
2482 UnitFileInstallInfo
*i
;
2487 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2489 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2493 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2497 STRV_FOREACH(f
, files
) {
2498 r
= install_info_discover(scope
, &c
, &paths
, *f
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2499 &i
, changes
, n_changes
);
2502 r
= install_info_may_process(i
, &paths
, changes
, n_changes
);
2506 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2509 /* This will return the number of symlink rules that were
2510 supposed to be created, not the ones actually created. This
2511 is useful to determine whether the passed files had any
2512 installation data at all. */
2514 return install_context_apply(scope
, &c
, &paths
, config_path
, !!(flags
& UNIT_FILE_FORCE
), SEARCH_LOAD
, changes
, n_changes
);
2517 int unit_file_disable(
2518 UnitFileScope scope
,
2519 UnitFileFlags flags
,
2520 const char *root_dir
,
2522 UnitFileChange
**changes
,
2523 unsigned *n_changes
) {
2525 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2526 _cleanup_(install_context_done
) InstallContext c
= {};
2527 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2528 const char *config_path
;
2533 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2535 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2539 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
2543 STRV_FOREACH(i
, files
) {
2544 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2547 r
= install_info_add(&c
, *i
, NULL
, false, NULL
);
2552 r
= install_context_mark_for_removal(scope
, &c
, &paths
, &remove_symlinks_to
, config_path
, changes
, n_changes
);
2556 return remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, !!(flags
& UNIT_FILE_DRY_RUN
), changes
, n_changes
);
2559 int unit_file_reenable(
2560 UnitFileScope scope
,
2561 UnitFileFlags flags
,
2562 const char *root_dir
,
2564 UnitFileChange
**changes
,
2565 unsigned *n_changes
) {
2571 /* First, we invoke the disable command with only the basename... */
2572 l
= strv_length(files
);
2573 n
= newa(char*, l
+1);
2574 for (i
= 0; i
< l
; i
++)
2575 n
[i
] = basename(files
[i
]);
2578 r
= unit_file_disable(scope
, flags
, root_dir
, n
, changes
, n_changes
);
2582 /* But the enable command with the full name */
2583 return unit_file_enable(scope
, flags
, root_dir
, files
, changes
, n_changes
);
2586 int unit_file_set_default(
2587 UnitFileScope scope
,
2588 UnitFileFlags flags
,
2589 const char *root_dir
,
2591 UnitFileChange
**changes
,
2592 unsigned *n_changes
) {
2594 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2595 _cleanup_(install_context_done
) InstallContext c
= {};
2596 UnitFileInstallInfo
*i
;
2597 const char *new_path
;
2601 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2604 if (unit_name_to_type(name
) != UNIT_TARGET
) /* this also validates the name */
2606 if (streq(name
, SPECIAL_DEFAULT_TARGET
))
2609 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2613 r
= install_info_discover(scope
, &c
, &paths
, name
, 0, &i
, changes
, n_changes
);
2616 r
= install_info_may_process(i
, &paths
, changes
, n_changes
);
2620 new_path
= strjoina(paths
.persistent_config
, "/" SPECIAL_DEFAULT_TARGET
);
2621 return create_symlink(&paths
, i
->path
, new_path
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
2624 int unit_file_get_default(
2625 UnitFileScope scope
,
2626 const char *root_dir
,
2629 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2630 _cleanup_(install_context_done
) InstallContext c
= {};
2631 UnitFileInstallInfo
*i
;
2636 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2639 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2643 r
= install_info_discover(scope
, &c
, &paths
, SPECIAL_DEFAULT_TARGET
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2647 r
= install_info_may_process(i
, &paths
, NULL
, 0);
2651 n
= strdup(i
->name
);
2659 static int unit_file_lookup_state(
2660 UnitFileScope scope
,
2661 const LookupPaths
*paths
,
2663 UnitFileState
*ret
) {
2665 _cleanup_(install_context_done
) InstallContext c
= {};
2666 UnitFileInstallInfo
*i
;
2667 UnitFileState state
;
2673 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2676 r
= install_info_discover(scope
, &c
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2681 /* Shortcut things, if the caller just wants to know if this unit exists. */
2687 case UNIT_FILE_TYPE_MASKED
:
2688 r
= path_is_runtime(paths
, i
->path
, true);
2692 state
= r
> 0 ? UNIT_FILE_MASKED_RUNTIME
: UNIT_FILE_MASKED
;
2695 case UNIT_FILE_TYPE_REGULAR
:
2696 r
= path_is_generator(paths
, i
->path
);
2700 state
= UNIT_FILE_GENERATED
;
2704 r
= path_is_transient(paths
, i
->path
);
2708 state
= UNIT_FILE_TRANSIENT
;
2712 /* Check if any of the Alias= symlinks have been created.
2713 * We ignore other aliases, and only check those that would
2714 * be created by systemctl enable for this unit. */
2715 r
= find_symlinks_in_scope(scope
, paths
, i
, true, &state
);
2721 /* Check if the file is known under other names. If it is,
2722 * it might be in use. Report that as UNIT_FILE_INDIRECT. */
2723 r
= find_symlinks_in_scope(scope
, paths
, i
, false, &state
);
2727 state
= UNIT_FILE_INDIRECT
;
2729 if (unit_file_install_info_has_rules(i
))
2730 state
= UNIT_FILE_DISABLED
;
2731 else if (unit_file_install_info_has_also(i
))
2732 state
= UNIT_FILE_INDIRECT
;
2734 state
= UNIT_FILE_STATIC
;
2740 assert_not_reached("Unexpect unit file type.");
2747 int unit_file_get_state(
2748 UnitFileScope scope
,
2749 const char *root_dir
,
2751 UnitFileState
*ret
) {
2753 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2757 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2760 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2764 return unit_file_lookup_state(scope
, &paths
, name
, ret
);
2767 int unit_file_exists(UnitFileScope scope
, const LookupPaths
*paths
, const char *name
) {
2768 _cleanup_(install_context_done
) InstallContext c
= {};
2774 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2777 r
= install_info_discover(scope
, &c
, paths
, name
, 0, NULL
, NULL
, NULL
);
2786 static int read_presets(UnitFileScope scope
, const char *root_dir
, Presets
*presets
) {
2787 _cleanup_(presets_freep
) Presets ps
= {};
2788 size_t n_allocated
= 0;
2789 _cleanup_strv_free_
char **files
= NULL
;
2794 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2797 if (scope
== UNIT_FILE_SYSTEM
)
2798 r
= conf_files_list(&files
, ".preset", root_dir
, 0,
2799 "/etc/systemd/system-preset",
2800 "/run/systemd/system-preset",
2801 "/usr/local/lib/systemd/system-preset",
2802 "/usr/lib/systemd/system-preset",
2804 "/lib/systemd/system-preset",
2807 else if (scope
== UNIT_FILE_GLOBAL
)
2808 r
= conf_files_list(&files
, ".preset", root_dir
, 0,
2809 "/etc/systemd/user-preset",
2810 "/run/systemd/user-preset",
2811 "/usr/local/lib/systemd/user-preset",
2812 "/usr/lib/systemd/user-preset",
2815 *presets
= (Presets
){};
2823 STRV_FOREACH(p
, files
) {
2824 _cleanup_fclose_
FILE *f
;
2825 char line
[LINE_MAX
];
2828 f
= fopen(*p
, "re");
2830 if (errno
== ENOENT
)
2836 FOREACH_LINE(line
, f
, return -errno
) {
2837 PresetRule rule
= {};
2838 const char *parameter
;
2846 if (strchr(COMMENTS
, *l
))
2849 parameter
= first_word(l
, "enable");
2853 pattern
= strdup(parameter
);
2857 rule
= (PresetRule
) {
2859 .action
= PRESET_ENABLE
,
2863 parameter
= first_word(l
, "disable");
2867 pattern
= strdup(parameter
);
2871 rule
= (PresetRule
) {
2873 .action
= PRESET_DISABLE
,
2878 if (!GREEDY_REALLOC(ps
.rules
, n_allocated
, ps
.n_rules
+ 1))
2881 ps
.rules
[ps
.n_rules
++] = rule
;
2885 log_syntax(NULL
, LOG_WARNING
, *p
, n
, 0, "Couldn't parse line '%s'. Ignoring.", line
);
2895 static int query_presets(const char *name
, const Presets presets
) {
2896 PresetAction action
= PRESET_UNKNOWN
;
2899 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2902 for (i
= 0; i
< presets
.n_rules
; i
++)
2903 if (fnmatch(presets
.rules
[i
].pattern
, name
, FNM_NOESCAPE
) == 0) {
2904 action
= presets
.rules
[i
].action
;
2909 case PRESET_UNKNOWN
:
2910 log_debug("Preset files don't specify rule for %s. Enabling.", name
);
2913 log_debug("Preset files say enable %s.", name
);
2915 case PRESET_DISABLE
:
2916 log_debug("Preset files say disable %s.", name
);
2919 assert_not_reached("invalid preset action");
2923 int unit_file_query_preset(UnitFileScope scope
, const char *root_dir
, const char *name
) {
2924 _cleanup_(presets_freep
) Presets presets
= {};
2927 r
= read_presets(scope
, root_dir
, &presets
);
2931 return query_presets(name
, presets
);
2934 static int execute_preset(
2935 UnitFileScope scope
,
2936 InstallContext
*plus
,
2937 InstallContext
*minus
,
2938 const LookupPaths
*paths
,
2939 const char *config_path
,
2941 UnitFilePresetMode mode
,
2943 UnitFileChange
**changes
,
2944 unsigned *n_changes
) {
2951 assert(config_path
);
2953 if (mode
!= UNIT_FILE_PRESET_ENABLE_ONLY
) {
2954 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2956 r
= install_context_mark_for_removal(scope
, minus
, paths
, &remove_symlinks_to
, config_path
, changes
, n_changes
);
2960 r
= remove_marked_symlinks(remove_symlinks_to
, config_path
, paths
, false, changes
, n_changes
);
2964 if (mode
!= UNIT_FILE_PRESET_DISABLE_ONLY
) {
2967 /* Returns number of symlinks that where supposed to be installed. */
2968 q
= install_context_apply(scope
, plus
, paths
, config_path
, force
, SEARCH_LOAD
, changes
, n_changes
);
2980 static int preset_prepare_one(
2981 UnitFileScope scope
,
2982 InstallContext
*plus
,
2983 InstallContext
*minus
,
2987 UnitFileChange
**changes
,
2988 unsigned *n_changes
) {
2990 _cleanup_(install_context_done
) InstallContext tmp
= {};
2991 UnitFileInstallInfo
*i
;
2994 if (install_info_find(plus
, name
) || install_info_find(minus
, name
))
2997 r
= install_info_discover(scope
, &tmp
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2998 &i
, changes
, n_changes
);
3001 if (!streq(name
, i
->name
)) {
3002 log_debug("Skipping %s because it is an alias for %s.", name
, i
->name
);
3006 r
= query_presets(name
, presets
);
3011 r
= install_info_discover(scope
, plus
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3012 &i
, changes
, n_changes
);
3016 r
= install_info_may_process(i
, paths
, changes
, n_changes
);
3020 r
= install_info_discover(scope
, minus
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
3021 &i
, changes
, n_changes
);
3026 int unit_file_preset(
3027 UnitFileScope scope
,
3028 UnitFileFlags flags
,
3029 const char *root_dir
,
3031 UnitFilePresetMode mode
,
3032 UnitFileChange
**changes
,
3033 unsigned *n_changes
) {
3035 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
3036 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
3037 _cleanup_(presets_freep
) Presets presets
= {};
3038 const char *config_path
;
3043 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3044 assert(mode
< _UNIT_FILE_PRESET_MAX
);
3046 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3050 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
3054 r
= read_presets(scope
, root_dir
, &presets
);
3058 STRV_FOREACH(i
, files
) {
3059 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, *i
, presets
, changes
, n_changes
);
3064 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, files
, mode
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
3067 int unit_file_preset_all(
3068 UnitFileScope scope
,
3069 UnitFileFlags flags
,
3070 const char *root_dir
,
3071 UnitFilePresetMode mode
,
3072 UnitFileChange
**changes
,
3073 unsigned *n_changes
) {
3075 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
3076 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
3077 _cleanup_(presets_freep
) Presets presets
= {};
3078 const char *config_path
= NULL
;
3083 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3084 assert(mode
< _UNIT_FILE_PRESET_MAX
);
3086 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3090 config_path
= (flags
& UNIT_FILE_RUNTIME
) ? paths
.runtime_config
: paths
.persistent_config
;
3094 r
= read_presets(scope
, root_dir
, &presets
);
3098 STRV_FOREACH(i
, paths
.search_path
) {
3099 _cleanup_closedir_
DIR *d
= NULL
;
3104 if (errno
== ENOENT
)
3110 FOREACH_DIRENT(de
, d
, return -errno
) {
3112 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
3115 dirent_ensure_type(d
, de
);
3117 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
3120 /* we don't pass changes[] in, because we want to handle errors on our own */
3121 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, de
->d_name
, presets
, NULL
, 0);
3123 r
= unit_file_changes_add(changes
, n_changes
,
3124 UNIT_FILE_IS_MASKED
, de
->d_name
, NULL
);
3125 else if (r
== -ENOLINK
)
3126 r
= unit_file_changes_add(changes
, n_changes
,
3127 UNIT_FILE_IS_DANGLING
, de
->d_name
, NULL
);
3128 else if (r
== -EADDRNOTAVAIL
) /* Ignore generated/transient units when applying preset */
3135 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, NULL
, mode
, !!(flags
& UNIT_FILE_FORCE
), changes
, n_changes
);
3138 static void unit_file_list_free_one(UnitFileList
*f
) {
3146 Hashmap
* unit_file_list_free(Hashmap
*h
) {
3147 return hashmap_free_with_destructor(h
, unit_file_list_free_one
);
3150 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList
*, unit_file_list_free_one
);
3152 int unit_file_get_list(
3153 UnitFileScope scope
,
3154 const char *root_dir
,
3159 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
3164 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
3167 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
3171 STRV_FOREACH(i
, paths
.search_path
) {
3172 _cleanup_closedir_
DIR *d
= NULL
;
3177 if (errno
== ENOENT
)
3179 if (IN_SET(errno
, ENOTDIR
, EACCES
)) {
3180 log_debug_errno(errno
, "Failed to open \"%s\": %m", *i
);
3187 FOREACH_DIRENT(de
, d
, return -errno
) {
3188 _cleanup_(unit_file_list_free_onep
) UnitFileList
*f
= NULL
;
3190 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
3193 if (!strv_fnmatch_or_empty(patterns
, de
->d_name
, FNM_NOESCAPE
))
3196 if (hashmap_get(h
, de
->d_name
))
3199 dirent_ensure_type(d
, de
);
3201 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
3204 f
= new0(UnitFileList
, 1);
3208 f
->path
= path_make_absolute(de
->d_name
, *i
);
3212 r
= unit_file_lookup_state(scope
, &paths
, de
->d_name
, &f
->state
);
3214 f
->state
= UNIT_FILE_BAD
;
3216 if (!strv_isempty(states
) &&
3217 !strv_contains(states
, unit_file_state_to_string(f
->state
)))
3220 r
= hashmap_put(h
, basename(f
->path
), f
);
3224 f
= NULL
; /* prevent cleanup */
3231 static const char* const unit_file_state_table
[_UNIT_FILE_STATE_MAX
] = {
3232 [UNIT_FILE_ENABLED
] = "enabled",
3233 [UNIT_FILE_ENABLED_RUNTIME
] = "enabled-runtime",
3234 [UNIT_FILE_LINKED
] = "linked",
3235 [UNIT_FILE_LINKED_RUNTIME
] = "linked-runtime",
3236 [UNIT_FILE_MASKED
] = "masked",
3237 [UNIT_FILE_MASKED_RUNTIME
] = "masked-runtime",
3238 [UNIT_FILE_STATIC
] = "static",
3239 [UNIT_FILE_DISABLED
] = "disabled",
3240 [UNIT_FILE_INDIRECT
] = "indirect",
3241 [UNIT_FILE_GENERATED
] = "generated",
3242 [UNIT_FILE_TRANSIENT
] = "transient",
3243 [UNIT_FILE_BAD
] = "bad",
3246 DEFINE_STRING_TABLE_LOOKUP(unit_file_state
, UnitFileState
);
3248 static const char* const unit_file_change_type_table
[_UNIT_FILE_CHANGE_TYPE_MAX
] = {
3249 [UNIT_FILE_SYMLINK
] = "symlink",
3250 [UNIT_FILE_UNLINK
] = "unlink",
3251 [UNIT_FILE_IS_MASKED
] = "masked",
3252 [UNIT_FILE_IS_DANGLING
] = "dangling",
3255 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type
, UnitFileChangeType
);
3257 static const char* const unit_file_preset_mode_table
[_UNIT_FILE_PRESET_MAX
] = {
3258 [UNIT_FILE_PRESET_FULL
] = "full",
3259 [UNIT_FILE_PRESET_ENABLE_ONLY
] = "enable-only",
3260 [UNIT_FILE_PRESET_DISABLE_ONLY
] = "disable-only",
3263 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode
, UnitFilePresetMode
);