2 This file is part of systemd.
4 Copyright 2011 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty <of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
32 #include "alloc-util.h"
33 #include "conf-files.h"
34 #include "conf-parser.h"
35 #include "dirent-util.h"
36 #include "extract-word.h"
41 #include "install-printf.h"
46 #include "path-lookup.h"
47 #include "path-util.h"
51 #include "stat-util.h"
52 #include "string-table.h"
53 #include "string-util.h"
55 #include "unit-name.h"
57 #define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
59 typedef enum SearchFlags
{
61 SEARCH_FOLLOW_CONFIG_SYMLINKS
= 2,
65 OrderedHashmap
*will_process
;
66 OrderedHashmap
*have_processed
;
69 static int unit_file_lookup_state(UnitFileScope scope
, const LookupPaths
*paths
, const char *name
, UnitFileState
*ret
);
71 static int in_search_path(const LookupPaths
*p
, const char *path
) {
72 _cleanup_free_
char *parent
= NULL
;
77 parent
= dirname_malloc(path
);
81 STRV_FOREACH(i
, p
->search_path
)
82 if (path_equal(parent
, *i
))
88 static const char* skip_root(const LookupPaths
*p
, const char *path
) {
97 e
= path_startswith(path
, p
->root_dir
);
101 /* Make sure the returned path starts with a slash */
103 if (e
== path
|| e
[-1] != '/')
112 static int path_is_generator(const LookupPaths
*p
, const char *path
) {
113 _cleanup_free_
char *parent
= NULL
;
118 parent
= dirname_malloc(path
);
122 return path_equal_ptr(parent
, p
->generator
) ||
123 path_equal_ptr(parent
, p
->generator_early
) ||
124 path_equal_ptr(parent
, p
->generator_late
);
127 static int path_is_transient(const LookupPaths
*p
, const char *path
) {
128 _cleanup_free_
char *parent
= NULL
;
133 parent
= dirname_malloc(path
);
137 return path_equal_ptr(parent
, p
->transient
);
140 static int path_is_control(const LookupPaths
*p
, const char *path
) {
141 _cleanup_free_
char *parent
= NULL
;
146 parent
= dirname_malloc(path
);
150 return path_equal_ptr(parent
, p
->persistent_control
) ||
151 path_equal_ptr(parent
, p
->runtime_control
);
154 static int path_is_config(const LookupPaths
*p
, const char *path
) {
155 _cleanup_free_
char *parent
= NULL
;
160 /* Note that we do *not* have generic checks for /etc or /run in place, since with them we couldn't discern
161 * configuration from transient or generated units */
163 parent
= dirname_malloc(path
);
167 return path_equal_ptr(parent
, p
->persistent_config
) ||
168 path_equal_ptr(parent
, p
->runtime_config
);
171 static int path_is_runtime(const LookupPaths
*p
, const char *path
) {
172 _cleanup_free_
char *parent
= NULL
;
178 /* Everything in /run is considered runtime. On top of that we also add explicit checks for the various runtime
179 * directories, as safety net. */
181 rpath
= skip_root(p
, path
);
182 if (rpath
&& path_startswith(rpath
, "/run"))
185 parent
= dirname_malloc(path
);
189 return path_equal_ptr(parent
, p
->runtime_config
) ||
190 path_equal_ptr(parent
, p
->generator
) ||
191 path_equal_ptr(parent
, p
->generator_early
) ||
192 path_equal_ptr(parent
, p
->generator_late
) ||
193 path_equal_ptr(parent
, p
->transient
) ||
194 path_equal_ptr(parent
, p
->runtime_control
);
197 static int path_is_vendor(const LookupPaths
*p
, const char *path
) {
203 rpath
= skip_root(p
, path
);
207 if (path_startswith(rpath
, "/usr"))
210 #ifdef HAVE_SPLIT_USR
211 if (path_startswith(rpath
, "/lib"))
215 return path_equal(rpath
, SYSTEM_DATA_UNIT_PATH
);
218 int unit_file_changes_add(
219 UnitFileChange
**changes
,
221 UnitFileChangeType type
,
223 const char *source
) {
229 assert(!changes
== !n_changes
);
234 c
= realloc(*changes
, (*n_changes
+ 1) * sizeof(UnitFileChange
));
242 c
[i
].path
= strdup(path
);
246 path_kill_slashes(c
[i
].path
);
249 c
[i
].source
= strdup(source
);
255 path_kill_slashes(c
[i
].path
);
263 void unit_file_changes_free(UnitFileChange
*changes
, unsigned n_changes
) {
266 assert(changes
|| n_changes
== 0);
271 for (i
= 0; i
< n_changes
; i
++) {
272 free(changes
[i
].path
);
273 free(changes
[i
].source
);
279 static int create_symlink(
280 const char *old_path
,
281 const char *new_path
,
283 UnitFileChange
**changes
,
284 unsigned *n_changes
) {
286 _cleanup_free_
char *dest
= NULL
;
292 /* Actually create a symlink, and remember that we did. Is
293 * smart enough to check if there's already a valid symlink in
296 mkdir_parents_label(new_path
, 0755);
298 if (symlink(old_path
, new_path
) >= 0) {
299 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
306 r
= readlink_malloc(new_path
, &dest
);
310 if (path_equal(dest
, old_path
))
316 r
= symlink_atomic(old_path
, new_path
);
320 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, new_path
, NULL
);
321 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
326 static int mark_symlink_for_removal(
327 Set
**remove_symlinks_to
,
335 r
= set_ensure_allocated(remove_symlinks_to
, &string_hash_ops
);
343 path_kill_slashes(n
);
345 r
= set_consume(*remove_symlinks_to
, n
);
354 static int remove_marked_symlinks_fd(
355 Set
*remove_symlinks_to
,
358 const char *config_path
,
359 const LookupPaths
*lp
,
361 UnitFileChange
**changes
,
362 unsigned *n_changes
) {
364 _cleanup_closedir_
DIR *d
= NULL
;
368 assert(remove_symlinks_to
);
383 FOREACH_DIRENT(de
, d
, return -errno
) {
385 dirent_ensure_type(d
, de
);
387 if (de
->d_type
== DT_DIR
) {
388 _cleanup_free_
char *p
= NULL
;
391 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
401 p
= path_make_absolute(de
->d_name
, path
);
407 /* This will close nfd, regardless whether it succeeds or not */
408 q
= remove_marked_symlinks_fd(remove_symlinks_to
, nfd
, p
, config_path
, lp
, restart
, changes
, n_changes
);
412 } else if (de
->d_type
== DT_LNK
) {
413 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
418 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
421 p
= path_make_absolute(de
->d_name
, path
);
425 q
= readlink_malloc(p
, &dest
);
434 /* We remove all links pointing to a file or path that is marked, as well as all files sharing
435 * the same name as a file that is marked. */
437 found
= set_contains(remove_symlinks_to
, dest
) ||
438 set_contains(remove_symlinks_to
, basename(dest
)) ||
439 set_contains(remove_symlinks_to
, de
->d_name
);
444 if (unlinkat(fd
, de
->d_name
, 0) < 0 && errno
!= ENOENT
) {
450 path_kill_slashes(p
);
451 (void) rmdir_parents(p
, config_path
);
453 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, p
, NULL
);
455 /* Now, remember the full path (but with the root prefix removed) of the symlink we just
456 * removed, and remove any symlinks to it, too */
458 rp
= skip_root(lp
, p
);
459 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: p
);
470 static int remove_marked_symlinks(
471 Set
*remove_symlinks_to
,
472 const char *config_path
,
473 const LookupPaths
*lp
,
474 UnitFileChange
**changes
,
475 unsigned *n_changes
) {
477 _cleanup_close_
int fd
= -1;
484 if (set_size(remove_symlinks_to
) <= 0)
487 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
495 cfd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
499 /* This takes possession of cfd and closes it */
500 q
= remove_marked_symlinks_fd(remove_symlinks_to
, cfd
, config_path
, config_path
, lp
, &restart
, changes
, n_changes
);
508 static int find_symlinks_fd(
509 const char *root_dir
,
513 const char *config_path
,
514 const LookupPaths
*lp
,
515 bool *same_name_link
) {
517 _cleanup_closedir_
DIR *d
= NULL
;
526 assert(same_name_link
);
534 FOREACH_DIRENT(de
, d
, return -errno
) {
536 dirent_ensure_type(d
, de
);
538 if (de
->d_type
== DT_DIR
) {
539 _cleanup_free_
char *p
= NULL
;
542 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
552 p
= path_make_absolute(de
->d_name
, path
);
558 /* This will close nfd, regardless whether it succeeds or not */
559 q
= find_symlinks_fd(root_dir
, name
, nfd
, p
, config_path
, lp
, same_name_link
);
565 } else if (de
->d_type
== DT_LNK
) {
566 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
567 bool found_path
, found_dest
, b
= false;
570 /* Acquire symlink name */
571 p
= path_make_absolute(de
->d_name
, path
);
575 /* Acquire symlink destination */
576 q
= readlink_malloc(p
, &dest
);
586 if (!path_is_absolute(dest
)) {
589 x
= prefix_root(root_dir
, dest
);
597 /* Check if the symlink itself matches what we
599 if (path_is_absolute(name
))
600 found_path
= path_equal(p
, name
);
602 found_path
= streq(de
->d_name
, name
);
604 /* Check if what the symlink points to
605 * matches what we are looking for */
606 if (path_is_absolute(name
))
607 found_dest
= path_equal(dest
, name
);
609 found_dest
= streq(basename(dest
), name
);
611 if (found_path
&& found_dest
) {
612 _cleanup_free_
char *t
= NULL
;
614 /* Filter out same name links in the main
616 t
= path_make_absolute(name
, config_path
);
620 b
= path_equal(t
, p
);
624 *same_name_link
= true;
625 else if (found_path
|| found_dest
)
633 static int find_symlinks(
634 const char *root_dir
,
636 const char *config_path
,
637 const LookupPaths
*lp
,
638 bool *same_name_link
) {
644 assert(same_name_link
);
646 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
653 /* This takes possession of fd and closes it */
654 return find_symlinks_fd(root_dir
, name
, fd
, config_path
, config_path
, lp
, same_name_link
);
657 static int find_symlinks_in_scope(
659 const LookupPaths
*paths
,
661 UnitFileState
*state
) {
663 bool same_name_link_runtime
= false, same_name_link
= false;
667 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
671 /* First look in the persistent config path */
672 r
= find_symlinks(paths
->root_dir
, name
, paths
->persistent_config
, paths
, &same_name_link
);
676 *state
= UNIT_FILE_ENABLED
;
680 /* Then look in runtime config path */
681 r
= find_symlinks(paths
->root_dir
, name
, paths
->runtime_config
, paths
, &same_name_link_runtime
);
685 *state
= UNIT_FILE_ENABLED_RUNTIME
;
689 /* Hmm, we didn't find it, but maybe we found the same name
691 if (same_name_link
) {
692 *state
= UNIT_FILE_LINKED
;
695 if (same_name_link_runtime
) {
696 *state
= UNIT_FILE_LINKED_RUNTIME
;
703 static void install_info_free(UnitFileInstallInfo
*i
) {
710 strv_free(i
->aliases
);
711 strv_free(i
->wanted_by
);
712 strv_free(i
->required_by
);
714 free(i
->default_instance
);
715 free(i
->symlink_target
);
719 static OrderedHashmap
* install_info_hashmap_free(OrderedHashmap
*m
) {
720 UnitFileInstallInfo
*i
;
725 while ((i
= ordered_hashmap_steal_first(m
)))
726 install_info_free(i
);
728 return ordered_hashmap_free(m
);
731 static void install_context_done(InstallContext
*c
) {
734 c
->will_process
= install_info_hashmap_free(c
->will_process
);
735 c
->have_processed
= install_info_hashmap_free(c
->have_processed
);
738 static UnitFileInstallInfo
*install_info_find(InstallContext
*c
, const char *name
) {
739 UnitFileInstallInfo
*i
;
741 i
= ordered_hashmap_get(c
->have_processed
, name
);
745 return ordered_hashmap_get(c
->will_process
, name
);
748 static int install_info_may_process(UnitFileInstallInfo
*i
, const LookupPaths
*paths
) {
752 /* Checks whether the loaded unit file is one we should process, or is masked, transient or generated and thus
753 * not subject to enable/disable operations. */
755 if (i
->type
== UNIT_FILE_TYPE_MASKED
)
757 if (path_is_generator(paths
, i
->path
))
758 return -EADDRNOTAVAIL
;
759 if (path_is_transient(paths
, i
->path
))
760 return -EADDRNOTAVAIL
;
765 static int install_info_add(
769 UnitFileInstallInfo
**ret
) {
771 UnitFileInstallInfo
*i
= NULL
;
775 assert(name
|| path
);
778 name
= basename(path
);
780 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
783 i
= install_info_find(c
, name
);
790 r
= ordered_hashmap_ensure_allocated(&c
->will_process
, &string_hash_ops
);
794 i
= new0(UnitFileInstallInfo
, 1);
797 i
->type
= _UNIT_FILE_TYPE_INVALID
;
799 i
->name
= strdup(name
);
806 i
->path
= strdup(path
);
813 r
= ordered_hashmap_put(c
->will_process
, i
->name
, i
);
823 install_info_free(i
);
827 static int config_parse_also(
829 const char *filename
,
832 unsigned section_line
,
839 UnitFileInstallInfo
*i
= userdata
;
840 InstallContext
*c
= data
;
848 _cleanup_free_
char *word
= NULL
;
850 r
= extract_first_word(&rvalue
, &word
, NULL
, 0);
856 r
= install_info_add(c
, word
, NULL
, NULL
);
860 r
= strv_push(&i
->also
, word
);
870 static int config_parse_default_instance(
872 const char *filename
,
875 unsigned section_line
,
882 UnitFileInstallInfo
*i
= data
;
890 r
= install_full_printf(i
, rvalue
, &printed
);
894 if (!unit_instance_is_valid(printed
)) {
899 free(i
->default_instance
);
900 i
->default_instance
= printed
;
905 static int unit_file_load(
907 UnitFileInstallInfo
*info
,
911 const ConfigTableItem items
[] = {
912 { "Install", "Alias", config_parse_strv
, 0, &info
->aliases
},
913 { "Install", "WantedBy", config_parse_strv
, 0, &info
->wanted_by
},
914 { "Install", "RequiredBy", config_parse_strv
, 0, &info
->required_by
},
915 { "Install", "DefaultInstance", config_parse_default_instance
, 0, info
},
916 { "Install", "Also", config_parse_also
, 0, c
},
920 _cleanup_fclose_
FILE *f
= NULL
;
921 _cleanup_close_
int fd
= -1;
929 if (!(flags
& SEARCH_LOAD
)) {
930 r
= lstat(path
, &st
);
934 if (null_or_empty(&st
))
935 info
->type
= UNIT_FILE_TYPE_MASKED
;
936 else if (S_ISREG(st
.st_mode
))
937 info
->type
= UNIT_FILE_TYPE_REGULAR
;
938 else if (S_ISLNK(st
.st_mode
))
940 else if (S_ISDIR(st
.st_mode
))
948 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
951 if (fstat(fd
, &st
) < 0)
953 if (null_or_empty(&st
)) {
954 info
->type
= UNIT_FILE_TYPE_MASKED
;
957 if (S_ISDIR(st
.st_mode
))
959 if (!S_ISREG(st
.st_mode
))
962 f
= fdopen(fd
, "re");
967 r
= config_parse(NULL
, path
, f
,
969 config_item_table_lookup
, items
,
970 true, true, false, info
);
974 info
->type
= UNIT_FILE_TYPE_REGULAR
;
977 (int) strv_length(info
->aliases
) +
978 (int) strv_length(info
->wanted_by
) +
979 (int) strv_length(info
->required_by
);
982 static int unit_file_load_or_readlink(
984 UnitFileInstallInfo
*info
,
986 const char *root_dir
,
989 _cleanup_free_
char *target
= NULL
;
992 r
= unit_file_load(c
, info
, path
, flags
);
996 /* This is a symlink, let's read it. */
998 r
= readlink_malloc(path
, &target
);
1002 if (path_equal(target
, "/dev/null"))
1003 info
->type
= UNIT_FILE_TYPE_MASKED
;
1008 bn
= basename(target
);
1010 if (unit_name_is_valid(info
->name
, UNIT_NAME_PLAIN
)) {
1012 if (!unit_name_is_valid(bn
, UNIT_NAME_PLAIN
))
1015 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1017 if (!unit_name_is_valid(bn
, UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
))
1020 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
)) {
1022 if (!unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
))
1027 /* Enforce that the symlink destination does not
1028 * change the unit file type. */
1030 a
= unit_name_to_type(info
->name
);
1031 b
= unit_name_to_type(bn
);
1032 if (a
< 0 || b
< 0 || a
!= b
)
1035 if (path_is_absolute(target
))
1036 /* This is an absolute path, prefix the root so that we always deal with fully qualified paths */
1037 info
->symlink_target
= prefix_root(root_dir
, target
);
1039 /* This is a relative path, take it relative to the dir the symlink is located in. */
1040 info
->symlink_target
= file_in_same_dir(path
, target
);
1041 if (!info
->symlink_target
)
1044 info
->type
= UNIT_FILE_TYPE_SYMLINK
;
1050 static int unit_file_search(
1052 UnitFileInstallInfo
*info
,
1053 const LookupPaths
*paths
,
1054 SearchFlags flags
) {
1063 /* Was this unit already loaded? */
1064 if (info
->type
!= _UNIT_FILE_TYPE_INVALID
)
1068 return unit_file_load_or_readlink(c
, info
, info
->path
, paths
->root_dir
, flags
);
1072 STRV_FOREACH(p
, paths
->search_path
) {
1073 _cleanup_free_
char *path
= NULL
;
1075 path
= strjoin(*p
, "/", info
->name
, NULL
);
1079 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1090 if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1092 /* Unit file doesn't exist, however instance
1093 * enablement was requested. We will check if it is
1094 * possible to load template unit file. */
1096 _cleanup_free_
char *template = NULL
;
1098 r
= unit_name_template(info
->name
, &template);
1102 STRV_FOREACH(p
, paths
->search_path
) {
1103 _cleanup_free_
char *path
= NULL
;
1105 path
= strjoin(*p
, "/", template, NULL
);
1109 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1124 static int install_info_follow(
1126 UnitFileInstallInfo
*i
,
1127 const char *root_dir
,
1128 SearchFlags flags
) {
1133 if (i
->type
!= UNIT_FILE_TYPE_SYMLINK
)
1135 if (!i
->symlink_target
)
1138 /* If the basename doesn't match, the caller should add a
1139 * complete new entry for this. */
1141 if (!streq(basename(i
->symlink_target
), i
->name
))
1145 i
->path
= i
->symlink_target
;
1146 i
->symlink_target
= NULL
;
1147 i
->type
= _UNIT_FILE_TYPE_INVALID
;
1149 return unit_file_load_or_readlink(c
, i
, i
->path
, root_dir
, flags
);
1152 static int install_info_traverse(
1153 UnitFileScope scope
,
1155 const LookupPaths
*paths
,
1156 UnitFileInstallInfo
*start
,
1158 UnitFileInstallInfo
**ret
) {
1160 UnitFileInstallInfo
*i
;
1168 r
= unit_file_search(c
, start
, paths
, flags
);
1173 while (i
->type
== UNIT_FILE_TYPE_SYMLINK
) {
1174 /* Follow the symlink */
1176 if (++k
> UNIT_FILE_FOLLOW_SYMLINK_MAX
)
1179 if (!(flags
& SEARCH_FOLLOW_CONFIG_SYMLINKS
)) {
1180 r
= path_is_config(paths
, i
->path
);
1187 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
);
1189 _cleanup_free_
char *buffer
= NULL
;
1195 /* Target has a different name, create a new
1196 * install info object for that, and continue
1199 bn
= basename(i
->symlink_target
);
1201 if (unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
) &&
1202 unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
)) {
1204 _cleanup_free_
char *instance
= NULL
;
1206 r
= unit_name_to_instance(i
->name
, &instance
);
1210 r
= unit_name_replace_instance(bn
, instance
, &buffer
);
1217 r
= install_info_add(c
, bn
, NULL
, &i
);
1221 r
= unit_file_search(c
, i
, paths
, flags
);
1226 /* Try again, with the new target we found. */
1235 static int install_info_add_auto(
1237 const LookupPaths
*paths
,
1238 const char *name_or_path
,
1239 UnitFileInstallInfo
**ret
) {
1242 assert(name_or_path
);
1244 if (path_is_absolute(name_or_path
)) {
1247 pp
= prefix_roota(paths
->root_dir
, name_or_path
);
1249 return install_info_add(c
, NULL
, pp
, ret
);
1251 return install_info_add(c
, name_or_path
, NULL
, ret
);
1254 static int install_info_discover(
1255 UnitFileScope scope
,
1257 const LookupPaths
*paths
,
1260 UnitFileInstallInfo
**ret
) {
1262 UnitFileInstallInfo
*i
;
1269 r
= install_info_add_auto(c
, paths
, name
, &i
);
1273 return install_info_traverse(scope
, c
, paths
, i
, flags
, ret
);
1276 static int install_info_symlink_alias(
1277 UnitFileInstallInfo
*i
,
1278 const LookupPaths
*paths
,
1279 const char *config_path
,
1281 UnitFileChange
**changes
,
1282 unsigned *n_changes
) {
1289 assert(config_path
);
1291 STRV_FOREACH(s
, i
->aliases
) {
1292 _cleanup_free_
char *alias_path
= NULL
, *dst
= NULL
;
1295 q
= install_full_printf(i
, *s
, &dst
);
1299 alias_path
= path_make_absolute(dst
, config_path
);
1303 rp
= skip_root(paths
, i
->path
);
1305 q
= create_symlink(rp
?: i
->path
, alias_path
, force
, changes
, n_changes
);
1313 static int install_info_symlink_wants(
1314 UnitFileInstallInfo
*i
,
1315 const LookupPaths
*paths
,
1316 const char *config_path
,
1320 UnitFileChange
**changes
,
1321 unsigned *n_changes
) {
1323 _cleanup_free_
char *buf
= NULL
;
1330 assert(config_path
);
1332 if (unit_name_is_valid(i
->name
, UNIT_NAME_TEMPLATE
)) {
1334 /* Don't install any symlink if there's no default
1335 * instance configured */
1337 if (!i
->default_instance
)
1340 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &buf
);
1348 STRV_FOREACH(s
, list
) {
1349 _cleanup_free_
char *path
= NULL
, *dst
= NULL
;
1352 q
= install_full_printf(i
, *s
, &dst
);
1356 if (!unit_name_is_valid(dst
, UNIT_NAME_ANY
)) {
1361 path
= strjoin(config_path
, "/", dst
, suffix
, n
, NULL
);
1365 rp
= skip_root(paths
, i
->path
);
1367 q
= create_symlink(rp
?: i
->path
, path
, force
, changes
, n_changes
);
1375 static int install_info_symlink_link(
1376 UnitFileInstallInfo
*i
,
1377 const LookupPaths
*paths
,
1378 const char *config_path
,
1380 UnitFileChange
**changes
,
1381 unsigned *n_changes
) {
1383 _cleanup_free_
char *path
= NULL
;
1389 assert(config_path
);
1392 r
= in_search_path(paths
, i
->path
);
1396 path
= strjoin(config_path
, "/", i
->name
, NULL
);
1400 rp
= skip_root(paths
, i
->path
);
1402 return create_symlink(rp
?: i
->path
, path
, force
, changes
, n_changes
);
1405 static int install_info_apply(
1406 UnitFileInstallInfo
*i
,
1407 const LookupPaths
*paths
,
1408 const char *config_path
,
1410 UnitFileChange
**changes
,
1411 unsigned *n_changes
) {
1417 assert(config_path
);
1419 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
1422 r
= install_info_symlink_alias(i
, paths
, config_path
, force
, changes
, n_changes
);
1424 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->wanted_by
, ".wants/", force
, changes
, n_changes
);
1428 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->required_by
, ".requires/", force
, changes
, n_changes
);
1432 q
= install_info_symlink_link(i
, paths
, config_path
, force
, changes
, n_changes
);
1439 static int install_context_apply(
1440 UnitFileScope scope
,
1442 const LookupPaths
*paths
,
1443 const char *config_path
,
1446 UnitFileChange
**changes
,
1447 unsigned *n_changes
) {
1449 UnitFileInstallInfo
*i
;
1454 assert(config_path
);
1456 if (ordered_hashmap_isempty(c
->will_process
))
1459 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
1464 while ((i
= ordered_hashmap_first(c
->will_process
))) {
1467 q
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
1471 r
= install_info_traverse(scope
, c
, paths
, i
, flags
, NULL
);
1475 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
1478 q
= install_info_apply(i
, paths
, config_path
, force
, changes
, n_changes
);
1490 static int install_context_mark_for_removal(
1491 UnitFileScope scope
,
1493 const LookupPaths
*paths
,
1494 Set
**remove_symlinks_to
,
1495 const char *config_path
) {
1497 UnitFileInstallInfo
*i
;
1502 assert(config_path
);
1504 /* Marks all items for removal */
1506 if (ordered_hashmap_isempty(c
->will_process
))
1509 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
1513 while ((i
= ordered_hashmap_first(c
->will_process
))) {
1515 r
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
1519 r
= install_info_traverse(scope
, c
, paths
, i
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, NULL
);
1523 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
1526 r
= mark_symlink_for_removal(remove_symlinks_to
, i
->name
);
1535 UnitFileScope scope
,
1537 const char *root_dir
,
1540 UnitFileChange
**changes
,
1541 unsigned *n_changes
) {
1543 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1544 const char *config_path
;
1549 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1551 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1555 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
1557 STRV_FOREACH(i
, files
) {
1558 _cleanup_free_
char *path
= NULL
;
1561 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
)) {
1567 path
= path_make_absolute(*i
, config_path
);
1571 q
= create_symlink("/dev/null", path
, force
, changes
, n_changes
);
1572 if (q
< 0 && r
>= 0)
1579 int unit_file_unmask(
1580 UnitFileScope scope
,
1582 const char *root_dir
,
1584 UnitFileChange
**changes
,
1585 unsigned *n_changes
) {
1587 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1588 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
1589 _cleanup_free_
char **todo
= NULL
;
1590 size_t n_todo
= 0, n_allocated
= 0;
1591 const char *config_path
;
1596 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1598 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1602 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
1604 STRV_FOREACH(i
, files
) {
1605 _cleanup_free_
char *path
= NULL
;
1607 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
1610 path
= path_make_absolute(*i
, config_path
);
1614 r
= null_or_empty_path(path
);
1622 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
1625 todo
[n_todo
++] = *i
;
1631 STRV_FOREACH(i
, todo
) {
1632 _cleanup_free_
char *path
= NULL
;
1635 path
= path_make_absolute(*i
, config_path
);
1639 if (unlink(path
) < 0) {
1640 if (errno
!= ENOENT
&& r
>= 0)
1646 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
1648 rp
= skip_root(&paths
, path
);
1649 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: path
);
1654 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, changes
, n_changes
);
1662 UnitFileScope scope
,
1664 const char *root_dir
,
1667 UnitFileChange
**changes
,
1668 unsigned *n_changes
) {
1670 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1671 _cleanup_free_
char **todo
= NULL
;
1672 size_t n_todo
= 0, n_allocated
= 0;
1673 const char *config_path
;
1678 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1680 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1684 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
1686 STRV_FOREACH(i
, files
) {
1687 _cleanup_free_
char *full
= NULL
;
1691 if (!path_is_absolute(*i
))
1695 if (!unit_name_is_valid(fn
, UNIT_NAME_ANY
))
1698 full
= prefix_root(paths
.root_dir
, *i
);
1702 if (lstat(full
, &st
) < 0)
1704 if (S_ISLNK(st
.st_mode
))
1706 if (S_ISDIR(st
.st_mode
))
1708 if (!S_ISREG(st
.st_mode
))
1711 q
= in_search_path(&paths
, *i
);
1717 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
1720 todo
[n_todo
++] = *i
;
1726 STRV_FOREACH(i
, todo
) {
1727 _cleanup_free_
char *new_path
= NULL
;
1728 const char *old_path
;
1730 old_path
= skip_root(&paths
, *i
);
1731 new_path
= path_make_absolute(basename(*i
), config_path
);
1735 q
= create_symlink(old_path
?: *i
, new_path
, force
, changes
, n_changes
);
1736 if (q
< 0 && r
>= 0)
1743 static int path_shall_revert(const LookupPaths
*paths
, const char *path
) {
1749 /* Checks whether the path is one where the drop-in directories shall be removed. */
1751 r
= path_is_config(paths
, path
);
1755 r
= path_is_control(paths
, path
);
1759 return path_is_transient(paths
, path
);
1762 int unit_file_revert(
1763 UnitFileScope scope
,
1764 const char *root_dir
,
1766 UnitFileChange
**changes
,
1767 unsigned *n_changes
) {
1769 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
1770 /* _cleanup_(install_context_done) InstallContext c = {}; */
1771 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1772 _cleanup_strv_free_
char **todo
= NULL
;
1773 size_t n_todo
= 0, n_allocated
= 0;
1777 /* Puts a unit file back into vendor state. This means:
1779 * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and
1780 * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated").
1782 * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in
1783 * "config", but not in "transient" or "control" or even "generated").
1785 * We remove all that in both the runtime and the persistant directories, if that applies.
1788 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1792 STRV_FOREACH(i
, files
) {
1793 bool has_vendor
= false;
1796 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
1799 STRV_FOREACH(p
, paths
.search_path
) {
1800 _cleanup_free_
char *path
= NULL
, *dropin
= NULL
;
1803 path
= path_make_absolute(*i
, *p
);
1807 r
= lstat(path
, &st
);
1809 if (errno
!= ENOENT
)
1811 } else if (S_ISREG(st
.st_mode
)) {
1812 /* Check if there's a vendor version */
1813 r
= path_is_vendor(&paths
, path
);
1820 dropin
= strappend(path
, ".d");
1824 r
= lstat(dropin
, &st
);
1826 if (errno
!= ENOENT
)
1828 } else if (S_ISDIR(st
.st_mode
)) {
1829 /* Remove the drop-ins */
1830 r
= path_shall_revert(&paths
, dropin
);
1834 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
1837 todo
[n_todo
++] = dropin
;
1846 /* OK, there's a vendor version, hence drop all configuration versions */
1847 STRV_FOREACH(p
, paths
.search_path
) {
1848 _cleanup_free_
char *path
= NULL
;
1851 path
= path_make_absolute(*i
, *p
);
1855 r
= lstat(path
, &st
);
1857 if (errno
!= ENOENT
)
1859 } else if (S_ISREG(st
.st_mode
) || S_ISLNK(st
.st_mode
)) {
1860 r
= path_is_config(&paths
, path
);
1864 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
1867 todo
[n_todo
++] = path
;
1877 STRV_FOREACH(i
, todo
) {
1878 _cleanup_strv_free_
char **fs
= NULL
;
1882 (void) get_files_in_directory(*i
, &fs
);
1884 q
= rm_rf(*i
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
1885 if (q
< 0 && q
!= -ENOENT
&& r
>= 0) {
1890 STRV_FOREACH(j
, fs
) {
1891 _cleanup_free_
char *t
= NULL
;
1893 t
= strjoin(*i
, "/", *j
, NULL
);
1897 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, t
, NULL
);
1900 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, *i
, NULL
);
1902 rp
= skip_root(&paths
, *i
);
1903 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: *i
);
1908 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.runtime_config
, &paths
, changes
, n_changes
);
1912 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.persistent_config
, &paths
, changes
, n_changes
);
1919 int unit_file_add_dependency(
1920 UnitFileScope scope
,
1922 const char *root_dir
,
1927 UnitFileChange
**changes
,
1928 unsigned *n_changes
) {
1930 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1931 _cleanup_(install_context_done
) InstallContext c
= {};
1932 UnitFileInstallInfo
*i
, *target_info
;
1933 const char *config_path
;
1938 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1941 if (!IN_SET(dep
, UNIT_WANTS
, UNIT_REQUIRES
))
1944 if (!unit_name_is_valid(target
, UNIT_NAME_ANY
))
1947 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1951 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
1953 r
= install_info_discover(scope
, &c
, &paths
, target
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, &target_info
);
1956 r
= install_info_may_process(target_info
, &paths
);
1960 assert(target_info
->type
== UNIT_FILE_TYPE_REGULAR
);
1962 STRV_FOREACH(f
, files
) {
1965 r
= install_info_discover(scope
, &c
, &paths
, *f
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
1968 r
= install_info_may_process(i
, &paths
);
1972 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
1974 /* We didn't actually load anything from the unit
1975 * file, but instead just add in our new symlink to
1978 if (dep
== UNIT_WANTS
)
1981 l
= &i
->required_by
;
1984 *l
= strv_new(target_info
->name
, NULL
);
1989 return install_context_apply(scope
, &c
, &paths
, config_path
, force
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, changes
, n_changes
);
1992 int unit_file_enable(
1993 UnitFileScope scope
,
1995 const char *root_dir
,
1998 UnitFileChange
**changes
,
1999 unsigned *n_changes
) {
2001 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2002 _cleanup_(install_context_done
) InstallContext c
= {};
2003 const char *config_path
;
2004 UnitFileInstallInfo
*i
;
2009 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2011 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2015 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2017 STRV_FOREACH(f
, files
) {
2018 r
= install_info_discover(scope
, &c
, &paths
, *f
, SEARCH_LOAD
, &i
);
2021 r
= install_info_may_process(i
, &paths
);
2025 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2028 /* This will return the number of symlink rules that were
2029 supposed to be created, not the ones actually created. This
2030 is useful to determine whether the passed files had any
2031 installation data at all. */
2033 return install_context_apply(scope
, &c
, &paths
, config_path
, force
, SEARCH_LOAD
, changes
, n_changes
);
2036 int unit_file_disable(
2037 UnitFileScope scope
,
2039 const char *root_dir
,
2041 UnitFileChange
**changes
,
2042 unsigned *n_changes
) {
2044 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2045 _cleanup_(install_context_done
) InstallContext c
= {};
2046 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2047 const char *config_path
;
2052 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2054 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2058 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2060 STRV_FOREACH(i
, files
) {
2061 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2064 r
= install_info_add(&c
, *i
, NULL
, NULL
);
2069 r
= install_context_mark_for_removal(scope
, &c
, &paths
, &remove_symlinks_to
, config_path
);
2073 return remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, changes
, n_changes
);
2076 int unit_file_reenable(
2077 UnitFileScope scope
,
2079 const char *root_dir
,
2082 UnitFileChange
**changes
,
2083 unsigned *n_changes
) {
2089 /* First, we invoke the disable command with only the basename... */
2090 l
= strv_length(files
);
2091 n
= newa(char*, l
+1);
2092 for (i
= 0; i
< l
; i
++)
2093 n
[i
] = basename(files
[i
]);
2096 r
= unit_file_disable(scope
, runtime
, root_dir
, n
, changes
, n_changes
);
2100 /* But the enable command with the full name */
2101 return unit_file_enable(scope
, runtime
, root_dir
, files
, force
, changes
, n_changes
);
2104 int unit_file_set_default(
2105 UnitFileScope scope
,
2106 const char *root_dir
,
2109 UnitFileChange
**changes
,
2110 unsigned *n_changes
) {
2112 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2113 _cleanup_(install_context_done
) InstallContext c
= {};
2114 UnitFileInstallInfo
*i
;
2115 const char *new_path
, *old_path
;
2119 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2122 if (unit_name_to_type(name
) != UNIT_TARGET
) /* this also validates the name */
2124 if (streq(name
, SPECIAL_DEFAULT_TARGET
))
2127 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2131 r
= install_info_discover(scope
, &c
, &paths
, name
, 0, &i
);
2134 r
= install_info_may_process(i
, &paths
);
2138 old_path
= skip_root(&paths
, i
->path
);
2139 new_path
= strjoina(paths
.persistent_config
, "/" SPECIAL_DEFAULT_TARGET
);
2141 return create_symlink(old_path
?: i
->path
, new_path
, force
, changes
, n_changes
);
2144 int unit_file_get_default(
2145 UnitFileScope scope
,
2146 const char *root_dir
,
2149 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2150 _cleanup_(install_context_done
) InstallContext c
= {};
2151 UnitFileInstallInfo
*i
;
2156 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2159 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2163 r
= install_info_discover(scope
, &c
, &paths
, SPECIAL_DEFAULT_TARGET
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2166 r
= install_info_may_process(i
, &paths
);
2170 n
= strdup(i
->name
);
2178 static int unit_file_lookup_state(
2179 UnitFileScope scope
,
2180 const LookupPaths
*paths
,
2182 UnitFileState
*ret
) {
2184 _cleanup_(install_context_done
) InstallContext c
= {};
2185 UnitFileInstallInfo
*i
;
2186 UnitFileState state
;
2192 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2195 r
= install_info_discover(scope
, &c
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2199 /* Shortcut things, if the caller just wants to know if this unit exists. */
2205 case UNIT_FILE_TYPE_MASKED
:
2206 r
= path_is_runtime(paths
, i
->path
);
2210 state
= r
> 0 ? UNIT_FILE_MASKED_RUNTIME
: UNIT_FILE_MASKED
;
2213 case UNIT_FILE_TYPE_REGULAR
:
2214 r
= path_is_generator(paths
, i
->path
);
2218 state
= UNIT_FILE_GENERATED
;
2222 r
= path_is_transient(paths
, i
->path
);
2226 state
= UNIT_FILE_TRANSIENT
;
2230 r
= find_symlinks_in_scope(scope
, paths
, i
->name
, &state
);
2234 if (UNIT_FILE_INSTALL_INFO_HAS_RULES(i
))
2235 state
= UNIT_FILE_DISABLED
;
2236 else if (UNIT_FILE_INSTALL_INFO_HAS_ALSO(i
))
2237 state
= UNIT_FILE_INDIRECT
;
2239 state
= UNIT_FILE_STATIC
;
2245 assert_not_reached("Unexpect unit file type.");
2252 int unit_file_get_state(
2253 UnitFileScope scope
,
2254 const char *root_dir
,
2256 UnitFileState
*ret
) {
2258 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2262 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2265 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2269 return unit_file_lookup_state(scope
, &paths
, name
, ret
);
2272 int unit_file_exists(UnitFileScope scope
, const LookupPaths
*paths
, const char *name
) {
2273 _cleanup_(install_context_done
) InstallContext c
= {};
2279 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2282 r
= install_info_discover(scope
, &c
, paths
, name
, 0, NULL
);
2291 int unit_file_query_preset(UnitFileScope scope
, const char *root_dir
, const char *name
) {
2292 _cleanup_strv_free_
char **files
= NULL
;
2297 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2300 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2303 if (scope
== UNIT_FILE_SYSTEM
)
2304 r
= conf_files_list(&files
, ".preset", root_dir
,
2305 "/etc/systemd/system-preset",
2306 "/usr/local/lib/systemd/system-preset",
2307 "/usr/lib/systemd/system-preset",
2308 #ifdef HAVE_SPLIT_USR
2309 "/lib/systemd/system-preset",
2312 else if (scope
== UNIT_FILE_GLOBAL
)
2313 r
= conf_files_list(&files
, ".preset", root_dir
,
2314 "/etc/systemd/user-preset",
2315 "/usr/local/lib/systemd/user-preset",
2316 "/usr/lib/systemd/user-preset",
2319 return 1; /* Default is "enable" */
2324 STRV_FOREACH(p
, files
) {
2325 _cleanup_fclose_
FILE *f
;
2326 char line
[LINE_MAX
];
2328 f
= fopen(*p
, "re");
2330 if (errno
== ENOENT
)
2336 FOREACH_LINE(line
, f
, return -errno
) {
2337 const char *parameter
;
2344 if (strchr(COMMENTS
, *l
))
2347 parameter
= first_word(l
, "enable");
2349 if (fnmatch(parameter
, name
, FNM_NOESCAPE
) == 0) {
2350 log_debug("Preset file says enable %s.", name
);
2357 parameter
= first_word(l
, "disable");
2359 if (fnmatch(parameter
, name
, FNM_NOESCAPE
) == 0) {
2360 log_debug("Preset file says disable %s.", name
);
2367 log_debug("Couldn't parse line '%s'", l
);
2371 /* Default is "enable" */
2372 log_debug("Preset file doesn't say anything about %s, enabling.", name
);
2376 static int execute_preset(
2377 UnitFileScope scope
,
2378 InstallContext
*plus
,
2379 InstallContext
*minus
,
2380 const LookupPaths
*paths
,
2381 const char *config_path
,
2383 UnitFilePresetMode mode
,
2385 UnitFileChange
**changes
,
2386 unsigned *n_changes
) {
2393 assert(config_path
);
2395 if (mode
!= UNIT_FILE_PRESET_ENABLE_ONLY
) {
2396 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2398 r
= install_context_mark_for_removal(scope
, minus
, paths
, &remove_symlinks_to
, config_path
);
2402 r
= remove_marked_symlinks(remove_symlinks_to
, config_path
, paths
, changes
, n_changes
);
2406 if (mode
!= UNIT_FILE_PRESET_DISABLE_ONLY
) {
2409 /* Returns number of symlinks that where supposed to be installed. */
2410 q
= install_context_apply(scope
, plus
, paths
, config_path
, force
, SEARCH_LOAD
, changes
, n_changes
);
2422 static int preset_prepare_one(
2423 UnitFileScope scope
,
2424 InstallContext
*plus
,
2425 InstallContext
*minus
,
2427 UnitFilePresetMode mode
,
2430 UnitFileInstallInfo
*i
;
2433 if (install_info_find(plus
, name
) ||
2434 install_info_find(minus
, name
))
2437 r
= unit_file_query_preset(scope
, paths
->root_dir
, name
);
2442 r
= install_info_discover(scope
, plus
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2446 r
= install_info_may_process(i
, paths
);
2450 r
= install_info_discover(scope
, minus
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2455 int unit_file_preset(
2456 UnitFileScope scope
,
2458 const char *root_dir
,
2460 UnitFilePresetMode mode
,
2462 UnitFileChange
**changes
,
2463 unsigned *n_changes
) {
2465 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
2466 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2467 const char *config_path
;
2472 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2473 assert(mode
< _UNIT_FILE_PRESET_MAX
);
2475 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2479 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2481 STRV_FOREACH(i
, files
) {
2482 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2485 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, mode
, *i
);
2490 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, files
, mode
, force
, changes
, n_changes
);
2493 int unit_file_preset_all(
2494 UnitFileScope scope
,
2496 const char *root_dir
,
2497 UnitFilePresetMode mode
,
2499 UnitFileChange
**changes
,
2500 unsigned *n_changes
) {
2502 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
2503 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2504 const char *config_path
= NULL
;
2509 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2510 assert(mode
< _UNIT_FILE_PRESET_MAX
);
2512 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2516 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2518 STRV_FOREACH(i
, paths
.search_path
) {
2519 _cleanup_closedir_
DIR *d
= NULL
;
2524 if (errno
== ENOENT
)
2530 FOREACH_DIRENT(de
, d
, return -errno
) {
2532 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
2535 dirent_ensure_type(d
, de
);
2537 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
2540 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, mode
, de
->d_name
);
2542 r
= unit_file_changes_add(changes
, n_changes
,
2543 UNIT_FILE_IS_MASKED
, de
->d_name
, NULL
);
2549 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, NULL
, mode
, force
, changes
, n_changes
);
2552 static void unit_file_list_free_one(UnitFileList
*f
) {
2560 Hashmap
* unit_file_list_free(Hashmap
*h
) {
2563 while ((i
= hashmap_steal_first(h
)))
2564 unit_file_list_free_one(i
);
2566 return hashmap_free(h
);
2569 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList
*, unit_file_list_free_one
);
2571 int unit_file_get_list(
2572 UnitFileScope scope
,
2573 const char *root_dir
,
2576 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2581 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2584 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2588 STRV_FOREACH(i
, paths
.search_path
) {
2589 _cleanup_closedir_
DIR *d
= NULL
;
2594 if (errno
== ENOENT
)
2600 FOREACH_DIRENT(de
, d
, return -errno
) {
2601 _cleanup_(unit_file_list_free_onep
) UnitFileList
*f
= NULL
;
2603 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
2606 if (hashmap_get(h
, de
->d_name
))
2609 dirent_ensure_type(d
, de
);
2611 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
2614 f
= new0(UnitFileList
, 1);
2618 f
->path
= path_make_absolute(de
->d_name
, *i
);
2622 r
= unit_file_lookup_state(scope
, &paths
, de
->d_name
, &f
->state
);
2624 f
->state
= UNIT_FILE_BAD
;
2626 r
= hashmap_put(h
, basename(f
->path
), f
);
2630 f
= NULL
; /* prevent cleanup */
2637 static const char* const unit_file_state_table
[_UNIT_FILE_STATE_MAX
] = {
2638 [UNIT_FILE_ENABLED
] = "enabled",
2639 [UNIT_FILE_ENABLED_RUNTIME
] = "enabled-runtime",
2640 [UNIT_FILE_LINKED
] = "linked",
2641 [UNIT_FILE_LINKED_RUNTIME
] = "linked-runtime",
2642 [UNIT_FILE_MASKED
] = "masked",
2643 [UNIT_FILE_MASKED_RUNTIME
] = "masked-runtime",
2644 [UNIT_FILE_STATIC
] = "static",
2645 [UNIT_FILE_DISABLED
] = "disabled",
2646 [UNIT_FILE_INDIRECT
] = "indirect",
2647 [UNIT_FILE_GENERATED
] = "generated",
2648 [UNIT_FILE_TRANSIENT
] = "transient",
2649 [UNIT_FILE_BAD
] = "bad",
2652 DEFINE_STRING_TABLE_LOOKUP(unit_file_state
, UnitFileState
);
2654 static const char* const unit_file_change_type_table
[_UNIT_FILE_CHANGE_TYPE_MAX
] = {
2655 [UNIT_FILE_SYMLINK
] = "symlink",
2656 [UNIT_FILE_UNLINK
] = "unlink",
2657 [UNIT_FILE_IS_MASKED
] = "masked",
2660 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type
, UnitFileChangeType
);
2662 static const char* const unit_file_preset_mode_table
[_UNIT_FILE_PRESET_MAX
] = {
2663 [UNIT_FILE_PRESET_FULL
] = "full",
2664 [UNIT_FILE_PRESET_ENABLE_ONLY
] = "enable-only",
2665 [UNIT_FILE_PRESET_DISABLE_ONLY
] = "disable-only",
2668 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode
, UnitFilePresetMode
);