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 static int in_search_path(const char *path, char **search) {
49 _cleanup_free_ char *parent = NULL;
54 r = path_get_parent(path, &parent);
58 return strv_contains(search, parent);
61 static int lookup_paths_init_from_scope(LookupPaths *paths,
63 const char *root_dir) {
66 assert(scope < _UNIT_FILE_SCOPE_MAX);
70 return lookup_paths_init(paths,
71 scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
72 scope == UNIT_FILE_USER,
77 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
82 assert(scope < _UNIT_FILE_SCOPE_MAX);
87 case UNIT_FILE_SYSTEM:
90 p = path_join(root_dir, "/run/systemd/system", NULL);
92 p = path_join(root_dir, SYSTEM_CONFIG_UNIT_PATH, NULL);
95 case UNIT_FILE_GLOBAL:
101 p = strdup("/run/systemd/user");
103 p = strdup(USER_CONFIG_UNIT_PATH);
108 if (root_dir || runtime)
111 r = user_config_home(&p);
113 return r < 0 ? r : -ENOENT;
118 assert_not_reached("Bad scope");
128 static int add_file_change(
129 UnitFileChange **changes,
131 UnitFileChangeType type,
133 const char *source) {
139 assert(!changes == !n_changes);
144 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
152 c[i].path = strdup(path);
156 path_kill_slashes(c[i].path);
159 c[i].source = strdup(source);
165 path_kill_slashes(c[i].path);
173 static int mark_symlink_for_removal(
174 Set **remove_symlinks_to,
182 r = set_ensure_allocated(remove_symlinks_to, &string_hash_ops);
190 path_kill_slashes(n);
192 r = set_consume(*remove_symlinks_to, n);
194 return r == -EEXIST ? 0 : r;
199 static int remove_marked_symlinks_fd(
200 Set *remove_symlinks_to,
203 const char *config_path,
205 UnitFileChange **changes,
207 char** instance_whitelist) {
209 _cleanup_closedir_ DIR *d = NULL;
212 assert(remove_symlinks_to);
231 if (!de && errno != 0) {
239 if (ignore_file(de->d_name))
242 dirent_ensure_type(d, de);
244 if (de->d_type == DT_DIR) {
246 _cleanup_free_ char *p = NULL;
248 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
258 p = path_make_absolute(de->d_name, path);
264 /* This will close nfd, regardless whether it succeeds or not */
265 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, instance_whitelist);
269 } else if (de->d_type == DT_LNK) {
270 _cleanup_free_ char *p = NULL, *dest = NULL;
274 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
277 if (unit_name_is_instance(de->d_name) &&
278 instance_whitelist &&
279 !strv_contains(instance_whitelist, de->d_name)) {
281 _cleanup_free_ char *w;
283 /* OK, the file is not listed directly
284 * in the whitelist, so let's check if
285 * the template of it might be
288 w = unit_name_template(de->d_name);
292 if (!strv_contains(instance_whitelist, w))
296 p = path_make_absolute(de->d_name, path);
300 q = readlink_and_canonicalize(p, &dest);
311 set_get(remove_symlinks_to, dest) ||
312 set_get(remove_symlinks_to, basename(dest));
317 if (unlink(p) < 0 && errno != ENOENT) {
323 path_kill_slashes(p);
324 rmdir_parents(p, config_path);
325 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
327 if (!set_get(remove_symlinks_to, p)) {
329 q = mark_symlink_for_removal(&remove_symlinks_to, p);
342 static int remove_marked_symlinks(
343 Set *remove_symlinks_to,
344 const char *config_path,
345 UnitFileChange **changes,
347 char** instance_whitelist) {
349 _cleanup_close_ int fd = -1;
355 if (set_size(remove_symlinks_to) <= 0)
358 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
366 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
372 /* This takes possession of cfd and closes it */
373 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist);
381 static int find_symlinks_fd(
385 const char *config_path,
386 bool *same_name_link) {
389 _cleanup_closedir_ DIR *d = NULL;
395 assert(same_name_link);
408 if (!de && errno != 0)
414 if (ignore_file(de->d_name))
417 dirent_ensure_type(d, de);
419 if (de->d_type == DT_DIR) {
421 _cleanup_free_ char *p = NULL;
423 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
433 p = path_make_absolute(de->d_name, path);
439 /* This will close nfd, regardless whether it succeeds or not */
440 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
446 } else if (de->d_type == DT_LNK) {
447 _cleanup_free_ char *p = NULL, *dest = NULL;
448 bool found_path, found_dest, b = false;
451 /* Acquire symlink name */
452 p = path_make_absolute(de->d_name, path);
456 /* Acquire symlink destination */
457 q = readlink_and_canonicalize(p, &dest);
467 /* Check if the symlink itself matches what we
469 if (path_is_absolute(name))
470 found_path = path_equal(p, name);
472 found_path = streq(de->d_name, name);
474 /* Check if what the symlink points to
475 * matches what we are looking for */
476 if (path_is_absolute(name))
477 found_dest = path_equal(dest, name);
479 found_dest = streq(basename(dest), name);
481 if (found_path && found_dest) {
482 _cleanup_free_ char *t = NULL;
484 /* Filter out same name links in the main
486 t = path_make_absolute(name, config_path);
490 b = path_equal(t, p);
494 *same_name_link = true;
495 else if (found_path || found_dest)
501 static int find_symlinks(
503 const char *config_path,
504 bool *same_name_link) {
510 assert(same_name_link);
512 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
519 /* This takes possession of fd and closes it */
520 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
523 static int find_symlinks_in_scope(
525 const char *root_dir,
527 UnitFileState *state) {
530 _cleanup_free_ char *path2 = NULL;
531 bool same_name_link_runtime = false, same_name_link = false;
534 assert(scope < _UNIT_FILE_SCOPE_MAX);
537 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
538 _cleanup_free_ char *path = NULL;
540 /* First look in runtime config path */
541 r = get_config_path(scope, true, root_dir, &path);
545 r = find_symlinks(name, path, &same_name_link_runtime);
549 *state = UNIT_FILE_ENABLED_RUNTIME;
554 /* Then look in the normal config path */
555 r = get_config_path(scope, false, root_dir, &path2);
559 r = find_symlinks(name, path2, &same_name_link);
563 *state = UNIT_FILE_ENABLED;
567 /* Hmm, we didn't find it, but maybe we found the same name
569 if (same_name_link_runtime) {
570 *state = UNIT_FILE_LINKED_RUNTIME;
572 } else if (same_name_link) {
573 *state = UNIT_FILE_LINKED;
583 const char *root_dir,
586 UnitFileChange **changes,
587 unsigned *n_changes) {
590 _cleanup_free_ char *prefix = NULL;
594 assert(scope < _UNIT_FILE_SCOPE_MAX);
596 r = get_config_path(scope, runtime, root_dir, &prefix);
600 STRV_FOREACH(i, files) {
601 _cleanup_free_ char *path = NULL;
603 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
609 path = path_make_absolute(*i, prefix);
615 if (symlink("/dev/null", path) >= 0) {
616 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
620 if (errno == EEXIST) {
622 if (null_or_empty_path(path) > 0)
626 if (symlink_atomic("/dev/null", path) >= 0) {
627 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
628 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
644 int unit_file_unmask(
647 const char *root_dir,
649 UnitFileChange **changes,
650 unsigned *n_changes) {
652 char **i, *config_path = NULL;
654 Set *remove_symlinks_to = NULL;
657 assert(scope < _UNIT_FILE_SCOPE_MAX);
659 r = get_config_path(scope, runtime, root_dir, &config_path);
663 STRV_FOREACH(i, files) {
666 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
672 path = path_make_absolute(*i, config_path);
678 q = null_or_empty_path(path);
680 if (unlink(path) >= 0) {
681 mark_symlink_for_removal(&remove_symlinks_to, path);
682 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
691 if (q != -ENOENT && r == 0)
699 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
703 set_free_free(remove_symlinks_to);
712 const char *root_dir,
715 UnitFileChange **changes,
716 unsigned *n_changes) {
718 _cleanup_lookup_paths_free_ LookupPaths paths = {};
720 _cleanup_free_ char *config_path = NULL;
724 assert(scope < _UNIT_FILE_SCOPE_MAX);
726 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
730 r = get_config_path(scope, runtime, root_dir, &config_path);
734 STRV_FOREACH(i, files) {
735 _cleanup_free_ char *path = NULL;
741 if (!path_is_absolute(*i) ||
742 !unit_name_is_valid(fn, TEMPLATE_VALID)) {
748 if (lstat(*i, &st) < 0) {
754 if (!S_ISREG(st.st_mode)) {
759 q = in_search_path(*i, paths.unit_path);
766 path = path_make_absolute(fn, config_path);
770 if (symlink(*i, path) >= 0) {
771 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
775 if (errno == EEXIST) {
776 _cleanup_free_ char *dest = NULL;
778 q = readlink_and_make_absolute(path, &dest);
779 if (q < 0 && errno != ENOENT) {
785 if (q >= 0 && path_equal(dest, *i))
789 if (symlink_atomic(*i, path) >= 0) {
790 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
791 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
807 void unit_file_list_free(Hashmap *h) {
810 while ((i = hashmap_steal_first(h))) {
818 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
821 assert(changes || n_changes == 0);
826 for (i = 0; i < n_changes; i++) {
827 free(changes[i].path);
828 free(changes[i].source);
834 static void install_info_free(InstallInfo *i) {
839 strv_free(i->aliases);
840 strv_free(i->wanted_by);
841 strv_free(i->required_by);
842 free(i->default_instance);
846 static void install_info_hashmap_free(Hashmap *m) {
852 while ((i = hashmap_steal_first(m)))
853 install_info_free(i);
858 static void install_context_done(InstallContext *c) {
861 install_info_hashmap_free(c->will_install);
862 install_info_hashmap_free(c->have_installed);
864 c->will_install = c->have_installed = NULL;
867 static int install_info_add(
871 InstallInfo *i = NULL;
875 assert(name || path);
878 name = basename(path);
880 if (!unit_name_is_valid(name, TEMPLATE_VALID))
883 if (hashmap_get(c->have_installed, name) ||
884 hashmap_get(c->will_install, name))
887 r = hashmap_ensure_allocated(&c->will_install, &string_hash_ops);
891 i = new0(InstallInfo, 1);
895 i->name = strdup(name);
902 i->path = strdup(path);
909 r = hashmap_put(c->will_install, i->name, i);
917 install_info_free(i);
922 static int install_info_add_auto(
924 const char *name_or_path) {
927 assert(name_or_path);
929 if (path_is_absolute(name_or_path))
930 return install_info_add(c, NULL, name_or_path);
932 return install_info_add(c, name_or_path, NULL);
935 static int config_parse_also(
937 const char *filename,
940 unsigned section_line,
948 const char *word, *state;
949 InstallContext *c = data;
955 FOREACH_WORD_QUOTED(word, l, rvalue, state) {
956 _cleanup_free_ char *n;
959 n = strndup(word, l);
963 r = install_info_add(c, n, NULL);
968 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
969 "Trailing garbage, ignoring.");
974 static int config_parse_user(
976 const char *filename,
979 unsigned section_line,
986 InstallInfo *i = data;
994 r = install_full_printf(i, rvalue, &printed);
1004 static int config_parse_default_instance(
1006 const char *filename,
1008 const char *section,
1009 unsigned section_line,
1016 InstallInfo *i = data;
1024 r = install_full_printf(i, rvalue, &printed);
1028 if (!unit_instance_is_valid(printed)) {
1033 free(i->default_instance);
1034 i->default_instance = printed;
1039 static int unit_file_load(
1043 const char *root_dir,
1044 bool allow_symlink) {
1046 const ConfigTableItem items[] = {
1047 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
1048 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1049 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1050 { "Install", "DefaultInstance", config_parse_default_instance, 0, info },
1051 { "Install", "Also", config_parse_also, 0, c },
1052 { "Exec", "User", config_parse_user, 0, info },
1056 _cleanup_fclose_ FILE *f = NULL;
1063 if (!isempty(root_dir))
1064 path = strappenda(root_dir, "/", path);
1066 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1070 f = fdopen(fd, "re");
1076 r = config_parse(NULL, path, f,
1078 config_item_table_lookup, items,
1079 true, true, false, info);
1084 (int) strv_length(info->aliases) +
1085 (int) strv_length(info->wanted_by) +
1086 (int) strv_length(info->required_by);
1089 static int unit_file_search(
1093 const char *root_dir,
1094 bool allow_symlink) {
1104 return unit_file_load(c, info, info->path, root_dir, allow_symlink);
1108 STRV_FOREACH(p, paths->unit_path) {
1109 _cleanup_free_ char *path = NULL;
1111 path = strjoin(*p, "/", info->name, NULL);
1115 r = unit_file_load(c, info, path, root_dir, allow_symlink);
1121 if (r != -ENOENT && r != -ELOOP)
1125 if (unit_name_is_instance(info->name)) {
1127 /* Unit file doesn't exist, however instance
1128 * enablement was requested. We will check if it is
1129 * possible to load template unit file. */
1131 _cleanup_free_ char *template = NULL;
1133 template = unit_name_template(info->name);
1137 STRV_FOREACH(p, paths->unit_path) {
1138 _cleanup_free_ char *path = NULL;
1140 path = strjoin(*p, "/", template, NULL);
1144 r = unit_file_load(c, info, path, root_dir, allow_symlink);
1150 if (r != -ENOENT && r != -ELOOP)
1158 static int unit_file_can_install(
1160 const char *root_dir,
1162 bool allow_symlink) {
1164 _cleanup_(install_context_done) InstallContext c = {};
1171 r = install_info_add_auto(&c, name);
1175 assert_se(i = hashmap_first(c.will_install));
1177 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1181 (int) strv_length(i->aliases) +
1182 (int) strv_length(i->wanted_by) +
1183 (int) strv_length(i->required_by);
1188 static int create_symlink(
1189 const char *old_path,
1190 const char *new_path,
1192 UnitFileChange **changes,
1193 unsigned *n_changes) {
1195 _cleanup_free_ char *dest = NULL;
1201 mkdir_parents_label(new_path, 0755);
1203 if (symlink(old_path, new_path) >= 0) {
1204 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1208 if (errno != EEXIST)
1211 r = readlink_and_make_absolute(new_path, &dest);
1215 if (path_equal(dest, old_path))
1221 r = symlink_atomic(old_path, new_path);
1225 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1226 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1231 static int install_info_symlink_alias(
1233 const char *config_path,
1235 UnitFileChange **changes,
1236 unsigned *n_changes) {
1242 assert(config_path);
1244 STRV_FOREACH(s, i->aliases) {
1245 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1247 q = install_full_printf(i, *s, &dst);
1251 alias_path = path_make_absolute(dst, config_path);
1255 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1263 static int install_info_symlink_wants(
1265 const char *config_path,
1269 UnitFileChange **changes,
1270 unsigned *n_changes) {
1272 _cleanup_free_ char *buf = NULL;
1278 assert(config_path);
1280 if (unit_name_is_template(i->name)) {
1282 /* Don't install any symlink if there's no default
1283 * instance configured */
1285 if (!i->default_instance)
1288 buf = unit_name_replace_instance(i->name, i->default_instance);
1296 STRV_FOREACH(s, list) {
1297 _cleanup_free_ char *path = NULL, *dst = NULL;
1299 q = install_full_printf(i, *s, &dst);
1303 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1308 path = strjoin(config_path, "/", dst, suffix, n, NULL);
1312 q = create_symlink(i->path, path, force, changes, n_changes);
1320 static int install_info_symlink_link(
1323 const char *config_path,
1324 const char *root_dir,
1326 UnitFileChange **changes,
1327 unsigned *n_changes) {
1329 _cleanup_free_ char *path = NULL;
1334 assert(config_path);
1337 r = in_search_path(i->path, paths->unit_path);
1341 path = strjoin(config_path, "/", i->name, NULL);
1345 return create_symlink(i->path, path, force, changes, n_changes);
1348 static int install_info_apply(
1351 const char *config_path,
1352 const char *root_dir,
1354 UnitFileChange **changes,
1355 unsigned *n_changes) {
1361 assert(config_path);
1363 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1365 q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes);
1369 q = install_info_symlink_wants(i, config_path, i->required_by, ".requires/", force, changes, n_changes);
1373 q = install_info_symlink_link(i, paths, config_path, root_dir, force, changes, n_changes);
1380 static int install_context_apply(
1383 const char *config_path,
1384 const char *root_dir,
1386 UnitFileChange **changes,
1387 unsigned *n_changes) {
1394 assert(config_path);
1396 while ((i = hashmap_first(c->will_install))) {
1398 q = hashmap_ensure_allocated(&c->have_installed, &string_hash_ops);
1402 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1404 q = unit_file_search(c, i, paths, root_dir, false);
1413 q = install_info_apply(i, paths, config_path, root_dir, force, changes, n_changes);
1414 if (r >= 0 && q < 0)
1421 static int install_context_mark_for_removal(
1424 Set **remove_symlinks_to,
1425 const char *config_path,
1426 const char *root_dir) {
1433 assert(config_path);
1435 /* Marks all items for removal */
1437 while ((i = hashmap_first(c->will_install))) {
1439 q = hashmap_ensure_allocated(&c->have_installed, &string_hash_ops);
1443 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1445 q = unit_file_search(c, i, paths, root_dir, false);
1456 if (unit_name_is_instance(i->name)) {
1460 unit_file = basename(i->path);
1462 if (unit_name_is_instance(unit_file))
1463 /* unit file named as instance exists, thus all symlinks
1464 * pointing to it will be removed */
1465 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1467 /* does not exist, thus we will mark for removal symlinks
1468 * to template unit file */
1469 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1471 /* If i->path is not set, it means that we didn't actually find
1472 * the unit file. But we can still remove symlinks to the
1473 * nonexistent template. */
1474 unit_file = unit_name_template(i->name);
1478 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1482 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1484 if (r >= 0 && q < 0)
1491 int unit_file_enable(
1492 UnitFileScope scope,
1494 const char *root_dir,
1497 UnitFileChange **changes,
1498 unsigned *n_changes) {
1500 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1501 _cleanup_(install_context_done) InstallContext c = {};
1503 _cleanup_free_ char *config_path = NULL;
1507 assert(scope < _UNIT_FILE_SCOPE_MAX);
1509 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1513 r = get_config_path(scope, runtime, root_dir, &config_path);
1517 STRV_FOREACH(i, files) {
1518 r = install_info_add_auto(&c, *i);
1523 /* This will return the number of symlink rules that were
1524 supposed to be created, not the ones actually created. This is
1525 useful to determine whether the passed files had any
1526 installation data at all. */
1528 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1531 int unit_file_disable(
1532 UnitFileScope scope,
1534 const char *root_dir,
1536 UnitFileChange **changes,
1537 unsigned *n_changes) {
1539 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1540 _cleanup_(install_context_done) InstallContext c = {};
1542 _cleanup_free_ char *config_path = NULL;
1543 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1547 assert(scope < _UNIT_FILE_SCOPE_MAX);
1549 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1553 r = get_config_path(scope, runtime, root_dir, &config_path);
1557 STRV_FOREACH(i, files) {
1558 r = install_info_add_auto(&c, *i);
1563 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1565 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1572 int unit_file_reenable(
1573 UnitFileScope scope,
1575 const char *root_dir,
1578 UnitFileChange **changes,
1579 unsigned *n_changes) {
1582 r = unit_file_disable(scope, runtime, root_dir, files,
1583 changes, n_changes);
1587 return unit_file_enable(scope, runtime, root_dir, files, force,
1588 changes, n_changes);
1591 int unit_file_set_default(
1592 UnitFileScope scope,
1593 const char *root_dir,
1596 UnitFileChange **changes,
1597 unsigned *n_changes) {
1599 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1600 _cleanup_(install_context_done) InstallContext c = {};
1601 _cleanup_free_ char *config_path = NULL;
1604 InstallInfo *i = NULL;
1607 assert(scope < _UNIT_FILE_SCOPE_MAX);
1610 if (unit_name_to_type(file) != UNIT_TARGET)
1613 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1617 r = get_config_path(scope, false, root_dir, &config_path);
1621 r = install_info_add_auto(&c, file);
1625 assert_se(i = hashmap_first(c.will_install));
1627 r = unit_file_search(&c, i, &paths, root_dir, false);
1631 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1633 r = create_symlink(i->path, path, force, changes, n_changes);
1640 int unit_file_get_default(
1641 UnitFileScope scope,
1642 const char *root_dir,
1645 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1650 assert(scope < _UNIT_FILE_SCOPE_MAX);
1653 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1657 STRV_FOREACH(p, paths.unit_path) {
1658 _cleanup_free_ char *path = NULL, *tmp = NULL;
1661 path = path_join(root_dir, *p, SPECIAL_DEFAULT_TARGET);
1665 r = readlink_malloc(path, &tmp);
1668 else if (r == -EINVAL)
1670 n = strdup(SPECIAL_DEFAULT_TARGET);
1674 n = strdup(basename(tmp));
1686 UnitFileState unit_file_get_state(
1687 UnitFileScope scope,
1688 const char *root_dir,
1691 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1692 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1694 _cleanup_free_ char *path = NULL;
1698 assert(scope < _UNIT_FILE_SCOPE_MAX);
1701 if (root_dir && scope != UNIT_FILE_SYSTEM)
1704 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1707 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1711 STRV_FOREACH(i, paths.unit_path) {
1718 path = path_join(root_dir, *i, name);
1723 partial = path + strlen(root_dir);
1728 * Search for a unit file in our default paths, to
1729 * be sure, that there are no broken symlinks.
1731 if (lstat(path, &st) < 0) {
1733 if (errno != ENOENT)
1736 if (!unit_name_is_instance(name))
1739 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1742 r = null_or_empty_path(path);
1743 if (r < 0 && r != -ENOENT)
1746 state = path_startswith(*i, "/run") ?
1747 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1752 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1758 r = unit_file_can_install(&paths, root_dir, partial, true);
1759 if (r < 0 && errno != ENOENT)
1762 return UNIT_FILE_DISABLED;
1764 return UNIT_FILE_STATIC;
1767 return r < 0 ? r : state;
1770 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
1771 _cleanup_strv_free_ char **files = NULL;
1776 assert(scope < _UNIT_FILE_SCOPE_MAX);
1779 if (scope == UNIT_FILE_SYSTEM)
1780 r = conf_files_list(&files, ".preset", root_dir,
1781 "/etc/systemd/system-preset",
1782 "/usr/local/lib/systemd/system-preset",
1783 "/usr/lib/systemd/system-preset",
1784 #ifdef HAVE_SPLIT_USR
1785 "/lib/systemd/system-preset",
1788 else if (scope == UNIT_FILE_GLOBAL)
1789 r = conf_files_list(&files, ".preset", root_dir,
1790 "/etc/systemd/user-preset",
1791 "/usr/local/lib/systemd/user-preset",
1792 "/usr/lib/systemd/user-preset",
1800 STRV_FOREACH(p, files) {
1801 _cleanup_fclose_ FILE *f;
1803 f = fopen(*p, "re");
1805 if (errno == ENOENT)
1812 char line[LINE_MAX], *l;
1814 if (!fgets(line, sizeof(line), f))
1821 if (strchr(COMMENTS "\n", *l))
1824 if (first_word(l, "enable")) {
1826 l += strspn(l, WHITESPACE);
1828 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1829 log_debug("Preset file says enable %s.", name);
1833 } else if (first_word(l, "disable")) {
1835 l += strspn(l, WHITESPACE);
1837 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1838 log_debug("Preset file says disable %s.", name);
1843 log_debug("Couldn't parse line '%s'", l);
1847 /* Default is "enable" */
1848 log_debug("Preset file doesn't say anything about %s, enabling.", name);
1852 int unit_file_preset(
1853 UnitFileScope scope,
1855 const char *root_dir,
1857 UnitFilePresetMode mode,
1859 UnitFileChange **changes,
1860 unsigned *n_changes) {
1862 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
1863 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1864 _cleanup_free_ char *config_path = NULL;
1869 assert(scope < _UNIT_FILE_SCOPE_MAX);
1870 assert(mode < _UNIT_FILE_PRESET_MAX);
1872 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1876 r = get_config_path(scope, runtime, root_dir, &config_path);
1880 STRV_FOREACH(i, files) {
1882 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1885 r = unit_file_query_preset(scope, root_dir, *i);
1889 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1890 r = install_info_add_auto(&plus, *i);
1891 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1892 r = install_info_add_auto(&minus, *i);
1901 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1902 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1904 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1906 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1911 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1912 /* Returns number of symlinks that where supposed to be installed. */
1913 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1921 int unit_file_preset_all(
1922 UnitFileScope scope,
1924 const char *root_dir,
1925 UnitFilePresetMode mode,
1927 UnitFileChange **changes,
1928 unsigned *n_changes) {
1930 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
1931 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1932 _cleanup_free_ char *config_path = NULL;
1937 assert(scope < _UNIT_FILE_SCOPE_MAX);
1938 assert(mode < _UNIT_FILE_PRESET_MAX);
1940 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1944 r = get_config_path(scope, runtime, root_dir, &config_path);
1948 STRV_FOREACH(i, paths.unit_path) {
1949 _cleanup_closedir_ DIR *d = NULL;
1950 _cleanup_free_ char *units_dir;
1952 units_dir = path_join(root_dir, *i, NULL);
1956 d = opendir(units_dir);
1958 if (errno == ENOENT)
1969 if (!de && errno != 0)
1975 if (ignore_file(de->d_name))
1978 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1981 dirent_ensure_type(d, de);
1983 if (de->d_type != DT_REG)
1986 r = unit_file_query_preset(scope, root_dir, de->d_name);
1990 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1991 r = install_info_add_auto(&plus, de->d_name);
1992 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1993 r = install_info_add_auto(&minus, de->d_name);
2003 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2004 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2006 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
2008 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
2013 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2014 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2022 static void unit_file_list_free_one(UnitFileList *f) {
2030 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one);
2032 int unit_file_get_list(
2033 UnitFileScope scope,
2034 const char *root_dir,
2037 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2042 assert(scope < _UNIT_FILE_SCOPE_MAX);
2045 if (root_dir && scope != UNIT_FILE_SYSTEM)
2049 r = access(root_dir, F_OK);
2054 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2058 STRV_FOREACH(i, paths.unit_path) {
2059 _cleanup_closedir_ DIR *d = NULL;
2060 _cleanup_free_ char *units_dir;
2062 units_dir = path_join(root_dir, *i, NULL);
2066 d = opendir(units_dir);
2068 if (errno == ENOENT)
2075 _cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL;
2077 _cleanup_free_ char *path = NULL;
2081 if (!de && errno != 0)
2087 if (ignore_file(de->d_name))
2090 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2093 if (hashmap_get(h, de->d_name))
2096 dirent_ensure_type(d, de);
2098 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2101 f = new0(UnitFileList, 1);
2105 f->path = path_make_absolute(de->d_name, units_dir);
2109 r = null_or_empty_path(f->path);
2110 if (r < 0 && r != -ENOENT)
2114 path_startswith(*i, "/run") ?
2115 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2119 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2123 f->state = UNIT_FILE_ENABLED;
2127 path = path_make_absolute(de->d_name, *i);
2131 r = unit_file_can_install(&paths, root_dir, path, true);
2132 if (r == -EINVAL || /* Invalid setting? */
2133 r == -EBADMSG || /* Invalid format? */
2134 r == -ENOENT /* Included file not found? */)
2135 f->state = UNIT_FILE_INVALID;
2139 f->state = UNIT_FILE_DISABLED;
2141 f->state = UNIT_FILE_STATIC;
2144 r = hashmap_put(h, basename(f->path), f);
2147 f = NULL; /* prevent cleanup */
2154 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2155 [UNIT_FILE_ENABLED] = "enabled",
2156 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2157 [UNIT_FILE_LINKED] = "linked",
2158 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2159 [UNIT_FILE_MASKED] = "masked",
2160 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2161 [UNIT_FILE_STATIC] = "static",
2162 [UNIT_FILE_DISABLED] = "disabled",
2163 [UNIT_FILE_INVALID] = "invalid",
2166 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2168 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2169 [UNIT_FILE_SYMLINK] = "symlink",
2170 [UNIT_FILE_UNLINK] = "unlink",
2173 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2175 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = {
2176 [UNIT_FILE_PRESET_FULL] = "full",
2177 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2178 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2181 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);