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 * Returns negative on error, 0 if the unit was already known, 1 otherwise.
940 static int install_info_add(
945 UnitFileInstallInfo
**ret
) {
947 UnitFileInstallInfo
*i
= NULL
;
951 assert(name
|| path
);
954 name
= basename(path
);
956 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
959 i
= install_info_find(c
, name
);
961 i
->auxiliary
= i
->auxiliary
&& auxiliary
;
968 r
= ordered_hashmap_ensure_allocated(&c
->will_process
, &string_hash_ops
);
972 i
= new0(UnitFileInstallInfo
, 1);
975 i
->type
= _UNIT_FILE_TYPE_INVALID
;
976 i
->auxiliary
= auxiliary
;
978 i
->name
= strdup(name
);
985 i
->path
= strdup(path
);
992 r
= ordered_hashmap_put(c
->will_process
, i
->name
, i
);
1002 install_info_free(i
);
1006 static int config_parse_alias(
1008 const char *filename
,
1010 const char *section
,
1011 unsigned section_line
,
1025 name
= basename(filename
);
1026 type
= unit_name_to_type(name
);
1027 if (!unit_type_may_alias(type
))
1028 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1029 "Alias= is not allowed for %s units, ignoring.",
1030 unit_type_to_string(type
));
1032 return config_parse_strv(unit
, filename
, line
, section
, section_line
,
1033 lvalue
, ltype
, rvalue
, data
, userdata
);
1036 static int config_parse_also(
1038 const char *filename
,
1040 const char *section
,
1041 unsigned section_line
,
1048 UnitFileInstallInfo
*info
= userdata
, *alsoinfo
= NULL
;
1049 InstallContext
*c
= data
;
1057 _cleanup_free_
char *word
= NULL
, *printed
= NULL
;
1059 r
= extract_first_word(&rvalue
, &word
, NULL
, 0);
1065 r
= install_full_printf(info
, word
, &printed
);
1069 if (!unit_name_is_valid(printed
, UNIT_NAME_ANY
))
1072 r
= install_info_add(c
, printed
, NULL
, true, &alsoinfo
);
1076 r
= strv_push(&info
->also
, printed
);
1086 static int config_parse_default_instance(
1088 const char *filename
,
1090 const char *section
,
1091 unsigned section_line
,
1098 UnitFileInstallInfo
*i
= data
;
1100 _cleanup_free_
char *printed
= NULL
;
1107 name
= basename(filename
);
1108 if (unit_name_is_valid(name
, UNIT_NAME_INSTANCE
))
1109 /* When enabling an instance, we might be using a template unit file,
1110 * but we should ignore DefaultInstance silently. */
1112 if (!unit_name_is_valid(name
, UNIT_NAME_TEMPLATE
))
1113 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1114 "DefaultInstance= only makes sense for template units, ignoring.");
1116 r
= install_full_printf(i
, rvalue
, &printed
);
1120 if (!unit_instance_is_valid(printed
))
1123 return free_and_replace(i
->default_instance
, printed
);
1126 static int unit_file_load(
1128 UnitFileInstallInfo
*info
,
1130 SearchFlags flags
) {
1132 const ConfigTableItem items
[] = {
1133 { "Install", "Alias", config_parse_alias
, 0, &info
->aliases
},
1134 { "Install", "WantedBy", config_parse_strv
, 0, &info
->wanted_by
},
1135 { "Install", "RequiredBy", config_parse_strv
, 0, &info
->required_by
},
1136 { "Install", "DefaultInstance", config_parse_default_instance
, 0, info
},
1137 { "Install", "Also", config_parse_also
, 0, c
},
1143 _cleanup_fclose_
FILE *f
= NULL
;
1144 _cleanup_close_
int fd
= -1;
1151 name
= basename(path
);
1152 type
= unit_name_to_type(name
);
1153 if (unit_name_is_valid(name
, UNIT_NAME_TEMPLATE
|UNIT_NAME_INSTANCE
) &&
1154 !unit_type_may_template(type
))
1155 return log_error_errno(EINVAL
, "Unit type %s cannot be templated.", unit_type_to_string(type
));
1157 if (!(flags
& SEARCH_LOAD
)) {
1158 r
= lstat(path
, &st
);
1162 if (null_or_empty(&st
))
1163 info
->type
= UNIT_FILE_TYPE_MASKED
;
1164 else if (S_ISREG(st
.st_mode
))
1165 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1166 else if (S_ISLNK(st
.st_mode
))
1168 else if (S_ISDIR(st
.st_mode
))
1176 /* c is only needed if we actually load the file */
1179 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
1182 if (fstat(fd
, &st
) < 0)
1184 if (null_or_empty(&st
)) {
1185 info
->type
= UNIT_FILE_TYPE_MASKED
;
1188 if (S_ISDIR(st
.st_mode
))
1190 if (!S_ISREG(st
.st_mode
))
1193 f
= fdopen(fd
, "re");
1198 r
= config_parse(NULL
, path
, f
,
1200 config_item_table_lookup
, items
,
1201 true, true, false, info
);
1203 return log_debug_errno(r
, "Failed to parse %s: %m", info
->name
);
1205 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1208 (int) strv_length(info
->aliases
) +
1209 (int) strv_length(info
->wanted_by
) +
1210 (int) strv_length(info
->required_by
);
1213 static int unit_file_load_or_readlink(
1215 UnitFileInstallInfo
*info
,
1217 const char *root_dir
,
1218 SearchFlags flags
) {
1220 _cleanup_free_
char *target
= NULL
;
1223 r
= unit_file_load(c
, info
, path
, flags
);
1227 /* This is a symlink, let's read it. */
1229 r
= readlink_malloc(path
, &target
);
1233 if (path_equal(target
, "/dev/null"))
1234 info
->type
= UNIT_FILE_TYPE_MASKED
;
1239 bn
= basename(target
);
1241 if (unit_name_is_valid(info
->name
, UNIT_NAME_PLAIN
)) {
1243 if (!unit_name_is_valid(bn
, UNIT_NAME_PLAIN
))
1246 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1248 if (!unit_name_is_valid(bn
, UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
))
1251 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
)) {
1253 if (!unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
))
1258 /* Enforce that the symlink destination does not
1259 * change the unit file type. */
1261 a
= unit_name_to_type(info
->name
);
1262 b
= unit_name_to_type(bn
);
1263 if (a
< 0 || b
< 0 || a
!= b
)
1266 if (path_is_absolute(target
))
1267 /* This is an absolute path, prefix the root so that we always deal with fully qualified paths */
1268 info
->symlink_target
= prefix_root(root_dir
, target
);
1270 /* This is a relative path, take it relative to the dir the symlink is located in. */
1271 info
->symlink_target
= file_in_same_dir(path
, target
);
1272 if (!info
->symlink_target
)
1275 info
->type
= UNIT_FILE_TYPE_SYMLINK
;
1281 static int unit_file_search(
1283 UnitFileInstallInfo
*info
,
1284 const LookupPaths
*paths
,
1285 SearchFlags flags
) {
1287 _cleanup_free_
char *template = NULL
;
1294 /* Was this unit already loaded? */
1295 if (info
->type
!= _UNIT_FILE_TYPE_INVALID
)
1299 return unit_file_load_or_readlink(c
, info
, info
->path
, paths
->root_dir
, flags
);
1303 STRV_FOREACH(p
, paths
->search_path
) {
1304 _cleanup_free_
char *path
= NULL
;
1306 path
= strjoin(*p
, "/", info
->name
, NULL
);
1310 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1315 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1319 if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1320 /* Unit file doesn't exist, however instance
1321 * enablement was requested. We will check if it is
1322 * possible to load template unit file. */
1324 r
= unit_name_template(info
->name
, &template);
1328 STRV_FOREACH(p
, paths
->search_path
) {
1329 _cleanup_free_
char *path
= NULL
;
1331 path
= strjoin(*p
, "/", template, NULL
);
1335 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1340 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1345 log_debug("Cannot find unit %s%s%s.", info
->name
, template ? " or " : "", strempty(template));
1349 static int install_info_follow(
1351 UnitFileInstallInfo
*i
,
1352 const char *root_dir
,
1353 SearchFlags flags
) {
1358 if (i
->type
!= UNIT_FILE_TYPE_SYMLINK
)
1360 if (!i
->symlink_target
)
1363 /* If the basename doesn't match, the caller should add a
1364 * complete new entry for this. */
1366 if (!streq(basename(i
->symlink_target
), i
->name
))
1369 free_and_replace(i
->path
, i
->symlink_target
);
1370 i
->type
= _UNIT_FILE_TYPE_INVALID
;
1372 return unit_file_load_or_readlink(c
, i
, i
->path
, root_dir
, flags
);
1376 * Search for the unit file. If the unit name is a symlink, follow the symlink to the
1377 * target, maybe more than once. Propagate the instance name if present.
1379 static int install_info_traverse(
1380 UnitFileScope scope
,
1382 const LookupPaths
*paths
,
1383 UnitFileInstallInfo
*start
,
1385 UnitFileInstallInfo
**ret
) {
1387 UnitFileInstallInfo
*i
;
1395 r
= unit_file_search(c
, start
, paths
, flags
);
1400 while (i
->type
== UNIT_FILE_TYPE_SYMLINK
) {
1401 /* Follow the symlink */
1403 if (++k
> UNIT_FILE_FOLLOW_SYMLINK_MAX
)
1406 if (!(flags
& SEARCH_FOLLOW_CONFIG_SYMLINKS
)) {
1407 r
= path_is_config(paths
, i
->path
);
1414 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
);
1416 _cleanup_free_
char *buffer
= NULL
;
1419 /* Target has a different name, create a new
1420 * install info object for that, and continue
1423 bn
= basename(i
->symlink_target
);
1425 if (unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
) &&
1426 unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
)) {
1428 _cleanup_free_
char *instance
= NULL
;
1430 r
= unit_name_to_instance(i
->name
, &instance
);
1434 r
= unit_name_replace_instance(bn
, instance
, &buffer
);
1441 r
= install_info_add(c
, bn
, NULL
, false, &i
);
1445 /* Try again, with the new target we found. */
1446 r
= unit_file_search(c
, i
, paths
, flags
);
1448 /* Translate error code to highlight this specific case */
1463 * Call install_info_add() with name_or_path as the path (if name_or_path starts with "/")
1464 * or the name (otherwise). root_dir is prepended to the path.
1466 static int install_info_add_auto(
1468 const LookupPaths
*paths
,
1469 const char *name_or_path
,
1470 UnitFileInstallInfo
**ret
) {
1473 assert(name_or_path
);
1475 if (path_is_absolute(name_or_path
)) {
1478 pp
= prefix_roota(paths
->root_dir
, name_or_path
);
1480 return install_info_add(c
, NULL
, pp
, false, ret
);
1482 return install_info_add(c
, name_or_path
, NULL
, false, ret
);
1485 static int install_info_discover(
1486 UnitFileScope scope
,
1488 const LookupPaths
*paths
,
1491 UnitFileInstallInfo
**ret
,
1492 UnitFileChange
**changes
,
1493 unsigned *n_changes
) {
1495 UnitFileInstallInfo
*i
;
1502 r
= install_info_add_auto(c
, paths
, name
, &i
);
1504 r
= install_info_traverse(scope
, c
, paths
, i
, flags
, ret
);
1507 unit_file_changes_add(changes
, n_changes
, r
, name
, NULL
);
1511 static int install_info_symlink_alias(
1512 UnitFileInstallInfo
*i
,
1513 const LookupPaths
*paths
,
1514 const char *config_path
,
1516 UnitFileChange
**changes
,
1517 unsigned *n_changes
) {
1524 assert(config_path
);
1526 STRV_FOREACH(s
, i
->aliases
) {
1527 _cleanup_free_
char *alias_path
= NULL
, *dst
= NULL
;
1529 q
= install_full_printf(i
, *s
, &dst
);
1533 alias_path
= path_make_absolute(dst
, config_path
);
1537 q
= create_symlink(paths
, i
->path
, alias_path
, force
, changes
, n_changes
);
1545 static int install_info_symlink_wants(
1546 UnitFileInstallInfo
*i
,
1547 const LookupPaths
*paths
,
1548 const char *config_path
,
1551 UnitFileChange
**changes
,
1552 unsigned *n_changes
) {
1554 _cleanup_free_
char *buf
= NULL
;
1561 assert(config_path
);
1563 if (strv_isempty(list
))
1566 if (unit_name_is_valid(i
->name
, UNIT_NAME_TEMPLATE
)) {
1567 UnitFileInstallInfo instance
= {
1568 .type
= _UNIT_FILE_TYPE_INVALID
,
1570 _cleanup_free_
char *path
= NULL
;
1572 /* Don't install any symlink if there's no default
1573 * instance configured */
1575 if (!i
->default_instance
)
1578 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &buf
);
1582 instance
.name
= buf
;
1583 r
= unit_file_search(NULL
, &instance
, paths
, SEARCH_FOLLOW_CONFIG_SYMLINKS
);
1587 path
= instance
.path
;
1588 instance
.path
= NULL
;
1590 if (instance
.type
== UNIT_FILE_TYPE_MASKED
) {
1591 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, path
, NULL
);
1599 STRV_FOREACH(s
, list
) {
1600 _cleanup_free_
char *path
= NULL
, *dst
= NULL
;
1602 q
= install_full_printf(i
, *s
, &dst
);
1606 if (!unit_name_is_valid(dst
, UNIT_NAME_ANY
)) {
1611 path
= strjoin(config_path
, "/", dst
, suffix
, n
, NULL
);
1615 q
= create_symlink(paths
, i
->path
, path
, true, changes
, n_changes
);
1623 static int install_info_symlink_link(
1624 UnitFileInstallInfo
*i
,
1625 const LookupPaths
*paths
,
1626 const char *config_path
,
1628 UnitFileChange
**changes
,
1629 unsigned *n_changes
) {
1631 _cleanup_free_
char *path
= NULL
;
1636 assert(config_path
);
1639 r
= in_search_path(paths
, i
->path
);
1645 path
= strjoin(config_path
, "/", i
->name
, NULL
);
1649 return create_symlink(paths
, i
->path
, path
, force
, changes
, n_changes
);
1652 static int install_info_apply(
1653 UnitFileInstallInfo
*i
,
1654 const LookupPaths
*paths
,
1655 const char *config_path
,
1657 UnitFileChange
**changes
,
1658 unsigned *n_changes
) {
1664 assert(config_path
);
1666 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
1669 r
= install_info_symlink_alias(i
, paths
, config_path
, force
, changes
, n_changes
);
1671 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->wanted_by
, ".wants/", changes
, n_changes
);
1675 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->required_by
, ".requires/", changes
, n_changes
);
1679 q
= install_info_symlink_link(i
, paths
, config_path
, force
, changes
, n_changes
);
1680 /* Do not count links to the unit file towards the "carries_install_info" count */
1681 if (r
== 0 && q
< 0)
1687 static int install_context_apply(
1688 UnitFileScope scope
,
1690 const LookupPaths
*paths
,
1691 const char *config_path
,
1694 UnitFileChange
**changes
,
1695 unsigned *n_changes
) {
1697 UnitFileInstallInfo
*i
;
1702 assert(config_path
);
1704 if (ordered_hashmap_isempty(c
->will_process
))
1707 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
1712 while ((i
= ordered_hashmap_first(c
->will_process
))) {
1715 q
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
1719 r
= install_info_traverse(scope
, c
, paths
, i
, flags
, NULL
);
1721 unit_file_changes_add(changes
, n_changes
, r
, i
->name
, NULL
);
1725 /* We can attempt to process a masked unit when a different unit
1726 * that we were processing specifies it in Also=. */
1727 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
1728 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_IS_MASKED
, i
->path
, NULL
);
1730 /* Assume that something *could* have been enabled here,
1731 * avoid "empty [Install] section" warning. */
1736 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
1739 q
= install_info_apply(i
, paths
, config_path
, force
, changes
, n_changes
);
1751 static int install_context_mark_for_removal(
1752 UnitFileScope scope
,
1754 const LookupPaths
*paths
,
1755 Set
**remove_symlinks_to
,
1756 const char *config_path
) {
1758 UnitFileInstallInfo
*i
;
1763 assert(config_path
);
1765 /* Marks all items for removal */
1767 if (ordered_hashmap_isempty(c
->will_process
))
1770 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
1774 while ((i
= ordered_hashmap_first(c
->will_process
))) {
1776 r
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
1780 r
= install_info_traverse(scope
, c
, paths
, i
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, NULL
);
1781 if (r
== -ENOLINK
) {
1782 log_debug_errno(r
, "Name %s leads to a dangling symlink, ignoring.", i
->name
);
1784 } else if (r
== -ENOENT
&& i
->auxiliary
) {
1785 /* some unit specified in Also= or similar is missing */
1786 log_debug_errno(r
, "Auxiliary unit %s not found, ignoring.", i
->name
);
1789 return log_debug_errno(r
, "Failed to find unit %s: %m", i
->name
);
1791 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
) {
1792 log_debug("Unit %s has type %s, ignoring.",
1794 unit_file_type_to_string(i
->type
) ?: "invalid");
1798 r
= mark_symlink_for_removal(remove_symlinks_to
, i
->name
);
1807 UnitFileScope scope
,
1809 const char *root_dir
,
1812 UnitFileChange
**changes
,
1813 unsigned *n_changes
) {
1815 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1816 const char *config_path
;
1821 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1823 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1827 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
1829 STRV_FOREACH(i
, files
) {
1830 _cleanup_free_
char *path
= NULL
;
1833 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
)) {
1839 path
= path_make_absolute(*i
, config_path
);
1843 q
= create_symlink(&paths
, "/dev/null", path
, force
, changes
, n_changes
);
1844 if (q
< 0 && r
>= 0)
1851 int unit_file_unmask(
1852 UnitFileScope scope
,
1854 const char *root_dir
,
1856 UnitFileChange
**changes
,
1857 unsigned *n_changes
) {
1859 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1860 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
1861 _cleanup_free_
char **todo
= NULL
;
1862 size_t n_todo
= 0, n_allocated
= 0;
1863 const char *config_path
;
1868 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1870 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1874 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
1876 STRV_FOREACH(i
, files
) {
1877 _cleanup_free_
char *path
= NULL
;
1879 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
1882 path
= path_make_absolute(*i
, config_path
);
1886 r
= null_or_empty_path(path
);
1894 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
1897 todo
[n_todo
++] = *i
;
1903 STRV_FOREACH(i
, todo
) {
1904 _cleanup_free_
char *path
= NULL
;
1907 path
= path_make_absolute(*i
, config_path
);
1911 if (unlink(path
) < 0) {
1912 if (errno
!= ENOENT
) {
1915 unit_file_changes_add(changes
, n_changes
, -errno
, path
, NULL
);
1921 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
1923 rp
= skip_root(&paths
, path
);
1924 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: path
);
1929 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, changes
, n_changes
);
1937 UnitFileScope scope
,
1939 const char *root_dir
,
1942 UnitFileChange
**changes
,
1943 unsigned *n_changes
) {
1945 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1946 _cleanup_free_
char **todo
= NULL
;
1947 size_t n_todo
= 0, n_allocated
= 0;
1948 const char *config_path
;
1953 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1955 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1959 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
1961 STRV_FOREACH(i
, files
) {
1962 _cleanup_free_
char *full
= NULL
;
1966 if (!path_is_absolute(*i
))
1970 if (!unit_name_is_valid(fn
, UNIT_NAME_ANY
))
1973 full
= prefix_root(paths
.root_dir
, *i
);
1977 if (lstat(full
, &st
) < 0)
1979 if (S_ISLNK(st
.st_mode
))
1981 if (S_ISDIR(st
.st_mode
))
1983 if (!S_ISREG(st
.st_mode
))
1986 q
= in_search_path(&paths
, *i
);
1992 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
1995 todo
[n_todo
++] = *i
;
2001 STRV_FOREACH(i
, todo
) {
2002 _cleanup_free_
char *new_path
= NULL
;
2004 new_path
= path_make_absolute(basename(*i
), config_path
);
2008 q
= create_symlink(&paths
, *i
, new_path
, force
, changes
, n_changes
);
2009 if (q
< 0 && r
>= 0)
2016 static int path_shall_revert(const LookupPaths
*paths
, const char *path
) {
2022 /* Checks whether the path is one where the drop-in directories shall be removed. */
2024 r
= path_is_config(paths
, path
);
2028 r
= path_is_control(paths
, path
);
2032 return path_is_transient(paths
, path
);
2035 int unit_file_revert(
2036 UnitFileScope scope
,
2037 const char *root_dir
,
2039 UnitFileChange
**changes
,
2040 unsigned *n_changes
) {
2042 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2043 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2044 _cleanup_strv_free_
char **todo
= NULL
;
2045 size_t n_todo
= 0, n_allocated
= 0;
2049 /* Puts a unit file back into vendor state. This means:
2051 * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and
2052 * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated").
2054 * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in
2055 * "config", but not in "transient" or "control" or even "generated").
2057 * We remove all that in both the runtime and the persistent directories, if that applies.
2060 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2064 STRV_FOREACH(i
, files
) {
2065 bool has_vendor
= false;
2068 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2071 STRV_FOREACH(p
, paths
.search_path
) {
2072 _cleanup_free_
char *path
= NULL
, *dropin
= NULL
;
2075 path
= path_make_absolute(*i
, *p
);
2079 r
= lstat(path
, &st
);
2081 if (errno
!= ENOENT
)
2083 } else if (S_ISREG(st
.st_mode
)) {
2084 /* Check if there's a vendor version */
2085 r
= path_is_vendor(&paths
, path
);
2092 dropin
= strappend(path
, ".d");
2096 r
= lstat(dropin
, &st
);
2098 if (errno
!= ENOENT
)
2100 } else if (S_ISDIR(st
.st_mode
)) {
2101 /* Remove the drop-ins */
2102 r
= path_shall_revert(&paths
, dropin
);
2106 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2109 todo
[n_todo
++] = dropin
;
2118 /* OK, there's a vendor version, hence drop all configuration versions */
2119 STRV_FOREACH(p
, paths
.search_path
) {
2120 _cleanup_free_
char *path
= NULL
;
2123 path
= path_make_absolute(*i
, *p
);
2127 r
= lstat(path
, &st
);
2129 if (errno
!= ENOENT
)
2131 } else if (S_ISREG(st
.st_mode
) || S_ISLNK(st
.st_mode
)) {
2132 r
= path_is_config(&paths
, path
);
2136 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2139 todo
[n_todo
++] = path
;
2149 STRV_FOREACH(i
, todo
) {
2150 _cleanup_strv_free_
char **fs
= NULL
;
2154 (void) get_files_in_directory(*i
, &fs
);
2156 q
= rm_rf(*i
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
2157 if (q
< 0 && q
!= -ENOENT
&& r
>= 0) {
2162 STRV_FOREACH(j
, fs
) {
2163 _cleanup_free_
char *t
= NULL
;
2165 t
= strjoin(*i
, "/", *j
, NULL
);
2169 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, t
, NULL
);
2172 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, *i
, NULL
);
2174 rp
= skip_root(&paths
, *i
);
2175 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: *i
);
2180 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.runtime_config
, &paths
, changes
, n_changes
);
2184 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.persistent_config
, &paths
, changes
, n_changes
);
2191 int unit_file_add_dependency(
2192 UnitFileScope scope
,
2194 const char *root_dir
,
2199 UnitFileChange
**changes
,
2200 unsigned *n_changes
) {
2202 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2203 _cleanup_(install_context_done
) InstallContext c
= {};
2204 UnitFileInstallInfo
*i
, *target_info
;
2205 const char *config_path
;
2210 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2213 if (!IN_SET(dep
, UNIT_WANTS
, UNIT_REQUIRES
))
2216 if (!unit_name_is_valid(target
, UNIT_NAME_ANY
))
2219 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2223 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2225 r
= install_info_discover(scope
, &c
, &paths
, target
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2226 &target_info
, changes
, n_changes
);
2229 r
= install_info_may_process(target_info
, &paths
, changes
, n_changes
);
2233 assert(target_info
->type
== UNIT_FILE_TYPE_REGULAR
);
2235 STRV_FOREACH(f
, files
) {
2238 r
= install_info_discover(scope
, &c
, &paths
, *f
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2239 &i
, changes
, n_changes
);
2242 r
= install_info_may_process(i
, &paths
, changes
, n_changes
);
2246 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2248 /* We didn't actually load anything from the unit
2249 * file, but instead just add in our new symlink to
2252 if (dep
== UNIT_WANTS
)
2255 l
= &i
->required_by
;
2258 *l
= strv_new(target_info
->name
, NULL
);
2263 return install_context_apply(scope
, &c
, &paths
, config_path
, force
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, changes
, n_changes
);
2266 int unit_file_enable(
2267 UnitFileScope scope
,
2269 const char *root_dir
,
2272 UnitFileChange
**changes
,
2273 unsigned *n_changes
) {
2275 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2276 _cleanup_(install_context_done
) InstallContext c
= {};
2277 const char *config_path
;
2278 UnitFileInstallInfo
*i
;
2283 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2285 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2289 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2291 STRV_FOREACH(f
, files
) {
2292 r
= install_info_discover(scope
, &c
, &paths
, *f
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2293 &i
, changes
, n_changes
);
2296 r
= install_info_may_process(i
, &paths
, changes
, n_changes
);
2300 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2303 /* This will return the number of symlink rules that were
2304 supposed to be created, not the ones actually created. This
2305 is useful to determine whether the passed files had any
2306 installation data at all. */
2308 return install_context_apply(scope
, &c
, &paths
, config_path
, force
, SEARCH_LOAD
, changes
, n_changes
);
2311 int unit_file_disable(
2312 UnitFileScope scope
,
2314 const char *root_dir
,
2316 UnitFileChange
**changes
,
2317 unsigned *n_changes
) {
2319 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2320 _cleanup_(install_context_done
) InstallContext c
= {};
2321 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2322 const char *config_path
;
2327 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2329 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2333 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2335 STRV_FOREACH(i
, files
) {
2336 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2339 r
= install_info_add(&c
, *i
, NULL
, false, NULL
);
2344 r
= install_context_mark_for_removal(scope
, &c
, &paths
, &remove_symlinks_to
, config_path
);
2348 return remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, changes
, n_changes
);
2351 int unit_file_reenable(
2352 UnitFileScope scope
,
2354 const char *root_dir
,
2357 UnitFileChange
**changes
,
2358 unsigned *n_changes
) {
2364 /* First, we invoke the disable command with only the basename... */
2365 l
= strv_length(files
);
2366 n
= newa(char*, l
+1);
2367 for (i
= 0; i
< l
; i
++)
2368 n
[i
] = basename(files
[i
]);
2371 r
= unit_file_disable(scope
, runtime
, root_dir
, n
, changes
, n_changes
);
2375 /* But the enable command with the full name */
2376 return unit_file_enable(scope
, runtime
, root_dir
, files
, force
, changes
, n_changes
);
2379 int unit_file_set_default(
2380 UnitFileScope scope
,
2381 const char *root_dir
,
2384 UnitFileChange
**changes
,
2385 unsigned *n_changes
) {
2387 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2388 _cleanup_(install_context_done
) InstallContext c
= {};
2389 UnitFileInstallInfo
*i
;
2390 const char *new_path
;
2394 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2397 if (unit_name_to_type(name
) != UNIT_TARGET
) /* this also validates the name */
2399 if (streq(name
, SPECIAL_DEFAULT_TARGET
))
2402 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2406 r
= install_info_discover(scope
, &c
, &paths
, name
, 0, &i
, changes
, n_changes
);
2409 r
= install_info_may_process(i
, &paths
, changes
, n_changes
);
2413 new_path
= strjoina(paths
.persistent_config
, "/" SPECIAL_DEFAULT_TARGET
);
2414 return create_symlink(&paths
, i
->path
, new_path
, force
, changes
, n_changes
);
2417 int unit_file_get_default(
2418 UnitFileScope scope
,
2419 const char *root_dir
,
2422 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2423 _cleanup_(install_context_done
) InstallContext c
= {};
2424 UnitFileInstallInfo
*i
;
2429 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2432 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2436 r
= install_info_discover(scope
, &c
, &paths
, SPECIAL_DEFAULT_TARGET
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2440 r
= install_info_may_process(i
, &paths
, NULL
, 0);
2444 n
= strdup(i
->name
);
2452 static int unit_file_lookup_state(
2453 UnitFileScope scope
,
2454 const LookupPaths
*paths
,
2456 UnitFileState
*ret
) {
2458 _cleanup_(install_context_done
) InstallContext c
= {};
2459 UnitFileInstallInfo
*i
;
2460 UnitFileState state
;
2466 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2469 r
= install_info_discover(scope
, &c
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2474 /* Shortcut things, if the caller just wants to know if this unit exists. */
2480 case UNIT_FILE_TYPE_MASKED
:
2481 r
= path_is_runtime(paths
, i
->path
);
2485 state
= r
> 0 ? UNIT_FILE_MASKED_RUNTIME
: UNIT_FILE_MASKED
;
2488 case UNIT_FILE_TYPE_REGULAR
:
2489 r
= path_is_generator(paths
, i
->path
);
2493 state
= UNIT_FILE_GENERATED
;
2497 r
= path_is_transient(paths
, i
->path
);
2501 state
= UNIT_FILE_TRANSIENT
;
2505 r
= find_symlinks_in_scope(scope
, paths
, i
->name
, &state
);
2509 if (UNIT_FILE_INSTALL_INFO_HAS_RULES(i
))
2510 state
= UNIT_FILE_DISABLED
;
2511 else if (UNIT_FILE_INSTALL_INFO_HAS_ALSO(i
))
2512 state
= UNIT_FILE_INDIRECT
;
2514 state
= UNIT_FILE_STATIC
;
2520 assert_not_reached("Unexpect unit file type.");
2527 int unit_file_get_state(
2528 UnitFileScope scope
,
2529 const char *root_dir
,
2531 UnitFileState
*ret
) {
2533 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2537 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2540 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2544 return unit_file_lookup_state(scope
, &paths
, name
, ret
);
2547 int unit_file_exists(UnitFileScope scope
, const LookupPaths
*paths
, const char *name
) {
2548 _cleanup_(install_context_done
) InstallContext c
= {};
2554 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2557 r
= install_info_discover(scope
, &c
, paths
, name
, 0, NULL
, NULL
, NULL
);
2566 static int read_presets(UnitFileScope scope
, const char *root_dir
, Presets
*presets
) {
2567 _cleanup_(presets_freep
) Presets ps
= {};
2568 size_t n_allocated
= 0;
2569 _cleanup_strv_free_
char **files
= NULL
;
2574 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2577 if (scope
== UNIT_FILE_SYSTEM
)
2578 r
= conf_files_list(&files
, ".preset", root_dir
,
2579 "/etc/systemd/system-preset",
2580 "/usr/local/lib/systemd/system-preset",
2581 "/usr/lib/systemd/system-preset",
2582 #ifdef HAVE_SPLIT_USR
2583 "/lib/systemd/system-preset",
2586 else if (scope
== UNIT_FILE_GLOBAL
)
2587 r
= conf_files_list(&files
, ".preset", root_dir
,
2588 "/etc/systemd/user-preset",
2589 "/usr/local/lib/systemd/user-preset",
2590 "/usr/lib/systemd/user-preset",
2593 *presets
= (Presets
){};
2601 STRV_FOREACH(p
, files
) {
2602 _cleanup_fclose_
FILE *f
;
2603 char line
[LINE_MAX
];
2606 f
= fopen(*p
, "re");
2608 if (errno
== ENOENT
)
2614 FOREACH_LINE(line
, f
, return -errno
) {
2615 PresetRule rule
= {};
2616 const char *parameter
;
2624 if (strchr(COMMENTS
, *l
))
2627 parameter
= first_word(l
, "enable");
2631 pattern
= strdup(parameter
);
2635 rule
= (PresetRule
) {
2637 .action
= PRESET_ENABLE
,
2641 parameter
= first_word(l
, "disable");
2645 pattern
= strdup(parameter
);
2649 rule
= (PresetRule
) {
2651 .action
= PRESET_DISABLE
,
2656 if (!GREEDY_REALLOC(ps
.rules
, n_allocated
, ps
.n_rules
+ 1))
2659 ps
.rules
[ps
.n_rules
++] = rule
;
2663 log_syntax(NULL
, LOG_WARNING
, *p
, n
, 0, "Couldn't parse line '%s'. Ignoring.", line
);
2673 static int query_presets(const char *name
, const Presets presets
) {
2674 PresetAction action
= PRESET_UNKNOWN
;
2677 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2680 for (i
= 0; i
< presets
.n_rules
; i
++)
2681 if (fnmatch(presets
.rules
[i
].pattern
, name
, FNM_NOESCAPE
) == 0) {
2682 action
= presets
.rules
[i
].action
;
2687 case PRESET_UNKNOWN
:
2688 log_debug("Preset files don't specify rule for %s. Enabling.", name
);
2691 log_debug("Preset files say enable %s.", name
);
2693 case PRESET_DISABLE
:
2694 log_debug("Preset files say disable %s.", name
);
2697 assert_not_reached("invalid preset action");
2701 int unit_file_query_preset(UnitFileScope scope
, const char *root_dir
, const char *name
) {
2702 _cleanup_(presets_freep
) Presets presets
= {};
2705 r
= read_presets(scope
, root_dir
, &presets
);
2709 return query_presets(name
, presets
);
2712 static int execute_preset(
2713 UnitFileScope scope
,
2714 InstallContext
*plus
,
2715 InstallContext
*minus
,
2716 const LookupPaths
*paths
,
2717 const char *config_path
,
2719 UnitFilePresetMode mode
,
2721 UnitFileChange
**changes
,
2722 unsigned *n_changes
) {
2729 assert(config_path
);
2731 if (mode
!= UNIT_FILE_PRESET_ENABLE_ONLY
) {
2732 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2734 r
= install_context_mark_for_removal(scope
, minus
, paths
, &remove_symlinks_to
, config_path
);
2738 r
= remove_marked_symlinks(remove_symlinks_to
, config_path
, paths
, changes
, n_changes
);
2742 if (mode
!= UNIT_FILE_PRESET_DISABLE_ONLY
) {
2745 /* Returns number of symlinks that where supposed to be installed. */
2746 q
= install_context_apply(scope
, plus
, paths
, config_path
, force
, SEARCH_LOAD
, changes
, n_changes
);
2758 static int preset_prepare_one(
2759 UnitFileScope scope
,
2760 InstallContext
*plus
,
2761 InstallContext
*minus
,
2765 UnitFileChange
**changes
,
2766 unsigned *n_changes
) {
2768 _cleanup_(install_context_done
) InstallContext tmp
= {};
2769 UnitFileInstallInfo
*i
;
2772 if (install_info_find(plus
, name
) || install_info_find(minus
, name
))
2775 r
= install_info_discover(scope
, &tmp
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2776 &i
, changes
, n_changes
);
2779 if (!streq(name
, i
->name
)) {
2780 log_debug("Skipping %s because is an alias for %s", name
, i
->name
);
2784 r
= query_presets(name
, presets
);
2789 r
= install_info_discover(scope
, plus
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2790 &i
, changes
, n_changes
);
2794 r
= install_info_may_process(i
, paths
, changes
, n_changes
);
2798 r
= install_info_discover(scope
, minus
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
,
2799 &i
, changes
, n_changes
);
2804 int unit_file_preset(
2805 UnitFileScope scope
,
2807 const char *root_dir
,
2809 UnitFilePresetMode mode
,
2811 UnitFileChange
**changes
,
2812 unsigned *n_changes
) {
2814 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
2815 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2816 _cleanup_(presets_freep
) Presets presets
= {};
2817 const char *config_path
;
2822 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2823 assert(mode
< _UNIT_FILE_PRESET_MAX
);
2825 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2829 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2831 r
= read_presets(scope
, root_dir
, &presets
);
2835 STRV_FOREACH(i
, files
) {
2836 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, *i
, presets
, changes
, n_changes
);
2841 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, files
, mode
, force
, changes
, n_changes
);
2844 int unit_file_preset_all(
2845 UnitFileScope scope
,
2847 const char *root_dir
,
2848 UnitFilePresetMode mode
,
2850 UnitFileChange
**changes
,
2851 unsigned *n_changes
) {
2853 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
2854 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2855 _cleanup_(presets_freep
) Presets presets
= {};
2856 const char *config_path
= NULL
;
2861 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2862 assert(mode
< _UNIT_FILE_PRESET_MAX
);
2864 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2868 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2870 r
= read_presets(scope
, root_dir
, &presets
);
2874 STRV_FOREACH(i
, paths
.search_path
) {
2875 _cleanup_closedir_
DIR *d
= NULL
;
2880 if (errno
== ENOENT
)
2886 FOREACH_DIRENT(de
, d
, return -errno
) {
2888 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
2891 dirent_ensure_type(d
, de
);
2893 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
2896 /* we don't pass changes[] in, because we want to handle errors on our own */
2897 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, de
->d_name
, presets
, NULL
, 0);
2899 r
= unit_file_changes_add(changes
, n_changes
,
2900 UNIT_FILE_IS_MASKED
, de
->d_name
, NULL
);
2901 else if (r
== -ENOLINK
)
2902 r
= unit_file_changes_add(changes
, n_changes
,
2903 UNIT_FILE_IS_DANGLING
, de
->d_name
, NULL
);
2909 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, NULL
, mode
, force
, changes
, n_changes
);
2912 static void unit_file_list_free_one(UnitFileList
*f
) {
2920 Hashmap
* unit_file_list_free(Hashmap
*h
) {
2923 while ((i
= hashmap_steal_first(h
)))
2924 unit_file_list_free_one(i
);
2926 return hashmap_free(h
);
2929 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList
*, unit_file_list_free_one
);
2931 int unit_file_get_list(
2932 UnitFileScope scope
,
2933 const char *root_dir
,
2938 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2943 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2946 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2950 STRV_FOREACH(i
, paths
.search_path
) {
2951 _cleanup_closedir_
DIR *d
= NULL
;
2956 if (errno
== ENOENT
)
2958 if (IN_SET(errno
, ENOTDIR
, EACCES
)) {
2959 log_debug("Failed to open \"%s\": %m", *i
);
2966 FOREACH_DIRENT(de
, d
, return -errno
) {
2967 _cleanup_(unit_file_list_free_onep
) UnitFileList
*f
= NULL
;
2969 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
2972 if (!strv_fnmatch_or_empty(patterns
, de
->d_name
, FNM_NOESCAPE
))
2975 if (hashmap_get(h
, de
->d_name
))
2978 dirent_ensure_type(d
, de
);
2980 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
2983 f
= new0(UnitFileList
, 1);
2987 f
->path
= path_make_absolute(de
->d_name
, *i
);
2991 r
= unit_file_lookup_state(scope
, &paths
, de
->d_name
, &f
->state
);
2993 f
->state
= UNIT_FILE_BAD
;
2995 if (!strv_isempty(states
) &&
2996 !strv_contains(states
, unit_file_state_to_string(f
->state
)))
2999 r
= hashmap_put(h
, basename(f
->path
), f
);
3003 f
= NULL
; /* prevent cleanup */
3010 static const char* const unit_file_state_table
[_UNIT_FILE_STATE_MAX
] = {
3011 [UNIT_FILE_ENABLED
] = "enabled",
3012 [UNIT_FILE_ENABLED_RUNTIME
] = "enabled-runtime",
3013 [UNIT_FILE_LINKED
] = "linked",
3014 [UNIT_FILE_LINKED_RUNTIME
] = "linked-runtime",
3015 [UNIT_FILE_MASKED
] = "masked",
3016 [UNIT_FILE_MASKED_RUNTIME
] = "masked-runtime",
3017 [UNIT_FILE_STATIC
] = "static",
3018 [UNIT_FILE_DISABLED
] = "disabled",
3019 [UNIT_FILE_INDIRECT
] = "indirect",
3020 [UNIT_FILE_GENERATED
] = "generated",
3021 [UNIT_FILE_TRANSIENT
] = "transient",
3022 [UNIT_FILE_BAD
] = "bad",
3025 DEFINE_STRING_TABLE_LOOKUP(unit_file_state
, UnitFileState
);
3027 static const char* const unit_file_change_type_table
[_UNIT_FILE_CHANGE_TYPE_MAX
] = {
3028 [UNIT_FILE_SYMLINK
] = "symlink",
3029 [UNIT_FILE_UNLINK
] = "unlink",
3030 [UNIT_FILE_IS_MASKED
] = "masked",
3031 [UNIT_FILE_IS_DANGLING
] = "dangling",
3034 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type
, UnitFileChangeType
);
3036 static const char* const unit_file_preset_mode_table
[_UNIT_FILE_PRESET_MAX
] = {
3037 [UNIT_FILE_PRESET_FULL
] = "full",
3038 [UNIT_FILE_PRESET_ENABLE_ONLY
] = "enable-only",
3039 [UNIT_FILE_PRESET_DISABLE_ONLY
] = "disable-only",
3042 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode
, UnitFilePresetMode
);