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"
43 #include "locale-util.h"
47 #include "path-lookup.h"
48 #include "path-util.h"
52 #include "stat-util.h"
53 #include "string-table.h"
54 #include "string-util.h"
56 #include "unit-name.h"
58 #define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
60 typedef enum SearchFlags
{
62 SEARCH_FOLLOW_CONFIG_SYMLINKS
= 2,
66 OrderedHashmap
*will_process
;
67 OrderedHashmap
*have_processed
;
86 static inline void presets_freep(Presets
*p
) {
92 for (i
= 0; i
< p
->n_rules
; i
++)
93 free(p
->rules
[i
].pattern
);
99 static int unit_file_lookup_state(UnitFileScope scope
, const LookupPaths
*paths
, const char *name
, UnitFileState
*ret
);
101 bool unit_type_may_alias(UnitType type
) {
111 bool unit_type_may_template(UnitType type
) {
120 static const char *unit_file_type_table
[_UNIT_FILE_TYPE_MAX
] = {
121 [UNIT_FILE_TYPE_REGULAR
] = "regular",
122 [UNIT_FILE_TYPE_SYMLINK
] = "symlink",
123 [UNIT_FILE_TYPE_MASKED
] = "masked",
126 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(unit_file_type
, UnitFileType
);
128 static int in_search_path(const LookupPaths
*p
, const char *path
) {
129 _cleanup_free_
char *parent
= NULL
;
134 parent
= dirname_malloc(path
);
138 STRV_FOREACH(i
, p
->search_path
)
139 if (path_equal(parent
, *i
))
145 static const char* skip_root(const LookupPaths
*p
, const char *path
) {
154 e
= path_startswith(path
, p
->root_dir
);
158 /* Make sure the returned path starts with a slash */
160 if (e
== path
|| e
[-1] != '/')
169 static int path_is_generator(const LookupPaths
*p
, const char *path
) {
170 _cleanup_free_
char *parent
= NULL
;
175 parent
= dirname_malloc(path
);
179 return path_equal_ptr(parent
, p
->generator
) ||
180 path_equal_ptr(parent
, p
->generator_early
) ||
181 path_equal_ptr(parent
, p
->generator_late
);
184 static int path_is_transient(const LookupPaths
*p
, const char *path
) {
185 _cleanup_free_
char *parent
= NULL
;
190 parent
= dirname_malloc(path
);
194 return path_equal_ptr(parent
, p
->transient
);
197 static int path_is_control(const LookupPaths
*p
, const char *path
) {
198 _cleanup_free_
char *parent
= NULL
;
203 parent
= dirname_malloc(path
);
207 return path_equal_ptr(parent
, p
->persistent_control
) ||
208 path_equal_ptr(parent
, p
->runtime_control
);
211 static int path_is_config(const LookupPaths
*p
, const char *path
) {
212 _cleanup_free_
char *parent
= NULL
;
217 /* Note that we do *not* have generic checks for /etc or /run in place, since with
218 * them we couldn't discern configuration from transient or generated units */
220 parent
= dirname_malloc(path
);
224 return path_equal_ptr(parent
, p
->persistent_config
) ||
225 path_equal_ptr(parent
, p
->runtime_config
);
228 static int path_is_runtime(const LookupPaths
*p
, const char *path
) {
229 _cleanup_free_
char *parent
= NULL
;
235 /* Everything in /run is considered runtime. On top of that we also add
236 * explicit checks for the various runtime directories, as safety net. */
238 rpath
= skip_root(p
, path
);
239 if (rpath
&& path_startswith(rpath
, "/run"))
242 parent
= dirname_malloc(path
);
246 return path_equal_ptr(parent
, p
->runtime_config
) ||
247 path_equal_ptr(parent
, p
->generator
) ||
248 path_equal_ptr(parent
, p
->generator_early
) ||
249 path_equal_ptr(parent
, p
->generator_late
) ||
250 path_equal_ptr(parent
, p
->transient
) ||
251 path_equal_ptr(parent
, p
->runtime_control
);
254 static int path_is_vendor(const LookupPaths
*p
, const char *path
) {
260 rpath
= skip_root(p
, path
);
264 if (path_startswith(rpath
, "/usr"))
267 #ifdef HAVE_SPLIT_USR
268 if (path_startswith(rpath
, "/lib"))
272 return path_equal(rpath
, SYSTEM_DATA_UNIT_PATH
);
275 int unit_file_changes_add(
276 UnitFileChange
**changes
,
278 UnitFileChangeType type
,
280 const char *source
) {
282 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
286 assert(!changes
== !n_changes
);
291 c
= realloc(*changes
, (*n_changes
+ 1) * sizeof(UnitFileChange
));
300 if (!p
|| (source
&& !s
))
303 path_kill_slashes(p
);
305 path_kill_slashes(s
);
307 c
[*n_changes
] = (UnitFileChange
) { type
, p
, s
};
313 void unit_file_changes_free(UnitFileChange
*changes
, unsigned n_changes
) {
316 assert(changes
|| n_changes
== 0);
318 for (i
= 0; i
< n_changes
; i
++) {
319 free(changes
[i
].path
);
320 free(changes
[i
].source
);
326 void unit_file_dump_changes(int r
, const char *verb
, const UnitFileChange
*changes
, unsigned n_changes
, bool quiet
) {
330 assert(changes
|| n_changes
== 0);
331 /* If verb is not specified, errors are not allowed! */
332 assert(verb
|| r
>= 0);
334 for (i
= 0; i
< n_changes
; i
++) {
335 assert(verb
|| changes
[i
].type
>= 0);
337 switch(changes
[i
].type
) {
338 case UNIT_FILE_SYMLINK
:
340 log_info("Created symlink %s %s %s.",
342 special_glyph(ARROW
),
345 case UNIT_FILE_UNLINK
:
347 log_info("Removed %s.", changes
[i
].path
);
349 case UNIT_FILE_IS_MASKED
:
351 log_info("Unit %s is masked, ignoring.", changes
[i
].path
);
353 case UNIT_FILE_IS_DANGLING
:
355 log_info("Unit %s is an alias to a unit that is not present, ignoring.",
359 if (changes
[i
].source
)
360 log_error_errno(changes
[i
].type
,
361 "Failed to %s unit, file %s already exists and is a symlink to %s.",
362 verb
, changes
[i
].path
, changes
[i
].source
);
364 log_error_errno(changes
[i
].type
,
365 "Failed to %s unit, file %s already exists.",
366 verb
, changes
[i
].path
);
370 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s is masked.",
371 verb
, changes
[i
].path
);
375 log_error_errno(changes
[i
].type
, "Failed to %s unit, unit %s is transient or generated.",
376 verb
, changes
[i
].path
);
380 log_error_errno(changes
[i
].type
, "Failed to %s unit, refusing to operate on linked unit file %s",
381 verb
, changes
[i
].path
);
385 assert(changes
[i
].type
< 0);
386 log_error_errno(changes
[i
].type
, "Failed to %s unit, file %s: %m.",
387 verb
, changes
[i
].path
);
392 if (r
< 0 && !logged
)
393 log_error_errno(r
, "Failed to %s: %m.", verb
);
397 * Checks if two paths or symlinks from wd are the same, when root is the root of the filesystem.
398 * wc should be the full path in the host file system.
400 static bool chroot_symlinks_same(const char *root
, const char *wd
, const char *a
, const char *b
) {
401 assert(path_is_absolute(wd
));
403 /* This will give incorrect results if the paths are relative and go outside
404 * of the chroot. False negatives are possible. */
409 a
= strjoina(path_is_absolute(a
) ? root
: wd
, "/", a
);
410 b
= strjoina(path_is_absolute(b
) ? root
: wd
, "/", b
);
411 return path_equal_or_files_same(a
, b
);
414 static int create_symlink(
415 const LookupPaths
*paths
,
416 const char *old_path
,
417 const char *new_path
,
419 UnitFileChange
**changes
,
420 unsigned *n_changes
) {
422 _cleanup_free_
char *dest
= NULL
, *dirname
= NULL
;
429 rp
= skip_root(paths
, old_path
);
433 /* Actually create a symlink, and remember that we did. Is
434 * smart enough to check if there's already a valid symlink in
437 * Returns 1 if a symlink was created or already exists and points to
438 * the right place, or negative on error.
441 mkdir_parents_label(new_path
, 0755);
443 if (symlink(old_path
, new_path
) >= 0) {
444 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
448 if (errno
!= EEXIST
) {
449 unit_file_changes_add(changes
, n_changes
, -errno
, new_path
, NULL
);
453 r
= readlink_malloc(new_path
, &dest
);
455 /* translate EINVAL (non-symlink exists) to EEXIST */
459 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
463 dirname
= dirname_malloc(new_path
);
467 if (chroot_symlinks_same(paths
->root_dir
, dirname
, dest
, old_path
))
471 unit_file_changes_add(changes
, n_changes
, -EEXIST
, new_path
, dest
);
475 r
= symlink_atomic(old_path
, new_path
);
477 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
481 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, new_path
, NULL
);
482 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
487 static int mark_symlink_for_removal(
488 Set
**remove_symlinks_to
,
496 r
= set_ensure_allocated(remove_symlinks_to
, &string_hash_ops
);
504 path_kill_slashes(n
);
506 r
= set_consume(*remove_symlinks_to
, n
);
515 static int remove_marked_symlinks_fd(
516 Set
*remove_symlinks_to
,
519 const char *config_path
,
520 const LookupPaths
*lp
,
522 UnitFileChange
**changes
,
523 unsigned *n_changes
) {
525 _cleanup_closedir_
DIR *d
= NULL
;
529 assert(remove_symlinks_to
);
544 FOREACH_DIRENT(de
, d
, return -errno
) {
546 dirent_ensure_type(d
, de
);
548 if (de
->d_type
== DT_DIR
) {
549 _cleanup_free_
char *p
= NULL
;
552 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
562 p
= path_make_absolute(de
->d_name
, path
);
568 /* This will close nfd, regardless whether it succeeds or not */
569 q
= remove_marked_symlinks_fd(remove_symlinks_to
, nfd
, p
, config_path
, lp
, restart
, changes
, n_changes
);
573 } else if (de
->d_type
== DT_LNK
) {
574 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
579 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
582 p
= path_make_absolute(de
->d_name
, path
);
585 path_kill_slashes(p
);
587 q
= readlink_malloc(p
, &dest
);
596 /* We remove all links pointing to a file or path that is marked, as well as all files sharing
597 * the same name as a file that is marked. */
599 found
= set_contains(remove_symlinks_to
, dest
) ||
600 set_contains(remove_symlinks_to
, basename(dest
)) ||
601 set_contains(remove_symlinks_to
, de
->d_name
);
606 if (unlinkat(fd
, de
->d_name
, 0) < 0 && errno
!= ENOENT
) {
609 unit_file_changes_add(changes
, n_changes
, -errno
, p
, NULL
);
613 (void) rmdir_parents(p
, config_path
);
615 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, p
, NULL
);
617 /* Now, remember the full path (but with the root prefix removed) of
618 * the symlink we just removed, and remove any symlinks to it, too. */
620 rp
= skip_root(lp
, p
);
621 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: p
);
632 static int remove_marked_symlinks(
633 Set
*remove_symlinks_to
,
634 const char *config_path
,
635 const LookupPaths
*lp
,
636 UnitFileChange
**changes
,
637 unsigned *n_changes
) {
639 _cleanup_close_
int fd
= -1;
646 if (set_size(remove_symlinks_to
) <= 0)
649 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
);
651 return errno
== ENOENT
? 0 : -errno
;
657 cfd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
661 /* This takes possession of cfd and closes it */
662 q
= remove_marked_symlinks_fd(remove_symlinks_to
, cfd
, config_path
, config_path
, lp
, &restart
, changes
, n_changes
);
670 static int find_symlinks_fd(
671 const char *root_dir
,
675 const char *config_path
,
676 const LookupPaths
*lp
,
677 bool *same_name_link
) {
679 _cleanup_closedir_
DIR *d
= NULL
;
688 assert(same_name_link
);
696 FOREACH_DIRENT(de
, d
, return -errno
) {
698 dirent_ensure_type(d
, de
);
700 if (de
->d_type
== DT_DIR
) {
701 _cleanup_free_
char *p
= NULL
;
704 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
714 p
= path_make_absolute(de
->d_name
, path
);
720 /* This will close nfd, regardless whether it succeeds or not */
721 q
= find_symlinks_fd(root_dir
, name
, nfd
, p
, config_path
, lp
, same_name_link
);
727 } else if (de
->d_type
== DT_LNK
) {
728 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
729 bool found_path
, found_dest
, b
= false;
732 /* Acquire symlink name */
733 p
= path_make_absolute(de
->d_name
, path
);
737 /* Acquire symlink destination */
738 q
= readlink_malloc(p
, &dest
);
748 if (!path_is_absolute(dest
)) {
751 x
= prefix_root(root_dir
, dest
);
759 /* Check if the symlink itself matches what we
761 if (path_is_absolute(name
))
762 found_path
= path_equal(p
, name
);
764 found_path
= streq(de
->d_name
, name
);
766 /* Check if what the symlink points to
767 * matches what we are looking for */
768 if (path_is_absolute(name
))
769 found_dest
= path_equal(dest
, name
);
771 found_dest
= streq(basename(dest
), name
);
773 if (found_path
&& found_dest
) {
774 _cleanup_free_
char *t
= NULL
;
776 /* Filter out same name links in the main
778 t
= path_make_absolute(name
, config_path
);
782 b
= path_equal(t
, p
);
786 *same_name_link
= true;
787 else if (found_path
|| found_dest
)
795 static int find_symlinks(
796 const char *root_dir
,
798 const char *config_path
,
799 const LookupPaths
*lp
,
800 bool *same_name_link
) {
806 assert(same_name_link
);
808 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
);
810 if (IN_SET(errno
, ENOENT
, ENOTDIR
, EACCES
))
815 /* This takes possession of fd and closes it */
816 return find_symlinks_fd(root_dir
, name
, fd
, config_path
, config_path
, lp
, same_name_link
);
819 static int find_symlinks_in_scope(
821 const LookupPaths
*paths
,
823 UnitFileState
*state
) {
825 bool same_name_link_runtime
= false, same_name_link
= false;
829 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
833 /* First look in the persistent config path */
834 r
= find_symlinks(paths
->root_dir
, name
, paths
->persistent_config
, paths
, &same_name_link
);
838 *state
= UNIT_FILE_ENABLED
;
842 /* Then look in runtime config path */
843 r
= find_symlinks(paths
->root_dir
, name
, paths
->runtime_config
, paths
, &same_name_link_runtime
);
847 *state
= UNIT_FILE_ENABLED_RUNTIME
;
851 /* Hmm, we didn't find it, but maybe we found the same name
853 if (same_name_link
) {
854 *state
= UNIT_FILE_LINKED
;
857 if (same_name_link_runtime
) {
858 *state
= UNIT_FILE_LINKED_RUNTIME
;
865 static void install_info_free(UnitFileInstallInfo
*i
) {
872 strv_free(i
->aliases
);
873 strv_free(i
->wanted_by
);
874 strv_free(i
->required_by
);
876 free(i
->default_instance
);
877 free(i
->symlink_target
);
881 static OrderedHashmap
* install_info_hashmap_free(OrderedHashmap
*m
) {
882 UnitFileInstallInfo
*i
;
887 while ((i
= ordered_hashmap_steal_first(m
)))
888 install_info_free(i
);
890 return ordered_hashmap_free(m
);
893 static void install_context_done(InstallContext
*c
) {
896 c
->will_process
= install_info_hashmap_free(c
->will_process
);
897 c
->have_processed
= install_info_hashmap_free(c
->have_processed
);
900 static UnitFileInstallInfo
*install_info_find(InstallContext
*c
, const char *name
) {
901 UnitFileInstallInfo
*i
;
903 i
= ordered_hashmap_get(c
->have_processed
, name
);
907 return ordered_hashmap_get(c
->will_process
, name
);
910 static int install_info_may_process(
911 UnitFileInstallInfo
*i
,
912 const LookupPaths
*paths
,
913 UnitFileChange
**changes
,
914 unsigned *n_changes
) {
918 /* Checks whether the loaded unit file is one we should process, or is masked,
919 * transient or generated and thus not subject to enable/disable operations. */
921 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
922 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, i
->path
, NULL
);
925 if (path_is_generator(paths
, i
->path
) ||
926 path_is_transient(paths
, i
->path
)) {
927 unit_file_changes_add(changes
, n_changes
, -EADDRNOTAVAIL
, i
->path
, NULL
);
928 return -EADDRNOTAVAIL
;
935 * Adds a new UnitFileInstallInfo entry under name in the InstallContext.will_process
936 * hashmap, or retrieves the existing one if already present.
938 static int install_info_add(
942 UnitFileInstallInfo
**ret
) {
944 UnitFileInstallInfo
*i
= NULL
;
948 assert(name
|| path
);
951 name
= basename(path
);
953 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
956 i
= install_info_find(c
, name
);
963 r
= ordered_hashmap_ensure_allocated(&c
->will_process
, &string_hash_ops
);
967 i
= new0(UnitFileInstallInfo
, 1);
970 i
->type
= _UNIT_FILE_TYPE_INVALID
;
972 i
->name
= strdup(name
);
979 i
->path
= strdup(path
);
986 r
= ordered_hashmap_put(c
->will_process
, i
->name
, i
);
996 install_info_free(i
);
1000 static int config_parse_alias(
1002 const char *filename
,
1004 const char *section
,
1005 unsigned section_line
,
1019 name
= basename(filename
);
1020 type
= unit_name_to_type(name
);
1021 if (!unit_type_may_alias(type
))
1022 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1023 "Alias= is not allowed for %s units, ignoring.",
1024 unit_type_to_string(type
));
1026 return config_parse_strv(unit
, filename
, line
, section
, section_line
,
1027 lvalue
, ltype
, rvalue
, data
, userdata
);
1030 static int config_parse_also(
1032 const char *filename
,
1034 const char *section
,
1035 unsigned section_line
,
1042 UnitFileInstallInfo
*i
= userdata
;
1043 InstallContext
*c
= data
;
1051 _cleanup_free_
char *word
= NULL
;
1053 r
= extract_first_word(&rvalue
, &word
, NULL
, 0);
1059 r
= install_info_add(c
, word
, NULL
, NULL
);
1063 r
= strv_push(&i
->also
, word
);
1073 static int config_parse_default_instance(
1075 const char *filename
,
1077 const char *section
,
1078 unsigned section_line
,
1085 UnitFileInstallInfo
*i
= data
;
1087 _cleanup_free_
char *printed
= NULL
;
1094 name
= basename(filename
);
1095 if (unit_name_is_valid(name
, UNIT_NAME_INSTANCE
))
1096 /* When enabling an instance, we might be using a template unit file,
1097 * but we should ignore DefaultInstance silently. */
1099 if (!unit_name_is_valid(name
, UNIT_NAME_TEMPLATE
))
1100 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1101 "DefaultInstance= only makes sense for template units, ignoring.");
1103 r
= install_full_printf(i
, rvalue
, &printed
);
1107 if (!unit_instance_is_valid(printed
))
1110 free(i
->default_instance
);
1111 i
->default_instance
= printed
;
1117 static int unit_file_load(
1119 UnitFileInstallInfo
*info
,
1121 SearchFlags flags
) {
1123 const ConfigTableItem items
[] = {
1124 { "Install", "Alias", config_parse_alias
, 0, &info
->aliases
},
1125 { "Install", "WantedBy", config_parse_strv
, 0, &info
->wanted_by
},
1126 { "Install", "RequiredBy", config_parse_strv
, 0, &info
->required_by
},
1127 { "Install", "DefaultInstance", config_parse_default_instance
, 0, info
},
1128 { "Install", "Also", config_parse_also
, 0, c
},
1134 _cleanup_fclose_
FILE *f
= NULL
;
1135 _cleanup_close_
int fd
= -1;
1142 name
= basename(path
);
1143 type
= unit_name_to_type(name
);
1144 if (unit_name_is_valid(name
, UNIT_NAME_TEMPLATE
|UNIT_NAME_INSTANCE
) &&
1145 !unit_type_may_template(type
))
1146 return log_error_errno(EINVAL
, "Unit type %s cannot be templated.", unit_type_to_string(type
));
1148 if (!(flags
& SEARCH_LOAD
)) {
1149 r
= lstat(path
, &st
);
1153 if (null_or_empty(&st
))
1154 info
->type
= UNIT_FILE_TYPE_MASKED
;
1155 else if (S_ISREG(st
.st_mode
))
1156 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1157 else if (S_ISLNK(st
.st_mode
))
1159 else if (S_ISDIR(st
.st_mode
))
1167 /* c is only needed if we actually load the file */
1170 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
1173 if (fstat(fd
, &st
) < 0)
1175 if (null_or_empty(&st
)) {
1176 info
->type
= UNIT_FILE_TYPE_MASKED
;
1179 if (S_ISDIR(st
.st_mode
))
1181 if (!S_ISREG(st
.st_mode
))
1184 f
= fdopen(fd
, "re");
1189 r
= config_parse(NULL
, path
, f
,
1191 config_item_table_lookup
, items
,
1192 true, true, false, info
);
1196 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1199 (int) strv_length(info
->aliases
) +
1200 (int) strv_length(info
->wanted_by
) +
1201 (int) strv_length(info
->required_by
);
1204 static int unit_file_load_or_readlink(
1206 UnitFileInstallInfo
*info
,
1208 const char *root_dir
,
1209 SearchFlags flags
) {
1211 _cleanup_free_
char *target
= NULL
;
1214 r
= unit_file_load(c
, info
, path
, flags
);
1218 /* This is a symlink, let's read it. */
1220 r
= readlink_malloc(path
, &target
);
1224 if (path_equal(target
, "/dev/null"))
1225 info
->type
= UNIT_FILE_TYPE_MASKED
;
1230 bn
= basename(target
);
1232 if (unit_name_is_valid(info
->name
, UNIT_NAME_PLAIN
)) {
1234 if (!unit_name_is_valid(bn
, UNIT_NAME_PLAIN
))
1237 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1239 if (!unit_name_is_valid(bn
, UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
))
1242 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
)) {
1244 if (!unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
))
1249 /* Enforce that the symlink destination does not
1250 * change the unit file type. */
1252 a
= unit_name_to_type(info
->name
);
1253 b
= unit_name_to_type(bn
);
1254 if (a
< 0 || b
< 0 || a
!= b
)
1257 if (path_is_absolute(target
))
1258 /* This is an absolute path, prefix the root so that we always deal with fully qualified paths */
1259 info
->symlink_target
= prefix_root(root_dir
, target
);
1261 /* This is a relative path, take it relative to the dir the symlink is located in. */
1262 info
->symlink_target
= file_in_same_dir(path
, target
);
1263 if (!info
->symlink_target
)
1266 info
->type
= UNIT_FILE_TYPE_SYMLINK
;
1272 static int unit_file_search(
1274 UnitFileInstallInfo
*info
,
1275 const LookupPaths
*paths
,
1276 SearchFlags flags
) {
1278 _cleanup_free_
char *template = NULL
;
1285 /* Was this unit already loaded? */
1286 if (info
->type
!= _UNIT_FILE_TYPE_INVALID
)
1290 return unit_file_load_or_readlink(c
, info
, info
->path
, paths
->root_dir
, flags
);
1294 STRV_FOREACH(p
, paths
->search_path
) {
1295 _cleanup_free_
char *path
= NULL
;
1297 path
= strjoin(*p
, "/", info
->name
, NULL
);
1301 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1306 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1310 if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1311 /* Unit file doesn't exist, however instance
1312 * enablement was requested. We will check if it is
1313 * possible to load template unit file. */
1315 r
= unit_name_template(info
->name
, &template);
1319 STRV_FOREACH(p
, paths
->search_path
) {
1320 _cleanup_free_
char *path
= NULL
;
1322 path
= strjoin(*p
, "/", template, NULL
);
1326 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1331 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1336 log_debug("Cannot find unit %s%s%s.", info
->name
, template ? " or " : "", strempty(template));
1340 static int install_info_follow(
1342 UnitFileInstallInfo
*i
,
1343 const char *root_dir
,
1344 SearchFlags flags
) {
1349 if (i
->type
!= UNIT_FILE_TYPE_SYMLINK
)
1351 if (!i
->symlink_target
)
1354 /* If the basename doesn't match, the caller should add a
1355 * complete new entry for this. */
1357 if (!streq(basename(i
->symlink_target
), i
->name
))
1361 i
->path
= i
->symlink_target
;
1362 i
->symlink_target
= NULL
;
1363 i
->type
= _UNIT_FILE_TYPE_INVALID
;
1365 return unit_file_load_or_readlink(c
, i
, i
->path
, root_dir
, flags
);
1369 * Search for the unit file. If the unit name is a symlink, follow the symlink to the
1370 * target, maybe more than once. Propagate the instance name if present.
1372 static int install_info_traverse(
1373 UnitFileScope scope
,
1375 const LookupPaths
*paths
,
1376 UnitFileInstallInfo
*start
,
1378 UnitFileInstallInfo
**ret
) {
1380 UnitFileInstallInfo
*i
;
1388 r
= unit_file_search(c
, start
, paths
, flags
);
1393 while (i
->type
== UNIT_FILE_TYPE_SYMLINK
) {
1394 /* Follow the symlink */
1396 if (++k
> UNIT_FILE_FOLLOW_SYMLINK_MAX
)
1399 if (!(flags
& SEARCH_FOLLOW_CONFIG_SYMLINKS
)) {
1400 r
= path_is_config(paths
, i
->path
);
1407 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
);
1409 _cleanup_free_
char *buffer
= NULL
;
1412 /* Target has a different name, create a new
1413 * install info object for that, and continue
1416 bn
= basename(i
->symlink_target
);
1418 if (unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
) &&
1419 unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
)) {
1421 _cleanup_free_
char *instance
= NULL
;
1423 r
= unit_name_to_instance(i
->name
, &instance
);
1427 r
= unit_name_replace_instance(bn
, instance
, &buffer
);
1434 r
= install_info_add(c
, bn
, NULL
, &i
);
1438 /* Try again, with the new target we found. */
1439 r
= unit_file_search(c
, i
, paths
, flags
);
1441 /* Translate error code to highlight this specific case */
1456 * Call install_info_add() with name_or_path as the path (if name_or_path starts with "/")
1457 * or the name (otherwise). root_dir is prepended to the path.
1459 static int install_info_add_auto(
1461 const LookupPaths
*paths
,
1462 const char *name_or_path
,
1463 UnitFileInstallInfo
**ret
) {
1466 assert(name_or_path
);
1468 if (path_is_absolute(name_or_path
)) {
1471 pp
= prefix_roota(paths
->root_dir
, name_or_path
);
1473 return install_info_add(c
, NULL
, pp
, ret
);
1475 return install_info_add(c
, name_or_path
, NULL
, ret
);
1478 static int install_info_discover(
1479 UnitFileScope scope
,
1481 const LookupPaths
*paths
,
1484 UnitFileInstallInfo
**ret
) {
1486 UnitFileInstallInfo
*i
;
1493 r
= install_info_add_auto(c
, paths
, name
, &i
);
1497 return install_info_traverse(scope
, c
, paths
, i
, flags
, ret
);
1500 static int install_info_symlink_alias(
1501 UnitFileInstallInfo
*i
,
1502 const LookupPaths
*paths
,
1503 const char *config_path
,
1505 UnitFileChange
**changes
,
1506 unsigned *n_changes
) {
1513 assert(config_path
);
1515 STRV_FOREACH(s
, i
->aliases
) {
1516 _cleanup_free_
char *alias_path
= NULL
, *dst
= NULL
;
1518 q
= install_full_printf(i
, *s
, &dst
);
1522 alias_path
= path_make_absolute(dst
, config_path
);
1526 q
= create_symlink(paths
, i
->path
, alias_path
, force
, changes
, n_changes
);
1534 static int install_info_symlink_wants(
1535 UnitFileInstallInfo
*i
,
1536 const LookupPaths
*paths
,
1537 const char *config_path
,
1540 UnitFileChange
**changes
,
1541 unsigned *n_changes
) {
1543 _cleanup_free_
char *buf
= NULL
;
1550 assert(config_path
);
1552 if (strv_isempty(list
))
1555 if (unit_name_is_valid(i
->name
, UNIT_NAME_TEMPLATE
)) {
1556 UnitFileInstallInfo instance
= {
1557 .type
= _UNIT_FILE_TYPE_INVALID
,
1559 _cleanup_free_
char *path
= NULL
;
1561 /* Don't install any symlink if there's no default
1562 * instance configured */
1564 if (!i
->default_instance
)
1567 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &buf
);
1571 instance
.name
= buf
;
1572 r
= unit_file_search(NULL
, &instance
, paths
, SEARCH_FOLLOW_CONFIG_SYMLINKS
);
1576 path
= instance
.path
;
1577 instance
.path
= NULL
;
1579 if (instance
.type
== UNIT_FILE_TYPE_MASKED
) {
1580 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, path
, NULL
);
1588 STRV_FOREACH(s
, list
) {
1589 _cleanup_free_
char *path
= NULL
, *dst
= NULL
;
1591 q
= install_full_printf(i
, *s
, &dst
);
1595 if (!unit_name_is_valid(dst
, UNIT_NAME_ANY
)) {
1600 path
= strjoin(config_path
, "/", dst
, suffix
, n
, NULL
);
1604 q
= create_symlink(paths
, i
->path
, path
, true, changes
, n_changes
);
1612 static int install_info_symlink_link(
1613 UnitFileInstallInfo
*i
,
1614 const LookupPaths
*paths
,
1615 const char *config_path
,
1617 UnitFileChange
**changes
,
1618 unsigned *n_changes
) {
1620 _cleanup_free_
char *path
= NULL
;
1625 assert(config_path
);
1628 r
= in_search_path(paths
, i
->path
);
1634 path
= strjoin(config_path
, "/", i
->name
, NULL
);
1638 return create_symlink(paths
, i
->path
, path
, force
, changes
, n_changes
);
1641 static int install_info_apply(
1642 UnitFileInstallInfo
*i
,
1643 const LookupPaths
*paths
,
1644 const char *config_path
,
1646 UnitFileChange
**changes
,
1647 unsigned *n_changes
) {
1653 assert(config_path
);
1655 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
1658 r
= install_info_symlink_alias(i
, paths
, config_path
, force
, changes
, n_changes
);
1660 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->wanted_by
, ".wants/", changes
, n_changes
);
1664 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->required_by
, ".requires/", changes
, n_changes
);
1668 q
= install_info_symlink_link(i
, paths
, config_path
, force
, changes
, n_changes
);
1669 /* Do not count links to the unit file towards the "carries_install_info" count */
1670 if (r
== 0 && q
< 0)
1676 static int install_context_apply(
1677 UnitFileScope scope
,
1679 const LookupPaths
*paths
,
1680 const char *config_path
,
1683 UnitFileChange
**changes
,
1684 unsigned *n_changes
) {
1686 UnitFileInstallInfo
*i
;
1691 assert(config_path
);
1693 if (ordered_hashmap_isempty(c
->will_process
))
1696 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
1701 while ((i
= ordered_hashmap_first(c
->will_process
))) {
1704 q
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
1708 r
= install_info_traverse(scope
, c
, paths
, i
, flags
, NULL
);
1712 /* We can attempt to process a masked unit when a different unit
1713 * that we were processing specifies it in Also=. */
1714 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
1715 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_MASKED
, i
->path
, NULL
);
1717 /* Assume that something *could* have been enabled here,
1718 * avoid "empty [Install] section" warning. */
1723 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
1726 q
= install_info_apply(i
, paths
, config_path
, force
, changes
, n_changes
);
1738 static int install_context_mark_for_removal(
1739 UnitFileScope scope
,
1741 const LookupPaths
*paths
,
1742 Set
**remove_symlinks_to
,
1743 const char *config_path
) {
1745 UnitFileInstallInfo
*i
;
1750 assert(config_path
);
1752 /* Marks all items for removal */
1754 if (ordered_hashmap_isempty(c
->will_process
))
1757 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
1761 while ((i
= ordered_hashmap_first(c
->will_process
))) {
1763 r
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
1767 r
= install_info_traverse(scope
, c
, paths
, i
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, NULL
);
1773 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
) {
1774 log_debug("Unit %s has type %s, ignoring.",
1776 unit_file_type_to_string(i
->type
) ?: "invalid");
1780 r
= mark_symlink_for_removal(remove_symlinks_to
, i
->name
);
1789 UnitFileScope scope
,
1791 const char *root_dir
,
1794 UnitFileChange
**changes
,
1795 unsigned *n_changes
) {
1797 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1798 const char *config_path
;
1803 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1805 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1809 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
1811 STRV_FOREACH(i
, files
) {
1812 _cleanup_free_
char *path
= NULL
;
1815 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
)) {
1821 path
= path_make_absolute(*i
, config_path
);
1825 q
= create_symlink(&paths
, "/dev/null", path
, force
, changes
, n_changes
);
1826 if (q
< 0 && r
>= 0)
1833 int unit_file_unmask(
1834 UnitFileScope scope
,
1836 const char *root_dir
,
1838 UnitFileChange
**changes
,
1839 unsigned *n_changes
) {
1841 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1842 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
1843 _cleanup_free_
char **todo
= NULL
;
1844 size_t n_todo
= 0, n_allocated
= 0;
1845 const char *config_path
;
1850 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1852 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1856 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
1858 STRV_FOREACH(i
, files
) {
1859 _cleanup_free_
char *path
= NULL
;
1861 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
1864 path
= path_make_absolute(*i
, config_path
);
1868 r
= null_or_empty_path(path
);
1876 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
1879 todo
[n_todo
++] = *i
;
1885 STRV_FOREACH(i
, todo
) {
1886 _cleanup_free_
char *path
= NULL
;
1889 path
= path_make_absolute(*i
, config_path
);
1893 if (unlink(path
) < 0) {
1894 if (errno
!= ENOENT
) {
1897 unit_file_changes_add(changes
, n_changes
, -errno
, path
, NULL
);
1903 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
1905 rp
= skip_root(&paths
, path
);
1906 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: path
);
1911 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, changes
, n_changes
);
1919 UnitFileScope scope
,
1921 const char *root_dir
,
1924 UnitFileChange
**changes
,
1925 unsigned *n_changes
) {
1927 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1928 _cleanup_free_
char **todo
= NULL
;
1929 size_t n_todo
= 0, n_allocated
= 0;
1930 const char *config_path
;
1935 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1937 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1941 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
1943 STRV_FOREACH(i
, files
) {
1944 _cleanup_free_
char *full
= NULL
;
1948 if (!path_is_absolute(*i
))
1952 if (!unit_name_is_valid(fn
, UNIT_NAME_ANY
))
1955 full
= prefix_root(paths
.root_dir
, *i
);
1959 if (lstat(full
, &st
) < 0)
1961 if (S_ISLNK(st
.st_mode
))
1963 if (S_ISDIR(st
.st_mode
))
1965 if (!S_ISREG(st
.st_mode
))
1968 q
= in_search_path(&paths
, *i
);
1974 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
1977 todo
[n_todo
++] = *i
;
1983 STRV_FOREACH(i
, todo
) {
1984 _cleanup_free_
char *new_path
= NULL
;
1986 new_path
= path_make_absolute(basename(*i
), config_path
);
1990 q
= create_symlink(&paths
, *i
, new_path
, force
, changes
, n_changes
);
1991 if (q
< 0 && r
>= 0)
1998 static int path_shall_revert(const LookupPaths
*paths
, const char *path
) {
2004 /* Checks whether the path is one where the drop-in directories shall be removed. */
2006 r
= path_is_config(paths
, path
);
2010 r
= path_is_control(paths
, path
);
2014 return path_is_transient(paths
, path
);
2017 int unit_file_revert(
2018 UnitFileScope scope
,
2019 const char *root_dir
,
2021 UnitFileChange
**changes
,
2022 unsigned *n_changes
) {
2024 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2025 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2026 _cleanup_strv_free_
char **todo
= NULL
;
2027 size_t n_todo
= 0, n_allocated
= 0;
2031 /* Puts a unit file back into vendor state. This means:
2033 * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and
2034 * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated").
2036 * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in
2037 * "config", but not in "transient" or "control" or even "generated").
2039 * We remove all that in both the runtime and the persistent directories, if that applies.
2042 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2046 STRV_FOREACH(i
, files
) {
2047 bool has_vendor
= false;
2050 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2053 STRV_FOREACH(p
, paths
.search_path
) {
2054 _cleanup_free_
char *path
= NULL
, *dropin
= NULL
;
2057 path
= path_make_absolute(*i
, *p
);
2061 r
= lstat(path
, &st
);
2063 if (errno
!= ENOENT
)
2065 } else if (S_ISREG(st
.st_mode
)) {
2066 /* Check if there's a vendor version */
2067 r
= path_is_vendor(&paths
, path
);
2074 dropin
= strappend(path
, ".d");
2078 r
= lstat(dropin
, &st
);
2080 if (errno
!= ENOENT
)
2082 } else if (S_ISDIR(st
.st_mode
)) {
2083 /* Remove the drop-ins */
2084 r
= path_shall_revert(&paths
, dropin
);
2088 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2091 todo
[n_todo
++] = dropin
;
2100 /* OK, there's a vendor version, hence drop all configuration versions */
2101 STRV_FOREACH(p
, paths
.search_path
) {
2102 _cleanup_free_
char *path
= NULL
;
2105 path
= path_make_absolute(*i
, *p
);
2109 r
= lstat(path
, &st
);
2111 if (errno
!= ENOENT
)
2113 } else if (S_ISREG(st
.st_mode
) || S_ISLNK(st
.st_mode
)) {
2114 r
= path_is_config(&paths
, path
);
2118 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2121 todo
[n_todo
++] = path
;
2131 STRV_FOREACH(i
, todo
) {
2132 _cleanup_strv_free_
char **fs
= NULL
;
2136 (void) get_files_in_directory(*i
, &fs
);
2138 q
= rm_rf(*i
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
2139 if (q
< 0 && q
!= -ENOENT
&& r
>= 0) {
2144 STRV_FOREACH(j
, fs
) {
2145 _cleanup_free_
char *t
= NULL
;
2147 t
= strjoin(*i
, "/", *j
, NULL
);
2151 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, t
, NULL
);
2154 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, *i
, NULL
);
2156 rp
= skip_root(&paths
, *i
);
2157 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: *i
);
2162 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.runtime_config
, &paths
, changes
, n_changes
);
2166 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.persistent_config
, &paths
, changes
, n_changes
);
2173 int unit_file_add_dependency(
2174 UnitFileScope scope
,
2176 const char *root_dir
,
2181 UnitFileChange
**changes
,
2182 unsigned *n_changes
) {
2184 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2185 _cleanup_(install_context_done
) InstallContext c
= {};
2186 UnitFileInstallInfo
*i
, *target_info
;
2187 const char *config_path
;
2192 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2195 if (!IN_SET(dep
, UNIT_WANTS
, UNIT_REQUIRES
))
2198 if (!unit_name_is_valid(target
, UNIT_NAME_ANY
))
2201 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2205 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2207 r
= install_info_discover(scope
, &c
, &paths
, target
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, &target_info
);
2210 r
= install_info_may_process(target_info
, &paths
, changes
, n_changes
);
2214 assert(target_info
->type
== UNIT_FILE_TYPE_REGULAR
);
2216 STRV_FOREACH(f
, files
) {
2219 r
= install_info_discover(scope
, &c
, &paths
, *f
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2222 r
= install_info_may_process(i
, &paths
, changes
, n_changes
);
2226 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2228 /* We didn't actually load anything from the unit
2229 * file, but instead just add in our new symlink to
2232 if (dep
== UNIT_WANTS
)
2235 l
= &i
->required_by
;
2238 *l
= strv_new(target_info
->name
, NULL
);
2243 return install_context_apply(scope
, &c
, &paths
, config_path
, force
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, changes
, n_changes
);
2246 int unit_file_enable(
2247 UnitFileScope scope
,
2249 const char *root_dir
,
2252 UnitFileChange
**changes
,
2253 unsigned *n_changes
) {
2255 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2256 _cleanup_(install_context_done
) InstallContext c
= {};
2257 const char *config_path
;
2258 UnitFileInstallInfo
*i
;
2263 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2265 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2269 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2271 STRV_FOREACH(f
, files
) {
2272 r
= install_info_discover(scope
, &c
, &paths
, *f
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2275 r
= install_info_may_process(i
, &paths
, changes
, n_changes
);
2279 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2282 /* This will return the number of symlink rules that were
2283 supposed to be created, not the ones actually created. This
2284 is useful to determine whether the passed files had any
2285 installation data at all. */
2287 return install_context_apply(scope
, &c
, &paths
, config_path
, force
, SEARCH_LOAD
, changes
, n_changes
);
2290 int unit_file_disable(
2291 UnitFileScope scope
,
2293 const char *root_dir
,
2295 UnitFileChange
**changes
,
2296 unsigned *n_changes
) {
2298 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2299 _cleanup_(install_context_done
) InstallContext c
= {};
2300 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2301 const char *config_path
;
2306 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2308 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2312 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2314 STRV_FOREACH(i
, files
) {
2315 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2318 r
= install_info_add(&c
, *i
, NULL
, NULL
);
2323 r
= install_context_mark_for_removal(scope
, &c
, &paths
, &remove_symlinks_to
, config_path
);
2327 return remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, changes
, n_changes
);
2330 int unit_file_reenable(
2331 UnitFileScope scope
,
2333 const char *root_dir
,
2336 UnitFileChange
**changes
,
2337 unsigned *n_changes
) {
2343 /* First, we invoke the disable command with only the basename... */
2344 l
= strv_length(files
);
2345 n
= newa(char*, l
+1);
2346 for (i
= 0; i
< l
; i
++)
2347 n
[i
] = basename(files
[i
]);
2350 r
= unit_file_disable(scope
, runtime
, root_dir
, n
, changes
, n_changes
);
2354 /* But the enable command with the full name */
2355 return unit_file_enable(scope
, runtime
, root_dir
, files
, force
, changes
, n_changes
);
2358 int unit_file_set_default(
2359 UnitFileScope scope
,
2360 const char *root_dir
,
2363 UnitFileChange
**changes
,
2364 unsigned *n_changes
) {
2366 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2367 _cleanup_(install_context_done
) InstallContext c
= {};
2368 UnitFileInstallInfo
*i
;
2369 const char *new_path
;
2373 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2376 if (unit_name_to_type(name
) != UNIT_TARGET
) /* this also validates the name */
2378 if (streq(name
, SPECIAL_DEFAULT_TARGET
))
2381 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2385 r
= install_info_discover(scope
, &c
, &paths
, name
, 0, &i
);
2388 r
= install_info_may_process(i
, &paths
, changes
, n_changes
);
2392 new_path
= strjoina(paths
.persistent_config
, "/" SPECIAL_DEFAULT_TARGET
);
2393 return create_symlink(&paths
, i
->path
, new_path
, force
, changes
, n_changes
);
2396 int unit_file_get_default(
2397 UnitFileScope scope
,
2398 const char *root_dir
,
2401 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2402 _cleanup_(install_context_done
) InstallContext c
= {};
2403 UnitFileInstallInfo
*i
;
2408 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2411 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2415 r
= install_info_discover(scope
, &c
, &paths
, SPECIAL_DEFAULT_TARGET
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2418 r
= install_info_may_process(i
, &paths
, NULL
, 0);
2422 n
= strdup(i
->name
);
2430 static int unit_file_lookup_state(
2431 UnitFileScope scope
,
2432 const LookupPaths
*paths
,
2434 UnitFileState
*ret
) {
2436 _cleanup_(install_context_done
) InstallContext c
= {};
2437 UnitFileInstallInfo
*i
;
2438 UnitFileState state
;
2444 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2447 r
= install_info_discover(scope
, &c
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2451 /* Shortcut things, if the caller just wants to know if this unit exists. */
2457 case UNIT_FILE_TYPE_MASKED
:
2458 r
= path_is_runtime(paths
, i
->path
);
2462 state
= r
> 0 ? UNIT_FILE_MASKED_RUNTIME
: UNIT_FILE_MASKED
;
2465 case UNIT_FILE_TYPE_REGULAR
:
2466 r
= path_is_generator(paths
, i
->path
);
2470 state
= UNIT_FILE_GENERATED
;
2474 r
= path_is_transient(paths
, i
->path
);
2478 state
= UNIT_FILE_TRANSIENT
;
2482 r
= find_symlinks_in_scope(scope
, paths
, i
->name
, &state
);
2486 if (UNIT_FILE_INSTALL_INFO_HAS_RULES(i
))
2487 state
= UNIT_FILE_DISABLED
;
2488 else if (UNIT_FILE_INSTALL_INFO_HAS_ALSO(i
))
2489 state
= UNIT_FILE_INDIRECT
;
2491 state
= UNIT_FILE_STATIC
;
2497 assert_not_reached("Unexpect unit file type.");
2504 int unit_file_get_state(
2505 UnitFileScope scope
,
2506 const char *root_dir
,
2508 UnitFileState
*ret
) {
2510 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2514 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2517 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2521 return unit_file_lookup_state(scope
, &paths
, name
, ret
);
2524 int unit_file_exists(UnitFileScope scope
, const LookupPaths
*paths
, const char *name
) {
2525 _cleanup_(install_context_done
) InstallContext c
= {};
2531 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2534 r
= install_info_discover(scope
, &c
, paths
, name
, 0, NULL
);
2543 static int read_presets(UnitFileScope scope
, const char *root_dir
, Presets
*presets
) {
2544 _cleanup_(presets_freep
) Presets ps
= {};
2545 size_t n_allocated
= 0;
2546 _cleanup_strv_free_
char **files
= NULL
;
2551 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2554 if (scope
== UNIT_FILE_SYSTEM
)
2555 r
= conf_files_list(&files
, ".preset", root_dir
,
2556 "/etc/systemd/system-preset",
2557 "/usr/local/lib/systemd/system-preset",
2558 "/usr/lib/systemd/system-preset",
2559 #ifdef HAVE_SPLIT_USR
2560 "/lib/systemd/system-preset",
2563 else if (scope
== UNIT_FILE_GLOBAL
)
2564 r
= conf_files_list(&files
, ".preset", root_dir
,
2565 "/etc/systemd/user-preset",
2566 "/usr/local/lib/systemd/user-preset",
2567 "/usr/lib/systemd/user-preset",
2570 *presets
= (Presets
){};
2578 STRV_FOREACH(p
, files
) {
2579 _cleanup_fclose_
FILE *f
;
2580 char line
[LINE_MAX
];
2583 f
= fopen(*p
, "re");
2585 if (errno
== ENOENT
)
2591 FOREACH_LINE(line
, f
, return -errno
) {
2592 PresetRule rule
= {};
2593 const char *parameter
;
2601 if (strchr(COMMENTS
, *l
))
2604 parameter
= first_word(l
, "enable");
2608 pattern
= strdup(parameter
);
2612 rule
= (PresetRule
) {
2614 .action
= PRESET_ENABLE
,
2618 parameter
= first_word(l
, "disable");
2622 pattern
= strdup(parameter
);
2626 rule
= (PresetRule
) {
2628 .action
= PRESET_DISABLE
,
2633 if (!GREEDY_REALLOC(ps
.rules
, n_allocated
, ps
.n_rules
+ 1))
2636 ps
.rules
[ps
.n_rules
++] = rule
;
2640 log_syntax(NULL
, LOG_WARNING
, *p
, n
, 0, "Couldn't parse line '%s'. Ignoring.", line
);
2650 static int query_presets(const char *name
, const Presets presets
) {
2651 PresetAction action
= PRESET_UNKNOWN
;
2654 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2657 for (i
= 0; i
< presets
.n_rules
; i
++)
2658 if (fnmatch(presets
.rules
[i
].pattern
, name
, FNM_NOESCAPE
) == 0) {
2659 action
= presets
.rules
[i
].action
;
2664 case PRESET_UNKNOWN
:
2665 log_debug("Preset files don't specify rule for %s. Enabling.", name
);
2668 log_debug("Preset files say enable %s.", name
);
2670 case PRESET_DISABLE
:
2671 log_debug("Preset files say disable %s.", name
);
2674 assert_not_reached("invalid preset action");
2678 int unit_file_query_preset(UnitFileScope scope
, const char *root_dir
, const char *name
) {
2679 _cleanup_(presets_freep
) Presets presets
= {};
2682 r
= read_presets(scope
, root_dir
, &presets
);
2686 return query_presets(name
, presets
);
2689 static int execute_preset(
2690 UnitFileScope scope
,
2691 InstallContext
*plus
,
2692 InstallContext
*minus
,
2693 const LookupPaths
*paths
,
2694 const char *config_path
,
2696 UnitFilePresetMode mode
,
2698 UnitFileChange
**changes
,
2699 unsigned *n_changes
) {
2706 assert(config_path
);
2708 if (mode
!= UNIT_FILE_PRESET_ENABLE_ONLY
) {
2709 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2711 r
= install_context_mark_for_removal(scope
, minus
, paths
, &remove_symlinks_to
, config_path
);
2715 r
= remove_marked_symlinks(remove_symlinks_to
, config_path
, paths
, changes
, n_changes
);
2719 if (mode
!= UNIT_FILE_PRESET_DISABLE_ONLY
) {
2722 /* Returns number of symlinks that where supposed to be installed. */
2723 q
= install_context_apply(scope
, plus
, paths
, config_path
, force
, SEARCH_LOAD
, changes
, n_changes
);
2735 static int preset_prepare_one(
2736 UnitFileScope scope
,
2737 InstallContext
*plus
,
2738 InstallContext
*minus
,
2742 UnitFileChange
**changes
,
2743 unsigned *n_changes
) {
2745 _cleanup_(install_context_done
) InstallContext tmp
= {};
2746 UnitFileInstallInfo
*i
;
2749 if (install_info_find(plus
, name
) || install_info_find(minus
, name
))
2752 r
= install_info_discover(scope
, &tmp
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2755 if (!streq(name
, i
->name
)) {
2756 log_debug("Skipping %s because is an alias for %s", name
, i
->name
);
2760 r
= query_presets(name
, presets
);
2765 r
= install_info_discover(scope
, plus
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2769 r
= install_info_may_process(i
, paths
, changes
, n_changes
);
2773 r
= install_info_discover(scope
, minus
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2778 int unit_file_preset(
2779 UnitFileScope scope
,
2781 const char *root_dir
,
2783 UnitFilePresetMode mode
,
2785 UnitFileChange
**changes
,
2786 unsigned *n_changes
) {
2788 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
2789 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2790 _cleanup_(presets_freep
) Presets presets
= {};
2791 const char *config_path
;
2796 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2797 assert(mode
< _UNIT_FILE_PRESET_MAX
);
2799 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2803 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2805 r
= read_presets(scope
, root_dir
, &presets
);
2809 STRV_FOREACH(i
, files
) {
2810 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, *i
, presets
, changes
, n_changes
);
2815 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, files
, mode
, force
, changes
, n_changes
);
2818 int unit_file_preset_all(
2819 UnitFileScope scope
,
2821 const char *root_dir
,
2822 UnitFilePresetMode mode
,
2824 UnitFileChange
**changes
,
2825 unsigned *n_changes
) {
2827 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
2828 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2829 _cleanup_(presets_freep
) Presets presets
= {};
2830 const char *config_path
= NULL
;
2835 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2836 assert(mode
< _UNIT_FILE_PRESET_MAX
);
2838 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2842 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2844 r
= read_presets(scope
, root_dir
, &presets
);
2848 STRV_FOREACH(i
, paths
.search_path
) {
2849 _cleanup_closedir_
DIR *d
= NULL
;
2854 if (errno
== ENOENT
)
2860 FOREACH_DIRENT(de
, d
, return -errno
) {
2862 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
2865 dirent_ensure_type(d
, de
);
2867 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
2870 /* we don't pass changes[] in, because we want to handle errors on our own */
2871 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, de
->d_name
, presets
, NULL
, 0);
2873 r
= unit_file_changes_add(changes
, n_changes
,
2874 UNIT_FILE_IS_MASKED
, de
->d_name
, NULL
);
2875 else if (r
== -ENOLINK
)
2876 r
= unit_file_changes_add(changes
, n_changes
,
2877 UNIT_FILE_IS_DANGLING
, de
->d_name
, NULL
);
2883 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, NULL
, mode
, force
, changes
, n_changes
);
2886 static void unit_file_list_free_one(UnitFileList
*f
) {
2894 Hashmap
* unit_file_list_free(Hashmap
*h
) {
2897 while ((i
= hashmap_steal_first(h
)))
2898 unit_file_list_free_one(i
);
2900 return hashmap_free(h
);
2903 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList
*, unit_file_list_free_one
);
2905 int unit_file_get_list(
2906 UnitFileScope scope
,
2907 const char *root_dir
,
2912 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2917 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2920 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2924 STRV_FOREACH(i
, paths
.search_path
) {
2925 _cleanup_closedir_
DIR *d
= NULL
;
2930 if (errno
== ENOENT
)
2932 if (IN_SET(errno
, ENOTDIR
, EACCES
)) {
2933 log_debug("Failed to open \"%s\": %m", *i
);
2940 FOREACH_DIRENT(de
, d
, return -errno
) {
2941 _cleanup_(unit_file_list_free_onep
) UnitFileList
*f
= NULL
;
2943 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
2946 if (!strv_fnmatch_or_empty(patterns
, de
->d_name
, FNM_NOESCAPE
))
2949 if (hashmap_get(h
, de
->d_name
))
2952 dirent_ensure_type(d
, de
);
2954 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
2957 f
= new0(UnitFileList
, 1);
2961 f
->path
= path_make_absolute(de
->d_name
, *i
);
2965 r
= unit_file_lookup_state(scope
, &paths
, de
->d_name
, &f
->state
);
2967 f
->state
= UNIT_FILE_BAD
;
2969 if (!strv_isempty(states
) &&
2970 !strv_contains(states
, unit_file_state_to_string(f
->state
)))
2973 r
= hashmap_put(h
, basename(f
->path
), f
);
2977 f
= NULL
; /* prevent cleanup */
2984 static const char* const unit_file_state_table
[_UNIT_FILE_STATE_MAX
] = {
2985 [UNIT_FILE_ENABLED
] = "enabled",
2986 [UNIT_FILE_ENABLED_RUNTIME
] = "enabled-runtime",
2987 [UNIT_FILE_LINKED
] = "linked",
2988 [UNIT_FILE_LINKED_RUNTIME
] = "linked-runtime",
2989 [UNIT_FILE_MASKED
] = "masked",
2990 [UNIT_FILE_MASKED_RUNTIME
] = "masked-runtime",
2991 [UNIT_FILE_STATIC
] = "static",
2992 [UNIT_FILE_DISABLED
] = "disabled",
2993 [UNIT_FILE_INDIRECT
] = "indirect",
2994 [UNIT_FILE_GENERATED
] = "generated",
2995 [UNIT_FILE_TRANSIENT
] = "transient",
2996 [UNIT_FILE_BAD
] = "bad",
2999 DEFINE_STRING_TABLE_LOOKUP(unit_file_state
, UnitFileState
);
3001 static const char* const unit_file_change_type_table
[_UNIT_FILE_CHANGE_TYPE_MAX
] = {
3002 [UNIT_FILE_SYMLINK
] = "symlink",
3003 [UNIT_FILE_UNLINK
] = "unlink",
3004 [UNIT_FILE_IS_MASKED
] = "masked",
3005 [UNIT_FILE_IS_DANGLING
] = "dangling",
3008 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type
, UnitFileChangeType
);
3010 static const char* const unit_file_preset_mode_table
[_UNIT_FILE_PRESET_MAX
] = {
3011 [UNIT_FILE_PRESET_FULL
] = "full",
3012 [UNIT_FILE_PRESET_ENABLE_ONLY
] = "enable-only",
3013 [UNIT_FILE_PRESET_DISABLE_ONLY
] = "disable-only",
3016 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode
, UnitFilePresetMode
);