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_func, string_compare_func);
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_func, string_compare_func);
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))
1031 free(i->default_instance);
1032 i->default_instance = printed;
1037 static int unit_file_load(
1041 const char *root_dir,
1042 bool allow_symlink) {
1044 const ConfigTableItem items[] = {
1045 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
1046 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1047 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1048 { "Install", "DefaultInstance", config_parse_default_instance, 0, info },
1049 { "Install", "Also", config_parse_also, 0, c },
1050 { "Exec", "User", config_parse_user, 0, info },
1054 _cleanup_fclose_ FILE *f = NULL;
1061 if (!isempty(root_dir))
1062 path = strappenda(root_dir, "/", path);
1064 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1068 f = fdopen(fd, "re");
1074 r = config_parse(NULL, path, f,
1076 config_item_table_lookup, items,
1077 true, true, false, info);
1082 (int) strv_length(info->aliases) +
1083 (int) strv_length(info->wanted_by) +
1084 (int) strv_length(info->required_by);
1087 static int unit_file_search(
1091 const char *root_dir,
1092 bool allow_symlink) {
1102 return unit_file_load(c, info, info->path, root_dir, allow_symlink);
1106 STRV_FOREACH(p, paths->unit_path) {
1107 _cleanup_free_ char *path = NULL;
1109 path = strjoin(*p, "/", info->name, NULL);
1113 r = unit_file_load(c, info, path, root_dir, allow_symlink);
1119 if (r != -ENOENT && r != -ELOOP)
1123 if (unit_name_is_instance(info->name)) {
1125 /* Unit file doesn't exist, however instance
1126 * enablement was requested. We will check if it is
1127 * possible to load template unit file. */
1129 _cleanup_free_ char *template = NULL;
1131 template = unit_name_template(info->name);
1135 STRV_FOREACH(p, paths->unit_path) {
1136 _cleanup_free_ char *path = NULL;
1138 path = strjoin(*p, "/", template, NULL);
1142 r = unit_file_load(c, info, path, root_dir, allow_symlink);
1148 if (r != -ENOENT && r != -ELOOP)
1156 static int unit_file_can_install(
1158 const char *root_dir,
1160 bool allow_symlink) {
1162 _cleanup_(install_context_done) InstallContext c = {};
1169 r = install_info_add_auto(&c, name);
1173 assert_se(i = hashmap_first(c.will_install));
1175 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1179 (int) strv_length(i->aliases) +
1180 (int) strv_length(i->wanted_by) +
1181 (int) strv_length(i->required_by);
1186 static int create_symlink(
1187 const char *old_path,
1188 const char *new_path,
1190 UnitFileChange **changes,
1191 unsigned *n_changes) {
1193 _cleanup_free_ char *dest = NULL;
1199 mkdir_parents_label(new_path, 0755);
1201 if (symlink(old_path, new_path) >= 0) {
1202 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1206 if (errno != EEXIST)
1209 r = readlink_and_make_absolute(new_path, &dest);
1213 if (path_equal(dest, old_path))
1219 r = symlink_atomic(old_path, new_path);
1223 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1224 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1229 static int install_info_symlink_alias(
1231 const char *config_path,
1233 UnitFileChange **changes,
1234 unsigned *n_changes) {
1240 assert(config_path);
1242 STRV_FOREACH(s, i->aliases) {
1243 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1245 q = install_full_printf(i, *s, &dst);
1249 alias_path = path_make_absolute(dst, config_path);
1253 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1261 static int install_info_symlink_wants(
1263 const char *config_path,
1267 UnitFileChange **changes,
1268 unsigned *n_changes) {
1270 _cleanup_free_ char *buf = NULL;
1276 assert(config_path);
1278 if (unit_name_is_template(i->name)) {
1280 /* Don't install any symlink if there's no default
1281 * instance configured */
1283 if (!i->default_instance)
1286 buf = unit_name_replace_instance(i->name, i->default_instance);
1294 STRV_FOREACH(s, list) {
1295 _cleanup_free_ char *path = NULL, *dst = NULL;
1297 q = install_full_printf(i, *s, &dst);
1301 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1306 path = strjoin(config_path, "/", dst, suffix, n, NULL);
1310 q = create_symlink(i->path, path, force, changes, n_changes);
1318 static int install_info_symlink_link(
1321 const char *config_path,
1322 const char *root_dir,
1324 UnitFileChange **changes,
1325 unsigned *n_changes) {
1327 _cleanup_free_ char *path = NULL;
1332 assert(config_path);
1335 r = in_search_path(i->path, paths->unit_path);
1339 path = strjoin(config_path, "/", i->name, NULL);
1343 return create_symlink(i->path, path, force, changes, n_changes);
1346 static int install_info_apply(
1349 const char *config_path,
1350 const char *root_dir,
1352 UnitFileChange **changes,
1353 unsigned *n_changes) {
1359 assert(config_path);
1361 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1363 q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes);
1367 q = install_info_symlink_wants(i, config_path, i->required_by, ".requires/", force, changes, n_changes);
1371 q = install_info_symlink_link(i, paths, config_path, root_dir, force, changes, n_changes);
1378 static int install_context_apply(
1381 const char *config_path,
1382 const char *root_dir,
1384 UnitFileChange **changes,
1385 unsigned *n_changes) {
1392 assert(config_path);
1394 while ((i = hashmap_first(c->will_install))) {
1396 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1400 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1402 q = unit_file_search(c, i, paths, root_dir, false);
1411 q = install_info_apply(i, paths, config_path, root_dir, force, changes, n_changes);
1412 if (r >= 0 && q < 0)
1419 static int install_context_mark_for_removal(
1422 Set **remove_symlinks_to,
1423 const char *config_path,
1424 const char *root_dir) {
1431 assert(config_path);
1433 /* Marks all items for removal */
1435 while ((i = hashmap_first(c->will_install))) {
1437 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1441 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1443 q = unit_file_search(c, i, paths, root_dir, false);
1454 if (unit_name_is_instance(i->name)) {
1458 unit_file = basename(i->path);
1460 if (unit_name_is_instance(unit_file))
1461 /* unit file named as instance exists, thus all symlinks
1462 * pointing to it will be removed */
1463 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1465 /* does not exist, thus we will mark for removal symlinks
1466 * to template unit file */
1467 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1469 /* If i->path is not set, it means that we didn't actually find
1470 * the unit file. But we can still remove symlinks to the
1471 * nonexistent template. */
1472 unit_file = unit_name_template(i->name);
1476 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1480 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1482 if (r >= 0 && q < 0)
1489 int unit_file_enable(
1490 UnitFileScope scope,
1492 const char *root_dir,
1495 UnitFileChange **changes,
1496 unsigned *n_changes) {
1498 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1499 _cleanup_(install_context_done) InstallContext c = {};
1501 _cleanup_free_ char *config_path = NULL;
1505 assert(scope < _UNIT_FILE_SCOPE_MAX);
1507 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1511 r = get_config_path(scope, runtime, root_dir, &config_path);
1515 STRV_FOREACH(i, files) {
1516 r = install_info_add_auto(&c, *i);
1521 /* This will return the number of symlink rules that were
1522 supposed to be created, not the ones actually created. This is
1523 useful to determine whether the passed files had any
1524 installation data at all. */
1526 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1529 int unit_file_disable(
1530 UnitFileScope scope,
1532 const char *root_dir,
1534 UnitFileChange **changes,
1535 unsigned *n_changes) {
1537 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1538 _cleanup_(install_context_done) InstallContext c = {};
1540 _cleanup_free_ char *config_path = NULL;
1541 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1545 assert(scope < _UNIT_FILE_SCOPE_MAX);
1547 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1551 r = get_config_path(scope, runtime, root_dir, &config_path);
1555 STRV_FOREACH(i, files) {
1556 r = install_info_add_auto(&c, *i);
1561 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1563 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1570 int unit_file_reenable(
1571 UnitFileScope scope,
1573 const char *root_dir,
1576 UnitFileChange **changes,
1577 unsigned *n_changes) {
1580 r = unit_file_disable(scope, runtime, root_dir, files,
1581 changes, n_changes);
1585 return unit_file_enable(scope, runtime, root_dir, files, force,
1586 changes, n_changes);
1589 int unit_file_set_default(
1590 UnitFileScope scope,
1591 const char *root_dir,
1594 UnitFileChange **changes,
1595 unsigned *n_changes) {
1597 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1598 _cleanup_(install_context_done) InstallContext c = {};
1599 _cleanup_free_ char *config_path = NULL;
1602 InstallInfo *i = NULL;
1605 assert(scope < _UNIT_FILE_SCOPE_MAX);
1608 if (unit_name_to_type(file) != UNIT_TARGET)
1611 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1615 r = get_config_path(scope, false, root_dir, &config_path);
1619 r = install_info_add_auto(&c, file);
1623 assert_se(i = hashmap_first(c.will_install));
1625 r = unit_file_search(&c, i, &paths, root_dir, false);
1629 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1631 r = create_symlink(i->path, path, force, changes, n_changes);
1638 int unit_file_get_default(
1639 UnitFileScope scope,
1640 const char *root_dir,
1643 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1648 assert(scope < _UNIT_FILE_SCOPE_MAX);
1651 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1655 STRV_FOREACH(p, paths.unit_path) {
1656 _cleanup_free_ char *path = NULL, *tmp = NULL;
1659 path = path_join(root_dir, *p, SPECIAL_DEFAULT_TARGET);
1663 r = readlink_malloc(path, &tmp);
1666 else if (r == -EINVAL)
1668 n = strdup(SPECIAL_DEFAULT_TARGET);
1672 n = strdup(basename(tmp));
1684 UnitFileState unit_file_get_state(
1685 UnitFileScope scope,
1686 const char *root_dir,
1689 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1690 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1692 _cleanup_free_ char *path = NULL;
1696 assert(scope < _UNIT_FILE_SCOPE_MAX);
1699 if (root_dir && scope != UNIT_FILE_SYSTEM)
1702 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1705 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1709 STRV_FOREACH(i, paths.unit_path) {
1716 path = path_join(root_dir, *i, name);
1721 partial = path + strlen(root_dir);
1726 * Search for a unit file in our default paths, to
1727 * be sure, that there are no broken symlinks.
1729 if (lstat(path, &st) < 0) {
1731 if (errno != ENOENT)
1734 if (!unit_name_is_instance(name))
1737 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1740 r = null_or_empty_path(path);
1741 if (r < 0 && r != -ENOENT)
1744 state = path_startswith(*i, "/run") ?
1745 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1750 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1756 r = unit_file_can_install(&paths, root_dir, partial, true);
1757 if (r < 0 && errno != ENOENT)
1760 return UNIT_FILE_DISABLED;
1762 return UNIT_FILE_STATIC;
1765 return r < 0 ? r : state;
1768 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
1769 _cleanup_strv_free_ char **files = NULL;
1774 assert(scope < _UNIT_FILE_SCOPE_MAX);
1777 if (scope == UNIT_FILE_SYSTEM)
1778 r = conf_files_list(&files, ".preset", root_dir,
1779 "/etc/systemd/system-preset",
1780 "/usr/local/lib/systemd/system-preset",
1781 "/usr/lib/systemd/system-preset",
1782 #ifdef HAVE_SPLIT_USR
1783 "/lib/systemd/system-preset",
1786 else if (scope == UNIT_FILE_GLOBAL)
1787 r = conf_files_list(&files, ".preset", root_dir,
1788 "/etc/systemd/user-preset",
1789 "/usr/local/lib/systemd/user-preset",
1790 "/usr/lib/systemd/user-preset",
1798 STRV_FOREACH(p, files) {
1799 _cleanup_fclose_ FILE *f;
1801 f = fopen(*p, "re");
1803 if (errno == ENOENT)
1810 char line[LINE_MAX], *l;
1812 if (!fgets(line, sizeof(line), f))
1819 if (strchr(COMMENTS "\n", *l))
1822 if (first_word(l, "enable")) {
1824 l += strspn(l, WHITESPACE);
1826 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1827 log_debug("Preset file says enable %s.", name);
1831 } else if (first_word(l, "disable")) {
1833 l += strspn(l, WHITESPACE);
1835 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1836 log_debug("Preset file says disable %s.", name);
1841 log_debug("Couldn't parse line '%s'", l);
1845 /* Default is "enable" */
1846 log_debug("Preset file doesn't say anything about %s, enabling.", name);
1850 int unit_file_preset(
1851 UnitFileScope scope,
1853 const char *root_dir,
1855 UnitFilePresetMode mode,
1857 UnitFileChange **changes,
1858 unsigned *n_changes) {
1860 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
1861 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1862 _cleanup_free_ char *config_path = NULL;
1867 assert(scope < _UNIT_FILE_SCOPE_MAX);
1868 assert(mode < _UNIT_FILE_PRESET_MAX);
1870 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1874 r = get_config_path(scope, runtime, root_dir, &config_path);
1878 STRV_FOREACH(i, files) {
1880 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1883 r = unit_file_query_preset(scope, root_dir, *i);
1887 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1888 r = install_info_add_auto(&plus, *i);
1889 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1890 r = install_info_add_auto(&minus, *i);
1899 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1900 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1902 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1904 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1909 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1910 /* Returns number of symlinks that where supposed to be installed. */
1911 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1919 int unit_file_preset_all(
1920 UnitFileScope scope,
1922 const char *root_dir,
1923 UnitFilePresetMode mode,
1925 UnitFileChange **changes,
1926 unsigned *n_changes) {
1928 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
1929 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1930 _cleanup_free_ char *config_path = NULL;
1935 assert(scope < _UNIT_FILE_SCOPE_MAX);
1936 assert(mode < _UNIT_FILE_PRESET_MAX);
1938 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1942 r = get_config_path(scope, runtime, root_dir, &config_path);
1946 STRV_FOREACH(i, paths.unit_path) {
1947 _cleanup_closedir_ DIR *d = NULL;
1948 _cleanup_free_ char *units_dir;
1950 units_dir = path_join(root_dir, *i, NULL);
1954 d = opendir(units_dir);
1956 if (errno == ENOENT)
1967 if (!de && errno != 0)
1973 if (ignore_file(de->d_name))
1976 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1979 dirent_ensure_type(d, de);
1981 if (de->d_type != DT_REG)
1984 r = unit_file_query_preset(scope, root_dir, de->d_name);
1988 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1989 r = install_info_add_auto(&plus, de->d_name);
1990 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1991 r = install_info_add_auto(&minus, de->d_name);
2001 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2002 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2004 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
2006 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
2011 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2012 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2020 static void unit_file_list_free_one(UnitFileList *f) {
2028 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one);
2030 int unit_file_get_list(
2031 UnitFileScope scope,
2032 const char *root_dir,
2035 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2040 assert(scope < _UNIT_FILE_SCOPE_MAX);
2043 if (root_dir && scope != UNIT_FILE_SYSTEM)
2047 r = access(root_dir, F_OK);
2052 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2056 STRV_FOREACH(i, paths.unit_path) {
2057 _cleanup_closedir_ DIR *d = NULL;
2058 _cleanup_free_ char *units_dir;
2060 units_dir = path_join(root_dir, *i, NULL);
2064 d = opendir(units_dir);
2066 if (errno == ENOENT)
2073 _cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL;
2075 _cleanup_free_ char *path = NULL;
2079 if (!de && errno != 0)
2085 if (ignore_file(de->d_name))
2088 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2091 if (hashmap_get(h, de->d_name))
2094 dirent_ensure_type(d, de);
2096 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2099 f = new0(UnitFileList, 1);
2103 f->path = path_make_absolute(de->d_name, units_dir);
2107 r = null_or_empty_path(f->path);
2108 if (r < 0 && r != -ENOENT)
2112 path_startswith(*i, "/run") ?
2113 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2117 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2121 f->state = UNIT_FILE_ENABLED;
2125 path = path_make_absolute(de->d_name, *i);
2129 r = unit_file_can_install(&paths, root_dir, path, true);
2130 if (r == -EINVAL || /* Invalid setting? */
2131 r == -EBADMSG || /* Invalid format? */
2132 r == -ENOENT /* Included file not found? */)
2133 f->state = UNIT_FILE_INVALID;
2137 f->state = UNIT_FILE_DISABLED;
2139 f->state = UNIT_FILE_STATIC;
2142 r = hashmap_put(h, basename(f->path), f);
2145 f = NULL; /* prevent cleanup */
2152 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2153 [UNIT_FILE_ENABLED] = "enabled",
2154 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2155 [UNIT_FILE_LINKED] = "linked",
2156 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2157 [UNIT_FILE_MASKED] = "masked",
2158 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2159 [UNIT_FILE_STATIC] = "static",
2160 [UNIT_FILE_DISABLED] = "disabled",
2161 [UNIT_FILE_INVALID] = "invalid",
2164 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2166 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2167 [UNIT_FILE_SYMLINK] = "symlink",
2168 [UNIT_FILE_UNLINK] = "unlink",
2171 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2173 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = {
2174 [UNIT_FILE_PRESET_FULL] = "full",
2175 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2176 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2179 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);