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"
44 Hashmap *will_install;
45 Hashmap *have_installed;
48 #define _cleanup_install_context_done_ _cleanup_(install_context_done)
50 static int in_search_path(const char *path, char **search) {
51 _cleanup_free_ char *parent = NULL;
56 r = path_get_parent(path, &parent);
60 return strv_contains(search, parent);
63 static int lookup_paths_init_from_scope(LookupPaths *paths,
65 const char *root_dir) {
68 assert(scope < _UNIT_FILE_SCOPE_MAX);
72 return lookup_paths_init(paths,
73 scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
74 scope == UNIT_FILE_USER,
79 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
84 assert(scope < _UNIT_FILE_SCOPE_MAX);
89 case UNIT_FILE_SYSTEM:
91 if (root_dir && runtime) {
92 if (asprintf(&p, "%s/run/systemd/system", root_dir) < 0)
95 p = strdup("/run/systemd/system");
97 if (asprintf(&p, "%s/%s", root_dir,
98 SYSTEM_CONFIG_UNIT_PATH) < 0)
101 p = strdup(SYSTEM_CONFIG_UNIT_PATH);
105 case UNIT_FILE_GLOBAL:
111 p = strdup("/run/systemd/user");
113 p = strdup(USER_CONFIG_UNIT_PATH);
118 if (root_dir || runtime)
121 r = user_config_home(&p);
123 return r < 0 ? r : -ENOENT;
128 assert_not_reached("Bad scope");
138 static int add_file_change(
139 UnitFileChange **changes,
141 UnitFileChangeType type,
143 const char *source) {
149 assert(!changes == !n_changes);
154 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
162 c[i].path = strdup(path);
166 path_kill_slashes(c[i].path);
169 c[i].source = strdup(source);
175 path_kill_slashes(c[i].path);
183 static int mark_symlink_for_removal(
184 Set **remove_symlinks_to,
192 r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
200 path_kill_slashes(n);
202 r = set_consume(*remove_symlinks_to, n);
204 return r == -EEXIST ? 0 : r;
209 static int remove_marked_symlinks_fd(
210 Set *remove_symlinks_to,
213 const char *config_path,
215 UnitFileChange **changes,
217 char** instance_whitelist) {
219 _cleanup_closedir_ DIR *d = NULL;
222 assert(remove_symlinks_to);
241 if (!de && errno != 0) {
249 if (ignore_file(de->d_name))
252 dirent_ensure_type(d, de);
254 if (de->d_type == DT_DIR) {
256 _cleanup_free_ char *p = NULL;
258 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
268 p = path_make_absolute(de->d_name, path);
274 /* This will close nfd, regardless whether it succeeds or not */
275 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, instance_whitelist);
279 } else if (de->d_type == DT_LNK) {
280 _cleanup_free_ char *p = NULL, *dest = NULL;
284 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
287 if (unit_name_is_instance(de->d_name) &&
288 instance_whitelist &&
289 !strv_contains(instance_whitelist, de->d_name)) {
291 _cleanup_free_ char *w;
293 /* OK, the file is not listed directly
294 * in the whitelist, so let's check if
295 * the template of it might be
298 w = unit_name_template(de->d_name);
302 if (!strv_contains(instance_whitelist, w))
306 p = path_make_absolute(de->d_name, path);
310 q = readlink_and_canonicalize(p, &dest);
321 set_get(remove_symlinks_to, dest) ||
322 set_get(remove_symlinks_to, basename(dest));
327 if (unlink(p) < 0 && errno != ENOENT) {
333 path_kill_slashes(p);
334 rmdir_parents(p, config_path);
335 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
337 if (!set_get(remove_symlinks_to, p)) {
339 q = mark_symlink_for_removal(&remove_symlinks_to, p);
352 static int remove_marked_symlinks(
353 Set *remove_symlinks_to,
354 const char *config_path,
355 UnitFileChange **changes,
357 char** instance_whitelist) {
359 _cleanup_close_ int fd = -1;
365 if (set_size(remove_symlinks_to) <= 0)
368 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
376 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
382 /* This takes possession of cfd and closes it */
383 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist);
391 static int find_symlinks_fd(
395 const char *config_path,
396 bool *same_name_link) {
399 _cleanup_closedir_ DIR *d = NULL;
405 assert(same_name_link);
418 if (!de && errno != 0)
424 if (ignore_file(de->d_name))
427 dirent_ensure_type(d, de);
429 if (de->d_type == DT_DIR) {
431 _cleanup_free_ char *p = NULL;
433 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
443 p = path_make_absolute(de->d_name, path);
449 /* This will close nfd, regardless whether it succeeds or not */
450 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
456 } else if (de->d_type == DT_LNK) {
457 _cleanup_free_ char *p = NULL, *dest = NULL;
458 bool found_path, found_dest, b = false;
461 /* Acquire symlink name */
462 p = path_make_absolute(de->d_name, path);
466 /* Acquire symlink destination */
467 q = readlink_and_canonicalize(p, &dest);
477 /* Check if the symlink itself matches what we
479 if (path_is_absolute(name))
480 found_path = path_equal(p, name);
482 found_path = streq(de->d_name, name);
484 /* Check if what the symlink points to
485 * matches what we are looking for */
486 if (path_is_absolute(name))
487 found_dest = path_equal(dest, name);
489 found_dest = streq(basename(dest), name);
491 if (found_path && found_dest) {
492 _cleanup_free_ char *t = NULL;
494 /* Filter out same name links in the main
496 t = path_make_absolute(name, config_path);
500 b = path_equal(t, p);
504 *same_name_link = true;
505 else if (found_path || found_dest)
511 static int find_symlinks(
513 const char *config_path,
514 bool *same_name_link) {
520 assert(same_name_link);
522 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
529 /* This takes possession of fd and closes it */
530 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
533 static int find_symlinks_in_scope(
535 const char *root_dir,
537 UnitFileState *state) {
540 _cleanup_free_ char *path2 = NULL;
541 bool same_name_link_runtime = false, same_name_link = false;
544 assert(scope < _UNIT_FILE_SCOPE_MAX);
547 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
548 _cleanup_free_ char *path = NULL;
550 /* First look in runtime config path */
551 r = get_config_path(scope, true, root_dir, &path);
555 r = find_symlinks(name, path, &same_name_link_runtime);
559 *state = UNIT_FILE_ENABLED_RUNTIME;
564 /* Then look in the normal config path */
565 r = get_config_path(scope, false, root_dir, &path2);
569 r = find_symlinks(name, path2, &same_name_link);
573 *state = UNIT_FILE_ENABLED;
577 /* Hmm, we didn't find it, but maybe we found the same name
579 if (same_name_link_runtime) {
580 *state = UNIT_FILE_LINKED_RUNTIME;
582 } else if (same_name_link) {
583 *state = UNIT_FILE_LINKED;
593 const char *root_dir,
596 UnitFileChange **changes,
597 unsigned *n_changes) {
600 _cleanup_free_ char *prefix = NULL;
604 assert(scope < _UNIT_FILE_SCOPE_MAX);
606 r = get_config_path(scope, runtime, root_dir, &prefix);
610 STRV_FOREACH(i, files) {
611 _cleanup_free_ char *path = NULL;
613 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
619 path = path_make_absolute(*i, prefix);
625 if (symlink("/dev/null", path) >= 0) {
626 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
630 if (errno == EEXIST) {
632 if (null_or_empty_path(path) > 0)
636 if (symlink_atomic("/dev/null", path) >= 0) {
637 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
638 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
654 int unit_file_unmask(
657 const char *root_dir,
659 UnitFileChange **changes,
660 unsigned *n_changes) {
662 char **i, *config_path = NULL;
664 Set *remove_symlinks_to = NULL;
667 assert(scope < _UNIT_FILE_SCOPE_MAX);
669 r = get_config_path(scope, runtime, root_dir, &config_path);
673 STRV_FOREACH(i, files) {
676 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
682 path = path_make_absolute(*i, config_path);
688 q = null_or_empty_path(path);
690 if (unlink(path) >= 0) {
691 mark_symlink_for_removal(&remove_symlinks_to, path);
692 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
701 if (q != -ENOENT && r == 0)
709 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
713 set_free_free(remove_symlinks_to);
722 const char *root_dir,
725 UnitFileChange **changes,
726 unsigned *n_changes) {
728 _cleanup_lookup_paths_free_ LookupPaths paths = {};
730 _cleanup_free_ char *config_path = NULL;
734 assert(scope < _UNIT_FILE_SCOPE_MAX);
736 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
740 r = get_config_path(scope, runtime, root_dir, &config_path);
744 STRV_FOREACH(i, files) {
745 _cleanup_free_ char *path = NULL;
751 if (!path_is_absolute(*i) ||
752 !unit_name_is_valid(fn, TEMPLATE_VALID)) {
758 if (lstat(*i, &st) < 0) {
764 if (!S_ISREG(st.st_mode)) {
769 q = in_search_path(*i, paths.unit_path);
776 path = path_make_absolute(fn, config_path);
780 if (symlink(*i, path) >= 0) {
781 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
785 if (errno == EEXIST) {
786 _cleanup_free_ char *dest = NULL;
788 q = readlink_and_make_absolute(path, &dest);
789 if (q < 0 && errno != ENOENT) {
795 if (q >= 0 && path_equal(dest, *i))
799 if (symlink_atomic(*i, path) >= 0) {
800 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
801 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
817 void unit_file_list_free(Hashmap *h) {
820 while ((i = hashmap_steal_first(h))) {
828 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
831 assert(changes || n_changes == 0);
836 for (i = 0; i < n_changes; i++) {
837 free(changes[i].path);
838 free(changes[i].source);
844 static void install_info_free(InstallInfo *i) {
849 strv_free(i->aliases);
850 strv_free(i->wanted_by);
851 strv_free(i->required_by);
852 free(i->default_instance);
856 static void install_info_hashmap_free(Hashmap *m) {
862 while ((i = hashmap_steal_first(m)))
863 install_info_free(i);
868 static void install_context_done(InstallContext *c) {
871 install_info_hashmap_free(c->will_install);
872 install_info_hashmap_free(c->have_installed);
874 c->will_install = c->have_installed = NULL;
877 static int install_info_add(
881 InstallInfo *i = NULL;
885 assert(name || path);
888 name = basename(path);
890 if (!unit_name_is_valid(name, TEMPLATE_VALID))
893 if (hashmap_get(c->have_installed, name) ||
894 hashmap_get(c->will_install, name))
897 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
901 i = new0(InstallInfo, 1);
905 i->name = strdup(name);
912 i->path = strdup(path);
919 r = hashmap_put(c->will_install, i->name, i);
927 install_info_free(i);
932 static int install_info_add_auto(
934 const char *name_or_path) {
937 assert(name_or_path);
939 if (path_is_absolute(name_or_path))
940 return install_info_add(c, NULL, name_or_path);
942 return install_info_add(c, name_or_path, NULL);
945 static int config_parse_also(
947 const char *filename,
950 unsigned section_line,
960 InstallContext *c = data;
966 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
967 _cleanup_free_ char *n;
974 r = install_info_add(c, n, NULL);
982 static int config_parse_user(
984 const char *filename,
987 unsigned section_line,
994 InstallInfo *i = data;
1002 r = install_full_printf(i, rvalue, &printed);
1012 static int config_parse_default_instance(
1014 const char *filename,
1016 const char *section,
1017 unsigned section_line,
1024 InstallInfo *i = data;
1032 r = install_full_printf(i, rvalue, &printed);
1036 if (!unit_instance_is_valid(printed))
1039 free(i->default_instance);
1040 i->default_instance = printed;
1045 static int unit_file_load(
1049 const char *root_dir,
1050 bool allow_symlink) {
1052 const ConfigTableItem items[] = {
1053 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
1054 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1055 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1056 { "Install", "DefaultInstance", config_parse_default_instance, 0, info },
1057 { "Install", "Also", config_parse_also, 0, c },
1058 { "Exec", "User", config_parse_user, 0, info },
1062 _cleanup_fclose_ FILE *f = NULL;
1069 if (!isempty(root_dir))
1070 path = strappenda3(root_dir, "/", path);
1072 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1076 f = fdopen(fd, "re");
1082 r = config_parse(NULL, path, f,
1084 config_item_table_lookup, items,
1085 true, true, false, info);
1090 (int) strv_length(info->aliases) +
1091 (int) strv_length(info->wanted_by) +
1092 (int) strv_length(info->required_by);
1095 static int unit_file_search(
1099 const char *root_dir,
1100 bool allow_symlink) {
1110 return unit_file_load(c, info, info->path, root_dir, allow_symlink);
1114 STRV_FOREACH(p, paths->unit_path) {
1115 _cleanup_free_ char *path = NULL;
1117 path = strjoin(*p, "/", info->name, NULL);
1121 r = unit_file_load(c, info, path, root_dir, allow_symlink);
1127 if (r != -ENOENT && r != -ELOOP)
1131 if (unit_name_is_instance(info->name)) {
1133 /* Unit file doesn't exist, however instance
1134 * enablement was requested. We will check if it is
1135 * possible to load template unit file. */
1137 _cleanup_free_ char *template = NULL;
1139 template = unit_name_template(info->name);
1143 STRV_FOREACH(p, paths->unit_path) {
1144 _cleanup_free_ char *path = NULL;
1146 path = strjoin(*p, "/", template, NULL);
1150 r = unit_file_load(c, info, path, root_dir, allow_symlink);
1156 if (r != -ENOENT && r != -ELOOP)
1164 static int unit_file_can_install(
1166 const char *root_dir,
1168 bool allow_symlink) {
1170 _cleanup_install_context_done_ InstallContext c = {};
1177 r = install_info_add_auto(&c, name);
1181 assert_se(i = hashmap_first(c.will_install));
1183 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1187 (int) strv_length(i->aliases) +
1188 (int) strv_length(i->wanted_by) +
1189 (int) strv_length(i->required_by);
1194 static int create_symlink(
1195 const char *old_path,
1196 const char *new_path,
1198 UnitFileChange **changes,
1199 unsigned *n_changes) {
1201 _cleanup_free_ char *dest = NULL;
1207 mkdir_parents_label(new_path, 0755);
1209 if (symlink(old_path, new_path) >= 0) {
1210 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1214 if (errno != EEXIST)
1217 r = readlink_and_make_absolute(new_path, &dest);
1221 if (path_equal(dest, old_path))
1227 r = symlink_atomic(old_path, new_path);
1231 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1232 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1237 static int install_info_symlink_alias(
1239 const char *config_path,
1241 UnitFileChange **changes,
1242 unsigned *n_changes) {
1248 assert(config_path);
1250 STRV_FOREACH(s, i->aliases) {
1251 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1253 q = install_full_printf(i, *s, &dst);
1257 alias_path = path_make_absolute(dst, config_path);
1261 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1269 static int install_info_symlink_wants(
1271 const char *config_path,
1275 UnitFileChange **changes,
1276 unsigned *n_changes) {
1278 _cleanup_free_ char *buf = NULL;
1284 assert(config_path);
1286 if (unit_name_is_template(i->name)) {
1288 /* Don't install any symlink if there's no default
1289 * instance configured */
1291 if (!i->default_instance)
1294 buf = unit_name_replace_instance(i->name, i->default_instance);
1302 STRV_FOREACH(s, list) {
1303 _cleanup_free_ char *path = NULL, *dst = NULL;
1305 q = install_full_printf(i, *s, &dst);
1309 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1314 path = strjoin(config_path, "/", dst, suffix, n, NULL);
1318 q = create_symlink(i->path, path, force, changes, n_changes);
1326 static int install_info_symlink_link(
1329 const char *config_path,
1330 const char *root_dir,
1332 UnitFileChange **changes,
1333 unsigned *n_changes) {
1335 _cleanup_free_ char *path = NULL;
1340 assert(config_path);
1343 r = in_search_path(i->path, paths->unit_path);
1347 path = strjoin(config_path, "/", i->name, NULL);
1351 return create_symlink(i->path, path, force, changes, n_changes);
1354 static int install_info_apply(
1357 const char *config_path,
1358 const char *root_dir,
1360 UnitFileChange **changes,
1361 unsigned *n_changes) {
1367 assert(config_path);
1369 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1371 q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes);
1375 q = install_info_symlink_wants(i, config_path, i->required_by, ".requires/", force, changes, n_changes);
1379 q = install_info_symlink_link(i, paths, config_path, root_dir, force, changes, n_changes);
1386 static int install_context_apply(
1389 const char *config_path,
1390 const char *root_dir,
1392 UnitFileChange **changes,
1393 unsigned *n_changes) {
1400 assert(config_path);
1402 while ((i = hashmap_first(c->will_install))) {
1404 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1408 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1410 q = unit_file_search(c, i, paths, root_dir, false);
1419 q = install_info_apply(i, paths, config_path, root_dir, force, changes, n_changes);
1420 if (r >= 0 && q < 0)
1427 static int install_context_mark_for_removal(
1430 Set **remove_symlinks_to,
1431 const char *config_path,
1432 const char *root_dir) {
1439 assert(config_path);
1441 /* Marks all items for removal */
1443 while ((i = hashmap_first(c->will_install))) {
1445 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1449 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1451 q = unit_file_search(c, i, paths, root_dir, false);
1462 if (unit_name_is_instance(i->name)) {
1466 unit_file = basename(i->path);
1468 if (unit_name_is_instance(unit_file))
1469 /* unit file named as instance exists, thus all symlinks
1470 * pointing to it will be removed */
1471 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1473 /* does not exist, thus we will mark for removal symlinks
1474 * to template unit file */
1475 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1477 /* If i->path is not set, it means that we didn't actually find
1478 * the unit file. But we can still remove symlinks to the
1479 * nonexistent template. */
1480 unit_file = unit_name_template(i->name);
1484 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1488 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1490 if (r >= 0 && q < 0)
1497 int unit_file_enable(
1498 UnitFileScope scope,
1500 const char *root_dir,
1503 UnitFileChange **changes,
1504 unsigned *n_changes) {
1506 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1507 _cleanup_install_context_done_ InstallContext c = {};
1509 _cleanup_free_ char *config_path = NULL;
1513 assert(scope < _UNIT_FILE_SCOPE_MAX);
1515 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1519 r = get_config_path(scope, runtime, root_dir, &config_path);
1523 STRV_FOREACH(i, files) {
1524 r = install_info_add_auto(&c, *i);
1529 /* This will return the number of symlink rules that were
1530 supposed to be created, not the ones actually created. This is
1531 useful to determine whether the passed files had any
1532 installation data at all. */
1534 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1537 int unit_file_disable(
1538 UnitFileScope scope,
1540 const char *root_dir,
1542 UnitFileChange **changes,
1543 unsigned *n_changes) {
1545 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1546 _cleanup_install_context_done_ InstallContext c = {};
1548 _cleanup_free_ char *config_path = NULL;
1549 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1553 assert(scope < _UNIT_FILE_SCOPE_MAX);
1555 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1559 r = get_config_path(scope, runtime, root_dir, &config_path);
1563 STRV_FOREACH(i, files) {
1564 r = install_info_add_auto(&c, *i);
1569 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1571 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1578 int unit_file_reenable(
1579 UnitFileScope scope,
1581 const char *root_dir,
1584 UnitFileChange **changes,
1585 unsigned *n_changes) {
1588 r = unit_file_disable(scope, runtime, root_dir, files,
1589 changes, n_changes);
1593 return unit_file_enable(scope, runtime, root_dir, files, force,
1594 changes, n_changes);
1597 int unit_file_set_default(
1598 UnitFileScope scope,
1599 const char *root_dir,
1602 UnitFileChange **changes,
1603 unsigned *n_changes) {
1605 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1606 _cleanup_install_context_done_ InstallContext c = {};
1607 _cleanup_free_ char *config_path = NULL;
1610 InstallInfo *i = NULL;
1613 assert(scope < _UNIT_FILE_SCOPE_MAX);
1616 if (unit_name_to_type(file) != UNIT_TARGET)
1619 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1623 r = get_config_path(scope, false, root_dir, &config_path);
1627 r = install_info_add_auto(&c, file);
1631 assert_se(i = hashmap_first(c.will_install));
1633 r = unit_file_search(&c, i, &paths, root_dir, false);
1637 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1639 r = create_symlink(i->path, path, force, changes, n_changes);
1646 int unit_file_get_default(
1647 UnitFileScope scope,
1648 const char *root_dir,
1651 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1656 assert(scope < _UNIT_FILE_SCOPE_MAX);
1659 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1663 STRV_FOREACH(p, paths.unit_path) {
1664 _cleanup_free_ char *path = NULL, *tmp = NULL;
1667 if (isempty(root_dir))
1668 path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
1670 path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
1675 r = readlink_malloc(path, &tmp);
1678 else if (r == -EINVAL)
1680 n = strdup(SPECIAL_DEFAULT_TARGET);
1684 n = strdup(basename(tmp));
1696 UnitFileState unit_file_get_state(
1697 UnitFileScope scope,
1698 const char *root_dir,
1701 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1702 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1704 _cleanup_free_ char *path = NULL;
1708 assert(scope < _UNIT_FILE_SCOPE_MAX);
1711 if (root_dir && scope != UNIT_FILE_SYSTEM)
1714 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1717 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1721 STRV_FOREACH(i, paths.unit_path) {
1729 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1731 asprintf(&path, "%s/%s", *i, name);
1736 partial = path + strlen(root_dir) + 1;
1741 * Search for a unit file in our default paths, to
1742 * be sure, that there are no broken symlinks.
1744 if (lstat(path, &st) < 0) {
1746 if (errno != ENOENT)
1749 if (!unit_name_is_instance(name))
1752 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1755 r = null_or_empty_path(path);
1756 if (r < 0 && r != -ENOENT)
1759 state = path_startswith(*i, "/run") ?
1760 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1765 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1771 r = unit_file_can_install(&paths, root_dir, partial, true);
1772 if (r < 0 && errno != ENOENT)
1775 return UNIT_FILE_DISABLED;
1777 return UNIT_FILE_STATIC;
1780 return r < 0 ? r : state;
1783 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
1784 _cleanup_strv_free_ char **files = NULL;
1789 assert(scope < _UNIT_FILE_SCOPE_MAX);
1792 if (scope == UNIT_FILE_SYSTEM)
1793 r = conf_files_list(&files, ".preset", root_dir,
1794 "/etc/systemd/system-preset",
1795 "/usr/local/lib/systemd/system-preset",
1796 "/usr/lib/systemd/system-preset",
1797 #ifdef HAVE_SPLIT_USR
1798 "/lib/systemd/system-preset",
1801 else if (scope == UNIT_FILE_GLOBAL)
1802 r = conf_files_list(&files, ".preset", root_dir,
1803 "/etc/systemd/user-preset",
1804 "/usr/local/lib/systemd/user-preset",
1805 "/usr/lib/systemd/user-preset",
1813 STRV_FOREACH(p, files) {
1814 _cleanup_fclose_ FILE *f;
1816 f = fopen(*p, "re");
1818 if (errno == ENOENT)
1825 char line[LINE_MAX], *l;
1827 if (!fgets(line, sizeof(line), f))
1834 if (strchr(COMMENTS "\n", *l))
1837 if (first_word(l, "enable")) {
1839 l += strspn(l, WHITESPACE);
1841 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1842 log_debug("Preset file says enable %s.", name);
1846 } else if (first_word(l, "disable")) {
1848 l += strspn(l, WHITESPACE);
1850 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1851 log_debug("Preset file says disable %s.", name);
1856 log_debug("Couldn't parse line '%s'", l);
1860 /* Default is "enable" */
1861 log_debug("Preset file doesn't say anything about %s, enabling.", name);
1865 int unit_file_preset(
1866 UnitFileScope scope,
1868 const char *root_dir,
1870 UnitFilePresetMode mode,
1872 UnitFileChange **changes,
1873 unsigned *n_changes) {
1875 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1876 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1877 _cleanup_free_ char *config_path = NULL;
1882 assert(scope < _UNIT_FILE_SCOPE_MAX);
1883 assert(mode < _UNIT_FILE_PRESET_MAX);
1885 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1889 r = get_config_path(scope, runtime, root_dir, &config_path);
1893 STRV_FOREACH(i, files) {
1895 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1898 r = unit_file_query_preset(scope, root_dir, *i);
1902 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1903 r = install_info_add_auto(&plus, *i);
1904 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1905 r = install_info_add_auto(&minus, *i);
1914 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1915 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1917 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1919 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1924 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1925 /* Returns number of symlinks that where supposed to be installed. */
1926 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1934 int unit_file_preset_all(
1935 UnitFileScope scope,
1937 const char *root_dir,
1938 UnitFilePresetMode mode,
1940 UnitFileChange **changes,
1941 unsigned *n_changes) {
1943 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1944 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1945 _cleanup_free_ char *config_path = NULL;
1950 assert(scope < _UNIT_FILE_SCOPE_MAX);
1951 assert(mode < _UNIT_FILE_PRESET_MAX);
1953 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1957 r = get_config_path(scope, runtime, root_dir, &config_path);
1961 STRV_FOREACH(i, paths.unit_path) {
1962 _cleanup_closedir_ DIR *d = NULL;
1963 _cleanup_free_ char *buf = NULL;
1964 const char *units_dir;
1966 if (!isempty(root_dir)) {
1967 buf = strjoin(root_dir, "/", *i, NULL);
1975 d = opendir(units_dir);
1977 if (errno == ENOENT)
1988 if (!de && errno != 0)
1994 if (ignore_file(de->d_name))
1997 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2000 dirent_ensure_type(d, de);
2002 if (de->d_type != DT_REG)
2005 r = unit_file_query_preset(scope, root_dir, de->d_name);
2009 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
2010 r = install_info_add_auto(&plus, de->d_name);
2011 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
2012 r = install_info_add_auto(&minus, de->d_name);
2022 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2023 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2025 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
2027 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
2032 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2033 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2041 static void unitfilelist_free(UnitFileList **f) {
2048 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
2050 int unit_file_get_list(
2051 UnitFileScope scope,
2052 const char *root_dir,
2055 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2060 assert(scope < _UNIT_FILE_SCOPE_MAX);
2063 if (root_dir && scope != UNIT_FILE_SYSTEM)
2066 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2070 STRV_FOREACH(i, paths.unit_path) {
2071 _cleanup_closedir_ DIR *d = NULL;
2072 _cleanup_free_ char *buf = NULL;
2073 const char *units_dir;
2075 if (!isempty(root_dir)) {
2076 buf = strjoin(root_dir, "/", *i, NULL);
2084 d = opendir(units_dir);
2086 if (errno == ENOENT)
2093 _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
2098 if (!de && errno != 0)
2104 if (ignore_file(de->d_name))
2107 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2110 if (hashmap_get(h, de->d_name))
2113 dirent_ensure_type(d, de);
2115 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2118 f = new0(UnitFileList, 1);
2122 f->path = path_make_absolute(de->d_name, units_dir);
2126 r = null_or_empty_path(f->path);
2127 if (r < 0 && r != -ENOENT)
2131 path_startswith(*i, "/run") ?
2132 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2136 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2140 f->state = UNIT_FILE_ENABLED;
2144 r = unit_file_can_install(&paths, root_dir, f->path, true);
2145 if (r == -EINVAL || /* Invalid setting? */
2146 r == -EBADMSG || /* Invalid format? */
2147 r == -ENOENT /* Included file not found? */)
2148 f->state = UNIT_FILE_INVALID;
2152 f->state = UNIT_FILE_DISABLED;
2154 f->state = UNIT_FILE_STATIC;
2157 r = hashmap_put(h, basename(f->path), f);
2160 f = NULL; /* prevent cleanup */
2167 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2168 [UNIT_FILE_ENABLED] = "enabled",
2169 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2170 [UNIT_FILE_LINKED] = "linked",
2171 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2172 [UNIT_FILE_MASKED] = "masked",
2173 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2174 [UNIT_FILE_STATIC] = "static",
2175 [UNIT_FILE_DISABLED] = "disabled",
2176 [UNIT_FILE_INVALID] = "invalid",
2179 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2181 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2182 [UNIT_FILE_SYMLINK] = "symlink",
2183 [UNIT_FILE_UNLINK] = "unlink",
2186 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2188 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = {
2189 [UNIT_FILE_PRESET_FULL] = "full",
2190 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2191 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2194 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);