1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty <of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
32 #include "path-util.h"
33 #include "path-lookup.h"
35 #include "unit-name.h"
37 #include "conf-parser.h"
38 #include "conf-files.h"
39 #include "specifier.h"
40 #include "install-printf.h"
43 Hashmap
*will_install
;
44 Hashmap
*have_installed
;
47 #define _cleanup_lookup_paths_free_ \
48 __attribute__((cleanup(lookup_paths_free)))
49 #define _cleanup_install_context_done_ \
50 __attribute__((cleanup(install_context_done)))
52 static int lookup_paths_init_from_scope(LookupPaths
*paths
, UnitFileScope scope
) {
55 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
59 return lookup_paths_init(paths
,
60 scope
== UNIT_FILE_SYSTEM
? SYSTEMD_SYSTEM
: SYSTEMD_USER
,
61 scope
== UNIT_FILE_USER
,
65 static int get_config_path(UnitFileScope scope
, bool runtime
, const char *root_dir
, char **ret
) {
70 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
75 case UNIT_FILE_SYSTEM
:
77 if (root_dir
&& runtime
)
78 asprintf(&p
, "%s/run/systemd/system", root_dir
);
80 p
= strdup("/run/systemd/system");
82 asprintf(&p
, "%s/%s", root_dir
, SYSTEM_CONFIG_UNIT_PATH
);
84 p
= strdup(SYSTEM_CONFIG_UNIT_PATH
);
88 case UNIT_FILE_GLOBAL
:
94 p
= strdup("/run/systemd/user");
96 p
= strdup(USER_CONFIG_UNIT_PATH
);
101 if (root_dir
|| runtime
)
104 r
= user_config_home(&p
);
106 return r
< 0 ? r
: -ENOENT
;
111 assert_not_reached("Bad scope");
121 static int add_file_change(
122 UnitFileChange
**changes
,
124 UnitFileChangeType type
,
126 const char *source
) {
132 assert(!changes
== !n_changes
);
137 c
= realloc(*changes
, (*n_changes
+ 1) * sizeof(UnitFileChange
));
145 c
[i
].path
= strdup(path
);
150 c
[i
].source
= strdup(source
);
162 static int mark_symlink_for_removal(
163 Set
**remove_symlinks_to
,
171 r
= set_ensure_allocated(remove_symlinks_to
, string_hash_func
, string_compare_func
);
179 path_kill_slashes(n
);
181 r
= set_consume(*remove_symlinks_to
, n
);
183 return r
== -EEXIST
? 0 : r
;
188 static int remove_marked_symlinks_fd(
189 Set
*remove_symlinks_to
,
192 const char *config_path
,
194 UnitFileChange
**changes
,
199 _cleanup_closedir_
DIR *d
= NULL
;
201 assert(remove_symlinks_to
);
209 close_nointr_nofail(fd
);
217 union dirent_storage buf
;
220 k
= readdir_r(d
, &buf
.de
, &de
);
229 if (ignore_file(de
->d_name
))
232 dirent_ensure_type(d
, de
);
234 if (de
->d_type
== DT_DIR
) {
236 _cleanup_free_
char *p
= NULL
;
238 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
248 p
= path_make_absolute(de
->d_name
, path
);
250 close_nointr_nofail(nfd
);
254 /* This will close nfd, regardless whether it succeeds or not */
255 q
= remove_marked_symlinks_fd(remove_symlinks_to
, nfd
, p
, config_path
, deleted
, changes
, n_changes
, files
);
260 } else if (de
->d_type
== DT_LNK
) {
261 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
265 p
= path_make_absolute(de
->d_name
, path
);
269 q
= readlink_and_canonicalize(p
, &dest
);
280 set_get(remove_symlinks_to
, dest
) ||
281 set_get(remove_symlinks_to
, path_get_file_name(dest
));
283 if (unit_name_is_instance(p
))
284 found
= found
&& strv_contains(files
, path_get_file_name(p
));
288 if (unlink(p
) < 0 && errno
!= ENOENT
) {
293 rmdir_parents(p
, config_path
);
294 path_kill_slashes(p
);
296 add_file_change(changes
, n_changes
, UNIT_FILE_UNLINK
, p
, NULL
);
298 if (!set_get(remove_symlinks_to
, p
)) {
300 q
= mark_symlink_for_removal(&remove_symlinks_to
, p
);
315 static int remove_marked_symlinks(
316 Set
*remove_symlinks_to
,
317 const char *config_path
,
318 UnitFileChange
**changes
,
327 if (set_size(remove_symlinks_to
) <= 0)
330 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
344 /* This takes possession of cfd and closes it */
345 q
= remove_marked_symlinks_fd(remove_symlinks_to
, cfd
, config_path
, config_path
, &deleted
, changes
, n_changes
, files
);
350 close_nointr_nofail(fd
);
355 static int find_symlinks_fd(
359 const char *config_path
,
360 bool *same_name_link
) {
363 _cleanup_closedir_
DIR *d
= NULL
;
369 assert(same_name_link
);
373 close_nointr_nofail(fd
);
380 union dirent_storage buf
;
382 k
= readdir_r(d
, &buf
.de
, &de
);
389 if (ignore_file(de
->d_name
))
392 dirent_ensure_type(d
, de
);
394 if (de
->d_type
== DT_DIR
) {
396 _cleanup_free_
char *p
= NULL
;
398 nfd
= openat(fd
, de
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
408 p
= path_make_absolute(de
->d_name
, path
);
410 close_nointr_nofail(nfd
);
414 /* This will close nfd, regardless whether it succeeds or not */
415 q
= find_symlinks_fd(name
, nfd
, p
, config_path
, same_name_link
);
423 } else if (de
->d_type
== DT_LNK
) {
424 _cleanup_free_
char *p
= NULL
, *dest
= NULL
;
425 bool found_path
, found_dest
, b
= false;
428 /* Acquire symlink name */
429 p
= path_make_absolute(de
->d_name
, path
);
433 /* Acquire symlink destination */
434 q
= readlink_and_canonicalize(p
, &dest
);
444 /* Check if the symlink itself matches what we
446 if (path_is_absolute(name
))
447 found_path
= path_equal(p
, name
);
449 found_path
= streq(de
->d_name
, name
);
451 /* Check if what the symlink points to
452 * matches what we are looking for */
453 if (path_is_absolute(name
))
454 found_dest
= path_equal(dest
, name
);
456 found_dest
= streq(path_get_file_name(dest
), name
);
458 if (found_path
&& found_dest
) {
459 _cleanup_free_
char *t
= NULL
;
461 /* Filter out same name links in the main
463 t
= path_make_absolute(name
, config_path
);
467 b
= path_equal(t
, p
);
471 *same_name_link
= true;
472 else if (found_path
|| found_dest
)
480 static int find_symlinks(
482 const char *config_path
,
483 bool *same_name_link
) {
489 assert(same_name_link
);
491 fd
= open(config_path
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|O_NOFOLLOW
);
498 /* This takes possession of fd and closes it */
499 return find_symlinks_fd(name
, fd
, config_path
, config_path
, same_name_link
);
502 static int find_symlinks_in_scope(
504 const char *root_dir
,
506 UnitFileState
*state
) {
509 _cleanup_free_
char *path
= NULL
;
510 bool same_name_link_runtime
= false, same_name_link
= false;
513 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
516 if (scope
== UNIT_FILE_SYSTEM
|| scope
== UNIT_FILE_GLOBAL
) {
518 /* First look in runtime config path */
519 r
= get_config_path(scope
, true, root_dir
, &path
);
523 r
= find_symlinks(name
, path
, &same_name_link_runtime
);
527 *state
= UNIT_FILE_ENABLED_RUNTIME
;
532 /* Then look in the normal config path */
533 r
= get_config_path(scope
, false, root_dir
, &path
);
537 r
= find_symlinks(name
, path
, &same_name_link
);
541 *state
= UNIT_FILE_ENABLED
;
545 /* Hmm, we didn't find it, but maybe we found the same name
547 if (same_name_link_runtime
) {
548 *state
= UNIT_FILE_LINKED_RUNTIME
;
550 } else if (same_name_link
) {
551 *state
= UNIT_FILE_LINKED
;
561 const char *root_dir
,
564 UnitFileChange
**changes
,
565 unsigned *n_changes
) {
568 _cleanup_free_
char *prefix
;
572 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
574 r
= get_config_path(scope
, runtime
, root_dir
, &prefix
);
578 STRV_FOREACH(i
, files
) {
579 _cleanup_free_
char *path
= NULL
;
581 if (!unit_name_is_valid(*i
, true)) {
587 path
= path_make_absolute(*i
, prefix
);
593 if (symlink("/dev/null", path
) >= 0) {
594 add_file_change(changes
, n_changes
, UNIT_FILE_SYMLINK
, path
, "/dev/null");
599 if (errno
== EEXIST
) {
601 if (null_or_empty_path(path
) > 0)
607 if (symlink("/dev/null", path
) >= 0) {
609 add_file_change(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
610 add_file_change(changes
, n_changes
, UNIT_FILE_SYMLINK
, path
, "/dev/null");
627 int unit_file_unmask(
630 const char *root_dir
,
632 UnitFileChange
**changes
,
633 unsigned *n_changes
) {
635 char **i
, *config_path
= NULL
;
637 Set
*remove_symlinks_to
= NULL
;
640 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
642 r
= get_config_path(scope
, runtime
, root_dir
, &config_path
);
646 STRV_FOREACH(i
, files
) {
649 if (!unit_name_is_valid(*i
, true)) {
655 path
= path_make_absolute(*i
, config_path
);
661 q
= null_or_empty_path(path
);
663 if (unlink(path
) >= 0) {
664 mark_symlink_for_removal(&remove_symlinks_to
, path
);
665 add_file_change(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
674 if (q
!= -ENOENT
&& r
== 0)
682 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
, changes
, n_changes
, files
);
686 set_free_free(remove_symlinks_to
);
695 const char *root_dir
,
698 UnitFileChange
**changes
,
699 unsigned *n_changes
) {
701 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
703 _cleanup_free_
char *config_path
= NULL
;
707 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
709 r
= lookup_paths_init_from_scope(&paths
, scope
);
713 r
= get_config_path(scope
, runtime
, root_dir
, &config_path
);
717 STRV_FOREACH(i
, files
) {
718 _cleanup_free_
char *path
= NULL
;
722 fn
= path_get_file_name(*i
);
724 if (!path_is_absolute(*i
) ||
725 !unit_name_is_valid(fn
, true)) {
731 if (lstat(*i
, &st
) < 0) {
737 if (!S_ISREG(st
.st_mode
)) {
742 q
= in_search_path(*i
, paths
.unit_path
);
749 path
= path_make_absolute(fn
, config_path
);
753 if (symlink(*i
, path
) >= 0) {
754 add_file_change(changes
, n_changes
, UNIT_FILE_SYMLINK
, path
, *i
);
758 if (errno
== EEXIST
) {
759 _cleanup_free_
char *dest
= NULL
;
761 q
= readlink_and_make_absolute(path
, &dest
);
763 if (q
< 0 && errno
!= ENOENT
) {
769 if (q
>= 0 && path_equal(dest
, *i
))
775 if (symlink(*i
, path
) >= 0) {
777 add_file_change(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
778 add_file_change(changes
, n_changes
, UNIT_FILE_SYMLINK
, path
, *i
);
795 void unit_file_list_free(Hashmap
*h
) {
798 while ((i
= hashmap_steal_first(h
))) {
806 void unit_file_changes_free(UnitFileChange
*changes
, unsigned n_changes
) {
809 assert(changes
|| n_changes
== 0);
814 for (i
= 0; i
< n_changes
; i
++) {
815 free(changes
[i
].path
);
816 free(changes
[i
].source
);
822 static void install_info_free(InstallInfo
*i
) {
827 strv_free(i
->aliases
);
828 strv_free(i
->wanted_by
);
829 strv_free(i
->required_by
);
833 static void install_info_hashmap_free(Hashmap
*m
) {
839 while ((i
= hashmap_steal_first(m
)))
840 install_info_free(i
);
845 static void install_context_done(InstallContext
*c
) {
848 install_info_hashmap_free(c
->will_install
);
849 install_info_hashmap_free(c
->have_installed
);
851 c
->will_install
= c
->have_installed
= NULL
;
854 static int install_info_add(
858 InstallInfo
*i
= NULL
;
862 assert(name
|| path
);
865 name
= path_get_file_name(path
);
867 if (!unit_name_is_valid(name
, true))
870 if (hashmap_get(c
->have_installed
, name
) ||
871 hashmap_get(c
->will_install
, name
))
874 r
= hashmap_ensure_allocated(&c
->will_install
, string_hash_func
, string_compare_func
);
878 i
= new0(InstallInfo
, 1);
882 i
->name
= strdup(name
);
889 i
->path
= strdup(path
);
896 r
= hashmap_put(c
->will_install
, i
->name
, i
);
904 install_info_free(i
);
909 static int install_info_add_auto(
911 const char *name_or_path
) {
914 assert(name_or_path
);
916 if (path_is_absolute(name_or_path
))
917 return install_info_add(c
, NULL
, name_or_path
);
919 return install_info_add(c
, name_or_path
, NULL
);
922 static int config_parse_also(const char *unit
,
923 const char *filename
,
935 InstallContext
*c
= data
;
941 FOREACH_WORD_QUOTED(w
, l
, rvalue
, state
) {
942 _cleanup_free_
char *n
;
949 r
= install_info_add(c
, n
, NULL
);
957 static int config_parse_user(const char *unit
,
958 const char *filename
,
967 InstallInfo
*i
= data
;
974 printed
= install_full_printf(i
, rvalue
);
984 static int unit_file_load(
988 bool allow_symlink
) {
990 const ConfigTableItem items
[] = {
991 { "Install", "Alias", config_parse_strv
, 0, &info
->aliases
},
992 { "Install", "WantedBy", config_parse_strv
, 0, &info
->wanted_by
},
993 { "Install", "RequiredBy", config_parse_strv
, 0, &info
->required_by
},
994 { "Install", "Also", config_parse_also
, 0, c
},
995 { "Exec", "User", config_parse_user
, 0, info
},
996 { NULL
, NULL
, NULL
, 0, NULL
}
1000 _cleanup_fclose_
FILE *f
= NULL
;
1007 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|(allow_symlink
? 0 : O_NOFOLLOW
));
1011 f
= fdopen(fd
, "re");
1013 close_nointr_nofail(fd
);
1017 r
= config_parse(NULL
, path
, f
, NULL
,
1018 config_item_table_lookup
, (void*) items
, true, true, info
);
1023 strv_length(info
->aliases
) +
1024 strv_length(info
->wanted_by
) +
1025 strv_length(info
->required_by
);
1028 static int unit_file_search(
1032 const char *root_dir
,
1033 bool allow_symlink
) {
1043 return unit_file_load(c
, info
, info
->path
, allow_symlink
);
1047 STRV_FOREACH(p
, paths
->unit_path
) {
1050 if (isempty(root_dir
))
1051 asprintf(&path
, "%s/%s", *p
, info
->name
);
1053 asprintf(&path
, "%s/%s/%s", root_dir
, *p
, info
->name
);
1058 r
= unit_file_load(c
, info
, path
, allow_symlink
);
1063 if (r
== -ENOENT
&& unit_name_is_instance(info
->name
)) {
1064 /* unit file doesn't exist, however instance enablement was request */
1065 /* we will check if it is possible to load template unit file */
1066 char *template = NULL
,
1067 *template_path
= NULL
,
1068 *template_dir
= NULL
;
1070 template = unit_name_template(info
->name
);
1076 /* we will reuse path variable since we don't need it anymore */
1077 template_dir
= path
;
1078 *(strrchr(path
, '/') + 1) = '\0';
1080 template_path
= strjoin(template_dir
, template, NULL
);
1081 if (!template_path
) {
1087 /* let's try to load template unit */
1088 r
= unit_file_load(c
, info
, template_path
, allow_symlink
);
1090 info
->path
= strdup(template_path
);
1094 free(template_path
);
1100 free(template_path
);
1105 if (r
!= -ENOENT
&& r
!= -ELOOP
)
1112 static int unit_file_can_install(
1114 const char *root_dir
,
1116 bool allow_symlink
) {
1118 _cleanup_install_context_done_ InstallContext c
= {};
1125 r
= install_info_add_auto(&c
, name
);
1129 assert_se(i
= hashmap_first(c
.will_install
));
1131 r
= unit_file_search(&c
, i
, paths
, root_dir
, allow_symlink
);
1135 strv_length(i
->aliases
) +
1136 strv_length(i
->wanted_by
) +
1137 strv_length(i
->required_by
);
1142 static int create_symlink(
1143 const char *old_path
,
1144 const char *new_path
,
1146 UnitFileChange
**changes
,
1147 unsigned *n_changes
) {
1149 _cleanup_free_
char *dest
= NULL
;
1155 mkdir_parents_label(new_path
, 0755);
1157 if (symlink(old_path
, new_path
) >= 0) {
1158 add_file_change(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
1162 if (errno
!= EEXIST
)
1165 r
= readlink_and_make_absolute(new_path
, &dest
);
1169 if (path_equal(dest
, old_path
))
1177 if (symlink(old_path
, new_path
) >= 0) {
1178 add_file_change(changes
, n_changes
, UNIT_FILE_UNLINK
, new_path
, NULL
);
1179 add_file_change(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
1186 static int install_info_symlink_alias(
1188 const char *config_path
,
1190 UnitFileChange
**changes
,
1191 unsigned *n_changes
) {
1197 assert(config_path
);
1199 STRV_FOREACH(s
, i
->aliases
) {
1200 _cleanup_free_
char *alias_path
= NULL
, *dst
= NULL
;
1202 dst
= install_full_printf(i
, *s
);
1206 alias_path
= path_make_absolute(dst
, config_path
);
1210 q
= create_symlink(i
->path
, alias_path
, force
, changes
, n_changes
);
1218 static int install_info_symlink_wants(
1220 const char *config_path
,
1222 UnitFileChange
**changes
,
1223 unsigned *n_changes
) {
1229 assert(config_path
);
1231 STRV_FOREACH(s
, i
->wanted_by
) {
1232 _cleanup_free_
char *path
= NULL
, *dst
= NULL
;
1234 dst
= install_full_printf(i
, *s
);
1238 if (!unit_name_is_valid(dst
, true)) {
1243 if (asprintf(&path
, "%s/%s.wants/%s", config_path
, dst
, i
->name
) < 0)
1246 q
= create_symlink(i
->path
, path
, force
, changes
, n_changes
);
1255 static int install_info_symlink_requires(
1257 const char *config_path
,
1259 UnitFileChange
**changes
,
1260 unsigned *n_changes
) {
1266 assert(config_path
);
1268 STRV_FOREACH(s
, i
->required_by
) {
1269 _cleanup_free_
char *path
= NULL
, *dst
= NULL
;
1271 dst
= install_full_printf(i
, *s
);
1275 if (!unit_name_is_valid(dst
, true)) {
1280 if (asprintf(&path
, "%s/%s.requires/%s", config_path
, dst
, i
->name
) < 0)
1283 q
= create_symlink(i
->path
, path
, force
, changes
, n_changes
);
1292 static int install_info_symlink_link(
1295 const char *config_path
,
1297 UnitFileChange
**changes
,
1298 unsigned *n_changes
) {
1301 _cleanup_free_
char *path
= NULL
;
1305 assert(config_path
);
1308 r
= in_search_path(i
->path
, paths
->unit_path
);
1312 if (asprintf(&path
, "%s/%s", config_path
, i
->name
) < 0)
1315 r
= create_symlink(i
->path
, path
, force
, changes
, n_changes
);
1319 static int install_info_apply(
1322 const char *config_path
,
1324 UnitFileChange
**changes
,
1325 unsigned *n_changes
) {
1331 assert(config_path
);
1333 r
= install_info_symlink_alias(i
, config_path
, force
, changes
, n_changes
);
1335 q
= install_info_symlink_wants(i
, config_path
, force
, changes
, n_changes
);
1339 q
= install_info_symlink_requires(i
, config_path
, force
, changes
, n_changes
);
1343 q
= install_info_symlink_link(i
, paths
, config_path
, force
, changes
, n_changes
);
1350 static int install_context_apply(
1353 const char *config_path
,
1354 const char *root_dir
,
1356 UnitFileChange
**changes
,
1357 unsigned *n_changes
) {
1364 assert(config_path
);
1366 while ((i
= hashmap_first(c
->will_install
))) {
1368 q
= hashmap_ensure_allocated(&c
->have_installed
, string_hash_func
, string_compare_func
);
1372 assert_se(hashmap_move_one(c
->have_installed
, c
->will_install
, i
->name
) == 0);
1374 q
= unit_file_search(c
, i
, paths
, root_dir
, false);
1383 q
= install_info_apply(i
, paths
, config_path
, force
, changes
, n_changes
);
1384 if (r
>= 0 && q
< 0)
1391 static int install_context_mark_for_removal(
1394 Set
**remove_symlinks_to
,
1395 const char *config_path
,
1396 const char *root_dir
) {
1403 assert(config_path
);
1405 /* Marks all items for removal */
1407 while ((i
= hashmap_first(c
->will_install
))) {
1409 q
= hashmap_ensure_allocated(&c
->have_installed
, string_hash_func
, string_compare_func
);
1413 assert_se(hashmap_move_one(c
->have_installed
, c
->will_install
, i
->name
) == 0);
1415 q
= unit_file_search(c
, i
, paths
, root_dir
, false);
1426 if (unit_name_is_instance(i
->name
)) {
1427 char *unit_file
= NULL
;
1429 unit_file
= path_get_file_name(i
->path
);
1431 if (unit_name_is_instance(unit_file
))
1432 /* unit file named as instance exists, thus all symlinks pointing to it, will be removed */
1433 q
= mark_symlink_for_removal(remove_symlinks_to
, i
->name
);
1435 /* does not exist, thus we will mark for removal symlinks to template unit file */
1436 q
= mark_symlink_for_removal(remove_symlinks_to
, unit_file
);
1438 q
= mark_symlink_for_removal(remove_symlinks_to
, i
->name
);
1440 if (r
>= 0 && q
< 0)
1447 int unit_file_enable(
1448 UnitFileScope scope
,
1450 const char *root_dir
,
1453 UnitFileChange
**changes
,
1454 unsigned *n_changes
) {
1456 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1457 _cleanup_install_context_done_ InstallContext c
= {};
1459 _cleanup_free_
char *config_path
= NULL
;
1463 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1465 r
= lookup_paths_init_from_scope(&paths
, scope
);
1469 r
= get_config_path(scope
, runtime
, root_dir
, &config_path
);
1473 STRV_FOREACH(i
, files
) {
1474 r
= install_info_add_auto(&c
, *i
);
1479 /* This will return the number of symlink rules that were
1480 supposed to be created, not the ones actually created. This is
1481 useful to determine whether the passed files had any
1482 installation data at all. */
1483 r
= install_context_apply(&c
, &paths
, config_path
, root_dir
, force
, changes
, n_changes
);
1487 int unit_file_disable(
1488 UnitFileScope scope
,
1490 const char *root_dir
,
1492 UnitFileChange
**changes
,
1493 unsigned *n_changes
) {
1495 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1496 _cleanup_install_context_done_ InstallContext c
= {};
1498 _cleanup_free_
char *config_path
= NULL
;
1499 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
1503 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1505 r
= lookup_paths_init_from_scope(&paths
, scope
);
1509 r
= get_config_path(scope
, runtime
, root_dir
, &config_path
);
1513 STRV_FOREACH(i
, files
) {
1514 r
= install_info_add_auto(&c
, *i
);
1519 r
= install_context_mark_for_removal(&c
, &paths
, &remove_symlinks_to
, config_path
, root_dir
);
1521 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
, changes
, n_changes
, files
);
1528 int unit_file_reenable(
1529 UnitFileScope scope
,
1531 const char *root_dir
,
1534 UnitFileChange
**changes
,
1535 unsigned *n_changes
) {
1537 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1538 _cleanup_install_context_done_ InstallContext c
= {};
1540 _cleanup_free_
char *config_path
= NULL
;
1541 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
1545 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1547 r
= lookup_paths_init_from_scope(&paths
, scope
);
1551 r
= get_config_path(scope
, runtime
, root_dir
, &config_path
);
1555 STRV_FOREACH(i
, files
) {
1556 r
= mark_symlink_for_removal(&remove_symlinks_to
, *i
);
1560 r
= install_info_add_auto(&c
, *i
);
1565 r
= remove_marked_symlinks(remove_symlinks_to
, config_path
, changes
, n_changes
, files
);
1567 /* Returns number of symlinks that where supposed to be installed. */
1568 q
= install_context_apply(&c
, &paths
, config_path
, root_dir
, force
, changes
, n_changes
);
1575 int unit_file_set_default(
1576 UnitFileScope scope
,
1577 const char *root_dir
,
1579 UnitFileChange
**changes
,
1580 unsigned *n_changes
) {
1582 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1583 _cleanup_install_context_done_ InstallContext c
= {};
1584 _cleanup_free_
char *config_path
= NULL
;
1587 InstallInfo
*i
= NULL
;
1590 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1592 if (unit_name_to_type(file
) != UNIT_TARGET
)
1595 r
= lookup_paths_init_from_scope(&paths
, scope
);
1599 r
= get_config_path(scope
, false, root_dir
, &config_path
);
1603 r
= install_info_add_auto(&c
, file
);
1607 i
= (InstallInfo
*)hashmap_first(c
.will_install
);
1609 r
= unit_file_search(&c
, i
, &paths
, root_dir
, false);
1613 path
= strappenda(config_path
, "/default.target");
1614 r
= create_symlink(i
->path
, path
, true, changes
, n_changes
);
1621 int unit_file_get_default(
1622 UnitFileScope scope
,
1623 const char *root_dir
,
1626 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1630 r
= lookup_paths_init_from_scope(&paths
, scope
);
1634 STRV_FOREACH(p
, paths
.unit_path
) {
1635 _cleanup_free_
char *path
= NULL
, *tmp
= NULL
;
1637 if (isempty(root_dir
))
1638 path
= strappend(*p
, "/default.target");
1640 path
= strjoin(root_dir
, "/", *p
, "/default.target", NULL
);
1645 r
= readlink_malloc(path
, &tmp
);
1651 *name
= strdup(path_get_file_name(tmp
));
1661 UnitFileState
unit_file_get_state(
1662 UnitFileScope scope
,
1663 const char *root_dir
,
1666 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1667 UnitFileState state
= _UNIT_FILE_STATE_INVALID
;
1669 _cleanup_free_
char *path
= NULL
;
1673 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1676 if (root_dir
&& scope
!= UNIT_FILE_SYSTEM
)
1679 if (!unit_name_is_valid(name
, true))
1682 r
= lookup_paths_init_from_scope(&paths
, scope
);
1686 STRV_FOREACH(i
, paths
.unit_path
) {
1693 asprintf(&path
, "%s/%s/%s", root_dir
, *i
, name
);
1695 asprintf(&path
, "%s/%s", *i
, name
);
1701 * Search for a unit file in our default paths, to
1702 * be sure, that there are no broken symlinks.
1704 if (lstat(path
, &st
) < 0) {
1706 if (errno
!= ENOENT
)
1709 if (!unit_name_is_instance(name
))
1712 if (!S_ISREG(st
.st_mode
) && !S_ISLNK(st
.st_mode
))
1715 r
= null_or_empty_path(path
);
1716 if (r
< 0 && r
!= -ENOENT
)
1719 state
= path_startswith(*i
, "/run") ?
1720 UNIT_FILE_MASKED_RUNTIME
: UNIT_FILE_MASKED
;
1725 r
= find_symlinks_in_scope(scope
, root_dir
, name
, &state
);
1731 r
= unit_file_can_install(&paths
, root_dir
, path
, true);
1732 if (r
< 0 && errno
!= ENOENT
)
1735 return UNIT_FILE_DISABLED
;
1737 return UNIT_FILE_STATIC
;
1740 return r
< 0 ? r
: state
;
1743 int unit_file_query_preset(UnitFileScope scope
, const char *name
) {
1744 _cleanup_strv_free_
char **files
= NULL
;
1749 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1752 if (scope
== UNIT_FILE_SYSTEM
)
1753 r
= conf_files_list(&files
, ".preset", NULL
,
1754 "/etc/systemd/system-preset",
1755 "/usr/local/lib/systemd/system-preset",
1756 "/usr/lib/systemd/system-preset",
1757 #ifdef HAVE_SPLIT_USR
1758 "/lib/systemd/system-preset",
1761 else if (scope
== UNIT_FILE_GLOBAL
)
1762 r
= conf_files_list(&files
, ".preset", NULL
,
1763 "/etc/systemd/user-preset",
1764 "/usr/local/lib/systemd/user-preset",
1765 "/usr/lib/systemd/user-preset",
1773 STRV_FOREACH(i
, files
) {
1774 _cleanup_fclose_
FILE *f
;
1776 f
= fopen(*i
, "re");
1778 if (errno
== ENOENT
)
1785 char line
[LINE_MAX
], *l
;
1787 if (!fgets(line
, sizeof(line
), f
))
1794 if (strchr(COMMENTS
"\n", *l
))
1797 if (first_word(l
, "enable")) {
1799 l
+= strspn(l
, WHITESPACE
);
1801 if (fnmatch(l
, name
, FNM_NOESCAPE
) == 0)
1804 } else if (first_word(l
, "disable")) {
1806 l
+= strspn(l
, WHITESPACE
);
1808 if (fnmatch(l
, name
, FNM_NOESCAPE
) == 0)
1812 log_debug("Couldn't parse line '%s'", l
);
1816 /* Default is "enable" */
1820 int unit_file_preset(
1821 UnitFileScope scope
,
1823 const char *root_dir
,
1826 UnitFileChange
**changes
,
1827 unsigned *n_changes
) {
1829 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1830 _cleanup_install_context_done_ InstallContext plus
= {}, minus
= {};
1832 _cleanup_free_
char *config_path
= NULL
;
1833 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
1837 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1839 r
= lookup_paths_init_from_scope(&paths
, scope
);
1843 r
= get_config_path(scope
, runtime
, root_dir
, &config_path
);
1847 STRV_FOREACH(i
, files
) {
1849 if (!unit_name_is_valid(*i
, true))
1852 r
= unit_file_query_preset(scope
, *i
);
1857 r
= install_info_add_auto(&plus
, *i
);
1859 r
= install_info_add_auto(&minus
, *i
);
1865 r
= install_context_mark_for_removal(&minus
, &paths
, &remove_symlinks_to
,
1866 config_path
, root_dir
);
1868 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
,
1869 changes
, n_changes
, files
);
1873 /* Returns number of symlinks that where supposed to be installed. */
1874 q
= install_context_apply(&plus
, &paths
, config_path
, root_dir
, force
,
1875 changes
, n_changes
);
1882 static void unitfilelist_free(UnitFileList
**f
) {
1890 int unit_file_get_list(
1891 UnitFileScope scope
,
1892 const char *root_dir
,
1895 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1897 _cleanup_free_
char *buf
= NULL
;
1898 _cleanup_closedir_
DIR *d
= NULL
;
1902 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1905 if (root_dir
&& scope
!= UNIT_FILE_SYSTEM
)
1908 r
= lookup_paths_init_from_scope(&paths
, scope
);
1912 STRV_FOREACH(i
, paths
.unit_path
) {
1913 const char *units_dir
;
1919 if (asprintf(&buf
, "%s/%s", root_dir
, *i
) < 0)
1929 d
= opendir(units_dir
);
1931 if (errno
== ENOENT
)
1939 union dirent_storage buffer
;
1940 UnitFileList
__attribute__((cleanup(unitfilelist_free
)))
1943 r
= readdir_r(d
, &buffer
.de
, &de
);
1950 if (ignore_file(de
->d_name
))
1953 if (!unit_name_is_valid(de
->d_name
, true))
1956 if (hashmap_get(h
, de
->d_name
))
1959 r
= dirent_ensure_type(d
, de
);
1967 if (de
->d_type
!= DT_LNK
&& de
->d_type
!= DT_REG
)
1970 f
= new0(UnitFileList
, 1);
1974 f
->path
= path_make_absolute(de
->d_name
, units_dir
);
1978 r
= null_or_empty_path(f
->path
);
1979 if (r
< 0 && r
!= -ENOENT
)
1983 path_startswith(*i
, "/run") ?
1984 UNIT_FILE_MASKED_RUNTIME
: UNIT_FILE_MASKED
;
1988 r
= find_symlinks_in_scope(scope
, root_dir
, de
->d_name
, &f
->state
);
1992 f
->state
= UNIT_FILE_ENABLED
;
1996 r
= unit_file_can_install(&paths
, root_dir
, f
->path
, true);
1997 if (r
== -EINVAL
|| /* Invalid setting? */
1998 r
== -EBADMSG
|| /* Invalid format? */
1999 r
== -ENOENT
/* Included file not found? */)
2000 f
->state
= UNIT_FILE_INVALID
;
2004 f
->state
= UNIT_FILE_DISABLED
;
2006 f
->state
= UNIT_FILE_STATIC
;
2009 r
= hashmap_put(h
, path_get_file_name(f
->path
), f
);
2012 f
= NULL
; /* prevent cleanup */
2019 static const char* const unit_file_state_table
[_UNIT_FILE_STATE_MAX
] = {
2020 [UNIT_FILE_ENABLED
] = "enabled",
2021 [UNIT_FILE_ENABLED_RUNTIME
] = "enabled-runtime",
2022 [UNIT_FILE_LINKED
] = "linked",
2023 [UNIT_FILE_LINKED_RUNTIME
] = "linked-runtime",
2024 [UNIT_FILE_MASKED
] = "masked",
2025 [UNIT_FILE_MASKED_RUNTIME
] = "masked-runtime",
2026 [UNIT_FILE_STATIC
] = "static",
2027 [UNIT_FILE_DISABLED
] = "disabled",
2028 [UNIT_FILE_INVALID
] = "invalid",
2031 DEFINE_STRING_TABLE_LOOKUP(unit_file_state
, UnitFileState
);
2033 static const char* const unit_file_change_type_table
[_UNIT_FILE_CHANGE_TYPE_MAX
] = {
2034 [UNIT_FILE_SYMLINK
] = "symlink",
2035 [UNIT_FILE_UNLINK
] = "unlink",
2038 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type
, UnitFileChangeType
);