2 This file is part of systemd.
4 Copyright 2011 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty <of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
32 #include "alloc-util.h"
33 #include "conf-files.h"
34 #include "conf-parser.h"
35 #include "dirent-util.h"
36 #include "extract-word.h"
41 #include "install-printf.h"
46 #include "path-lookup.h"
47 #include "path-util.h"
51 #include "stat-util.h"
52 #include "string-table.h"
53 #include "string-util.h"
55 #include "unit-name.h"
57 #define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
59 typedef enum SearchFlags
{
61 SEARCH_FOLLOW_CONFIG_SYMLINKS
= 2,
65 OrderedHashmap
*will_process
;
66 OrderedHashmap
*have_processed
;
85 static inline void presets_freep(Presets
*p
) {
91 for (i
= 0; i
< p
->n_rules
; i
++)
92 free(p
->rules
[i
].pattern
);
98 static int unit_file_lookup_state(UnitFileScope scope
, const LookupPaths
*paths
, const char *name
, UnitFileState
*ret
);
100 bool unit_type_may_alias(UnitType type
) {
110 bool unit_type_may_template(UnitType type
) {
119 static const char *unit_file_type_table
[_UNIT_FILE_TYPE_MAX
] = {
120 [UNIT_FILE_TYPE_REGULAR
] = "regular",
121 [UNIT_FILE_TYPE_SYMLINK
] = "symlink",
122 [UNIT_FILE_TYPE_MASKED
] = "masked",
125 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(unit_file_type
, UnitFileType
);
127 static int in_search_path(const LookupPaths
*p
, const char *path
) {
128 _cleanup_free_
char *parent
= NULL
;
133 parent
= dirname_malloc(path
);
137 STRV_FOREACH(i
, p
->search_path
)
138 if (path_equal(parent
, *i
))
144 static const char* skip_root(const LookupPaths
*p
, const char *path
) {
153 e
= path_startswith(path
, p
->root_dir
);
157 /* Make sure the returned path starts with a slash */
159 if (e
== path
|| e
[-1] != '/')
168 static int path_is_generator(const LookupPaths
*p
, const char *path
) {
169 _cleanup_free_
char *parent
= NULL
;
174 parent
= dirname_malloc(path
);
178 return path_equal_ptr(parent
, p
->generator
) ||
179 path_equal_ptr(parent
, p
->generator_early
) ||
180 path_equal_ptr(parent
, p
->generator_late
);
183 static int path_is_transient(const LookupPaths
*p
, const char *path
) {
184 _cleanup_free_
char *parent
= NULL
;
189 parent
= dirname_malloc(path
);
193 return path_equal_ptr(parent
, p
->transient
);
196 static int path_is_control(const LookupPaths
*p
, const char *path
) {
197 _cleanup_free_
char *parent
= NULL
;
202 parent
= dirname_malloc(path
);
206 return path_equal_ptr(parent
, p
->persistent_control
) ||
207 path_equal_ptr(parent
, p
->runtime_control
);
210 static int path_is_config(const LookupPaths
*p
, const char *path
) {
211 _cleanup_free_
char *parent
= NULL
;
216 /* Note that we do *not* have generic checks for /etc or /run in place, since with them we couldn't discern
217 * configuration from transient or generated units */
219 parent
= dirname_malloc(path
);
223 return path_equal_ptr(parent
, p
->persistent_config
) ||
224 path_equal_ptr(parent
, p
->runtime_config
);
227 static int path_is_runtime(const LookupPaths
*p
, const char *path
) {
228 _cleanup_free_
char *parent
= NULL
;
234 /* Everything in /run is considered runtime. On top of that we also add explicit checks for the various runtime
235 * directories, as safety net. */
237 rpath
= skip_root(p
, path
);
238 if (rpath
&& path_startswith(rpath
, "/run"))
241 parent
= dirname_malloc(path
);
245 return path_equal_ptr(parent
, p
->runtime_config
) ||
246 path_equal_ptr(parent
, p
->generator
) ||
247 path_equal_ptr(parent
, p
->generator_early
) ||
248 path_equal_ptr(parent
, p
->generator_late
) ||
249 path_equal_ptr(parent
, p
->transient
) ||
250 path_equal_ptr(parent
, p
->runtime_control
);
253 static int path_is_vendor(const LookupPaths
*p
, const char *path
) {
259 rpath
= skip_root(p
, path
);
263 if (path_startswith(rpath
, "/usr"))
266 #ifdef HAVE_SPLIT_USR
267 if (path_startswith(rpath
, "/lib"))
271 return path_equal(rpath
, SYSTEM_DATA_UNIT_PATH
);
274 int unit_file_changes_add(
275 UnitFileChange
**changes
,
277 UnitFileChangeType type
,
279 const char *source
) {
281 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
285 assert(!changes
== !n_changes
);
290 c
= realloc(*changes
, (*n_changes
+ 1) * sizeof(UnitFileChange
));
299 if (!p
|| (source
&& !s
))
302 path_kill_slashes(p
);
304 path_kill_slashes(s
);
306 c
[*n_changes
] = (UnitFileChange
) { type
, p
, s
};
312 void unit_file_changes_free(UnitFileChange
*changes
, unsigned n_changes
) {
315 assert(changes
|| n_changes
== 0);
317 for (i
= 0; i
< n_changes
; i
++) {
318 free(changes
[i
].path
);
319 free(changes
[i
].source
);
325 void unit_file_dump_changes(int r
, const char *verb
, const UnitFileChange
*changes
, unsigned n_changes
, bool quiet
) {
329 assert(changes
|| n_changes
== 0);
330 /* If verb is not specified, errors are not allowed! */
331 assert(verb
|| r
>= 0);
333 for (i
= 0; i
< n_changes
; i
++) {
334 assert(verb
|| changes
[i
].type
>= 0);
336 switch(changes
[i
].type
) {
337 case UNIT_FILE_SYMLINK
:
339 log_info("Created symlink %s, pointing to %s.", changes
[i
].path
, changes
[i
].source
);
341 case UNIT_FILE_UNLINK
:
343 log_info("Removed %s.", changes
[i
].path
);
345 case UNIT_FILE_IS_MASKED
:
347 log_info("Unit %s is masked, ignoring.", changes
[i
].path
);
350 if (changes
[i
].source
)
351 log_error_errno(changes
[i
].type
,
352 "Failed to %s unit, file %s already exists and is a symlink to %s.",
353 verb
, changes
[i
].path
, changes
[i
].source
);
355 log_error_errno(changes
[i
].type
,
356 "Failed to %s unit, file %s already exists.",
357 verb
, changes
[i
].path
);
361 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s is masked.",
362 verb
, changes
[i
].path
);
366 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s is transient or generated.",
367 verb
, changes
[i
].path
);
371 log_error_errno(changes
[i
].type
, "Failed to %s unit, refusing to operate on linked unit file %s",
372 verb
, changes
[i
].path
);
376 assert(changes
[i
].type
< 0);
377 log_error_errno(changes
[i
].type
, "Failed to %s unit, file %s: %m.",
378 verb
, changes
[i
].path
);
383 if (r
< 0 && !logged
)
384 log_error_errno(r
, "Failed to %s: %m.", verb
);
389 static int create_symlink(
390 const char *old_path
,
391 const char *new_path
,
393 UnitFileChange
**changes
,
394 unsigned *n_changes
) {
396 _cleanup_free_
char *dest
= NULL
;
402 /* Actually create a symlink, and remember that we did. Is
403 * smart enough to check if there's already a valid symlink in
406 mkdir_parents_label(new_path
, 0755);
408 if (symlink(old_path
, new_path
) >= 0) {
409 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
413 if (errno
!= EEXIST
) {
414 unit_file_changes_add(changes
, n_changes
, -errno
, new_path
, NULL
);
418 r
= readlink_malloc(new_path
, &dest
);
420 /* translate EINVAL (non-symlink exists) to EEXIST */
424 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
428 if (path_equal(dest
, old_path
))
432 unit_file_changes_add(changes
, n_changes
, -EEXIST
, new_path
, dest
);
436 r
= symlink_atomic(old_path
, new_path
);
438 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
442 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, new_path
, NULL
);
443 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
448 static int mark_symlink_for_removal(
449 Set
**remove_symlinks_to
,
457 r
= set_ensure_allocated(remove_symlinks_to
, &string_hash_ops
);
465 path_kill_slashes(n
);
467 r
= set_consume(*remove_symlinks_to
, n
);
476 static int remove_marked_symlinks_fd(
477 Set
*remove_symlinks_to
,
480 const char *config_path
,
481 const LookupPaths
*lp
,
483 UnitFileChange
**changes
,
484 unsigned *n_changes
) {
486 _cleanup_closedir_
DIR *d
= NULL
;
490 assert(remove_symlinks_to
);
505 FOREACH_DIRENT(de
, d
, return -errno
) {
507 dirent_ensure_type(d
, de
);
509 if (de
->d_type
== DT_DIR
) {
510 _cleanup_free_
char *p
= NULL
;
513 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
523 p
= path_make_absolute(de
->d_name
, path
);
529 /* This will close nfd, regardless whether it succeeds or not */
530 q
= remove_marked_symlinks_fd(remove_symlinks_to
, nfd
, p
, config_path
, lp
, restart
, changes
, n_changes
);
534 } else if (de
->d_type
== DT_LNK
) {
535 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
540 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
543 p
= path_make_absolute(de
->d_name
, path
);
546 path_kill_slashes(p
);
548 q
= readlink_malloc(p
, &dest
);
557 /* We remove all links pointing to a file or path that is marked, as well as all files sharing
558 * the same name as a file that is marked. */
560 found
= set_contains(remove_symlinks_to
, dest
) ||
561 set_contains(remove_symlinks_to
, basename(dest
)) ||
562 set_contains(remove_symlinks_to
, de
->d_name
);
567 if (unlinkat(fd
, de
->d_name
, 0) < 0 && errno
!= ENOENT
) {
570 unit_file_changes_add(changes
, n_changes
, -errno
, p
, NULL
);
574 (void) rmdir_parents(p
, config_path
);
576 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, p
, NULL
);
578 /* Now, remember the full path (but with the root prefix removed) of
579 * the symlink we just removed, and remove any symlinks to it, too. */
581 rp
= skip_root(lp
, p
);
582 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: p
);
593 static int remove_marked_symlinks(
594 Set
*remove_symlinks_to
,
595 const char *config_path
,
596 const LookupPaths
*lp
,
597 UnitFileChange
**changes
,
598 unsigned *n_changes
) {
600 _cleanup_close_
int fd
= -1;
607 if (set_size(remove_symlinks_to
) <= 0)
610 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
618 cfd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
622 /* This takes possession of cfd and closes it */
623 q
= remove_marked_symlinks_fd(remove_symlinks_to
, cfd
, config_path
, config_path
, lp
, &restart
, changes
, n_changes
);
631 static int find_symlinks_fd(
632 const char *root_dir
,
636 const char *config_path
,
637 const LookupPaths
*lp
,
638 bool *same_name_link
) {
640 _cleanup_closedir_
DIR *d
= NULL
;
649 assert(same_name_link
);
657 FOREACH_DIRENT(de
, d
, return -errno
) {
659 dirent_ensure_type(d
, de
);
661 if (de
->d_type
== DT_DIR
) {
662 _cleanup_free_
char *p
= NULL
;
665 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
675 p
= path_make_absolute(de
->d_name
, path
);
681 /* This will close nfd, regardless whether it succeeds or not */
682 q
= find_symlinks_fd(root_dir
, name
, nfd
, p
, config_path
, lp
, same_name_link
);
688 } else if (de
->d_type
== DT_LNK
) {
689 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
690 bool found_path
, found_dest
, b
= false;
693 /* Acquire symlink name */
694 p
= path_make_absolute(de
->d_name
, path
);
698 /* Acquire symlink destination */
699 q
= readlink_malloc(p
, &dest
);
709 if (!path_is_absolute(dest
)) {
712 x
= prefix_root(root_dir
, dest
);
720 /* Check if the symlink itself matches what we
722 if (path_is_absolute(name
))
723 found_path
= path_equal(p
, name
);
725 found_path
= streq(de
->d_name
, name
);
727 /* Check if what the symlink points to
728 * matches what we are looking for */
729 if (path_is_absolute(name
))
730 found_dest
= path_equal(dest
, name
);
732 found_dest
= streq(basename(dest
), name
);
734 if (found_path
&& found_dest
) {
735 _cleanup_free_
char *t
= NULL
;
737 /* Filter out same name links in the main
739 t
= path_make_absolute(name
, config_path
);
743 b
= path_equal(t
, p
);
747 *same_name_link
= true;
748 else if (found_path
|| found_dest
)
756 static int find_symlinks(
757 const char *root_dir
,
759 const char *config_path
,
760 const LookupPaths
*lp
,
761 bool *same_name_link
) {
767 assert(same_name_link
);
769 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
776 /* This takes possession of fd and closes it */
777 return find_symlinks_fd(root_dir
, name
, fd
, config_path
, config_path
, lp
, same_name_link
);
780 static int find_symlinks_in_scope(
782 const LookupPaths
*paths
,
784 UnitFileState
*state
) {
786 bool same_name_link_runtime
= false, same_name_link
= false;
790 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
794 /* First look in the persistent config path */
795 r
= find_symlinks(paths
->root_dir
, name
, paths
->persistent_config
, paths
, &same_name_link
);
799 *state
= UNIT_FILE_ENABLED
;
803 /* Then look in runtime config path */
804 r
= find_symlinks(paths
->root_dir
, name
, paths
->runtime_config
, paths
, &same_name_link_runtime
);
808 *state
= UNIT_FILE_ENABLED_RUNTIME
;
812 /* Hmm, we didn't find it, but maybe we found the same name
814 if (same_name_link
) {
815 *state
= UNIT_FILE_LINKED
;
818 if (same_name_link_runtime
) {
819 *state
= UNIT_FILE_LINKED_RUNTIME
;
826 static void install_info_free(UnitFileInstallInfo
*i
) {
833 strv_free(i
->aliases
);
834 strv_free(i
->wanted_by
);
835 strv_free(i
->required_by
);
837 free(i
->default_instance
);
838 free(i
->symlink_target
);
842 static OrderedHashmap
* install_info_hashmap_free(OrderedHashmap
*m
) {
843 UnitFileInstallInfo
*i
;
848 while ((i
= ordered_hashmap_steal_first(m
)))
849 install_info_free(i
);
851 return ordered_hashmap_free(m
);
854 static void install_context_done(InstallContext
*c
) {
857 c
->will_process
= install_info_hashmap_free(c
->will_process
);
858 c
->have_processed
= install_info_hashmap_free(c
->have_processed
);
861 static UnitFileInstallInfo
*install_info_find(InstallContext
*c
, const char *name
) {
862 UnitFileInstallInfo
*i
;
864 i
= ordered_hashmap_get(c
->have_processed
, name
);
868 return ordered_hashmap_get(c
->will_process
, name
);
871 static int install_info_may_process(
872 UnitFileInstallInfo
*i
,
873 const LookupPaths
*paths
,
874 UnitFileChange
**changes
,
875 unsigned *n_changes
) {
879 /* Checks whether the loaded unit file is one we should process, or is masked, transient or generated and thus
880 * not subject to enable/disable operations. */
882 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
883 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, i
->path
, NULL
);
886 if (path_is_generator(paths
, i
->path
) ||
887 path_is_transient(paths
, i
->path
)) {
888 unit_file_changes_add(changes
, n_changes
, -EADDRNOTAVAIL
, i
->path
, NULL
);
889 return -EADDRNOTAVAIL
;
895 static int install_info_add(
899 UnitFileInstallInfo
**ret
) {
901 UnitFileInstallInfo
*i
= NULL
;
905 assert(name
|| path
);
908 name
= basename(path
);
910 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
913 i
= install_info_find(c
, name
);
920 r
= ordered_hashmap_ensure_allocated(&c
->will_process
, &string_hash_ops
);
924 i
= new0(UnitFileInstallInfo
, 1);
927 i
->type
= _UNIT_FILE_TYPE_INVALID
;
929 i
->name
= strdup(name
);
936 i
->path
= strdup(path
);
943 r
= ordered_hashmap_put(c
->will_process
, i
->name
, i
);
953 install_info_free(i
);
957 static int config_parse_alias(
959 const char *filename
,
962 unsigned section_line
,
976 name
= basename(filename
);
977 type
= unit_name_to_type(name
);
978 if (!unit_type_may_alias(type
))
979 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
980 "Aliases are not allowed for %s units, ignoring.",
981 unit_type_to_string(type
));
983 return config_parse_strv(unit
, filename
, line
, section
, section_line
,
984 lvalue
, ltype
, rvalue
, data
, userdata
);
987 static int config_parse_also(
989 const char *filename
,
992 unsigned section_line
,
999 UnitFileInstallInfo
*i
= userdata
;
1000 InstallContext
*c
= data
;
1008 _cleanup_free_
char *word
= NULL
;
1010 r
= extract_first_word(&rvalue
, &word
, NULL
, 0);
1016 r
= install_info_add(c
, word
, NULL
, NULL
);
1020 r
= strv_push(&i
->also
, word
);
1030 static int config_parse_default_instance(
1032 const char *filename
,
1034 const char *section
,
1035 unsigned section_line
,
1042 UnitFileInstallInfo
*i
= data
;
1051 name
= basename(filename
);
1052 if (unit_name_is_valid(name
, UNIT_NAME_INSTANCE
))
1053 /* When enabling an instance, we might be using a template unit file,
1054 * but we should ignore DefaultInstance silently. */
1056 if (!unit_name_is_valid(name
, UNIT_NAME_TEMPLATE
))
1057 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1058 "DefaultInstance only makes sense for template units, ignoring.");
1060 r
= install_full_printf(i
, rvalue
, &printed
);
1064 if (!unit_instance_is_valid(printed
)) {
1069 free(i
->default_instance
);
1070 i
->default_instance
= printed
;
1075 static int unit_file_load(
1077 UnitFileInstallInfo
*info
,
1079 SearchFlags flags
) {
1081 const ConfigTableItem items
[] = {
1082 { "Install", "Alias", config_parse_alias
, 0, &info
->aliases
},
1083 { "Install", "WantedBy", config_parse_strv
, 0, &info
->wanted_by
},
1084 { "Install", "RequiredBy", config_parse_strv
, 0, &info
->required_by
},
1085 { "Install", "DefaultInstance", config_parse_default_instance
, 0, info
},
1086 { "Install", "Also", config_parse_also
, 0, c
},
1092 _cleanup_fclose_
FILE *f
= NULL
;
1093 _cleanup_close_
int fd
= -1;
1101 name
= basename(path
);
1102 type
= unit_name_to_type(name
);
1103 if (unit_name_is_valid(name
, UNIT_NAME_TEMPLATE
|UNIT_NAME_INSTANCE
) &&
1104 !unit_type_may_template(type
))
1105 return log_error_errno(EINVAL
, "Unit type %s cannot be templated.", unit_type_to_string(type
));
1107 if (!(flags
& SEARCH_LOAD
)) {
1108 r
= lstat(path
, &st
);
1112 if (null_or_empty(&st
))
1113 info
->type
= UNIT_FILE_TYPE_MASKED
;
1114 else if (S_ISREG(st
.st_mode
))
1115 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1116 else if (S_ISLNK(st
.st_mode
))
1118 else if (S_ISDIR(st
.st_mode
))
1126 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
1129 if (fstat(fd
, &st
) < 0)
1131 if (null_or_empty(&st
)) {
1132 info
->type
= UNIT_FILE_TYPE_MASKED
;
1135 if (S_ISDIR(st
.st_mode
))
1137 if (!S_ISREG(st
.st_mode
))
1140 f
= fdopen(fd
, "re");
1145 r
= config_parse(NULL
, path
, f
,
1147 config_item_table_lookup
, items
,
1148 true, true, false, info
);
1152 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1155 (int) strv_length(info
->aliases
) +
1156 (int) strv_length(info
->wanted_by
) +
1157 (int) strv_length(info
->required_by
);
1160 static int unit_file_load_or_readlink(
1162 UnitFileInstallInfo
*info
,
1164 const char *root_dir
,
1165 SearchFlags flags
) {
1167 _cleanup_free_
char *target
= NULL
;
1170 r
= unit_file_load(c
, info
, path
, flags
);
1174 /* This is a symlink, let's read it. */
1176 r
= readlink_malloc(path
, &target
);
1180 if (path_equal(target
, "/dev/null"))
1181 info
->type
= UNIT_FILE_TYPE_MASKED
;
1186 bn
= basename(target
);
1188 if (unit_name_is_valid(info
->name
, UNIT_NAME_PLAIN
)) {
1190 if (!unit_name_is_valid(bn
, UNIT_NAME_PLAIN
))
1193 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1195 if (!unit_name_is_valid(bn
, UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
))
1198 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
)) {
1200 if (!unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
))
1205 /* Enforce that the symlink destination does not
1206 * change the unit file type. */
1208 a
= unit_name_to_type(info
->name
);
1209 b
= unit_name_to_type(bn
);
1210 if (a
< 0 || b
< 0 || a
!= b
)
1213 if (path_is_absolute(target
))
1214 /* This is an absolute path, prefix the root so that we always deal with fully qualified paths */
1215 info
->symlink_target
= prefix_root(root_dir
, target
);
1217 /* This is a relative path, take it relative to the dir the symlink is located in. */
1218 info
->symlink_target
= file_in_same_dir(path
, target
);
1219 if (!info
->symlink_target
)
1222 info
->type
= UNIT_FILE_TYPE_SYMLINK
;
1228 static int unit_file_search(
1230 UnitFileInstallInfo
*info
,
1231 const LookupPaths
*paths
,
1232 SearchFlags flags
) {
1234 _cleanup_free_
char *template = NULL
;
1242 /* Was this unit already loaded? */
1243 if (info
->type
!= _UNIT_FILE_TYPE_INVALID
)
1247 return unit_file_load_or_readlink(c
, info
, info
->path
, paths
->root_dir
, flags
);
1251 STRV_FOREACH(p
, paths
->search_path
) {
1252 _cleanup_free_
char *path
= NULL
;
1254 path
= strjoin(*p
, "/", info
->name
, NULL
);
1258 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1263 } else if (r
!= -ENOENT
)
1267 if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1268 /* Unit file doesn't exist, however instance
1269 * enablement was requested. We will check if it is
1270 * possible to load template unit file. */
1272 r
= unit_name_template(info
->name
, &template);
1276 STRV_FOREACH(p
, paths
->search_path
) {
1277 _cleanup_free_
char *path
= NULL
;
1279 path
= strjoin(*p
, "/", template, NULL
);
1283 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1288 } else if (r
!= -ENOENT
)
1293 log_debug("Cannot find unit %s%s%s.", info
->name
, template ? " or " : "", strempty(template));
1297 static int install_info_follow(
1299 UnitFileInstallInfo
*i
,
1300 const char *root_dir
,
1301 SearchFlags flags
) {
1306 if (i
->type
!= UNIT_FILE_TYPE_SYMLINK
)
1308 if (!i
->symlink_target
)
1311 /* If the basename doesn't match, the caller should add a
1312 * complete new entry for this. */
1314 if (!streq(basename(i
->symlink_target
), i
->name
))
1318 i
->path
= i
->symlink_target
;
1319 i
->symlink_target
= NULL
;
1320 i
->type
= _UNIT_FILE_TYPE_INVALID
;
1322 return unit_file_load_or_readlink(c
, i
, i
->path
, root_dir
, flags
);
1326 * Search for the unit file. If the unit name is a symlink,
1327 * follow the symlink to the target, maybe more than once.
1328 * Propagate the instance name if present.
1330 static int install_info_traverse(
1331 UnitFileScope scope
,
1333 const LookupPaths
*paths
,
1334 UnitFileInstallInfo
*start
,
1336 UnitFileInstallInfo
**ret
) {
1338 UnitFileInstallInfo
*i
;
1346 r
= unit_file_search(c
, start
, paths
, flags
);
1351 while (i
->type
== UNIT_FILE_TYPE_SYMLINK
) {
1352 /* Follow the symlink */
1354 if (++k
> UNIT_FILE_FOLLOW_SYMLINK_MAX
)
1357 if (!(flags
& SEARCH_FOLLOW_CONFIG_SYMLINKS
)) {
1358 r
= path_is_config(paths
, i
->path
);
1365 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
);
1367 _cleanup_free_
char *buffer
= NULL
;
1370 /* Target has a different name, create a new
1371 * install info object for that, and continue
1374 bn
= basename(i
->symlink_target
);
1376 if (unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
) &&
1377 unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
)) {
1379 _cleanup_free_
char *instance
= NULL
;
1381 r
= unit_name_to_instance(i
->name
, &instance
);
1385 r
= unit_name_replace_instance(bn
, instance
, &buffer
);
1392 r
= install_info_add(c
, bn
, NULL
, &i
);
1396 /* Try again, with the new target we found. */
1397 r
= unit_file_search(c
, i
, paths
, flags
);
1410 static int install_info_add_auto(
1412 const LookupPaths
*paths
,
1413 const char *name_or_path
,
1414 UnitFileInstallInfo
**ret
) {
1417 assert(name_or_path
);
1419 if (path_is_absolute(name_or_path
)) {
1422 pp
= prefix_roota(paths
->root_dir
, name_or_path
);
1424 return install_info_add(c
, NULL
, pp
, ret
);
1426 return install_info_add(c
, name_or_path
, NULL
, ret
);
1429 static int install_info_discover(
1430 UnitFileScope scope
,
1432 const LookupPaths
*paths
,
1435 UnitFileInstallInfo
**ret
) {
1437 UnitFileInstallInfo
*i
;
1444 r
= install_info_add_auto(c
, paths
, name
, &i
);
1448 return install_info_traverse(scope
, c
, paths
, i
, flags
, ret
);
1451 static int install_info_symlink_alias(
1452 UnitFileInstallInfo
*i
,
1453 const LookupPaths
*paths
,
1454 const char *config_path
,
1456 UnitFileChange
**changes
,
1457 unsigned *n_changes
) {
1464 assert(config_path
);
1466 STRV_FOREACH(s
, i
->aliases
) {
1467 _cleanup_free_
char *alias_path
= NULL
, *dst
= NULL
;
1470 q
= install_full_printf(i
, *s
, &dst
);
1474 alias_path
= path_make_absolute(dst
, config_path
);
1478 rp
= skip_root(paths
, i
->path
);
1480 q
= create_symlink(rp
?: i
->path
, alias_path
, force
, changes
, n_changes
);
1488 static int install_info_symlink_wants(
1489 UnitFileInstallInfo
*i
,
1490 const LookupPaths
*paths
,
1491 const char *config_path
,
1494 UnitFileChange
**changes
,
1495 unsigned *n_changes
) {
1497 _cleanup_free_
char *buf
= NULL
;
1504 assert(config_path
);
1506 if (unit_name_is_valid(i
->name
, UNIT_NAME_TEMPLATE
)) {
1508 /* Don't install any symlink if there's no default
1509 * instance configured */
1511 if (!i
->default_instance
)
1514 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &buf
);
1522 STRV_FOREACH(s
, list
) {
1523 _cleanup_free_
char *path
= NULL
, *dst
= NULL
;
1526 q
= install_full_printf(i
, *s
, &dst
);
1530 if (!unit_name_is_valid(dst
, UNIT_NAME_ANY
)) {
1535 path
= strjoin(config_path
, "/", dst
, suffix
, n
, NULL
);
1539 rp
= skip_root(paths
, i
->path
);
1541 q
= create_symlink(rp
?: i
->path
, path
, true, changes
, n_changes
);
1549 static int install_info_symlink_link(
1550 UnitFileInstallInfo
*i
,
1551 const LookupPaths
*paths
,
1552 const char *config_path
,
1554 UnitFileChange
**changes
,
1555 unsigned *n_changes
) {
1557 _cleanup_free_
char *path
= NULL
;
1563 assert(config_path
);
1566 r
= in_search_path(paths
, i
->path
);
1572 path
= strjoin(config_path
, "/", i
->name
, NULL
);
1576 rp
= skip_root(paths
, i
->path
);
1578 return create_symlink(rp
?: i
->path
, path
, force
, changes
, n_changes
);
1581 static int install_info_apply(
1582 UnitFileInstallInfo
*i
,
1583 const LookupPaths
*paths
,
1584 const char *config_path
,
1586 UnitFileChange
**changes
,
1587 unsigned *n_changes
) {
1593 assert(config_path
);
1595 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
1598 r
= install_info_symlink_alias(i
, paths
, config_path
, force
, changes
, n_changes
);
1600 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->wanted_by
, ".wants/", changes
, n_changes
);
1604 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->required_by
, ".requires/", changes
, n_changes
);
1608 q
= install_info_symlink_link(i
, paths
, config_path
, force
, changes
, n_changes
);
1609 /* Do not count links to the unit file towards the "carries_install_info" count */
1610 if (r
== 0 && q
< 0)
1616 static int install_context_apply(
1617 UnitFileScope scope
,
1619 const LookupPaths
*paths
,
1620 const char *config_path
,
1623 UnitFileChange
**changes
,
1624 unsigned *n_changes
) {
1626 UnitFileInstallInfo
*i
;
1631 assert(config_path
);
1633 if (ordered_hashmap_isempty(c
->will_process
))
1636 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
1641 while ((i
= ordered_hashmap_first(c
->will_process
))) {
1644 q
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
1648 r
= install_info_traverse(scope
, c
, paths
, i
, flags
, NULL
);
1652 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
1655 q
= install_info_apply(i
, paths
, config_path
, force
, changes
, n_changes
);
1667 static int install_context_mark_for_removal(
1668 UnitFileScope scope
,
1670 const LookupPaths
*paths
,
1671 Set
**remove_symlinks_to
,
1672 const char *config_path
) {
1674 UnitFileInstallInfo
*i
;
1679 assert(config_path
);
1681 /* Marks all items for removal */
1683 if (ordered_hashmap_isempty(c
->will_process
))
1686 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
1690 while ((i
= ordered_hashmap_first(c
->will_process
))) {
1692 r
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
1696 r
= install_info_traverse(scope
, c
, paths
, i
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, NULL
);
1700 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
) {
1701 log_debug("Unit %s has type %s, ignoring.",
1703 unit_file_type_to_string(i
->type
) ?: "invalid");
1707 r
= mark_symlink_for_removal(remove_symlinks_to
, i
->name
);
1716 UnitFileScope scope
,
1718 const char *root_dir
,
1721 UnitFileChange
**changes
,
1722 unsigned *n_changes
) {
1724 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1725 const char *config_path
;
1730 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1732 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1736 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
1738 STRV_FOREACH(i
, files
) {
1739 _cleanup_free_
char *path
= NULL
;
1742 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
)) {
1748 path
= path_make_absolute(*i
, config_path
);
1752 q
= create_symlink("/dev/null", path
, force
, changes
, n_changes
);
1753 if (q
< 0 && r
>= 0)
1760 int unit_file_unmask(
1761 UnitFileScope scope
,
1763 const char *root_dir
,
1765 UnitFileChange
**changes
,
1766 unsigned *n_changes
) {
1768 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1769 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
1770 _cleanup_free_
char **todo
= NULL
;
1771 size_t n_todo
= 0, n_allocated
= 0;
1772 const char *config_path
;
1777 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1779 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1783 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
1785 STRV_FOREACH(i
, files
) {
1786 _cleanup_free_
char *path
= NULL
;
1788 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
1791 path
= path_make_absolute(*i
, config_path
);
1795 r
= null_or_empty_path(path
);
1803 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
1806 todo
[n_todo
++] = *i
;
1812 STRV_FOREACH(i
, todo
) {
1813 _cleanup_free_
char *path
= NULL
;
1816 path
= path_make_absolute(*i
, config_path
);
1820 if (unlink(path
) < 0) {
1821 if (errno
!= ENOENT
) {
1824 unit_file_changes_add(changes
, n_changes
, -errno
, path
, NULL
);
1830 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
1832 rp
= skip_root(&paths
, path
);
1833 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: path
);
1838 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, changes
, n_changes
);
1846 UnitFileScope scope
,
1848 const char *root_dir
,
1851 UnitFileChange
**changes
,
1852 unsigned *n_changes
) {
1854 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1855 _cleanup_free_
char **todo
= NULL
;
1856 size_t n_todo
= 0, n_allocated
= 0;
1857 const char *config_path
;
1862 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1864 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1868 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
1870 STRV_FOREACH(i
, files
) {
1871 _cleanup_free_
char *full
= NULL
;
1875 if (!path_is_absolute(*i
))
1879 if (!unit_name_is_valid(fn
, UNIT_NAME_ANY
))
1882 full
= prefix_root(paths
.root_dir
, *i
);
1886 if (lstat(full
, &st
) < 0)
1888 if (S_ISLNK(st
.st_mode
))
1890 if (S_ISDIR(st
.st_mode
))
1892 if (!S_ISREG(st
.st_mode
))
1895 q
= in_search_path(&paths
, *i
);
1901 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
1904 todo
[n_todo
++] = *i
;
1910 STRV_FOREACH(i
, todo
) {
1911 _cleanup_free_
char *new_path
= NULL
;
1912 const char *old_path
;
1914 old_path
= skip_root(&paths
, *i
);
1915 new_path
= path_make_absolute(basename(*i
), config_path
);
1919 q
= create_symlink(old_path
?: *i
, new_path
, force
, changes
, n_changes
);
1920 if (q
< 0 && r
>= 0)
1927 static int path_shall_revert(const LookupPaths
*paths
, const char *path
) {
1933 /* Checks whether the path is one where the drop-in directories shall be removed. */
1935 r
= path_is_config(paths
, path
);
1939 r
= path_is_control(paths
, path
);
1943 return path_is_transient(paths
, path
);
1946 int unit_file_revert(
1947 UnitFileScope scope
,
1948 const char *root_dir
,
1950 UnitFileChange
**changes
,
1951 unsigned *n_changes
) {
1953 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
1954 /* _cleanup_(install_context_done) InstallContext c = {}; */
1955 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1956 _cleanup_strv_free_
char **todo
= NULL
;
1957 size_t n_todo
= 0, n_allocated
= 0;
1961 /* Puts a unit file back into vendor state. This means:
1963 * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and
1964 * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated").
1966 * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in
1967 * "config", but not in "transient" or "control" or even "generated").
1969 * We remove all that in both the runtime and the persistent directories, if that applies.
1972 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1976 STRV_FOREACH(i
, files
) {
1977 bool has_vendor
= false;
1980 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
1983 STRV_FOREACH(p
, paths
.search_path
) {
1984 _cleanup_free_
char *path
= NULL
, *dropin
= NULL
;
1987 path
= path_make_absolute(*i
, *p
);
1991 r
= lstat(path
, &st
);
1993 if (errno
!= ENOENT
)
1995 } else if (S_ISREG(st
.st_mode
)) {
1996 /* Check if there's a vendor version */
1997 r
= path_is_vendor(&paths
, path
);
2004 dropin
= strappend(path
, ".d");
2008 r
= lstat(dropin
, &st
);
2010 if (errno
!= ENOENT
)
2012 } else if (S_ISDIR(st
.st_mode
)) {
2013 /* Remove the drop-ins */
2014 r
= path_shall_revert(&paths
, dropin
);
2018 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2021 todo
[n_todo
++] = dropin
;
2030 /* OK, there's a vendor version, hence drop all configuration versions */
2031 STRV_FOREACH(p
, paths
.search_path
) {
2032 _cleanup_free_
char *path
= NULL
;
2035 path
= path_make_absolute(*i
, *p
);
2039 r
= lstat(path
, &st
);
2041 if (errno
!= ENOENT
)
2043 } else if (S_ISREG(st
.st_mode
) || S_ISLNK(st
.st_mode
)) {
2044 r
= path_is_config(&paths
, path
);
2048 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2051 todo
[n_todo
++] = path
;
2061 STRV_FOREACH(i
, todo
) {
2062 _cleanup_strv_free_
char **fs
= NULL
;
2066 (void) get_files_in_directory(*i
, &fs
);
2068 q
= rm_rf(*i
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
2069 if (q
< 0 && q
!= -ENOENT
&& r
>= 0) {
2074 STRV_FOREACH(j
, fs
) {
2075 _cleanup_free_
char *t
= NULL
;
2077 t
= strjoin(*i
, "/", *j
, NULL
);
2081 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, t
, NULL
);
2084 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, *i
, NULL
);
2086 rp
= skip_root(&paths
, *i
);
2087 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: *i
);
2092 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.runtime_config
, &paths
, changes
, n_changes
);
2096 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.persistent_config
, &paths
, changes
, n_changes
);
2103 int unit_file_add_dependency(
2104 UnitFileScope scope
,
2106 const char *root_dir
,
2111 UnitFileChange
**changes
,
2112 unsigned *n_changes
) {
2114 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2115 _cleanup_(install_context_done
) InstallContext c
= {};
2116 UnitFileInstallInfo
*i
, *target_info
;
2117 const char *config_path
;
2122 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2125 if (!IN_SET(dep
, UNIT_WANTS
, UNIT_REQUIRES
))
2128 if (!unit_name_is_valid(target
, UNIT_NAME_ANY
))
2131 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2135 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2137 r
= install_info_discover(scope
, &c
, &paths
, target
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, &target_info
);
2140 r
= install_info_may_process(target_info
, &paths
, changes
, n_changes
);
2144 assert(target_info
->type
== UNIT_FILE_TYPE_REGULAR
);
2146 STRV_FOREACH(f
, files
) {
2149 r
= install_info_discover(scope
, &c
, &paths
, *f
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2152 r
= install_info_may_process(i
, &paths
, changes
, n_changes
);
2156 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2158 /* We didn't actually load anything from the unit
2159 * file, but instead just add in our new symlink to
2162 if (dep
== UNIT_WANTS
)
2165 l
= &i
->required_by
;
2168 *l
= strv_new(target_info
->name
, NULL
);
2173 return install_context_apply(scope
, &c
, &paths
, config_path
, force
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, changes
, n_changes
);
2176 int unit_file_enable(
2177 UnitFileScope scope
,
2179 const char *root_dir
,
2182 UnitFileChange
**changes
,
2183 unsigned *n_changes
) {
2185 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2186 _cleanup_(install_context_done
) InstallContext c
= {};
2187 const char *config_path
;
2188 UnitFileInstallInfo
*i
;
2193 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2195 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2199 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2201 STRV_FOREACH(f
, files
) {
2202 r
= install_info_discover(scope
, &c
, &paths
, *f
, SEARCH_LOAD
, &i
);
2205 r
= install_info_may_process(i
, &paths
, changes
, n_changes
);
2209 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2212 /* This will return the number of symlink rules that were
2213 supposed to be created, not the ones actually created. This
2214 is useful to determine whether the passed files had any
2215 installation data at all. */
2217 return install_context_apply(scope
, &c
, &paths
, config_path
, force
, SEARCH_LOAD
, changes
, n_changes
);
2220 int unit_file_disable(
2221 UnitFileScope scope
,
2223 const char *root_dir
,
2225 UnitFileChange
**changes
,
2226 unsigned *n_changes
) {
2228 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2229 _cleanup_(install_context_done
) InstallContext c
= {};
2230 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2231 const char *config_path
;
2236 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2238 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2242 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2244 STRV_FOREACH(i
, files
) {
2245 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2248 r
= install_info_add(&c
, *i
, NULL
, NULL
);
2253 r
= install_context_mark_for_removal(scope
, &c
, &paths
, &remove_symlinks_to
, config_path
);
2257 return remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, changes
, n_changes
);
2260 int unit_file_reenable(
2261 UnitFileScope scope
,
2263 const char *root_dir
,
2266 UnitFileChange
**changes
,
2267 unsigned *n_changes
) {
2273 /* First, we invoke the disable command with only the basename... */
2274 l
= strv_length(files
);
2275 n
= newa(char*, l
+1);
2276 for (i
= 0; i
< l
; i
++)
2277 n
[i
] = basename(files
[i
]);
2280 r
= unit_file_disable(scope
, runtime
, root_dir
, n
, changes
, n_changes
);
2284 /* But the enable command with the full name */
2285 return unit_file_enable(scope
, runtime
, root_dir
, files
, force
, changes
, n_changes
);
2288 int unit_file_set_default(
2289 UnitFileScope scope
,
2290 const char *root_dir
,
2293 UnitFileChange
**changes
,
2294 unsigned *n_changes
) {
2296 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2297 _cleanup_(install_context_done
) InstallContext c
= {};
2298 UnitFileInstallInfo
*i
;
2299 const char *new_path
, *old_path
;
2303 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2306 if (unit_name_to_type(name
) != UNIT_TARGET
) /* this also validates the name */
2308 if (streq(name
, SPECIAL_DEFAULT_TARGET
))
2311 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2315 r
= install_info_discover(scope
, &c
, &paths
, name
, 0, &i
);
2318 r
= install_info_may_process(i
, &paths
, changes
, n_changes
);
2322 old_path
= skip_root(&paths
, i
->path
);
2323 new_path
= strjoina(paths
.persistent_config
, "/" SPECIAL_DEFAULT_TARGET
);
2325 return create_symlink(old_path
?: i
->path
, new_path
, force
, changes
, n_changes
);
2328 int unit_file_get_default(
2329 UnitFileScope scope
,
2330 const char *root_dir
,
2333 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2334 _cleanup_(install_context_done
) InstallContext c
= {};
2335 UnitFileInstallInfo
*i
;
2340 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2343 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2347 r
= install_info_discover(scope
, &c
, &paths
, SPECIAL_DEFAULT_TARGET
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2350 r
= install_info_may_process(i
, &paths
, NULL
, 0);
2354 n
= strdup(i
->name
);
2362 static int unit_file_lookup_state(
2363 UnitFileScope scope
,
2364 const LookupPaths
*paths
,
2366 UnitFileState
*ret
) {
2368 _cleanup_(install_context_done
) InstallContext c
= {};
2369 UnitFileInstallInfo
*i
;
2370 UnitFileState state
;
2376 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2379 r
= install_info_discover(scope
, &c
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2383 /* Shortcut things, if the caller just wants to know if this unit exists. */
2389 case UNIT_FILE_TYPE_MASKED
:
2390 r
= path_is_runtime(paths
, i
->path
);
2394 state
= r
> 0 ? UNIT_FILE_MASKED_RUNTIME
: UNIT_FILE_MASKED
;
2397 case UNIT_FILE_TYPE_REGULAR
:
2398 r
= path_is_generator(paths
, i
->path
);
2402 state
= UNIT_FILE_GENERATED
;
2406 r
= path_is_transient(paths
, i
->path
);
2410 state
= UNIT_FILE_TRANSIENT
;
2414 r
= find_symlinks_in_scope(scope
, paths
, i
->name
, &state
);
2418 if (UNIT_FILE_INSTALL_INFO_HAS_RULES(i
))
2419 state
= UNIT_FILE_DISABLED
;
2420 else if (UNIT_FILE_INSTALL_INFO_HAS_ALSO(i
))
2421 state
= UNIT_FILE_INDIRECT
;
2423 state
= UNIT_FILE_STATIC
;
2429 assert_not_reached("Unexpect unit file type.");
2436 int unit_file_get_state(
2437 UnitFileScope scope
,
2438 const char *root_dir
,
2440 UnitFileState
*ret
) {
2442 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2446 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2449 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2453 return unit_file_lookup_state(scope
, &paths
, name
, ret
);
2456 int unit_file_exists(UnitFileScope scope
, const LookupPaths
*paths
, const char *name
) {
2457 _cleanup_(install_context_done
) InstallContext c
= {};
2463 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2466 r
= install_info_discover(scope
, &c
, paths
, name
, 0, NULL
);
2475 static int read_presets(UnitFileScope scope
, const char *root_dir
, Presets
*presets
) {
2476 _cleanup_(presets_freep
) Presets ps
= {};
2477 size_t n_allocated
= 0;
2478 _cleanup_strv_free_
char **files
= NULL
;
2483 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2486 if (scope
== UNIT_FILE_SYSTEM
)
2487 r
= conf_files_list(&files
, ".preset", root_dir
,
2488 "/etc/systemd/system-preset",
2489 "/usr/local/lib/systemd/system-preset",
2490 "/usr/lib/systemd/system-preset",
2491 #ifdef HAVE_SPLIT_USR
2492 "/lib/systemd/system-preset",
2495 else if (scope
== UNIT_FILE_GLOBAL
)
2496 r
= conf_files_list(&files
, ".preset", root_dir
,
2497 "/etc/systemd/user-preset",
2498 "/usr/local/lib/systemd/user-preset",
2499 "/usr/lib/systemd/user-preset",
2502 *presets
= (Presets
){};
2510 STRV_FOREACH(p
, files
) {
2511 _cleanup_fclose_
FILE *f
;
2512 char line
[LINE_MAX
];
2515 f
= fopen(*p
, "re");
2517 if (errno
== ENOENT
)
2523 FOREACH_LINE(line
, f
, return -errno
) {
2524 PresetRule rule
= {};
2525 const char *parameter
;
2533 if (strchr(COMMENTS
, *l
))
2536 parameter
= first_word(l
, "enable");
2540 pattern
= strdup(parameter
);
2544 rule
= (PresetRule
) {
2546 .action
= PRESET_ENABLE
,
2550 parameter
= first_word(l
, "disable");
2554 pattern
= strdup(parameter
);
2558 rule
= (PresetRule
) {
2560 .action
= PRESET_DISABLE
,
2565 if (!GREEDY_REALLOC(ps
.rules
, n_allocated
, ps
.n_rules
+ 1))
2568 ps
.rules
[ps
.n_rules
++] = rule
;
2572 log_syntax(NULL
, LOG_WARNING
, *p
, n
, 0, "Couldn't parse line '%s'. Ignoring.", line
);
2582 static int query_presets(const char *name
, const Presets presets
) {
2583 PresetAction action
= PRESET_UNKNOWN
;
2586 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2589 for (i
= 0; i
< presets
.n_rules
; i
++)
2590 if (fnmatch(presets
.rules
[i
].pattern
, name
, FNM_NOESCAPE
) == 0) {
2591 action
= presets
.rules
[i
].action
;
2596 case PRESET_UNKNOWN
:
2597 log_debug("Preset files don't specify rule for %s. Enabling.", name
);
2600 log_debug("Preset files say enable %s.", name
);
2602 case PRESET_DISABLE
:
2603 log_debug("Preset files say disable %s.", name
);
2606 assert_not_reached("invalid preset action");
2610 int unit_file_query_preset(UnitFileScope scope
, const char *root_dir
, const char *name
) {
2611 _cleanup_(presets_freep
) Presets presets
= {};
2614 r
= read_presets(scope
, root_dir
, &presets
);
2618 return query_presets(name
, presets
);
2621 static int execute_preset(
2622 UnitFileScope scope
,
2623 InstallContext
*plus
,
2624 InstallContext
*minus
,
2625 const LookupPaths
*paths
,
2626 const char *config_path
,
2628 UnitFilePresetMode mode
,
2630 UnitFileChange
**changes
,
2631 unsigned *n_changes
) {
2638 assert(config_path
);
2640 if (mode
!= UNIT_FILE_PRESET_ENABLE_ONLY
) {
2641 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2643 r
= install_context_mark_for_removal(scope
, minus
, paths
, &remove_symlinks_to
, config_path
);
2647 r
= remove_marked_symlinks(remove_symlinks_to
, config_path
, paths
, changes
, n_changes
);
2651 if (mode
!= UNIT_FILE_PRESET_DISABLE_ONLY
) {
2654 /* Returns number of symlinks that where supposed to be installed. */
2655 q
= install_context_apply(scope
, plus
, paths
, config_path
, force
, SEARCH_LOAD
, changes
, n_changes
);
2667 static int preset_prepare_one(
2668 UnitFileScope scope
,
2669 InstallContext
*plus
,
2670 InstallContext
*minus
,
2672 UnitFilePresetMode mode
,
2675 UnitFileChange
**changes
,
2676 unsigned *n_changes
) {
2678 UnitFileInstallInfo
*i
;
2681 if (install_info_find(plus
, name
) ||
2682 install_info_find(minus
, name
))
2685 r
= query_presets(name
, presets
);
2690 r
= install_info_discover(scope
, plus
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2694 r
= install_info_may_process(i
, paths
, changes
, n_changes
);
2698 r
= install_info_discover(scope
, minus
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2703 int unit_file_preset(
2704 UnitFileScope scope
,
2706 const char *root_dir
,
2708 UnitFilePresetMode mode
,
2710 UnitFileChange
**changes
,
2711 unsigned *n_changes
) {
2713 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
2714 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2715 _cleanup_(presets_freep
) Presets presets
= {};
2716 const char *config_path
;
2721 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2722 assert(mode
< _UNIT_FILE_PRESET_MAX
);
2724 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2728 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2730 r
= read_presets(scope
, root_dir
, &presets
);
2734 STRV_FOREACH(i
, files
) {
2735 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, mode
, *i
, presets
, changes
, n_changes
);
2740 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, files
, mode
, force
, changes
, n_changes
);
2743 int unit_file_preset_all(
2744 UnitFileScope scope
,
2746 const char *root_dir
,
2747 UnitFilePresetMode mode
,
2749 UnitFileChange
**changes
,
2750 unsigned *n_changes
) {
2752 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
2753 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2754 _cleanup_(presets_freep
) Presets presets
= {};
2755 const char *config_path
= NULL
;
2760 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2761 assert(mode
< _UNIT_FILE_PRESET_MAX
);
2763 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2767 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2769 r
= read_presets(scope
, root_dir
, &presets
);
2773 STRV_FOREACH(i
, paths
.search_path
) {
2774 _cleanup_closedir_
DIR *d
= NULL
;
2779 if (errno
== ENOENT
)
2785 FOREACH_DIRENT(de
, d
, return -errno
) {
2787 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
2790 dirent_ensure_type(d
, de
);
2792 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
2795 /* we don't pass changes[] in, because we want to handle errors on our own */
2796 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, mode
, de
->d_name
, presets
, NULL
, 0);
2798 r
= unit_file_changes_add(changes
, n_changes
,
2799 UNIT_FILE_IS_MASKED
, de
->d_name
, NULL
);
2805 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, NULL
, mode
, force
, changes
, n_changes
);
2808 static void unit_file_list_free_one(UnitFileList
*f
) {
2816 Hashmap
* unit_file_list_free(Hashmap
*h
) {
2819 while ((i
= hashmap_steal_first(h
)))
2820 unit_file_list_free_one(i
);
2822 return hashmap_free(h
);
2825 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList
*, unit_file_list_free_one
);
2827 int unit_file_get_list(
2828 UnitFileScope scope
,
2829 const char *root_dir
,
2834 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2839 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2842 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2846 STRV_FOREACH(i
, paths
.search_path
) {
2847 _cleanup_closedir_
DIR *d
= NULL
;
2852 if (errno
== ENOENT
)
2858 FOREACH_DIRENT(de
, d
, return -errno
) {
2859 _cleanup_(unit_file_list_free_onep
) UnitFileList
*f
= NULL
;
2861 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
2864 if (!strv_fnmatch_or_empty(patterns
, de
->d_name
, FNM_NOESCAPE
))
2867 if (hashmap_get(h
, de
->d_name
))
2870 dirent_ensure_type(d
, de
);
2872 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
2875 f
= new0(UnitFileList
, 1);
2879 f
->path
= path_make_absolute(de
->d_name
, *i
);
2883 r
= unit_file_lookup_state(scope
, &paths
, de
->d_name
, &f
->state
);
2885 f
->state
= UNIT_FILE_BAD
;
2887 if (!strv_isempty(states
) &&
2888 !strv_contains(states
, unit_file_state_to_string(f
->state
)))
2891 r
= hashmap_put(h
, basename(f
->path
), f
);
2895 f
= NULL
; /* prevent cleanup */
2902 static const char* const unit_file_state_table
[_UNIT_FILE_STATE_MAX
] = {
2903 [UNIT_FILE_ENABLED
] = "enabled",
2904 [UNIT_FILE_ENABLED_RUNTIME
] = "enabled-runtime",
2905 [UNIT_FILE_LINKED
] = "linked",
2906 [UNIT_FILE_LINKED_RUNTIME
] = "linked-runtime",
2907 [UNIT_FILE_MASKED
] = "masked",
2908 [UNIT_FILE_MASKED_RUNTIME
] = "masked-runtime",
2909 [UNIT_FILE_STATIC
] = "static",
2910 [UNIT_FILE_DISABLED
] = "disabled",
2911 [UNIT_FILE_INDIRECT
] = "indirect",
2912 [UNIT_FILE_GENERATED
] = "generated",
2913 [UNIT_FILE_TRANSIENT
] = "transient",
2914 [UNIT_FILE_BAD
] = "bad",
2917 DEFINE_STRING_TABLE_LOOKUP(unit_file_state
, UnitFileState
);
2919 static const char* const unit_file_change_type_table
[_UNIT_FILE_CHANGE_TYPE_MAX
] = {
2920 [UNIT_FILE_SYMLINK
] = "symlink",
2921 [UNIT_FILE_UNLINK
] = "unlink",
2922 [UNIT_FILE_IS_MASKED
] = "masked",
2925 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type
, UnitFileChangeType
);
2927 static const char* const unit_file_preset_mode_table
[_UNIT_FILE_PRESET_MAX
] = {
2928 [UNIT_FILE_PRESET_FULL
] = "full",
2929 [UNIT_FILE_PRESET_ENABLE_ONLY
] = "enable-only",
2930 [UNIT_FILE_PRESET_DISABLE_ONLY
] = "disable-only",
2933 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode
, UnitFilePresetMode
);