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:
92 p = path_join(root_dir, "/run/systemd/system", NULL);
94 p = path_join(root_dir, SYSTEM_CONFIG_UNIT_PATH, NULL);
97 case UNIT_FILE_GLOBAL:
103 p = strdup("/run/systemd/user");
105 p = strdup(USER_CONFIG_UNIT_PATH);
110 if (root_dir || runtime)
113 r = user_config_home(&p);
115 return r < 0 ? r : -ENOENT;
120 assert_not_reached("Bad scope");
130 static int add_file_change(
131 UnitFileChange **changes,
133 UnitFileChangeType type,
135 const char *source) {
141 assert(!changes == !n_changes);
146 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
154 c[i].path = strdup(path);
158 path_kill_slashes(c[i].path);
161 c[i].source = strdup(source);
167 path_kill_slashes(c[i].path);
175 static int mark_symlink_for_removal(
176 Set **remove_symlinks_to,
184 r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
192 path_kill_slashes(n);
194 r = set_consume(*remove_symlinks_to, n);
196 return r == -EEXIST ? 0 : r;
201 static int remove_marked_symlinks_fd(
202 Set *remove_symlinks_to,
205 const char *config_path,
207 UnitFileChange **changes,
209 char** instance_whitelist) {
211 _cleanup_closedir_ DIR *d = NULL;
214 assert(remove_symlinks_to);
233 if (!de && errno != 0) {
241 if (ignore_file(de->d_name))
244 dirent_ensure_type(d, de);
246 if (de->d_type == DT_DIR) {
248 _cleanup_free_ char *p = NULL;
250 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
260 p = path_make_absolute(de->d_name, path);
266 /* This will close nfd, regardless whether it succeeds or not */
267 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, instance_whitelist);
271 } else if (de->d_type == DT_LNK) {
272 _cleanup_free_ char *p = NULL, *dest = NULL;
276 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
279 if (unit_name_is_instance(de->d_name) &&
280 instance_whitelist &&
281 !strv_contains(instance_whitelist, de->d_name)) {
283 _cleanup_free_ char *w;
285 /* OK, the file is not listed directly
286 * in the whitelist, so let's check if
287 * the template of it might be
290 w = unit_name_template(de->d_name);
294 if (!strv_contains(instance_whitelist, w))
298 p = path_make_absolute(de->d_name, path);
302 q = readlink_and_canonicalize(p, &dest);
313 set_get(remove_symlinks_to, dest) ||
314 set_get(remove_symlinks_to, basename(dest));
319 if (unlink(p) < 0 && errno != ENOENT) {
325 path_kill_slashes(p);
326 rmdir_parents(p, config_path);
327 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
329 if (!set_get(remove_symlinks_to, p)) {
331 q = mark_symlink_for_removal(&remove_symlinks_to, p);
344 static int remove_marked_symlinks(
345 Set *remove_symlinks_to,
346 const char *config_path,
347 UnitFileChange **changes,
349 char** instance_whitelist) {
351 _cleanup_close_ int fd = -1;
357 if (set_size(remove_symlinks_to) <= 0)
360 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
368 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
374 /* This takes possession of cfd and closes it */
375 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist);
383 static int find_symlinks_fd(
387 const char *config_path,
388 bool *same_name_link) {
391 _cleanup_closedir_ DIR *d = NULL;
397 assert(same_name_link);
410 if (!de && errno != 0)
416 if (ignore_file(de->d_name))
419 dirent_ensure_type(d, de);
421 if (de->d_type == DT_DIR) {
423 _cleanup_free_ char *p = NULL;
425 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
435 p = path_make_absolute(de->d_name, path);
441 /* This will close nfd, regardless whether it succeeds or not */
442 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
448 } else if (de->d_type == DT_LNK) {
449 _cleanup_free_ char *p = NULL, *dest = NULL;
450 bool found_path, found_dest, b = false;
453 /* Acquire symlink name */
454 p = path_make_absolute(de->d_name, path);
458 /* Acquire symlink destination */
459 q = readlink_and_canonicalize(p, &dest);
469 /* Check if the symlink itself matches what we
471 if (path_is_absolute(name))
472 found_path = path_equal(p, name);
474 found_path = streq(de->d_name, name);
476 /* Check if what the symlink points to
477 * matches what we are looking for */
478 if (path_is_absolute(name))
479 found_dest = path_equal(dest, name);
481 found_dest = streq(basename(dest), name);
483 if (found_path && found_dest) {
484 _cleanup_free_ char *t = NULL;
486 /* Filter out same name links in the main
488 t = path_make_absolute(name, config_path);
492 b = path_equal(t, p);
496 *same_name_link = true;
497 else if (found_path || found_dest)
503 static int find_symlinks(
505 const char *config_path,
506 bool *same_name_link) {
512 assert(same_name_link);
514 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
521 /* This takes possession of fd and closes it */
522 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
525 static int find_symlinks_in_scope(
527 const char *root_dir,
529 UnitFileState *state) {
532 _cleanup_free_ char *path2 = NULL;
533 bool same_name_link_runtime = false, same_name_link = false;
536 assert(scope < _UNIT_FILE_SCOPE_MAX);
539 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
540 _cleanup_free_ char *path = NULL;
542 /* First look in runtime config path */
543 r = get_config_path(scope, true, root_dir, &path);
547 r = find_symlinks(name, path, &same_name_link_runtime);
551 *state = UNIT_FILE_ENABLED_RUNTIME;
556 /* Then look in the normal config path */
557 r = get_config_path(scope, false, root_dir, &path2);
561 r = find_symlinks(name, path2, &same_name_link);
565 *state = UNIT_FILE_ENABLED;
569 /* Hmm, we didn't find it, but maybe we found the same name
571 if (same_name_link_runtime) {
572 *state = UNIT_FILE_LINKED_RUNTIME;
574 } else if (same_name_link) {
575 *state = UNIT_FILE_LINKED;
585 const char *root_dir,
588 UnitFileChange **changes,
589 unsigned *n_changes) {
592 _cleanup_free_ char *prefix = NULL;
596 assert(scope < _UNIT_FILE_SCOPE_MAX);
598 r = get_config_path(scope, runtime, root_dir, &prefix);
602 STRV_FOREACH(i, files) {
603 _cleanup_free_ char *path = NULL;
605 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
611 path = path_make_absolute(*i, prefix);
617 if (symlink("/dev/null", path) >= 0) {
618 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
622 if (errno == EEXIST) {
624 if (null_or_empty_path(path) > 0)
628 if (symlink_atomic("/dev/null", path) >= 0) {
629 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
630 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
646 int unit_file_unmask(
649 const char *root_dir,
651 UnitFileChange **changes,
652 unsigned *n_changes) {
654 char **i, *config_path = NULL;
656 Set *remove_symlinks_to = NULL;
659 assert(scope < _UNIT_FILE_SCOPE_MAX);
661 r = get_config_path(scope, runtime, root_dir, &config_path);
665 STRV_FOREACH(i, files) {
668 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
674 path = path_make_absolute(*i, config_path);
680 q = null_or_empty_path(path);
682 if (unlink(path) >= 0) {
683 mark_symlink_for_removal(&remove_symlinks_to, path);
684 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
693 if (q != -ENOENT && r == 0)
701 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
705 set_free_free(remove_symlinks_to);
714 const char *root_dir,
717 UnitFileChange **changes,
718 unsigned *n_changes) {
720 _cleanup_lookup_paths_free_ LookupPaths paths = {};
722 _cleanup_free_ char *config_path = NULL;
726 assert(scope < _UNIT_FILE_SCOPE_MAX);
728 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
732 r = get_config_path(scope, runtime, root_dir, &config_path);
736 STRV_FOREACH(i, files) {
737 _cleanup_free_ char *path = NULL;
743 if (!path_is_absolute(*i) ||
744 !unit_name_is_valid(fn, TEMPLATE_VALID)) {
750 if (lstat(*i, &st) < 0) {
756 if (!S_ISREG(st.st_mode)) {
761 q = in_search_path(*i, paths.unit_path);
768 path = path_make_absolute(fn, config_path);
772 if (symlink(*i, path) >= 0) {
773 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
777 if (errno == EEXIST) {
778 _cleanup_free_ char *dest = NULL;
780 q = readlink_and_make_absolute(path, &dest);
781 if (q < 0 && errno != ENOENT) {
787 if (q >= 0 && path_equal(dest, *i))
791 if (symlink_atomic(*i, path) >= 0) {
792 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
793 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
809 void unit_file_list_free(Hashmap *h) {
812 while ((i = hashmap_steal_first(h))) {
820 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
823 assert(changes || n_changes == 0);
828 for (i = 0; i < n_changes; i++) {
829 free(changes[i].path);
830 free(changes[i].source);
836 static void install_info_free(InstallInfo *i) {
841 strv_free(i->aliases);
842 strv_free(i->wanted_by);
843 strv_free(i->required_by);
844 free(i->default_instance);
848 static void install_info_hashmap_free(Hashmap *m) {
854 while ((i = hashmap_steal_first(m)))
855 install_info_free(i);
860 static void install_context_done(InstallContext *c) {
863 install_info_hashmap_free(c->will_install);
864 install_info_hashmap_free(c->have_installed);
866 c->will_install = c->have_installed = NULL;
869 static int install_info_add(
873 InstallInfo *i = NULL;
877 assert(name || path);
880 name = basename(path);
882 if (!unit_name_is_valid(name, TEMPLATE_VALID))
885 if (hashmap_get(c->have_installed, name) ||
886 hashmap_get(c->will_install, name))
889 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
893 i = new0(InstallInfo, 1);
897 i->name = strdup(name);
904 i->path = strdup(path);
911 r = hashmap_put(c->will_install, i->name, i);
919 install_info_free(i);
924 static int install_info_add_auto(
926 const char *name_or_path) {
929 assert(name_or_path);
931 if (path_is_absolute(name_or_path))
932 return install_info_add(c, NULL, name_or_path);
934 return install_info_add(c, name_or_path, NULL);
937 static int config_parse_also(
939 const char *filename,
942 unsigned section_line,
950 const char *word, *state;
951 InstallContext *c = data;
957 FOREACH_WORD_QUOTED(word, l, rvalue, state) {
958 _cleanup_free_ char *n;
961 n = strndup(word, l);
965 r = install_info_add(c, n, NULL);
973 static int config_parse_user(
975 const char *filename,
978 unsigned section_line,
985 InstallInfo *i = data;
993 r = install_full_printf(i, rvalue, &printed);
1003 static int config_parse_default_instance(
1005 const char *filename,
1007 const char *section,
1008 unsigned section_line,
1015 InstallInfo *i = data;
1023 r = install_full_printf(i, rvalue, &printed);
1027 if (!unit_instance_is_valid(printed))
1030 free(i->default_instance);
1031 i->default_instance = printed;
1036 static int unit_file_load(
1040 const char *root_dir,
1041 bool allow_symlink) {
1043 const ConfigTableItem items[] = {
1044 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
1045 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1046 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1047 { "Install", "DefaultInstance", config_parse_default_instance, 0, info },
1048 { "Install", "Also", config_parse_also, 0, c },
1049 { "Exec", "User", config_parse_user, 0, info },
1053 _cleanup_fclose_ FILE *f = NULL;
1060 if (!isempty(root_dir))
1061 path = strappenda3(root_dir, "/", path);
1063 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1067 f = fdopen(fd, "re");
1073 r = config_parse(NULL, path, f,
1075 config_item_table_lookup, items,
1076 true, true, false, info);
1081 (int) strv_length(info->aliases) +
1082 (int) strv_length(info->wanted_by) +
1083 (int) strv_length(info->required_by);
1086 static int unit_file_search(
1090 const char *root_dir,
1091 bool allow_symlink) {
1101 return unit_file_load(c, info, info->path, root_dir, allow_symlink);
1105 STRV_FOREACH(p, paths->unit_path) {
1106 _cleanup_free_ char *path = NULL;
1108 path = strjoin(*p, "/", info->name, NULL);
1112 r = unit_file_load(c, info, path, root_dir, allow_symlink);
1118 if (r != -ENOENT && r != -ELOOP)
1122 if (unit_name_is_instance(info->name)) {
1124 /* Unit file doesn't exist, however instance
1125 * enablement was requested. We will check if it is
1126 * possible to load template unit file. */
1128 _cleanup_free_ char *template = NULL;
1130 template = unit_name_template(info->name);
1134 STRV_FOREACH(p, paths->unit_path) {
1135 _cleanup_free_ char *path = NULL;
1137 path = strjoin(*p, "/", template, NULL);
1141 r = unit_file_load(c, info, path, root_dir, allow_symlink);
1147 if (r != -ENOENT && r != -ELOOP)
1155 static int unit_file_can_install(
1157 const char *root_dir,
1159 bool allow_symlink) {
1161 _cleanup_install_context_done_ InstallContext c = {};
1168 r = install_info_add_auto(&c, name);
1172 assert_se(i = hashmap_first(c.will_install));
1174 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1178 (int) strv_length(i->aliases) +
1179 (int) strv_length(i->wanted_by) +
1180 (int) strv_length(i->required_by);
1185 static int create_symlink(
1186 const char *old_path,
1187 const char *new_path,
1189 UnitFileChange **changes,
1190 unsigned *n_changes) {
1192 _cleanup_free_ char *dest = NULL;
1198 mkdir_parents_label(new_path, 0755);
1200 if (symlink(old_path, new_path) >= 0) {
1201 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1205 if (errno != EEXIST)
1208 r = readlink_and_make_absolute(new_path, &dest);
1212 if (path_equal(dest, old_path))
1218 r = symlink_atomic(old_path, new_path);
1222 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1223 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1228 static int install_info_symlink_alias(
1230 const char *config_path,
1232 UnitFileChange **changes,
1233 unsigned *n_changes) {
1239 assert(config_path);
1241 STRV_FOREACH(s, i->aliases) {
1242 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1244 q = install_full_printf(i, *s, &dst);
1248 alias_path = path_make_absolute(dst, config_path);
1252 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1260 static int install_info_symlink_wants(
1262 const char *config_path,
1266 UnitFileChange **changes,
1267 unsigned *n_changes) {
1269 _cleanup_free_ char *buf = NULL;
1275 assert(config_path);
1277 if (unit_name_is_template(i->name)) {
1279 /* Don't install any symlink if there's no default
1280 * instance configured */
1282 if (!i->default_instance)
1285 buf = unit_name_replace_instance(i->name, i->default_instance);
1293 STRV_FOREACH(s, list) {
1294 _cleanup_free_ char *path = NULL, *dst = NULL;
1296 q = install_full_printf(i, *s, &dst);
1300 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1305 path = strjoin(config_path, "/", dst, suffix, n, NULL);
1309 q = create_symlink(i->path, path, force, changes, n_changes);
1317 static int install_info_symlink_link(
1320 const char *config_path,
1321 const char *root_dir,
1323 UnitFileChange **changes,
1324 unsigned *n_changes) {
1326 _cleanup_free_ char *path = NULL;
1331 assert(config_path);
1334 r = in_search_path(i->path, paths->unit_path);
1338 path = strjoin(config_path, "/", i->name, NULL);
1342 return create_symlink(i->path, path, force, changes, n_changes);
1345 static int install_info_apply(
1348 const char *config_path,
1349 const char *root_dir,
1351 UnitFileChange **changes,
1352 unsigned *n_changes) {
1358 assert(config_path);
1360 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1362 q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes);
1366 q = install_info_symlink_wants(i, config_path, i->required_by, ".requires/", force, changes, n_changes);
1370 q = install_info_symlink_link(i, paths, config_path, root_dir, force, changes, n_changes);
1377 static int install_context_apply(
1380 const char *config_path,
1381 const char *root_dir,
1383 UnitFileChange **changes,
1384 unsigned *n_changes) {
1391 assert(config_path);
1393 while ((i = hashmap_first(c->will_install))) {
1395 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1399 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1401 q = unit_file_search(c, i, paths, root_dir, false);
1410 q = install_info_apply(i, paths, config_path, root_dir, force, changes, n_changes);
1411 if (r >= 0 && q < 0)
1418 static int install_context_mark_for_removal(
1421 Set **remove_symlinks_to,
1422 const char *config_path,
1423 const char *root_dir) {
1430 assert(config_path);
1432 /* Marks all items for removal */
1434 while ((i = hashmap_first(c->will_install))) {
1436 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1440 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1442 q = unit_file_search(c, i, paths, root_dir, false);
1453 if (unit_name_is_instance(i->name)) {
1457 unit_file = basename(i->path);
1459 if (unit_name_is_instance(unit_file))
1460 /* unit file named as instance exists, thus all symlinks
1461 * pointing to it will be removed */
1462 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1464 /* does not exist, thus we will mark for removal symlinks
1465 * to template unit file */
1466 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1468 /* If i->path is not set, it means that we didn't actually find
1469 * the unit file. But we can still remove symlinks to the
1470 * nonexistent template. */
1471 unit_file = unit_name_template(i->name);
1475 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1479 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1481 if (r >= 0 && q < 0)
1488 int unit_file_enable(
1489 UnitFileScope scope,
1491 const char *root_dir,
1494 UnitFileChange **changes,
1495 unsigned *n_changes) {
1497 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1498 _cleanup_install_context_done_ InstallContext c = {};
1500 _cleanup_free_ char *config_path = NULL;
1504 assert(scope < _UNIT_FILE_SCOPE_MAX);
1506 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1510 r = get_config_path(scope, runtime, root_dir, &config_path);
1514 STRV_FOREACH(i, files) {
1515 r = install_info_add_auto(&c, *i);
1520 /* This will return the number of symlink rules that were
1521 supposed to be created, not the ones actually created. This is
1522 useful to determine whether the passed files had any
1523 installation data at all. */
1525 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1528 int unit_file_disable(
1529 UnitFileScope scope,
1531 const char *root_dir,
1533 UnitFileChange **changes,
1534 unsigned *n_changes) {
1536 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1537 _cleanup_install_context_done_ InstallContext c = {};
1539 _cleanup_free_ char *config_path = NULL;
1540 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1544 assert(scope < _UNIT_FILE_SCOPE_MAX);
1546 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1550 r = get_config_path(scope, runtime, root_dir, &config_path);
1554 STRV_FOREACH(i, files) {
1555 r = install_info_add_auto(&c, *i);
1560 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1562 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1569 int unit_file_reenable(
1570 UnitFileScope scope,
1572 const char *root_dir,
1575 UnitFileChange **changes,
1576 unsigned *n_changes) {
1579 r = unit_file_disable(scope, runtime, root_dir, files,
1580 changes, n_changes);
1584 return unit_file_enable(scope, runtime, root_dir, files, force,
1585 changes, n_changes);
1588 int unit_file_set_default(
1589 UnitFileScope scope,
1590 const char *root_dir,
1593 UnitFileChange **changes,
1594 unsigned *n_changes) {
1596 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1597 _cleanup_install_context_done_ InstallContext c = {};
1598 _cleanup_free_ char *config_path = NULL;
1601 InstallInfo *i = NULL;
1604 assert(scope < _UNIT_FILE_SCOPE_MAX);
1607 if (unit_name_to_type(file) != UNIT_TARGET)
1610 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1614 r = get_config_path(scope, false, root_dir, &config_path);
1618 r = install_info_add_auto(&c, file);
1622 assert_se(i = hashmap_first(c.will_install));
1624 r = unit_file_search(&c, i, &paths, root_dir, false);
1628 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1630 r = create_symlink(i->path, path, force, changes, n_changes);
1637 int unit_file_get_default(
1638 UnitFileScope scope,
1639 const char *root_dir,
1642 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1647 assert(scope < _UNIT_FILE_SCOPE_MAX);
1650 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1654 STRV_FOREACH(p, paths.unit_path) {
1655 _cleanup_free_ char *path = NULL, *tmp = NULL;
1658 path = path_join(root_dir, *p, SPECIAL_DEFAULT_TARGET);
1662 r = readlink_malloc(path, &tmp);
1665 else if (r == -EINVAL)
1667 n = strdup(SPECIAL_DEFAULT_TARGET);
1671 n = strdup(basename(tmp));
1683 UnitFileState unit_file_get_state(
1684 UnitFileScope scope,
1685 const char *root_dir,
1688 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1689 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1691 _cleanup_free_ char *path = NULL;
1695 assert(scope < _UNIT_FILE_SCOPE_MAX);
1698 if (root_dir && scope != UNIT_FILE_SYSTEM)
1701 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1704 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1708 STRV_FOREACH(i, paths.unit_path) {
1715 path = path_join(root_dir, *i, name);
1720 partial = path + strlen(root_dir);
1725 * Search for a unit file in our default paths, to
1726 * be sure, that there are no broken symlinks.
1728 if (lstat(path, &st) < 0) {
1730 if (errno != ENOENT)
1733 if (!unit_name_is_instance(name))
1736 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1739 r = null_or_empty_path(path);
1740 if (r < 0 && r != -ENOENT)
1743 state = path_startswith(*i, "/run") ?
1744 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1749 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1755 r = unit_file_can_install(&paths, root_dir, partial, true);
1756 if (r < 0 && errno != ENOENT)
1759 return UNIT_FILE_DISABLED;
1761 return UNIT_FILE_STATIC;
1764 return r < 0 ? r : state;
1767 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
1768 _cleanup_strv_free_ char **files = NULL;
1773 assert(scope < _UNIT_FILE_SCOPE_MAX);
1776 if (scope == UNIT_FILE_SYSTEM)
1777 r = conf_files_list(&files, ".preset", root_dir,
1778 "/etc/systemd/system-preset",
1779 "/usr/local/lib/systemd/system-preset",
1780 "/usr/lib/systemd/system-preset",
1781 #ifdef HAVE_SPLIT_USR
1782 "/lib/systemd/system-preset",
1785 else if (scope == UNIT_FILE_GLOBAL)
1786 r = conf_files_list(&files, ".preset", root_dir,
1787 "/etc/systemd/user-preset",
1788 "/usr/local/lib/systemd/user-preset",
1789 "/usr/lib/systemd/user-preset",
1797 STRV_FOREACH(p, files) {
1798 _cleanup_fclose_ FILE *f;
1800 f = fopen(*p, "re");
1802 if (errno == ENOENT)
1809 char line[LINE_MAX], *l;
1811 if (!fgets(line, sizeof(line), f))
1818 if (strchr(COMMENTS "\n", *l))
1821 if (first_word(l, "enable")) {
1823 l += strspn(l, WHITESPACE);
1825 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1826 log_debug("Preset file says enable %s.", name);
1830 } else if (first_word(l, "disable")) {
1832 l += strspn(l, WHITESPACE);
1834 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1835 log_debug("Preset file says disable %s.", name);
1840 log_debug("Couldn't parse line '%s'", l);
1844 /* Default is "enable" */
1845 log_debug("Preset file doesn't say anything about %s, enabling.", name);
1849 int unit_file_preset(
1850 UnitFileScope scope,
1852 const char *root_dir,
1854 UnitFilePresetMode mode,
1856 UnitFileChange **changes,
1857 unsigned *n_changes) {
1859 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1860 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1861 _cleanup_free_ char *config_path = NULL;
1866 assert(scope < _UNIT_FILE_SCOPE_MAX);
1867 assert(mode < _UNIT_FILE_PRESET_MAX);
1869 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1873 r = get_config_path(scope, runtime, root_dir, &config_path);
1877 STRV_FOREACH(i, files) {
1879 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1882 r = unit_file_query_preset(scope, root_dir, *i);
1886 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1887 r = install_info_add_auto(&plus, *i);
1888 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1889 r = install_info_add_auto(&minus, *i);
1898 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1899 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1901 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1903 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1908 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1909 /* Returns number of symlinks that where supposed to be installed. */
1910 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1918 int unit_file_preset_all(
1919 UnitFileScope scope,
1921 const char *root_dir,
1922 UnitFilePresetMode mode,
1924 UnitFileChange **changes,
1925 unsigned *n_changes) {
1927 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1928 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1929 _cleanup_free_ char *config_path = NULL;
1934 assert(scope < _UNIT_FILE_SCOPE_MAX);
1935 assert(mode < _UNIT_FILE_PRESET_MAX);
1937 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1941 r = get_config_path(scope, runtime, root_dir, &config_path);
1945 STRV_FOREACH(i, paths.unit_path) {
1946 _cleanup_closedir_ DIR *d = NULL;
1947 _cleanup_free_ char *units_dir;
1949 units_dir = path_join(root_dir, *i, NULL);
1953 d = opendir(units_dir);
1955 if (errno == ENOENT)
1966 if (!de && errno != 0)
1972 if (ignore_file(de->d_name))
1975 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1978 dirent_ensure_type(d, de);
1980 if (de->d_type != DT_REG)
1983 r = unit_file_query_preset(scope, root_dir, de->d_name);
1987 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1988 r = install_info_add_auto(&plus, de->d_name);
1989 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1990 r = install_info_add_auto(&minus, de->d_name);
2000 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2001 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2003 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
2005 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
2010 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2011 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2019 static void unitfilelist_free(UnitFileList **f) {
2026 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
2028 int unit_file_get_list(
2029 UnitFileScope scope,
2030 const char *root_dir,
2033 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2038 assert(scope < _UNIT_FILE_SCOPE_MAX);
2041 if (root_dir && scope != UNIT_FILE_SYSTEM)
2044 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2048 STRV_FOREACH(i, paths.unit_path) {
2049 _cleanup_closedir_ DIR *d = NULL;
2050 _cleanup_free_ char *units_dir;
2052 units_dir = path_join(root_dir, *i, NULL);
2056 d = opendir(units_dir);
2058 if (errno == ENOENT)
2065 _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
2070 if (!de && errno != 0)
2076 if (ignore_file(de->d_name))
2079 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2082 if (hashmap_get(h, de->d_name))
2085 dirent_ensure_type(d, de);
2087 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2090 f = new0(UnitFileList, 1);
2094 f->path = path_make_absolute(de->d_name, units_dir);
2098 r = null_or_empty_path(f->path);
2099 if (r < 0 && r != -ENOENT)
2103 path_startswith(*i, "/run") ?
2104 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2108 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2112 f->state = UNIT_FILE_ENABLED;
2116 r = unit_file_can_install(&paths, root_dir, f->path, true);
2117 if (r == -EINVAL || /* Invalid setting? */
2118 r == -EBADMSG || /* Invalid format? */
2119 r == -ENOENT /* Included file not found? */)
2120 f->state = UNIT_FILE_INVALID;
2124 f->state = UNIT_FILE_DISABLED;
2126 f->state = UNIT_FILE_STATIC;
2129 r = hashmap_put(h, basename(f->path), f);
2132 f = NULL; /* prevent cleanup */
2139 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2140 [UNIT_FILE_ENABLED] = "enabled",
2141 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2142 [UNIT_FILE_LINKED] = "linked",
2143 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2144 [UNIT_FILE_MASKED] = "masked",
2145 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2146 [UNIT_FILE_STATIC] = "static",
2147 [UNIT_FILE_DISABLED] = "disabled",
2148 [UNIT_FILE_INVALID] = "invalid",
2151 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2153 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2154 [UNIT_FILE_SYMLINK] = "symlink",
2155 [UNIT_FILE_UNLINK] = "unlink",
2158 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2160 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = {
2161 [UNIT_FILE_PRESET_FULL] = "full",
2162 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2163 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2166 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);