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 them we couldn't discern
218 * 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 explicit checks for the various runtime
236 * 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
);
396 static int create_symlink(
397 const char *old_path
,
398 const char *new_path
,
400 UnitFileChange
**changes
,
401 unsigned *n_changes
) {
403 _cleanup_free_
char *dest
= NULL
;
409 /* Actually create a symlink, and remember that we did. Is
410 * smart enough to check if there's already a valid symlink in
413 * Returns 1 if a symlink was created or already exists and points to
414 * the right place, or negative on error.
417 mkdir_parents_label(new_path
, 0755);
419 if (symlink(old_path
, new_path
) >= 0) {
420 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
424 if (errno
!= EEXIST
) {
425 unit_file_changes_add(changes
, n_changes
, -errno
, new_path
, NULL
);
429 r
= readlink_malloc(new_path
, &dest
);
431 /* translate EINVAL (non-symlink exists) to EEXIST */
435 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
439 if (path_equal(dest
, old_path
))
443 unit_file_changes_add(changes
, n_changes
, -EEXIST
, new_path
, dest
);
447 r
= symlink_atomic(old_path
, new_path
);
449 unit_file_changes_add(changes
, n_changes
, r
, new_path
, NULL
);
453 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, new_path
, NULL
);
454 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
459 static int mark_symlink_for_removal(
460 Set
**remove_symlinks_to
,
468 r
= set_ensure_allocated(remove_symlinks_to
, &string_hash_ops
);
476 path_kill_slashes(n
);
478 r
= set_consume(*remove_symlinks_to
, n
);
487 static int remove_marked_symlinks_fd(
488 Set
*remove_symlinks_to
,
491 const char *config_path
,
492 const LookupPaths
*lp
,
494 UnitFileChange
**changes
,
495 unsigned *n_changes
) {
497 _cleanup_closedir_
DIR *d
= NULL
;
501 assert(remove_symlinks_to
);
516 FOREACH_DIRENT(de
, d
, return -errno
) {
518 dirent_ensure_type(d
, de
);
520 if (de
->d_type
== DT_DIR
) {
521 _cleanup_free_
char *p
= NULL
;
524 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
534 p
= path_make_absolute(de
->d_name
, path
);
540 /* This will close nfd, regardless whether it succeeds or not */
541 q
= remove_marked_symlinks_fd(remove_symlinks_to
, nfd
, p
, config_path
, lp
, restart
, changes
, n_changes
);
545 } else if (de
->d_type
== DT_LNK
) {
546 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
551 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
554 p
= path_make_absolute(de
->d_name
, path
);
557 path_kill_slashes(p
);
559 q
= readlink_malloc(p
, &dest
);
568 /* We remove all links pointing to a file or path that is marked, as well as all files sharing
569 * the same name as a file that is marked. */
571 found
= set_contains(remove_symlinks_to
, dest
) ||
572 set_contains(remove_symlinks_to
, basename(dest
)) ||
573 set_contains(remove_symlinks_to
, de
->d_name
);
578 if (unlinkat(fd
, de
->d_name
, 0) < 0 && errno
!= ENOENT
) {
581 unit_file_changes_add(changes
, n_changes
, -errno
, p
, NULL
);
585 (void) rmdir_parents(p
, config_path
);
587 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, p
, NULL
);
589 /* Now, remember the full path (but with the root prefix removed) of
590 * the symlink we just removed, and remove any symlinks to it, too. */
592 rp
= skip_root(lp
, p
);
593 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: p
);
604 static int remove_marked_symlinks(
605 Set
*remove_symlinks_to
,
606 const char *config_path
,
607 const LookupPaths
*lp
,
608 UnitFileChange
**changes
,
609 unsigned *n_changes
) {
611 _cleanup_close_
int fd
= -1;
618 if (set_size(remove_symlinks_to
) <= 0)
621 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
623 return errno
== ENOENT
? 0 : -errno
;
629 cfd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
633 /* This takes possession of cfd and closes it */
634 q
= remove_marked_symlinks_fd(remove_symlinks_to
, cfd
, config_path
, config_path
, lp
, &restart
, changes
, n_changes
);
642 static int find_symlinks_fd(
643 const char *root_dir
,
647 const char *config_path
,
648 const LookupPaths
*lp
,
649 bool *same_name_link
) {
651 _cleanup_closedir_
DIR *d
= NULL
;
660 assert(same_name_link
);
668 FOREACH_DIRENT(de
, d
, return -errno
) {
670 dirent_ensure_type(d
, de
);
672 if (de
->d_type
== DT_DIR
) {
673 _cleanup_free_
char *p
= NULL
;
676 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
686 p
= path_make_absolute(de
->d_name
, path
);
692 /* This will close nfd, regardless whether it succeeds or not */
693 q
= find_symlinks_fd(root_dir
, name
, nfd
, p
, config_path
, lp
, same_name_link
);
699 } else if (de
->d_type
== DT_LNK
) {
700 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
701 bool found_path
, found_dest
, b
= false;
704 /* Acquire symlink name */
705 p
= path_make_absolute(de
->d_name
, path
);
709 /* Acquire symlink destination */
710 q
= readlink_malloc(p
, &dest
);
720 if (!path_is_absolute(dest
)) {
723 x
= prefix_root(root_dir
, dest
);
731 /* Check if the symlink itself matches what we
733 if (path_is_absolute(name
))
734 found_path
= path_equal(p
, name
);
736 found_path
= streq(de
->d_name
, name
);
738 /* Check if what the symlink points to
739 * matches what we are looking for */
740 if (path_is_absolute(name
))
741 found_dest
= path_equal(dest
, name
);
743 found_dest
= streq(basename(dest
), name
);
745 if (found_path
&& found_dest
) {
746 _cleanup_free_
char *t
= NULL
;
748 /* Filter out same name links in the main
750 t
= path_make_absolute(name
, config_path
);
754 b
= path_equal(t
, p
);
758 *same_name_link
= true;
759 else if (found_path
|| found_dest
)
767 static int find_symlinks(
768 const char *root_dir
,
770 const char *config_path
,
771 const LookupPaths
*lp
,
772 bool *same_name_link
) {
778 assert(same_name_link
);
780 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
);
782 if (IN_SET(errno
, ENOENT
, ENOTDIR
, EACCES
))
787 /* This takes possession of fd and closes it */
788 return find_symlinks_fd(root_dir
, name
, fd
, config_path
, config_path
, lp
, same_name_link
);
791 static int find_symlinks_in_scope(
793 const LookupPaths
*paths
,
795 UnitFileState
*state
) {
797 bool same_name_link_runtime
= false, same_name_link
= false;
801 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
805 /* First look in the persistent config path */
806 r
= find_symlinks(paths
->root_dir
, name
, paths
->persistent_config
, paths
, &same_name_link
);
810 *state
= UNIT_FILE_ENABLED
;
814 /* Then look in runtime config path */
815 r
= find_symlinks(paths
->root_dir
, name
, paths
->runtime_config
, paths
, &same_name_link_runtime
);
819 *state
= UNIT_FILE_ENABLED_RUNTIME
;
823 /* Hmm, we didn't find it, but maybe we found the same name
825 if (same_name_link
) {
826 *state
= UNIT_FILE_LINKED
;
829 if (same_name_link_runtime
) {
830 *state
= UNIT_FILE_LINKED_RUNTIME
;
837 static void install_info_free(UnitFileInstallInfo
*i
) {
844 strv_free(i
->aliases
);
845 strv_free(i
->wanted_by
);
846 strv_free(i
->required_by
);
848 free(i
->default_instance
);
849 free(i
->symlink_target
);
853 static OrderedHashmap
* install_info_hashmap_free(OrderedHashmap
*m
) {
854 UnitFileInstallInfo
*i
;
859 while ((i
= ordered_hashmap_steal_first(m
)))
860 install_info_free(i
);
862 return ordered_hashmap_free(m
);
865 static void install_context_done(InstallContext
*c
) {
868 c
->will_process
= install_info_hashmap_free(c
->will_process
);
869 c
->have_processed
= install_info_hashmap_free(c
->have_processed
);
872 static UnitFileInstallInfo
*install_info_find(InstallContext
*c
, const char *name
) {
873 UnitFileInstallInfo
*i
;
875 i
= ordered_hashmap_get(c
->have_processed
, name
);
879 return ordered_hashmap_get(c
->will_process
, name
);
882 static int install_info_may_process(
883 UnitFileInstallInfo
*i
,
884 const LookupPaths
*paths
,
885 UnitFileChange
**changes
,
886 unsigned *n_changes
) {
890 /* Checks whether the loaded unit file is one we should process, or is masked, transient or generated and thus
891 * not subject to enable/disable operations. */
893 if (i
->type
== UNIT_FILE_TYPE_MASKED
) {
894 unit_file_changes_add(changes
, n_changes
, -ERFKILL
, i
->path
, NULL
);
897 if (path_is_generator(paths
, i
->path
) ||
898 path_is_transient(paths
, i
->path
)) {
899 unit_file_changes_add(changes
, n_changes
, -EADDRNOTAVAIL
, i
->path
, NULL
);
900 return -EADDRNOTAVAIL
;
906 static int install_info_add(
910 UnitFileInstallInfo
**ret
) {
912 UnitFileInstallInfo
*i
= NULL
;
916 assert(name
|| path
);
919 name
= basename(path
);
921 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
924 i
= install_info_find(c
, name
);
931 r
= ordered_hashmap_ensure_allocated(&c
->will_process
, &string_hash_ops
);
935 i
= new0(UnitFileInstallInfo
, 1);
938 i
->type
= _UNIT_FILE_TYPE_INVALID
;
940 i
->name
= strdup(name
);
947 i
->path
= strdup(path
);
954 r
= ordered_hashmap_put(c
->will_process
, i
->name
, i
);
964 install_info_free(i
);
968 static int config_parse_alias(
970 const char *filename
,
973 unsigned section_line
,
987 name
= basename(filename
);
988 type
= unit_name_to_type(name
);
989 if (!unit_type_may_alias(type
))
990 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
991 "Aliases are not allowed for %s units, ignoring.",
992 unit_type_to_string(type
));
994 return config_parse_strv(unit
, filename
, line
, section
, section_line
,
995 lvalue
, ltype
, rvalue
, data
, userdata
);
998 static int config_parse_also(
1000 const char *filename
,
1002 const char *section
,
1003 unsigned section_line
,
1010 UnitFileInstallInfo
*i
= userdata
;
1011 InstallContext
*c
= data
;
1019 _cleanup_free_
char *word
= NULL
;
1021 r
= extract_first_word(&rvalue
, &word
, NULL
, 0);
1027 r
= install_info_add(c
, word
, NULL
, NULL
);
1031 r
= strv_push(&i
->also
, word
);
1041 static int config_parse_default_instance(
1043 const char *filename
,
1045 const char *section
,
1046 unsigned section_line
,
1053 UnitFileInstallInfo
*i
= data
;
1062 name
= basename(filename
);
1063 if (unit_name_is_valid(name
, UNIT_NAME_INSTANCE
))
1064 /* When enabling an instance, we might be using a template unit file,
1065 * but we should ignore DefaultInstance silently. */
1067 if (!unit_name_is_valid(name
, UNIT_NAME_TEMPLATE
))
1068 return log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1069 "DefaultInstance only makes sense for template units, ignoring.");
1071 r
= install_full_printf(i
, rvalue
, &printed
);
1075 if (!unit_instance_is_valid(printed
)) {
1080 free(i
->default_instance
);
1081 i
->default_instance
= printed
;
1086 static int unit_file_load(
1088 UnitFileInstallInfo
*info
,
1090 SearchFlags flags
) {
1092 const ConfigTableItem items
[] = {
1093 { "Install", "Alias", config_parse_alias
, 0, &info
->aliases
},
1094 { "Install", "WantedBy", config_parse_strv
, 0, &info
->wanted_by
},
1095 { "Install", "RequiredBy", config_parse_strv
, 0, &info
->required_by
},
1096 { "Install", "DefaultInstance", config_parse_default_instance
, 0, info
},
1097 { "Install", "Also", config_parse_also
, 0, c
},
1103 _cleanup_fclose_
FILE *f
= NULL
;
1104 _cleanup_close_
int fd
= -1;
1112 name
= basename(path
);
1113 type
= unit_name_to_type(name
);
1114 if (unit_name_is_valid(name
, UNIT_NAME_TEMPLATE
|UNIT_NAME_INSTANCE
) &&
1115 !unit_type_may_template(type
))
1116 return log_error_errno(EINVAL
, "Unit type %s cannot be templated.", unit_type_to_string(type
));
1118 if (!(flags
& SEARCH_LOAD
)) {
1119 r
= lstat(path
, &st
);
1123 if (null_or_empty(&st
))
1124 info
->type
= UNIT_FILE_TYPE_MASKED
;
1125 else if (S_ISREG(st
.st_mode
))
1126 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1127 else if (S_ISLNK(st
.st_mode
))
1129 else if (S_ISDIR(st
.st_mode
))
1137 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
1140 if (fstat(fd
, &st
) < 0)
1142 if (null_or_empty(&st
)) {
1143 info
->type
= UNIT_FILE_TYPE_MASKED
;
1146 if (S_ISDIR(st
.st_mode
))
1148 if (!S_ISREG(st
.st_mode
))
1151 f
= fdopen(fd
, "re");
1156 r
= config_parse(NULL
, path
, f
,
1158 config_item_table_lookup
, items
,
1159 true, true, false, info
);
1163 info
->type
= UNIT_FILE_TYPE_REGULAR
;
1166 (int) strv_length(info
->aliases
) +
1167 (int) strv_length(info
->wanted_by
) +
1168 (int) strv_length(info
->required_by
);
1171 static int unit_file_load_or_readlink(
1173 UnitFileInstallInfo
*info
,
1175 const char *root_dir
,
1176 SearchFlags flags
) {
1178 _cleanup_free_
char *target
= NULL
;
1181 r
= unit_file_load(c
, info
, path
, flags
);
1185 /* This is a symlink, let's read it. */
1187 r
= readlink_malloc(path
, &target
);
1191 if (path_equal(target
, "/dev/null"))
1192 info
->type
= UNIT_FILE_TYPE_MASKED
;
1197 bn
= basename(target
);
1199 if (unit_name_is_valid(info
->name
, UNIT_NAME_PLAIN
)) {
1201 if (!unit_name_is_valid(bn
, UNIT_NAME_PLAIN
))
1204 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1206 if (!unit_name_is_valid(bn
, UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
))
1209 } else if (unit_name_is_valid(info
->name
, UNIT_NAME_TEMPLATE
)) {
1211 if (!unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
))
1216 /* Enforce that the symlink destination does not
1217 * change the unit file type. */
1219 a
= unit_name_to_type(info
->name
);
1220 b
= unit_name_to_type(bn
);
1221 if (a
< 0 || b
< 0 || a
!= b
)
1224 if (path_is_absolute(target
))
1225 /* This is an absolute path, prefix the root so that we always deal with fully qualified paths */
1226 info
->symlink_target
= prefix_root(root_dir
, target
);
1228 /* This is a relative path, take it relative to the dir the symlink is located in. */
1229 info
->symlink_target
= file_in_same_dir(path
, target
);
1230 if (!info
->symlink_target
)
1233 info
->type
= UNIT_FILE_TYPE_SYMLINK
;
1239 static int unit_file_search(
1241 UnitFileInstallInfo
*info
,
1242 const LookupPaths
*paths
,
1243 SearchFlags flags
) {
1245 _cleanup_free_
char *template = NULL
;
1253 /* Was this unit already loaded? */
1254 if (info
->type
!= _UNIT_FILE_TYPE_INVALID
)
1258 return unit_file_load_or_readlink(c
, info
, info
->path
, paths
->root_dir
, flags
);
1262 STRV_FOREACH(p
, paths
->search_path
) {
1263 _cleanup_free_
char *path
= NULL
;
1265 path
= strjoin(*p
, "/", info
->name
, NULL
);
1269 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1274 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1278 if (unit_name_is_valid(info
->name
, UNIT_NAME_INSTANCE
)) {
1279 /* Unit file doesn't exist, however instance
1280 * enablement was requested. We will check if it is
1281 * possible to load template unit file. */
1283 r
= unit_name_template(info
->name
, &template);
1287 STRV_FOREACH(p
, paths
->search_path
) {
1288 _cleanup_free_
char *path
= NULL
;
1290 path
= strjoin(*p
, "/", template, NULL
);
1294 r
= unit_file_load_or_readlink(c
, info
, path
, paths
->root_dir
, flags
);
1299 } else if (!IN_SET(r
, -ENOENT
, -ENOTDIR
, -EACCES
))
1304 log_debug("Cannot find unit %s%s%s.", info
->name
, template ? " or " : "", strempty(template));
1308 static int install_info_follow(
1310 UnitFileInstallInfo
*i
,
1311 const char *root_dir
,
1312 SearchFlags flags
) {
1317 if (i
->type
!= UNIT_FILE_TYPE_SYMLINK
)
1319 if (!i
->symlink_target
)
1322 /* If the basename doesn't match, the caller should add a
1323 * complete new entry for this. */
1325 if (!streq(basename(i
->symlink_target
), i
->name
))
1329 i
->path
= i
->symlink_target
;
1330 i
->symlink_target
= NULL
;
1331 i
->type
= _UNIT_FILE_TYPE_INVALID
;
1333 return unit_file_load_or_readlink(c
, i
, i
->path
, root_dir
, flags
);
1337 * Search for the unit file. If the unit name is a symlink,
1338 * follow the symlink to the target, maybe more than once.
1339 * Propagate the instance name if present.
1341 static int install_info_traverse(
1342 UnitFileScope scope
,
1344 const LookupPaths
*paths
,
1345 UnitFileInstallInfo
*start
,
1347 UnitFileInstallInfo
**ret
) {
1349 UnitFileInstallInfo
*i
;
1357 r
= unit_file_search(c
, start
, paths
, flags
);
1362 while (i
->type
== UNIT_FILE_TYPE_SYMLINK
) {
1363 /* Follow the symlink */
1365 if (++k
> UNIT_FILE_FOLLOW_SYMLINK_MAX
)
1368 if (!(flags
& SEARCH_FOLLOW_CONFIG_SYMLINKS
)) {
1369 r
= path_is_config(paths
, i
->path
);
1376 r
= install_info_follow(c
, i
, paths
->root_dir
, flags
);
1378 _cleanup_free_
char *buffer
= NULL
;
1381 /* Target has a different name, create a new
1382 * install info object for that, and continue
1385 bn
= basename(i
->symlink_target
);
1387 if (unit_name_is_valid(i
->name
, UNIT_NAME_INSTANCE
) &&
1388 unit_name_is_valid(bn
, UNIT_NAME_TEMPLATE
)) {
1390 _cleanup_free_
char *instance
= NULL
;
1392 r
= unit_name_to_instance(i
->name
, &instance
);
1396 r
= unit_name_replace_instance(bn
, instance
, &buffer
);
1403 r
= install_info_add(c
, bn
, NULL
, &i
);
1407 /* Try again, with the new target we found. */
1408 r
= unit_file_search(c
, i
, paths
, flags
);
1410 /* Translate error code to highlight this specific case */
1424 static int install_info_add_auto(
1426 const LookupPaths
*paths
,
1427 const char *name_or_path
,
1428 UnitFileInstallInfo
**ret
) {
1431 assert(name_or_path
);
1433 if (path_is_absolute(name_or_path
)) {
1436 pp
= prefix_roota(paths
->root_dir
, name_or_path
);
1438 return install_info_add(c
, NULL
, pp
, ret
);
1440 return install_info_add(c
, name_or_path
, NULL
, ret
);
1443 static int install_info_discover(
1444 UnitFileScope scope
,
1446 const LookupPaths
*paths
,
1449 UnitFileInstallInfo
**ret
) {
1451 UnitFileInstallInfo
*i
;
1458 r
= install_info_add_auto(c
, paths
, name
, &i
);
1462 return install_info_traverse(scope
, c
, paths
, i
, flags
, ret
);
1465 static int install_info_symlink_alias(
1466 UnitFileInstallInfo
*i
,
1467 const LookupPaths
*paths
,
1468 const char *config_path
,
1470 UnitFileChange
**changes
,
1471 unsigned *n_changes
) {
1478 assert(config_path
);
1480 STRV_FOREACH(s
, i
->aliases
) {
1481 _cleanup_free_
char *alias_path
= NULL
, *dst
= NULL
;
1484 q
= install_full_printf(i
, *s
, &dst
);
1488 alias_path
= path_make_absolute(dst
, config_path
);
1492 rp
= skip_root(paths
, i
->path
);
1494 q
= create_symlink(rp
?: i
->path
, alias_path
, force
, changes
, n_changes
);
1502 static int install_info_symlink_wants(
1503 UnitFileInstallInfo
*i
,
1504 const LookupPaths
*paths
,
1505 const char *config_path
,
1508 UnitFileChange
**changes
,
1509 unsigned *n_changes
) {
1511 _cleanup_free_
char *buf
= NULL
;
1518 assert(config_path
);
1520 if (unit_name_is_valid(i
->name
, UNIT_NAME_TEMPLATE
)) {
1522 /* Don't install any symlink if there's no default
1523 * instance configured */
1525 if (!i
->default_instance
)
1528 r
= unit_name_replace_instance(i
->name
, i
->default_instance
, &buf
);
1536 STRV_FOREACH(s
, list
) {
1537 _cleanup_free_
char *path
= NULL
, *dst
= NULL
;
1540 q
= install_full_printf(i
, *s
, &dst
);
1544 if (!unit_name_is_valid(dst
, UNIT_NAME_ANY
)) {
1549 path
= strjoin(config_path
, "/", dst
, suffix
, n
, NULL
);
1553 rp
= skip_root(paths
, i
->path
);
1555 q
= create_symlink(rp
?: i
->path
, path
, true, changes
, n_changes
);
1563 static int install_info_symlink_link(
1564 UnitFileInstallInfo
*i
,
1565 const LookupPaths
*paths
,
1566 const char *config_path
,
1568 UnitFileChange
**changes
,
1569 unsigned *n_changes
) {
1571 _cleanup_free_
char *path
= NULL
;
1577 assert(config_path
);
1580 r
= in_search_path(paths
, i
->path
);
1586 path
= strjoin(config_path
, "/", i
->name
, NULL
);
1590 rp
= skip_root(paths
, i
->path
);
1592 return create_symlink(rp
?: i
->path
, path
, force
, changes
, n_changes
);
1595 static int install_info_apply(
1596 UnitFileInstallInfo
*i
,
1597 const LookupPaths
*paths
,
1598 const char *config_path
,
1600 UnitFileChange
**changes
,
1601 unsigned *n_changes
) {
1607 assert(config_path
);
1609 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
1612 r
= install_info_symlink_alias(i
, paths
, config_path
, force
, changes
, n_changes
);
1614 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->wanted_by
, ".wants/", changes
, n_changes
);
1618 q
= install_info_symlink_wants(i
, paths
, config_path
, i
->required_by
, ".requires/", changes
, n_changes
);
1622 q
= install_info_symlink_link(i
, paths
, config_path
, force
, changes
, n_changes
);
1623 /* Do not count links to the unit file towards the "carries_install_info" count */
1624 if (r
== 0 && q
< 0)
1630 static int install_context_apply(
1631 UnitFileScope scope
,
1633 const LookupPaths
*paths
,
1634 const char *config_path
,
1637 UnitFileChange
**changes
,
1638 unsigned *n_changes
) {
1640 UnitFileInstallInfo
*i
;
1645 assert(config_path
);
1647 if (ordered_hashmap_isempty(c
->will_process
))
1650 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
1655 while ((i
= ordered_hashmap_first(c
->will_process
))) {
1658 q
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
1662 r
= install_info_traverse(scope
, c
, paths
, i
, flags
, NULL
);
1666 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
)
1669 q
= install_info_apply(i
, paths
, config_path
, force
, changes
, n_changes
);
1681 static int install_context_mark_for_removal(
1682 UnitFileScope scope
,
1684 const LookupPaths
*paths
,
1685 Set
**remove_symlinks_to
,
1686 const char *config_path
) {
1688 UnitFileInstallInfo
*i
;
1693 assert(config_path
);
1695 /* Marks all items for removal */
1697 if (ordered_hashmap_isempty(c
->will_process
))
1700 r
= ordered_hashmap_ensure_allocated(&c
->have_processed
, &string_hash_ops
);
1704 while ((i
= ordered_hashmap_first(c
->will_process
))) {
1706 r
= ordered_hashmap_move_one(c
->have_processed
, c
->will_process
, i
->name
);
1710 r
= install_info_traverse(scope
, c
, paths
, i
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, NULL
);
1716 if (i
->type
!= UNIT_FILE_TYPE_REGULAR
) {
1717 log_debug("Unit %s has type %s, ignoring.",
1719 unit_file_type_to_string(i
->type
) ?: "invalid");
1723 r
= mark_symlink_for_removal(remove_symlinks_to
, i
->name
);
1732 UnitFileScope scope
,
1734 const char *root_dir
,
1737 UnitFileChange
**changes
,
1738 unsigned *n_changes
) {
1740 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1741 const char *config_path
;
1746 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1748 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1752 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
1754 STRV_FOREACH(i
, files
) {
1755 _cleanup_free_
char *path
= NULL
;
1758 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
)) {
1764 path
= path_make_absolute(*i
, config_path
);
1768 q
= create_symlink("/dev/null", path
, force
, changes
, n_changes
);
1769 if (q
< 0 && r
>= 0)
1776 int unit_file_unmask(
1777 UnitFileScope scope
,
1779 const char *root_dir
,
1781 UnitFileChange
**changes
,
1782 unsigned *n_changes
) {
1784 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1785 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
1786 _cleanup_free_
char **todo
= NULL
;
1787 size_t n_todo
= 0, n_allocated
= 0;
1788 const char *config_path
;
1793 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1795 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1799 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
1801 STRV_FOREACH(i
, files
) {
1802 _cleanup_free_
char *path
= NULL
;
1804 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
1807 path
= path_make_absolute(*i
, config_path
);
1811 r
= null_or_empty_path(path
);
1819 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
1822 todo
[n_todo
++] = *i
;
1828 STRV_FOREACH(i
, todo
) {
1829 _cleanup_free_
char *path
= NULL
;
1832 path
= path_make_absolute(*i
, config_path
);
1836 if (unlink(path
) < 0) {
1837 if (errno
!= ENOENT
) {
1840 unit_file_changes_add(changes
, n_changes
, -errno
, path
, NULL
);
1846 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
1848 rp
= skip_root(&paths
, path
);
1849 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: path
);
1854 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, changes
, n_changes
);
1862 UnitFileScope scope
,
1864 const char *root_dir
,
1867 UnitFileChange
**changes
,
1868 unsigned *n_changes
) {
1870 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1871 _cleanup_free_
char **todo
= NULL
;
1872 size_t n_todo
= 0, n_allocated
= 0;
1873 const char *config_path
;
1878 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1880 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1884 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
1886 STRV_FOREACH(i
, files
) {
1887 _cleanup_free_
char *full
= NULL
;
1891 if (!path_is_absolute(*i
))
1895 if (!unit_name_is_valid(fn
, UNIT_NAME_ANY
))
1898 full
= prefix_root(paths
.root_dir
, *i
);
1902 if (lstat(full
, &st
) < 0)
1904 if (S_ISLNK(st
.st_mode
))
1906 if (S_ISDIR(st
.st_mode
))
1908 if (!S_ISREG(st
.st_mode
))
1911 q
= in_search_path(&paths
, *i
);
1917 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
1920 todo
[n_todo
++] = *i
;
1926 STRV_FOREACH(i
, todo
) {
1927 _cleanup_free_
char *new_path
= NULL
;
1928 const char *old_path
;
1930 old_path
= skip_root(&paths
, *i
);
1931 new_path
= path_make_absolute(basename(*i
), config_path
);
1935 q
= create_symlink(old_path
?: *i
, new_path
, force
, changes
, n_changes
);
1936 if (q
< 0 && r
>= 0)
1943 static int path_shall_revert(const LookupPaths
*paths
, const char *path
) {
1949 /* Checks whether the path is one where the drop-in directories shall be removed. */
1951 r
= path_is_config(paths
, path
);
1955 r
= path_is_control(paths
, path
);
1959 return path_is_transient(paths
, path
);
1962 int unit_file_revert(
1963 UnitFileScope scope
,
1964 const char *root_dir
,
1966 UnitFileChange
**changes
,
1967 unsigned *n_changes
) {
1969 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
1970 /* _cleanup_(install_context_done) InstallContext c = {}; */
1971 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1972 _cleanup_strv_free_
char **todo
= NULL
;
1973 size_t n_todo
= 0, n_allocated
= 0;
1977 /* Puts a unit file back into vendor state. This means:
1979 * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and
1980 * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated").
1982 * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in
1983 * "config", but not in "transient" or "control" or even "generated").
1985 * We remove all that in both the runtime and the persistent directories, if that applies.
1988 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
1992 STRV_FOREACH(i
, files
) {
1993 bool has_vendor
= false;
1996 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
1999 STRV_FOREACH(p
, paths
.search_path
) {
2000 _cleanup_free_
char *path
= NULL
, *dropin
= NULL
;
2003 path
= path_make_absolute(*i
, *p
);
2007 r
= lstat(path
, &st
);
2009 if (errno
!= ENOENT
)
2011 } else if (S_ISREG(st
.st_mode
)) {
2012 /* Check if there's a vendor version */
2013 r
= path_is_vendor(&paths
, path
);
2020 dropin
= strappend(path
, ".d");
2024 r
= lstat(dropin
, &st
);
2026 if (errno
!= ENOENT
)
2028 } else if (S_ISDIR(st
.st_mode
)) {
2029 /* Remove the drop-ins */
2030 r
= path_shall_revert(&paths
, dropin
);
2034 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2037 todo
[n_todo
++] = dropin
;
2046 /* OK, there's a vendor version, hence drop all configuration versions */
2047 STRV_FOREACH(p
, paths
.search_path
) {
2048 _cleanup_free_
char *path
= NULL
;
2051 path
= path_make_absolute(*i
, *p
);
2055 r
= lstat(path
, &st
);
2057 if (errno
!= ENOENT
)
2059 } else if (S_ISREG(st
.st_mode
) || S_ISLNK(st
.st_mode
)) {
2060 r
= path_is_config(&paths
, path
);
2064 if (!GREEDY_REALLOC0(todo
, n_allocated
, n_todo
+ 2))
2067 todo
[n_todo
++] = path
;
2077 STRV_FOREACH(i
, todo
) {
2078 _cleanup_strv_free_
char **fs
= NULL
;
2082 (void) get_files_in_directory(*i
, &fs
);
2084 q
= rm_rf(*i
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
2085 if (q
< 0 && q
!= -ENOENT
&& r
>= 0) {
2090 STRV_FOREACH(j
, fs
) {
2091 _cleanup_free_
char *t
= NULL
;
2093 t
= strjoin(*i
, "/", *j
, NULL
);
2097 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, t
, NULL
);
2100 unit_file_changes_add(changes
, n_changes
, UNIT_FILE_UNLINK
, *i
, NULL
);
2102 rp
= skip_root(&paths
, *i
);
2103 q
= mark_symlink_for_removal(&remove_symlinks_to
, rp
?: *i
);
2108 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.runtime_config
, &paths
, changes
, n_changes
);
2112 q
= remove_marked_symlinks(remove_symlinks_to
, paths
.persistent_config
, &paths
, changes
, n_changes
);
2119 int unit_file_add_dependency(
2120 UnitFileScope scope
,
2122 const char *root_dir
,
2127 UnitFileChange
**changes
,
2128 unsigned *n_changes
) {
2130 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2131 _cleanup_(install_context_done
) InstallContext c
= {};
2132 UnitFileInstallInfo
*i
, *target_info
;
2133 const char *config_path
;
2138 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2141 if (!IN_SET(dep
, UNIT_WANTS
, UNIT_REQUIRES
))
2144 if (!unit_name_is_valid(target
, UNIT_NAME_ANY
))
2147 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2151 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2153 r
= install_info_discover(scope
, &c
, &paths
, target
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, &target_info
);
2156 r
= install_info_may_process(target_info
, &paths
, changes
, n_changes
);
2160 assert(target_info
->type
== UNIT_FILE_TYPE_REGULAR
);
2162 STRV_FOREACH(f
, files
) {
2165 r
= install_info_discover(scope
, &c
, &paths
, *f
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2168 r
= install_info_may_process(i
, &paths
, changes
, n_changes
);
2172 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2174 /* We didn't actually load anything from the unit
2175 * file, but instead just add in our new symlink to
2178 if (dep
== UNIT_WANTS
)
2181 l
= &i
->required_by
;
2184 *l
= strv_new(target_info
->name
, NULL
);
2189 return install_context_apply(scope
, &c
, &paths
, config_path
, force
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, changes
, n_changes
);
2192 int unit_file_enable(
2193 UnitFileScope scope
,
2195 const char *root_dir
,
2198 UnitFileChange
**changes
,
2199 unsigned *n_changes
) {
2201 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2202 _cleanup_(install_context_done
) InstallContext c
= {};
2203 const char *config_path
;
2204 UnitFileInstallInfo
*i
;
2209 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2211 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2215 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2217 STRV_FOREACH(f
, files
) {
2218 r
= install_info_discover(scope
, &c
, &paths
, *f
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2221 r
= install_info_may_process(i
, &paths
, changes
, n_changes
);
2225 assert(i
->type
== UNIT_FILE_TYPE_REGULAR
);
2228 /* This will return the number of symlink rules that were
2229 supposed to be created, not the ones actually created. This
2230 is useful to determine whether the passed files had any
2231 installation data at all. */
2233 return install_context_apply(scope
, &c
, &paths
, config_path
, force
, SEARCH_LOAD
, changes
, n_changes
);
2236 int unit_file_disable(
2237 UnitFileScope scope
,
2239 const char *root_dir
,
2241 UnitFileChange
**changes
,
2242 unsigned *n_changes
) {
2244 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2245 _cleanup_(install_context_done
) InstallContext c
= {};
2246 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2247 const char *config_path
;
2252 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2254 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2258 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2260 STRV_FOREACH(i
, files
) {
2261 if (!unit_name_is_valid(*i
, UNIT_NAME_ANY
))
2264 r
= install_info_add(&c
, *i
, NULL
, NULL
);
2269 r
= install_context_mark_for_removal(scope
, &c
, &paths
, &remove_symlinks_to
, config_path
);
2273 return remove_marked_symlinks(remove_symlinks_to
, config_path
, &paths
, changes
, n_changes
);
2276 int unit_file_reenable(
2277 UnitFileScope scope
,
2279 const char *root_dir
,
2282 UnitFileChange
**changes
,
2283 unsigned *n_changes
) {
2289 /* First, we invoke the disable command with only the basename... */
2290 l
= strv_length(files
);
2291 n
= newa(char*, l
+1);
2292 for (i
= 0; i
< l
; i
++)
2293 n
[i
] = basename(files
[i
]);
2296 r
= unit_file_disable(scope
, runtime
, root_dir
, n
, changes
, n_changes
);
2300 /* But the enable command with the full name */
2301 return unit_file_enable(scope
, runtime
, root_dir
, files
, force
, changes
, n_changes
);
2304 int unit_file_set_default(
2305 UnitFileScope scope
,
2306 const char *root_dir
,
2309 UnitFileChange
**changes
,
2310 unsigned *n_changes
) {
2312 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2313 _cleanup_(install_context_done
) InstallContext c
= {};
2314 UnitFileInstallInfo
*i
;
2315 const char *new_path
, *old_path
;
2319 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2322 if (unit_name_to_type(name
) != UNIT_TARGET
) /* this also validates the name */
2324 if (streq(name
, SPECIAL_DEFAULT_TARGET
))
2327 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2331 r
= install_info_discover(scope
, &c
, &paths
, name
, 0, &i
);
2334 r
= install_info_may_process(i
, &paths
, changes
, n_changes
);
2338 old_path
= skip_root(&paths
, i
->path
);
2339 new_path
= strjoina(paths
.persistent_config
, "/" SPECIAL_DEFAULT_TARGET
);
2341 return create_symlink(old_path
?: i
->path
, new_path
, force
, changes
, n_changes
);
2344 int unit_file_get_default(
2345 UnitFileScope scope
,
2346 const char *root_dir
,
2349 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2350 _cleanup_(install_context_done
) InstallContext c
= {};
2351 UnitFileInstallInfo
*i
;
2356 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2359 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2363 r
= install_info_discover(scope
, &c
, &paths
, SPECIAL_DEFAULT_TARGET
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2366 r
= install_info_may_process(i
, &paths
, NULL
, 0);
2370 n
= strdup(i
->name
);
2378 static int unit_file_lookup_state(
2379 UnitFileScope scope
,
2380 const LookupPaths
*paths
,
2382 UnitFileState
*ret
) {
2384 _cleanup_(install_context_done
) InstallContext c
= {};
2385 UnitFileInstallInfo
*i
;
2386 UnitFileState state
;
2392 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2395 r
= install_info_discover(scope
, &c
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2399 /* Shortcut things, if the caller just wants to know if this unit exists. */
2405 case UNIT_FILE_TYPE_MASKED
:
2406 r
= path_is_runtime(paths
, i
->path
);
2410 state
= r
> 0 ? UNIT_FILE_MASKED_RUNTIME
: UNIT_FILE_MASKED
;
2413 case UNIT_FILE_TYPE_REGULAR
:
2414 r
= path_is_generator(paths
, i
->path
);
2418 state
= UNIT_FILE_GENERATED
;
2422 r
= path_is_transient(paths
, i
->path
);
2426 state
= UNIT_FILE_TRANSIENT
;
2430 r
= find_symlinks_in_scope(scope
, paths
, i
->name
, &state
);
2434 if (UNIT_FILE_INSTALL_INFO_HAS_RULES(i
))
2435 state
= UNIT_FILE_DISABLED
;
2436 else if (UNIT_FILE_INSTALL_INFO_HAS_ALSO(i
))
2437 state
= UNIT_FILE_INDIRECT
;
2439 state
= UNIT_FILE_STATIC
;
2445 assert_not_reached("Unexpect unit file type.");
2452 int unit_file_get_state(
2453 UnitFileScope scope
,
2454 const char *root_dir
,
2456 UnitFileState
*ret
) {
2458 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2462 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2465 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2469 return unit_file_lookup_state(scope
, &paths
, name
, ret
);
2472 int unit_file_exists(UnitFileScope scope
, const LookupPaths
*paths
, const char *name
) {
2473 _cleanup_(install_context_done
) InstallContext c
= {};
2479 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2482 r
= install_info_discover(scope
, &c
, paths
, name
, 0, NULL
);
2491 static int read_presets(UnitFileScope scope
, const char *root_dir
, Presets
*presets
) {
2492 _cleanup_(presets_freep
) Presets ps
= {};
2493 size_t n_allocated
= 0;
2494 _cleanup_strv_free_
char **files
= NULL
;
2499 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2502 if (scope
== UNIT_FILE_SYSTEM
)
2503 r
= conf_files_list(&files
, ".preset", root_dir
,
2504 "/etc/systemd/system-preset",
2505 "/usr/local/lib/systemd/system-preset",
2506 "/usr/lib/systemd/system-preset",
2507 #ifdef HAVE_SPLIT_USR
2508 "/lib/systemd/system-preset",
2511 else if (scope
== UNIT_FILE_GLOBAL
)
2512 r
= conf_files_list(&files
, ".preset", root_dir
,
2513 "/etc/systemd/user-preset",
2514 "/usr/local/lib/systemd/user-preset",
2515 "/usr/lib/systemd/user-preset",
2518 *presets
= (Presets
){};
2526 STRV_FOREACH(p
, files
) {
2527 _cleanup_fclose_
FILE *f
;
2528 char line
[LINE_MAX
];
2531 f
= fopen(*p
, "re");
2533 if (errno
== ENOENT
)
2539 FOREACH_LINE(line
, f
, return -errno
) {
2540 PresetRule rule
= {};
2541 const char *parameter
;
2549 if (strchr(COMMENTS
, *l
))
2552 parameter
= first_word(l
, "enable");
2556 pattern
= strdup(parameter
);
2560 rule
= (PresetRule
) {
2562 .action
= PRESET_ENABLE
,
2566 parameter
= first_word(l
, "disable");
2570 pattern
= strdup(parameter
);
2574 rule
= (PresetRule
) {
2576 .action
= PRESET_DISABLE
,
2581 if (!GREEDY_REALLOC(ps
.rules
, n_allocated
, ps
.n_rules
+ 1))
2584 ps
.rules
[ps
.n_rules
++] = rule
;
2588 log_syntax(NULL
, LOG_WARNING
, *p
, n
, 0, "Couldn't parse line '%s'. Ignoring.", line
);
2598 static int query_presets(const char *name
, const Presets presets
) {
2599 PresetAction action
= PRESET_UNKNOWN
;
2602 if (!unit_name_is_valid(name
, UNIT_NAME_ANY
))
2605 for (i
= 0; i
< presets
.n_rules
; i
++)
2606 if (fnmatch(presets
.rules
[i
].pattern
, name
, FNM_NOESCAPE
) == 0) {
2607 action
= presets
.rules
[i
].action
;
2612 case PRESET_UNKNOWN
:
2613 log_debug("Preset files don't specify rule for %s. Enabling.", name
);
2616 log_debug("Preset files say enable %s.", name
);
2618 case PRESET_DISABLE
:
2619 log_debug("Preset files say disable %s.", name
);
2622 assert_not_reached("invalid preset action");
2626 int unit_file_query_preset(UnitFileScope scope
, const char *root_dir
, const char *name
) {
2627 _cleanup_(presets_freep
) Presets presets
= {};
2630 r
= read_presets(scope
, root_dir
, &presets
);
2634 return query_presets(name
, presets
);
2637 static int execute_preset(
2638 UnitFileScope scope
,
2639 InstallContext
*plus
,
2640 InstallContext
*minus
,
2641 const LookupPaths
*paths
,
2642 const char *config_path
,
2644 UnitFilePresetMode mode
,
2646 UnitFileChange
**changes
,
2647 unsigned *n_changes
) {
2654 assert(config_path
);
2656 if (mode
!= UNIT_FILE_PRESET_ENABLE_ONLY
) {
2657 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
2659 r
= install_context_mark_for_removal(scope
, minus
, paths
, &remove_symlinks_to
, config_path
);
2663 r
= remove_marked_symlinks(remove_symlinks_to
, config_path
, paths
, changes
, n_changes
);
2667 if (mode
!= UNIT_FILE_PRESET_DISABLE_ONLY
) {
2670 /* Returns number of symlinks that where supposed to be installed. */
2671 q
= install_context_apply(scope
, plus
, paths
, config_path
, force
, SEARCH_LOAD
, changes
, n_changes
);
2683 static int preset_prepare_one(
2684 UnitFileScope scope
,
2685 InstallContext
*plus
,
2686 InstallContext
*minus
,
2688 UnitFilePresetMode mode
,
2691 UnitFileChange
**changes
,
2692 unsigned *n_changes
) {
2694 UnitFileInstallInfo
*i
;
2697 if (install_info_find(plus
, name
) ||
2698 install_info_find(minus
, name
))
2701 r
= query_presets(name
, presets
);
2706 r
= install_info_discover(scope
, plus
, paths
, name
, SEARCH_LOAD
|SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2710 r
= install_info_may_process(i
, paths
, changes
, n_changes
);
2714 r
= install_info_discover(scope
, minus
, paths
, name
, SEARCH_FOLLOW_CONFIG_SYMLINKS
, &i
);
2719 int unit_file_preset(
2720 UnitFileScope scope
,
2722 const char *root_dir
,
2724 UnitFilePresetMode mode
,
2726 UnitFileChange
**changes
,
2727 unsigned *n_changes
) {
2729 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
2730 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2731 _cleanup_(presets_freep
) Presets presets
= {};
2732 const char *config_path
;
2737 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2738 assert(mode
< _UNIT_FILE_PRESET_MAX
);
2740 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2744 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2746 r
= read_presets(scope
, root_dir
, &presets
);
2750 STRV_FOREACH(i
, files
) {
2751 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, mode
, *i
, presets
, changes
, n_changes
);
2756 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, files
, mode
, force
, changes
, n_changes
);
2759 int unit_file_preset_all(
2760 UnitFileScope scope
,
2762 const char *root_dir
,
2763 UnitFilePresetMode mode
,
2765 UnitFileChange
**changes
,
2766 unsigned *n_changes
) {
2768 _cleanup_(install_context_done
) InstallContext plus
= {}, minus
= {};
2769 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2770 _cleanup_(presets_freep
) Presets presets
= {};
2771 const char *config_path
= NULL
;
2776 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2777 assert(mode
< _UNIT_FILE_PRESET_MAX
);
2779 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2783 config_path
= runtime
? paths
.runtime_config
: paths
.persistent_config
;
2785 r
= read_presets(scope
, root_dir
, &presets
);
2789 STRV_FOREACH(i
, paths
.search_path
) {
2790 _cleanup_closedir_
DIR *d
= NULL
;
2795 if (errno
== ENOENT
)
2801 FOREACH_DIRENT(de
, d
, return -errno
) {
2803 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
2806 dirent_ensure_type(d
, de
);
2808 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
2811 /* we don't pass changes[] in, because we want to handle errors on our own */
2812 r
= preset_prepare_one(scope
, &plus
, &minus
, &paths
, mode
, de
->d_name
, presets
, NULL
, 0);
2814 r
= unit_file_changes_add(changes
, n_changes
,
2815 UNIT_FILE_IS_MASKED
, de
->d_name
, NULL
);
2816 else if (r
== -ENOLINK
)
2817 r
= unit_file_changes_add(changes
, n_changes
,
2818 UNIT_FILE_IS_DANGLING
, de
->d_name
, NULL
);
2824 return execute_preset(scope
, &plus
, &minus
, &paths
, config_path
, NULL
, mode
, force
, changes
, n_changes
);
2827 static void unit_file_list_free_one(UnitFileList
*f
) {
2835 Hashmap
* unit_file_list_free(Hashmap
*h
) {
2838 while ((i
= hashmap_steal_first(h
)))
2839 unit_file_list_free_one(i
);
2841 return hashmap_free(h
);
2844 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList
*, unit_file_list_free_one
);
2846 int unit_file_get_list(
2847 UnitFileScope scope
,
2848 const char *root_dir
,
2853 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
2858 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
2861 r
= lookup_paths_init(&paths
, scope
, 0, root_dir
);
2865 STRV_FOREACH(i
, paths
.search_path
) {
2866 _cleanup_closedir_
DIR *d
= NULL
;
2871 if (errno
== ENOENT
)
2873 if (IN_SET(errno
, ENOTDIR
, EACCES
)) {
2874 log_debug("Failed to open \"%s\": %m", *i
);
2881 FOREACH_DIRENT(de
, d
, return -errno
) {
2882 _cleanup_(unit_file_list_free_onep
) UnitFileList
*f
= NULL
;
2884 if (!unit_name_is_valid(de
->d_name
, UNIT_NAME_ANY
))
2887 if (!strv_fnmatch_or_empty(patterns
, de
->d_name
, FNM_NOESCAPE
))
2890 if (hashmap_get(h
, de
->d_name
))
2893 dirent_ensure_type(d
, de
);
2895 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
))
2898 f
= new0(UnitFileList
, 1);
2902 f
->path
= path_make_absolute(de
->d_name
, *i
);
2906 r
= unit_file_lookup_state(scope
, &paths
, de
->d_name
, &f
->state
);
2908 f
->state
= UNIT_FILE_BAD
;
2910 if (!strv_isempty(states
) &&
2911 !strv_contains(states
, unit_file_state_to_string(f
->state
)))
2914 r
= hashmap_put(h
, basename(f
->path
), f
);
2918 f
= NULL
; /* prevent cleanup */
2925 static const char* const unit_file_state_table
[_UNIT_FILE_STATE_MAX
] = {
2926 [UNIT_FILE_ENABLED
] = "enabled",
2927 [UNIT_FILE_ENABLED_RUNTIME
] = "enabled-runtime",
2928 [UNIT_FILE_LINKED
] = "linked",
2929 [UNIT_FILE_LINKED_RUNTIME
] = "linked-runtime",
2930 [UNIT_FILE_MASKED
] = "masked",
2931 [UNIT_FILE_MASKED_RUNTIME
] = "masked-runtime",
2932 [UNIT_FILE_STATIC
] = "static",
2933 [UNIT_FILE_DISABLED
] = "disabled",
2934 [UNIT_FILE_INDIRECT
] = "indirect",
2935 [UNIT_FILE_GENERATED
] = "generated",
2936 [UNIT_FILE_TRANSIENT
] = "transient",
2937 [UNIT_FILE_BAD
] = "bad",
2940 DEFINE_STRING_TABLE_LOOKUP(unit_file_state
, UnitFileState
);
2942 static const char* const unit_file_change_type_table
[_UNIT_FILE_CHANGE_TYPE_MAX
] = {
2943 [UNIT_FILE_SYMLINK
] = "symlink",
2944 [UNIT_FILE_UNLINK
] = "unlink",
2945 [UNIT_FILE_IS_MASKED
] = "masked",
2946 [UNIT_FILE_IS_DANGLING
] = "dangling",
2949 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type
, UnitFileChangeType
);
2951 static const char* const unit_file_preset_mode_table
[_UNIT_FILE_PRESET_MAX
] = {
2952 [UNIT_FILE_PRESET_FULL
] = "full",
2953 [UNIT_FILE_PRESET_ENABLE_ONLY
] = "enable-only",
2954 [UNIT_FILE_PRESET_DISABLE_ONLY
] = "disable-only",
2957 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode
, UnitFilePresetMode
);