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 *path2
= 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
) {
517 _cleanup_free_
char *path
= NULL
;
519 /* First look in runtime config path */
520 r
= get_config_path(scope
, true, root_dir
, &path
);
524 r
= find_symlinks(name
, path
, &same_name_link_runtime
);
528 *state
= UNIT_FILE_ENABLED_RUNTIME
;
533 /* Then look in the normal config path */
534 r
= get_config_path(scope
, false, root_dir
, &path2
);
538 r
= find_symlinks(name
, path2
, &same_name_link
);
542 *state
= UNIT_FILE_ENABLED
;
546 /* Hmm, we didn't find it, but maybe we found the same name
548 if (same_name_link_runtime
) {
549 *state
= UNIT_FILE_LINKED_RUNTIME
;
551 } else if (same_name_link
) {
552 *state
= UNIT_FILE_LINKED
;
562 const char *root_dir
,
565 UnitFileChange
**changes
,
566 unsigned *n_changes
) {
569 _cleanup_free_
char *prefix
;
573 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
575 r
= get_config_path(scope
, runtime
, root_dir
, &prefix
);
579 STRV_FOREACH(i
, files
) {
580 _cleanup_free_
char *path
= NULL
;
582 if (!unit_name_is_valid(*i
, true)) {
588 path
= path_make_absolute(*i
, prefix
);
594 if (symlink("/dev/null", path
) >= 0) {
595 add_file_change(changes
, n_changes
, UNIT_FILE_SYMLINK
, path
, "/dev/null");
600 if (errno
== EEXIST
) {
602 if (null_or_empty_path(path
) > 0)
608 if (symlink("/dev/null", path
) >= 0) {
610 add_file_change(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
611 add_file_change(changes
, n_changes
, UNIT_FILE_SYMLINK
, path
, "/dev/null");
628 int unit_file_unmask(
631 const char *root_dir
,
633 UnitFileChange
**changes
,
634 unsigned *n_changes
) {
636 char **i
, *config_path
= NULL
;
638 Set
*remove_symlinks_to
= NULL
;
641 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
643 r
= get_config_path(scope
, runtime
, root_dir
, &config_path
);
647 STRV_FOREACH(i
, files
) {
650 if (!unit_name_is_valid(*i
, true)) {
656 path
= path_make_absolute(*i
, config_path
);
662 q
= null_or_empty_path(path
);
664 if (unlink(path
) >= 0) {
665 mark_symlink_for_removal(&remove_symlinks_to
, path
);
666 add_file_change(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
675 if (q
!= -ENOENT
&& r
== 0)
683 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
, changes
, n_changes
, files
);
687 set_free_free(remove_symlinks_to
);
696 const char *root_dir
,
699 UnitFileChange
**changes
,
700 unsigned *n_changes
) {
702 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
704 _cleanup_free_
char *config_path
= NULL
;
708 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
710 r
= lookup_paths_init_from_scope(&paths
, scope
);
714 r
= get_config_path(scope
, runtime
, root_dir
, &config_path
);
718 STRV_FOREACH(i
, files
) {
719 _cleanup_free_
char *path
= NULL
;
723 fn
= path_get_file_name(*i
);
725 if (!path_is_absolute(*i
) ||
726 !unit_name_is_valid(fn
, true)) {
732 if (lstat(*i
, &st
) < 0) {
738 if (!S_ISREG(st
.st_mode
)) {
743 q
= in_search_path(*i
, paths
.unit_path
);
750 path
= path_make_absolute(fn
, config_path
);
754 if (symlink(*i
, path
) >= 0) {
755 add_file_change(changes
, n_changes
, UNIT_FILE_SYMLINK
, path
, *i
);
759 if (errno
== EEXIST
) {
760 _cleanup_free_
char *dest
= NULL
;
762 q
= readlink_and_make_absolute(path
, &dest
);
764 if (q
< 0 && errno
!= ENOENT
) {
770 if (q
>= 0 && path_equal(dest
, *i
))
776 if (symlink(*i
, path
) >= 0) {
778 add_file_change(changes
, n_changes
, UNIT_FILE_UNLINK
, path
, NULL
);
779 add_file_change(changes
, n_changes
, UNIT_FILE_SYMLINK
, path
, *i
);
796 void unit_file_list_free(Hashmap
*h
) {
799 while ((i
= hashmap_steal_first(h
))) {
807 void unit_file_changes_free(UnitFileChange
*changes
, unsigned n_changes
) {
810 assert(changes
|| n_changes
== 0);
815 for (i
= 0; i
< n_changes
; i
++) {
816 free(changes
[i
].path
);
817 free(changes
[i
].source
);
823 static void install_info_free(InstallInfo
*i
) {
828 strv_free(i
->aliases
);
829 strv_free(i
->wanted_by
);
830 strv_free(i
->required_by
);
834 static void install_info_hashmap_free(Hashmap
*m
) {
840 while ((i
= hashmap_steal_first(m
)))
841 install_info_free(i
);
846 static void install_context_done(InstallContext
*c
) {
849 install_info_hashmap_free(c
->will_install
);
850 install_info_hashmap_free(c
->have_installed
);
852 c
->will_install
= c
->have_installed
= NULL
;
855 static int install_info_add(
859 InstallInfo
*i
= NULL
;
863 assert(name
|| path
);
866 name
= path_get_file_name(path
);
868 if (!unit_name_is_valid(name
, true))
871 if (hashmap_get(c
->have_installed
, name
) ||
872 hashmap_get(c
->will_install
, name
))
875 r
= hashmap_ensure_allocated(&c
->will_install
, string_hash_func
, string_compare_func
);
879 i
= new0(InstallInfo
, 1);
883 i
->name
= strdup(name
);
890 i
->path
= strdup(path
);
897 r
= hashmap_put(c
->will_install
, i
->name
, i
);
905 install_info_free(i
);
910 static int install_info_add_auto(
912 const char *name_or_path
) {
915 assert(name_or_path
);
917 if (path_is_absolute(name_or_path
))
918 return install_info_add(c
, NULL
, name_or_path
);
920 return install_info_add(c
, name_or_path
, NULL
);
923 static int config_parse_also(const char *unit
,
924 const char *filename
,
936 InstallContext
*c
= data
;
942 FOREACH_WORD_QUOTED(w
, l
, rvalue
, state
) {
943 _cleanup_free_
char *n
;
950 r
= install_info_add(c
, n
, NULL
);
958 static int config_parse_user(const char *unit
,
959 const char *filename
,
968 InstallInfo
*i
= data
;
976 r
= install_full_printf(i
, rvalue
, &printed
);
986 static int unit_file_load(
990 bool allow_symlink
) {
992 const ConfigTableItem items
[] = {
993 { "Install", "Alias", config_parse_strv
, 0, &info
->aliases
},
994 { "Install", "WantedBy", config_parse_strv
, 0, &info
->wanted_by
},
995 { "Install", "RequiredBy", config_parse_strv
, 0, &info
->required_by
},
996 { "Install", "Also", config_parse_also
, 0, c
},
997 { "Exec", "User", config_parse_user
, 0, info
},
998 { NULL
, NULL
, NULL
, 0, NULL
}
1002 _cleanup_fclose_
FILE *f
= NULL
;
1009 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|(allow_symlink
? 0 : O_NOFOLLOW
));
1013 f
= fdopen(fd
, "re");
1015 close_nointr_nofail(fd
);
1019 r
= config_parse(NULL
, path
, f
, NULL
,
1020 config_item_table_lookup
, (void*) items
, true, true, info
);
1025 strv_length(info
->aliases
) +
1026 strv_length(info
->wanted_by
) +
1027 strv_length(info
->required_by
);
1030 static int unit_file_search(
1034 const char *root_dir
,
1035 bool allow_symlink
) {
1045 return unit_file_load(c
, info
, info
->path
, allow_symlink
);
1049 STRV_FOREACH(p
, paths
->unit_path
) {
1052 if (isempty(root_dir
))
1053 asprintf(&path
, "%s/%s", *p
, info
->name
);
1055 asprintf(&path
, "%s/%s/%s", root_dir
, *p
, info
->name
);
1060 r
= unit_file_load(c
, info
, path
, allow_symlink
);
1065 if (r
== -ENOENT
&& unit_name_is_instance(info
->name
)) {
1066 /* Unit file doesn't exist, however instance enablement was requested.
1067 * We will check if it is possible to load template unit file. */
1068 char *template = NULL
,
1069 *template_path
= NULL
,
1070 *template_dir
= NULL
;
1072 template = unit_name_template(info
->name
);
1078 /* We will reuse path variable since we don't need it anymore. */
1079 template_dir
= path
;
1080 *(strrchr(path
, '/') + 1) = '\0';
1082 template_path
= strjoin(template_dir
, template, NULL
);
1083 if (!template_path
) {
1089 /* Let's try to load template unit. */
1090 r
= unit_file_load(c
, info
, template_path
, allow_symlink
);
1092 info
->path
= strdup(template_path
);
1096 free(template_path
);
1102 free(template_path
);
1107 if (r
!= -ENOENT
&& r
!= -ELOOP
)
1114 static int unit_file_can_install(
1116 const char *root_dir
,
1118 bool allow_symlink
) {
1120 _cleanup_install_context_done_ InstallContext c
= {};
1127 r
= install_info_add_auto(&c
, name
);
1131 assert_se(i
= hashmap_first(c
.will_install
));
1133 r
= unit_file_search(&c
, i
, paths
, root_dir
, allow_symlink
);
1137 strv_length(i
->aliases
) +
1138 strv_length(i
->wanted_by
) +
1139 strv_length(i
->required_by
);
1144 static int create_symlink(
1145 const char *old_path
,
1146 const char *new_path
,
1148 UnitFileChange
**changes
,
1149 unsigned *n_changes
) {
1151 _cleanup_free_
char *dest
= NULL
;
1157 mkdir_parents_label(new_path
, 0755);
1159 if (symlink(old_path
, new_path
) >= 0) {
1160 add_file_change(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
1164 if (errno
!= EEXIST
)
1167 r
= readlink_and_make_absolute(new_path
, &dest
);
1171 if (path_equal(dest
, old_path
))
1179 if (symlink(old_path
, new_path
) >= 0) {
1180 add_file_change(changes
, n_changes
, UNIT_FILE_UNLINK
, new_path
, NULL
);
1181 add_file_change(changes
, n_changes
, UNIT_FILE_SYMLINK
, new_path
, old_path
);
1188 static int install_info_symlink_alias(
1190 const char *config_path
,
1192 UnitFileChange
**changes
,
1193 unsigned *n_changes
) {
1199 assert(config_path
);
1201 STRV_FOREACH(s
, i
->aliases
) {
1202 _cleanup_free_
char *alias_path
= NULL
, *dst
= NULL
;
1204 q
= install_full_printf(i
, *s
, &dst
);
1208 alias_path
= path_make_absolute(dst
, config_path
);
1212 q
= create_symlink(i
->path
, alias_path
, force
, changes
, n_changes
);
1220 static int install_info_symlink_wants(
1222 const char *config_path
,
1224 UnitFileChange
**changes
,
1225 unsigned *n_changes
) {
1231 assert(config_path
);
1233 STRV_FOREACH(s
, i
->wanted_by
) {
1234 _cleanup_free_
char *path
= NULL
, *dst
= NULL
;
1236 q
= install_full_printf(i
, *s
, &dst
);
1240 if (!unit_name_is_valid(dst
, true)) {
1245 if (asprintf(&path
, "%s/%s.wants/%s", config_path
, dst
, i
->name
) < 0)
1248 q
= create_symlink(i
->path
, path
, force
, changes
, n_changes
);
1257 static int install_info_symlink_requires(
1259 const char *config_path
,
1261 UnitFileChange
**changes
,
1262 unsigned *n_changes
) {
1268 assert(config_path
);
1270 STRV_FOREACH(s
, i
->required_by
) {
1271 _cleanup_free_
char *path
= NULL
, *dst
= NULL
;
1273 q
= install_full_printf(i
, *s
, &dst
);
1277 if (!unit_name_is_valid(dst
, true)) {
1282 if (asprintf(&path
, "%s/%s.requires/%s", config_path
, dst
, i
->name
) < 0)
1285 q
= create_symlink(i
->path
, path
, force
, changes
, n_changes
);
1294 static int install_info_symlink_link(
1297 const char *config_path
,
1299 UnitFileChange
**changes
,
1300 unsigned *n_changes
) {
1303 _cleanup_free_
char *path
= NULL
;
1307 assert(config_path
);
1310 r
= in_search_path(i
->path
, paths
->unit_path
);
1314 if (asprintf(&path
, "%s/%s", config_path
, i
->name
) < 0)
1317 r
= create_symlink(i
->path
, path
, force
, changes
, n_changes
);
1321 static int install_info_apply(
1324 const char *config_path
,
1326 UnitFileChange
**changes
,
1327 unsigned *n_changes
) {
1333 assert(config_path
);
1335 r
= install_info_symlink_alias(i
, config_path
, force
, changes
, n_changes
);
1337 q
= install_info_symlink_wants(i
, config_path
, force
, changes
, n_changes
);
1341 q
= install_info_symlink_requires(i
, config_path
, force
, changes
, n_changes
);
1345 q
= install_info_symlink_link(i
, paths
, config_path
, force
, changes
, n_changes
);
1352 static int install_context_apply(
1355 const char *config_path
,
1356 const char *root_dir
,
1358 UnitFileChange
**changes
,
1359 unsigned *n_changes
) {
1366 assert(config_path
);
1368 while ((i
= hashmap_first(c
->will_install
))) {
1370 q
= hashmap_ensure_allocated(&c
->have_installed
, string_hash_func
, string_compare_func
);
1374 assert_se(hashmap_move_one(c
->have_installed
, c
->will_install
, i
->name
) == 0);
1376 q
= unit_file_search(c
, i
, paths
, root_dir
, false);
1385 q
= install_info_apply(i
, paths
, config_path
, force
, changes
, n_changes
);
1386 if (r
>= 0 && q
< 0)
1393 static int install_context_mark_for_removal(
1396 Set
**remove_symlinks_to
,
1397 const char *config_path
,
1398 const char *root_dir
) {
1405 assert(config_path
);
1407 /* Marks all items for removal */
1409 while ((i
= hashmap_first(c
->will_install
))) {
1411 q
= hashmap_ensure_allocated(&c
->have_installed
, string_hash_func
, string_compare_func
);
1415 assert_se(hashmap_move_one(c
->have_installed
, c
->will_install
, i
->name
) == 0);
1417 q
= unit_file_search(c
, i
, paths
, root_dir
, false);
1428 if (unit_name_is_instance(i
->name
)) {
1432 unit_file
= path_get_file_name(i
->path
);
1434 if (unit_name_is_instance(unit_file
))
1435 /* unit file named as instance exists, thus all symlinks
1436 * pointing to it will be removed */
1437 q
= mark_symlink_for_removal(remove_symlinks_to
, i
->name
);
1439 /* does not exist, thus we will mark for removal symlinks
1440 * to template unit file */
1441 q
= mark_symlink_for_removal(remove_symlinks_to
, unit_file
);
1443 /* If i->path is not set, it means that we didn't actually find
1444 * the unit file. But we can still remove symlinks to the
1445 * nonexistent template. */
1446 unit_file
= unit_name_template(i
->name
);
1450 q
= mark_symlink_for_removal(remove_symlinks_to
, unit_file
);
1454 q
= mark_symlink_for_removal(remove_symlinks_to
, i
->name
);
1456 if (r
>= 0 && q
< 0)
1463 int unit_file_enable(
1464 UnitFileScope scope
,
1466 const char *root_dir
,
1469 UnitFileChange
**changes
,
1470 unsigned *n_changes
) {
1472 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1473 _cleanup_install_context_done_ InstallContext c
= {};
1475 _cleanup_free_
char *config_path
= NULL
;
1479 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1481 r
= lookup_paths_init_from_scope(&paths
, scope
);
1485 r
= get_config_path(scope
, runtime
, root_dir
, &config_path
);
1489 STRV_FOREACH(i
, files
) {
1490 r
= install_info_add_auto(&c
, *i
);
1495 /* This will return the number of symlink rules that were
1496 supposed to be created, not the ones actually created. This is
1497 useful to determine whether the passed files had any
1498 installation data at all. */
1499 r
= install_context_apply(&c
, &paths
, config_path
, root_dir
, force
, changes
, n_changes
);
1503 int unit_file_disable(
1504 UnitFileScope scope
,
1506 const char *root_dir
,
1508 UnitFileChange
**changes
,
1509 unsigned *n_changes
) {
1511 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1512 _cleanup_install_context_done_ InstallContext c
= {};
1514 _cleanup_free_
char *config_path
= NULL
;
1515 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
1519 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1521 r
= lookup_paths_init_from_scope(&paths
, scope
);
1525 r
= get_config_path(scope
, runtime
, root_dir
, &config_path
);
1529 STRV_FOREACH(i
, files
) {
1530 r
= install_info_add_auto(&c
, *i
);
1535 r
= install_context_mark_for_removal(&c
, &paths
, &remove_symlinks_to
, config_path
, root_dir
);
1537 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
, changes
, n_changes
, files
);
1544 int unit_file_reenable(
1545 UnitFileScope scope
,
1547 const char *root_dir
,
1550 UnitFileChange
**changes
,
1551 unsigned *n_changes
) {
1554 r
= unit_file_disable(scope
, runtime
, root_dir
, files
,
1555 changes
, n_changes
);
1559 return unit_file_enable(scope
, runtime
, root_dir
, files
, force
,
1560 changes
, n_changes
);
1563 int unit_file_set_default(
1564 UnitFileScope scope
,
1565 const char *root_dir
,
1567 UnitFileChange
**changes
,
1568 unsigned *n_changes
) {
1570 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1571 _cleanup_install_context_done_ InstallContext c
= {};
1572 _cleanup_free_
char *config_path
= NULL
;
1575 InstallInfo
*i
= NULL
;
1578 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1580 if (unit_name_to_type(file
) != UNIT_TARGET
)
1583 r
= lookup_paths_init_from_scope(&paths
, scope
);
1587 r
= get_config_path(scope
, false, root_dir
, &config_path
);
1591 r
= install_info_add_auto(&c
, file
);
1595 i
= (InstallInfo
*)hashmap_first(c
.will_install
);
1597 r
= unit_file_search(&c
, i
, &paths
, root_dir
, false);
1601 path
= strappenda(config_path
, "/default.target");
1602 r
= create_symlink(i
->path
, path
, true, changes
, n_changes
);
1609 int unit_file_get_default(
1610 UnitFileScope scope
,
1611 const char *root_dir
,
1614 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1618 r
= lookup_paths_init_from_scope(&paths
, scope
);
1622 STRV_FOREACH(p
, paths
.unit_path
) {
1623 _cleanup_free_
char *path
= NULL
, *tmp
= NULL
;
1625 if (isempty(root_dir
))
1626 path
= strappend(*p
, "/default.target");
1628 path
= strjoin(root_dir
, "/", *p
, "/default.target", NULL
);
1633 r
= readlink_malloc(path
, &tmp
);
1639 *name
= strdup(path_get_file_name(tmp
));
1649 UnitFileState
unit_file_get_state(
1650 UnitFileScope scope
,
1651 const char *root_dir
,
1654 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1655 UnitFileState state
= _UNIT_FILE_STATE_INVALID
;
1657 _cleanup_free_
char *path
= NULL
;
1661 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1664 if (root_dir
&& scope
!= UNIT_FILE_SYSTEM
)
1667 if (!unit_name_is_valid(name
, true))
1670 r
= lookup_paths_init_from_scope(&paths
, scope
);
1674 STRV_FOREACH(i
, paths
.unit_path
) {
1681 asprintf(&path
, "%s/%s/%s", root_dir
, *i
, name
);
1683 asprintf(&path
, "%s/%s", *i
, name
);
1689 * Search for a unit file in our default paths, to
1690 * be sure, that there are no broken symlinks.
1692 if (lstat(path
, &st
) < 0) {
1694 if (errno
!= ENOENT
)
1697 if (!unit_name_is_instance(name
))
1700 if (!S_ISREG(st
.st_mode
) && !S_ISLNK(st
.st_mode
))
1703 r
= null_or_empty_path(path
);
1704 if (r
< 0 && r
!= -ENOENT
)
1707 state
= path_startswith(*i
, "/run") ?
1708 UNIT_FILE_MASKED_RUNTIME
: UNIT_FILE_MASKED
;
1713 r
= find_symlinks_in_scope(scope
, root_dir
, name
, &state
);
1719 r
= unit_file_can_install(&paths
, root_dir
, path
, true);
1720 if (r
< 0 && errno
!= ENOENT
)
1723 return UNIT_FILE_DISABLED
;
1725 return UNIT_FILE_STATIC
;
1728 return r
< 0 ? r
: state
;
1731 int unit_file_query_preset(UnitFileScope scope
, const char *name
) {
1732 _cleanup_strv_free_
char **files
= NULL
;
1737 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1740 if (scope
== UNIT_FILE_SYSTEM
)
1741 r
= conf_files_list(&files
, ".preset", NULL
,
1742 "/etc/systemd/system-preset",
1743 "/usr/local/lib/systemd/system-preset",
1744 "/usr/lib/systemd/system-preset",
1745 #ifdef HAVE_SPLIT_USR
1746 "/lib/systemd/system-preset",
1749 else if (scope
== UNIT_FILE_GLOBAL
)
1750 r
= conf_files_list(&files
, ".preset", NULL
,
1751 "/etc/systemd/user-preset",
1752 "/usr/local/lib/systemd/user-preset",
1753 "/usr/lib/systemd/user-preset",
1761 STRV_FOREACH(i
, files
) {
1762 _cleanup_fclose_
FILE *f
;
1764 f
= fopen(*i
, "re");
1766 if (errno
== ENOENT
)
1773 char line
[LINE_MAX
], *l
;
1775 if (!fgets(line
, sizeof(line
), f
))
1782 if (strchr(COMMENTS
"\n", *l
))
1785 if (first_word(l
, "enable")) {
1787 l
+= strspn(l
, WHITESPACE
);
1789 if (fnmatch(l
, name
, FNM_NOESCAPE
) == 0)
1792 } else if (first_word(l
, "disable")) {
1794 l
+= strspn(l
, WHITESPACE
);
1796 if (fnmatch(l
, name
, FNM_NOESCAPE
) == 0)
1800 log_debug("Couldn't parse line '%s'", l
);
1804 /* Default is "enable" */
1808 int unit_file_preset(
1809 UnitFileScope scope
,
1811 const char *root_dir
,
1814 UnitFileChange
**changes
,
1815 unsigned *n_changes
) {
1817 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1818 _cleanup_install_context_done_ InstallContext plus
= {}, minus
= {};
1820 _cleanup_free_
char *config_path
= NULL
;
1821 _cleanup_set_free_free_ Set
*remove_symlinks_to
= NULL
;
1825 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1827 r
= lookup_paths_init_from_scope(&paths
, scope
);
1831 r
= get_config_path(scope
, runtime
, root_dir
, &config_path
);
1835 STRV_FOREACH(i
, files
) {
1837 if (!unit_name_is_valid(*i
, true))
1840 r
= unit_file_query_preset(scope
, *i
);
1845 r
= install_info_add_auto(&plus
, *i
);
1847 r
= install_info_add_auto(&minus
, *i
);
1853 r
= install_context_mark_for_removal(&minus
, &paths
, &remove_symlinks_to
,
1854 config_path
, root_dir
);
1856 q
= remove_marked_symlinks(remove_symlinks_to
, config_path
,
1857 changes
, n_changes
, files
);
1861 /* Returns number of symlinks that where supposed to be installed. */
1862 q
= install_context_apply(&plus
, &paths
, config_path
, root_dir
, force
,
1863 changes
, n_changes
);
1870 static void unitfilelist_free(UnitFileList
**f
) {
1878 int unit_file_get_list(
1879 UnitFileScope scope
,
1880 const char *root_dir
,
1883 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
1885 _cleanup_free_
char *buf
= NULL
;
1886 _cleanup_closedir_
DIR *d
= NULL
;
1890 assert(scope
< _UNIT_FILE_SCOPE_MAX
);
1893 if (root_dir
&& scope
!= UNIT_FILE_SYSTEM
)
1896 r
= lookup_paths_init_from_scope(&paths
, scope
);
1900 STRV_FOREACH(i
, paths
.unit_path
) {
1901 const char *units_dir
;
1907 if (asprintf(&buf
, "%s/%s", root_dir
, *i
) < 0)
1917 d
= opendir(units_dir
);
1919 if (errno
== ENOENT
)
1927 union dirent_storage buffer
;
1928 UnitFileList
__attribute__((cleanup(unitfilelist_free
)))
1931 r
= readdir_r(d
, &buffer
.de
, &de
);
1938 if (ignore_file(de
->d_name
))
1941 if (!unit_name_is_valid(de
->d_name
, true))
1944 if (hashmap_get(h
, de
->d_name
))
1947 r
= dirent_ensure_type(d
, de
);
1955 if (de
->d_type
!= DT_LNK
&& de
->d_type
!= DT_REG
)
1958 f
= new0(UnitFileList
, 1);
1962 f
->path
= path_make_absolute(de
->d_name
, units_dir
);
1966 r
= null_or_empty_path(f
->path
);
1967 if (r
< 0 && r
!= -ENOENT
)
1971 path_startswith(*i
, "/run") ?
1972 UNIT_FILE_MASKED_RUNTIME
: UNIT_FILE_MASKED
;
1976 r
= find_symlinks_in_scope(scope
, root_dir
, de
->d_name
, &f
->state
);
1980 f
->state
= UNIT_FILE_ENABLED
;
1984 r
= unit_file_can_install(&paths
, root_dir
, f
->path
, true);
1985 if (r
== -EINVAL
|| /* Invalid setting? */
1986 r
== -EBADMSG
|| /* Invalid format? */
1987 r
== -ENOENT
/* Included file not found? */)
1988 f
->state
= UNIT_FILE_INVALID
;
1992 f
->state
= UNIT_FILE_DISABLED
;
1994 f
->state
= UNIT_FILE_STATIC
;
1997 r
= hashmap_put(h
, path_get_file_name(f
->path
), f
);
2000 f
= NULL
; /* prevent cleanup */
2007 static const char* const unit_file_state_table
[_UNIT_FILE_STATE_MAX
] = {
2008 [UNIT_FILE_ENABLED
] = "enabled",
2009 [UNIT_FILE_ENABLED_RUNTIME
] = "enabled-runtime",
2010 [UNIT_FILE_LINKED
] = "linked",
2011 [UNIT_FILE_LINKED_RUNTIME
] = "linked-runtime",
2012 [UNIT_FILE_MASKED
] = "masked",
2013 [UNIT_FILE_MASKED_RUNTIME
] = "masked-runtime",
2014 [UNIT_FILE_STATIC
] = "static",
2015 [UNIT_FILE_DISABLED
] = "disabled",
2016 [UNIT_FILE_INVALID
] = "invalid",
2019 DEFINE_STRING_TABLE_LOOKUP(unit_file_state
, UnitFileState
);
2021 static const char* const unit_file_change_type_table
[_UNIT_FILE_CHANGE_TYPE_MAX
] = {
2022 [UNIT_FILE_SYMLINK
] = "symlink",
2023 [UNIT_FILE_UNLINK
] = "unlink",
2026 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type
, UnitFileChangeType
);