1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty <of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
32 #include "path-util.h"
33 #include "path-lookup.h"
35 #include "unit-name.h"
37 #include "conf-parser.h"
38 #include "conf-files.h"
39 #include "specifier.h"
40 #include "install-printf.h"
44 Hashmap *will_install;
45 Hashmap *have_installed;
48 #define _cleanup_install_context_done_ _cleanup_(install_context_done)
50 static int in_search_path(const char *path, char **search) {
51 _cleanup_free_ char *parent = NULL;
56 r = path_get_parent(path, &parent);
60 return strv_contains(search, parent);
63 static int lookup_paths_init_from_scope(LookupPaths *paths,
65 const char *root_dir) {
68 assert(scope < _UNIT_FILE_SCOPE_MAX);
72 return lookup_paths_init(paths,
73 scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
74 scope == UNIT_FILE_USER,
79 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
84 assert(scope < _UNIT_FILE_SCOPE_MAX);
89 case UNIT_FILE_SYSTEM:
91 if (root_dir && runtime)
92 asprintf(&p, "%s/run/systemd/system", root_dir);
94 p = strdup("/run/systemd/system");
96 asprintf(&p, "%s/%s", root_dir, SYSTEM_CONFIG_UNIT_PATH);
98 p = strdup(SYSTEM_CONFIG_UNIT_PATH);
102 case UNIT_FILE_GLOBAL:
108 p = strdup("/run/systemd/user");
110 p = strdup(USER_CONFIG_UNIT_PATH);
115 if (root_dir || runtime)
118 r = user_config_home(&p);
120 return r < 0 ? r : -ENOENT;
125 assert_not_reached("Bad scope");
135 static int add_file_change(
136 UnitFileChange **changes,
138 UnitFileChangeType type,
140 const char *source) {
146 assert(!changes == !n_changes);
151 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
159 c[i].path = strdup(path);
163 path_kill_slashes(c[i].path);
166 c[i].source = strdup(source);
172 path_kill_slashes(c[i].path);
180 static int mark_symlink_for_removal(
181 Set **remove_symlinks_to,
189 r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
197 path_kill_slashes(n);
199 r = set_consume(*remove_symlinks_to, n);
201 return r == -EEXIST ? 0 : r;
206 static int remove_marked_symlinks_fd(
207 Set *remove_symlinks_to,
210 const char *config_path,
212 UnitFileChange **changes,
214 char** instance_whitelist) {
216 _cleanup_closedir_ DIR *d = NULL;
219 assert(remove_symlinks_to);
238 if (!de && errno != 0) {
246 if (ignore_file(de->d_name))
249 dirent_ensure_type(d, de);
251 if (de->d_type == DT_DIR) {
253 _cleanup_free_ char *p = NULL;
255 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
265 p = path_make_absolute(de->d_name, path);
271 /* This will close nfd, regardless whether it succeeds or not */
272 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, instance_whitelist);
276 } else if (de->d_type == DT_LNK) {
277 _cleanup_free_ char *p = NULL, *dest = NULL;
281 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
284 if (unit_name_is_instance(de->d_name) &&
285 instance_whitelist &&
286 !strv_contains(instance_whitelist, de->d_name)) {
288 _cleanup_free_ char *w;
290 /* OK, the file is not listed directly
291 * in the whitelist, so let's check if
292 * the template of it might be
295 w = unit_name_template(de->d_name);
299 if (!strv_contains(instance_whitelist, w))
303 p = path_make_absolute(de->d_name, path);
307 q = readlink_and_canonicalize(p, &dest);
318 set_get(remove_symlinks_to, dest) ||
319 set_get(remove_symlinks_to, basename(dest));
324 if (unlink(p) < 0 && errno != ENOENT) {
330 path_kill_slashes(p);
331 rmdir_parents(p, config_path);
332 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
334 if (!set_get(remove_symlinks_to, p)) {
336 q = mark_symlink_for_removal(&remove_symlinks_to, p);
349 static int remove_marked_symlinks(
350 Set *remove_symlinks_to,
351 const char *config_path,
352 UnitFileChange **changes,
354 char** instance_whitelist) {
356 _cleanup_close_ int fd = -1;
362 if (set_size(remove_symlinks_to) <= 0)
365 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
373 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
379 /* This takes possession of cfd and closes it */
380 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist);
388 static int find_symlinks_fd(
392 const char *config_path,
393 bool *same_name_link) {
396 _cleanup_closedir_ DIR *d = NULL;
402 assert(same_name_link);
415 if (!de && errno != 0)
421 if (ignore_file(de->d_name))
424 dirent_ensure_type(d, de);
426 if (de->d_type == DT_DIR) {
428 _cleanup_free_ char *p = NULL;
430 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
440 p = path_make_absolute(de->d_name, path);
446 /* This will close nfd, regardless whether it succeeds or not */
447 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
453 } else if (de->d_type == DT_LNK) {
454 _cleanup_free_ char *p = NULL, *dest = NULL;
455 bool found_path, found_dest, b = false;
458 /* Acquire symlink name */
459 p = path_make_absolute(de->d_name, path);
463 /* Acquire symlink destination */
464 q = readlink_and_canonicalize(p, &dest);
474 /* Check if the symlink itself matches what we
476 if (path_is_absolute(name))
477 found_path = path_equal(p, name);
479 found_path = streq(de->d_name, name);
481 /* Check if what the symlink points to
482 * matches what we are looking for */
483 if (path_is_absolute(name))
484 found_dest = path_equal(dest, name);
486 found_dest = streq(basename(dest), name);
488 if (found_path && found_dest) {
489 _cleanup_free_ char *t = NULL;
491 /* Filter out same name links in the main
493 t = path_make_absolute(name, config_path);
497 b = path_equal(t, p);
501 *same_name_link = true;
502 else if (found_path || found_dest)
508 static int find_symlinks(
510 const char *config_path,
511 bool *same_name_link) {
517 assert(same_name_link);
519 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
526 /* This takes possession of fd and closes it */
527 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
530 static int find_symlinks_in_scope(
532 const char *root_dir,
534 UnitFileState *state) {
537 _cleanup_free_ char *path2 = NULL;
538 bool same_name_link_runtime = false, same_name_link = false;
541 assert(scope < _UNIT_FILE_SCOPE_MAX);
544 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
545 _cleanup_free_ char *path = NULL;
547 /* First look in runtime config path */
548 r = get_config_path(scope, true, root_dir, &path);
552 r = find_symlinks(name, path, &same_name_link_runtime);
556 *state = UNIT_FILE_ENABLED_RUNTIME;
561 /* Then look in the normal config path */
562 r = get_config_path(scope, false, root_dir, &path2);
566 r = find_symlinks(name, path2, &same_name_link);
570 *state = UNIT_FILE_ENABLED;
574 /* Hmm, we didn't find it, but maybe we found the same name
576 if (same_name_link_runtime) {
577 *state = UNIT_FILE_LINKED_RUNTIME;
579 } else if (same_name_link) {
580 *state = UNIT_FILE_LINKED;
590 const char *root_dir,
593 UnitFileChange **changes,
594 unsigned *n_changes) {
597 _cleanup_free_ char *prefix = NULL;
601 assert(scope < _UNIT_FILE_SCOPE_MAX);
603 r = get_config_path(scope, runtime, root_dir, &prefix);
607 STRV_FOREACH(i, files) {
608 _cleanup_free_ char *path = NULL;
610 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
616 path = path_make_absolute(*i, prefix);
622 if (symlink("/dev/null", path) >= 0) {
623 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
627 if (errno == EEXIST) {
629 if (null_or_empty_path(path) > 0)
633 if (symlink_atomic("/dev/null", path) >= 0) {
634 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
635 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
651 int unit_file_unmask(
654 const char *root_dir,
656 UnitFileChange **changes,
657 unsigned *n_changes) {
659 char **i, *config_path = NULL;
661 Set *remove_symlinks_to = NULL;
664 assert(scope < _UNIT_FILE_SCOPE_MAX);
666 r = get_config_path(scope, runtime, root_dir, &config_path);
670 STRV_FOREACH(i, files) {
673 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
679 path = path_make_absolute(*i, config_path);
685 q = null_or_empty_path(path);
687 if (unlink(path) >= 0) {
688 mark_symlink_for_removal(&remove_symlinks_to, path);
689 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
698 if (q != -ENOENT && r == 0)
706 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
710 set_free_free(remove_symlinks_to);
719 const char *root_dir,
722 UnitFileChange **changes,
723 unsigned *n_changes) {
725 _cleanup_lookup_paths_free_ LookupPaths paths = {};
727 _cleanup_free_ char *config_path = NULL;
731 assert(scope < _UNIT_FILE_SCOPE_MAX);
733 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
737 r = get_config_path(scope, runtime, root_dir, &config_path);
741 STRV_FOREACH(i, files) {
742 _cleanup_free_ char *path = NULL;
748 if (!path_is_absolute(*i) ||
749 !unit_name_is_valid(fn, TEMPLATE_VALID)) {
755 if (lstat(*i, &st) < 0) {
761 if (!S_ISREG(st.st_mode)) {
766 q = in_search_path(*i, paths.unit_path);
773 path = path_make_absolute(fn, config_path);
777 if (symlink(*i, path) >= 0) {
778 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
782 if (errno == EEXIST) {
783 _cleanup_free_ char *dest = NULL;
785 q = readlink_and_make_absolute(path, &dest);
786 if (q < 0 && errno != ENOENT) {
792 if (q >= 0 && path_equal(dest, *i))
796 if (symlink_atomic(*i, path) >= 0) {
797 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
798 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
814 void unit_file_list_free(Hashmap *h) {
817 while ((i = hashmap_steal_first(h))) {
825 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
828 assert(changes || n_changes == 0);
833 for (i = 0; i < n_changes; i++) {
834 free(changes[i].path);
835 free(changes[i].source);
841 static void install_info_free(InstallInfo *i) {
846 strv_free(i->aliases);
847 strv_free(i->wanted_by);
848 strv_free(i->required_by);
849 free(i->default_instance);
853 static void install_info_hashmap_free(Hashmap *m) {
859 while ((i = hashmap_steal_first(m)))
860 install_info_free(i);
865 static void install_context_done(InstallContext *c) {
868 install_info_hashmap_free(c->will_install);
869 install_info_hashmap_free(c->have_installed);
871 c->will_install = c->have_installed = NULL;
874 static int install_info_add(
878 InstallInfo *i = NULL;
882 assert(name || path);
885 name = basename(path);
887 if (!unit_name_is_valid(name, TEMPLATE_VALID))
890 if (hashmap_get(c->have_installed, name) ||
891 hashmap_get(c->will_install, name))
894 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
898 i = new0(InstallInfo, 1);
902 i->name = strdup(name);
909 i->path = strdup(path);
916 r = hashmap_put(c->will_install, i->name, i);
924 install_info_free(i);
929 static int install_info_add_auto(
931 const char *name_or_path) {
934 assert(name_or_path);
936 if (path_is_absolute(name_or_path))
937 return install_info_add(c, NULL, name_or_path);
939 return install_info_add(c, name_or_path, NULL);
942 static int config_parse_also(
944 const char *filename,
947 unsigned section_line,
957 InstallContext *c = data;
963 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
964 _cleanup_free_ char *n;
971 r = install_info_add(c, n, NULL);
979 static int config_parse_user(
981 const char *filename,
984 unsigned section_line,
991 InstallInfo *i = data;
999 r = install_full_printf(i, rvalue, &printed);
1009 static int config_parse_default_instance(
1011 const char *filename,
1013 const char *section,
1014 unsigned section_line,
1021 InstallInfo *i = data;
1029 r = install_full_printf(i, rvalue, &printed);
1033 if (!unit_instance_is_valid(printed))
1036 free(i->default_instance);
1037 i->default_instance = printed;
1042 static int unit_file_load(
1046 const char *root_dir,
1047 bool allow_symlink) {
1049 const ConfigTableItem items[] = {
1050 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
1051 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1052 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1053 { "Install", "DefaultInstance", config_parse_default_instance, 0, info },
1054 { "Install", "Also", config_parse_also, 0, c },
1055 { "Exec", "User", config_parse_user, 0, info },
1059 _cleanup_fclose_ FILE *f = NULL;
1066 if (!isempty(root_dir))
1067 path = strappenda3(root_dir, "/", path);
1069 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1073 f = fdopen(fd, "re");
1079 r = config_parse(NULL, path, f,
1081 config_item_table_lookup, items,
1082 true, true, false, info);
1087 (int) strv_length(info->aliases) +
1088 (int) strv_length(info->wanted_by) +
1089 (int) strv_length(info->required_by);
1092 static int unit_file_search(
1096 const char *root_dir,
1097 bool allow_symlink) {
1107 return unit_file_load(c, info, info->path, root_dir, allow_symlink);
1111 STRV_FOREACH(p, paths->unit_path) {
1112 _cleanup_free_ char *path = NULL;
1114 path = strjoin(*p, "/", info->name, NULL);
1118 r = unit_file_load(c, info, path, root_dir, allow_symlink);
1124 if (r != -ENOENT && r != -ELOOP)
1128 if (unit_name_is_instance(info->name)) {
1130 /* Unit file doesn't exist, however instance
1131 * enablement was requested. We will check if it is
1132 * possible to load template unit file. */
1134 _cleanup_free_ char *template = NULL;
1136 template = unit_name_template(info->name);
1140 STRV_FOREACH(p, paths->unit_path) {
1141 _cleanup_free_ char *path = NULL;
1143 path = strjoin(*p, "/", template, NULL);
1147 r = unit_file_load(c, info, path, root_dir, allow_symlink);
1153 if (r != -ENOENT && r != -ELOOP)
1161 static int unit_file_can_install(
1163 const char *root_dir,
1165 bool allow_symlink) {
1167 _cleanup_install_context_done_ InstallContext c = {};
1174 r = install_info_add_auto(&c, name);
1178 assert_se(i = hashmap_first(c.will_install));
1180 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1184 (int) strv_length(i->aliases) +
1185 (int) strv_length(i->wanted_by) +
1186 (int) strv_length(i->required_by);
1191 static int create_symlink(
1192 const char *old_path,
1193 const char *new_path,
1195 UnitFileChange **changes,
1196 unsigned *n_changes) {
1198 _cleanup_free_ char *dest = NULL;
1204 mkdir_parents_label(new_path, 0755);
1206 if (symlink(old_path, new_path) >= 0) {
1207 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1211 if (errno != EEXIST)
1214 r = readlink_and_make_absolute(new_path, &dest);
1218 if (path_equal(dest, old_path))
1224 r = symlink_atomic(old_path, new_path);
1228 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1229 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1234 static int install_info_symlink_alias(
1236 const char *config_path,
1238 UnitFileChange **changes,
1239 unsigned *n_changes) {
1245 assert(config_path);
1247 STRV_FOREACH(s, i->aliases) {
1248 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1250 q = install_full_printf(i, *s, &dst);
1254 alias_path = path_make_absolute(dst, config_path);
1258 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1266 static int install_info_symlink_wants(
1268 const char *config_path,
1272 UnitFileChange **changes,
1273 unsigned *n_changes) {
1275 _cleanup_free_ char *buf = NULL;
1281 assert(config_path);
1283 if (unit_name_is_template(i->name)) {
1285 /* Don't install any symlink if there's no default
1286 * instance configured */
1288 if (!i->default_instance)
1291 buf = unit_name_replace_instance(i->name, i->default_instance);
1299 STRV_FOREACH(s, list) {
1300 _cleanup_free_ char *path = NULL, *dst = NULL;
1302 q = install_full_printf(i, *s, &dst);
1306 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1311 path = strjoin(config_path, "/", dst, suffix, n, NULL);
1315 q = create_symlink(i->path, path, force, changes, n_changes);
1323 static int install_info_symlink_link(
1326 const char *config_path,
1327 const char *root_dir,
1329 UnitFileChange **changes,
1330 unsigned *n_changes) {
1332 _cleanup_free_ char *path = NULL;
1337 assert(config_path);
1340 r = in_search_path(i->path, paths->unit_path);
1344 path = strjoin(config_path, "/", i->name, NULL);
1348 return create_symlink(i->path, path, force, changes, n_changes);
1351 static int install_info_apply(
1354 const char *config_path,
1355 const char *root_dir,
1357 UnitFileChange **changes,
1358 unsigned *n_changes) {
1364 assert(config_path);
1366 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1368 q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes);
1372 q = install_info_symlink_wants(i, config_path, i->required_by, ".requires/", force, changes, n_changes);
1376 q = install_info_symlink_link(i, paths, config_path, root_dir, force, changes, n_changes);
1383 static int install_context_apply(
1386 const char *config_path,
1387 const char *root_dir,
1389 UnitFileChange **changes,
1390 unsigned *n_changes) {
1397 assert(config_path);
1399 while ((i = hashmap_first(c->will_install))) {
1401 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1405 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1407 q = unit_file_search(c, i, paths, root_dir, false);
1416 q = install_info_apply(i, paths, config_path, root_dir, force, changes, n_changes);
1417 if (r >= 0 && q < 0)
1424 static int install_context_mark_for_removal(
1427 Set **remove_symlinks_to,
1428 const char *config_path,
1429 const char *root_dir) {
1436 assert(config_path);
1438 /* Marks all items for removal */
1440 while ((i = hashmap_first(c->will_install))) {
1442 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1446 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1448 q = unit_file_search(c, i, paths, root_dir, false);
1459 if (unit_name_is_instance(i->name)) {
1463 unit_file = basename(i->path);
1465 if (unit_name_is_instance(unit_file))
1466 /* unit file named as instance exists, thus all symlinks
1467 * pointing to it will be removed */
1468 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1470 /* does not exist, thus we will mark for removal symlinks
1471 * to template unit file */
1472 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1474 /* If i->path is not set, it means that we didn't actually find
1475 * the unit file. But we can still remove symlinks to the
1476 * nonexistent template. */
1477 unit_file = unit_name_template(i->name);
1481 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1485 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1487 if (r >= 0 && q < 0)
1494 int unit_file_enable(
1495 UnitFileScope scope,
1497 const char *root_dir,
1500 UnitFileChange **changes,
1501 unsigned *n_changes) {
1503 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1504 _cleanup_install_context_done_ InstallContext c = {};
1506 _cleanup_free_ char *config_path = NULL;
1510 assert(scope < _UNIT_FILE_SCOPE_MAX);
1512 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1516 r = get_config_path(scope, runtime, root_dir, &config_path);
1520 STRV_FOREACH(i, files) {
1521 r = install_info_add_auto(&c, *i);
1526 /* This will return the number of symlink rules that were
1527 supposed to be created, not the ones actually created. This is
1528 useful to determine whether the passed files had any
1529 installation data at all. */
1531 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1534 int unit_file_disable(
1535 UnitFileScope scope,
1537 const char *root_dir,
1539 UnitFileChange **changes,
1540 unsigned *n_changes) {
1542 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1543 _cleanup_install_context_done_ InstallContext c = {};
1545 _cleanup_free_ char *config_path = NULL;
1546 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1550 assert(scope < _UNIT_FILE_SCOPE_MAX);
1552 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1556 r = get_config_path(scope, runtime, root_dir, &config_path);
1560 STRV_FOREACH(i, files) {
1561 r = install_info_add_auto(&c, *i);
1566 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1568 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1575 int unit_file_reenable(
1576 UnitFileScope scope,
1578 const char *root_dir,
1581 UnitFileChange **changes,
1582 unsigned *n_changes) {
1585 r = unit_file_disable(scope, runtime, root_dir, files,
1586 changes, n_changes);
1590 return unit_file_enable(scope, runtime, root_dir, files, force,
1591 changes, n_changes);
1594 int unit_file_set_default(
1595 UnitFileScope scope,
1596 const char *root_dir,
1599 UnitFileChange **changes,
1600 unsigned *n_changes) {
1602 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1603 _cleanup_install_context_done_ InstallContext c = {};
1604 _cleanup_free_ char *config_path = NULL;
1607 InstallInfo *i = NULL;
1610 assert(scope < _UNIT_FILE_SCOPE_MAX);
1613 if (unit_name_to_type(file) != UNIT_TARGET)
1616 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1620 r = get_config_path(scope, false, root_dir, &config_path);
1624 r = install_info_add_auto(&c, file);
1628 assert_se(i = hashmap_first(c.will_install));
1630 r = unit_file_search(&c, i, &paths, root_dir, false);
1634 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1636 r = create_symlink(i->path, path, force, changes, n_changes);
1643 int unit_file_get_default(
1644 UnitFileScope scope,
1645 const char *root_dir,
1648 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1653 assert(scope < _UNIT_FILE_SCOPE_MAX);
1656 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1660 STRV_FOREACH(p, paths.unit_path) {
1661 _cleanup_free_ char *path = NULL, *tmp = NULL;
1664 if (isempty(root_dir))
1665 path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
1667 path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
1672 r = readlink_malloc(path, &tmp);
1675 else if (r == -EINVAL)
1677 n = strdup(SPECIAL_DEFAULT_TARGET);
1681 n = strdup(basename(tmp));
1693 UnitFileState unit_file_get_state(
1694 UnitFileScope scope,
1695 const char *root_dir,
1698 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1699 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1701 _cleanup_free_ char *path = NULL;
1705 assert(scope < _UNIT_FILE_SCOPE_MAX);
1708 if (root_dir && scope != UNIT_FILE_SYSTEM)
1711 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1714 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1718 STRV_FOREACH(i, paths.unit_path) {
1726 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1728 asprintf(&path, "%s/%s", *i, name);
1733 partial = path + strlen(root_dir) + 1;
1738 * Search for a unit file in our default paths, to
1739 * be sure, that there are no broken symlinks.
1741 if (lstat(path, &st) < 0) {
1743 if (errno != ENOENT)
1746 if (!unit_name_is_instance(name))
1749 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1752 r = null_or_empty_path(path);
1753 if (r < 0 && r != -ENOENT)
1756 state = path_startswith(*i, "/run") ?
1757 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1762 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1768 r = unit_file_can_install(&paths, root_dir, partial, true);
1769 if (r < 0 && errno != ENOENT)
1772 return UNIT_FILE_DISABLED;
1774 return UNIT_FILE_STATIC;
1777 return r < 0 ? r : state;
1780 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
1781 _cleanup_strv_free_ char **files = NULL;
1786 assert(scope < _UNIT_FILE_SCOPE_MAX);
1789 if (scope == UNIT_FILE_SYSTEM)
1790 r = conf_files_list(&files, ".preset", root_dir,
1791 "/etc/systemd/system-preset",
1792 "/usr/local/lib/systemd/system-preset",
1793 "/usr/lib/systemd/system-preset",
1794 #ifdef HAVE_SPLIT_USR
1795 "/lib/systemd/system-preset",
1798 else if (scope == UNIT_FILE_GLOBAL)
1799 r = conf_files_list(&files, ".preset", root_dir,
1800 "/etc/systemd/user-preset",
1801 "/usr/local/lib/systemd/user-preset",
1802 "/usr/lib/systemd/user-preset",
1810 STRV_FOREACH(p, files) {
1811 _cleanup_fclose_ FILE *f;
1813 f = fopen(*p, "re");
1815 if (errno == ENOENT)
1822 char line[LINE_MAX], *l;
1824 if (!fgets(line, sizeof(line), f))
1831 if (strchr(COMMENTS "\n", *l))
1834 if (first_word(l, "enable")) {
1836 l += strspn(l, WHITESPACE);
1838 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1839 log_debug("Preset file says enable %s.", name);
1843 } else if (first_word(l, "disable")) {
1845 l += strspn(l, WHITESPACE);
1847 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1848 log_debug("Preset file says disable %s.", name);
1853 log_debug("Couldn't parse line '%s'", l);
1857 /* Default is "enable" */
1858 log_debug("Preset file doesn't say anything about %s, enabling.", name);
1862 int unit_file_preset(
1863 UnitFileScope scope,
1865 const char *root_dir,
1867 UnitFilePresetMode mode,
1869 UnitFileChange **changes,
1870 unsigned *n_changes) {
1872 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1873 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1874 _cleanup_free_ char *config_path = NULL;
1879 assert(scope < _UNIT_FILE_SCOPE_MAX);
1880 assert(mode < _UNIT_FILE_PRESET_MAX);
1882 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1886 r = get_config_path(scope, runtime, root_dir, &config_path);
1890 STRV_FOREACH(i, files) {
1892 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1895 r = unit_file_query_preset(scope, root_dir, *i);
1899 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1900 r = install_info_add_auto(&plus, *i);
1901 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1902 r = install_info_add_auto(&minus, *i);
1911 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1912 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1914 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1916 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1921 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1922 /* Returns number of symlinks that where supposed to be installed. */
1923 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1931 int unit_file_preset_all(
1932 UnitFileScope scope,
1934 const char *root_dir,
1935 UnitFilePresetMode mode,
1937 UnitFileChange **changes,
1938 unsigned *n_changes) {
1940 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1941 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1942 _cleanup_free_ char *config_path = NULL;
1947 assert(scope < _UNIT_FILE_SCOPE_MAX);
1948 assert(mode < _UNIT_FILE_PRESET_MAX);
1950 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1954 r = get_config_path(scope, runtime, root_dir, &config_path);
1958 STRV_FOREACH(i, paths.unit_path) {
1959 _cleanup_closedir_ DIR *d = NULL;
1960 _cleanup_free_ char *buf = NULL;
1961 const char *units_dir;
1963 if (!isempty(root_dir)) {
1964 buf = strjoin(root_dir, "/", *i, NULL);
1972 d = opendir(units_dir);
1974 if (errno == ENOENT)
1985 if (!de && errno != 0)
1991 if (ignore_file(de->d_name))
1994 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1997 dirent_ensure_type(d, de);
1999 if (de->d_type != DT_REG)
2002 r = unit_file_query_preset(scope, root_dir, de->d_name);
2006 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
2007 r = install_info_add_auto(&plus, de->d_name);
2008 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
2009 r = install_info_add_auto(&minus, de->d_name);
2019 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2020 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2022 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
2024 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
2029 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2030 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2038 static void unitfilelist_free(UnitFileList **f) {
2045 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
2047 int unit_file_get_list(
2048 UnitFileScope scope,
2049 const char *root_dir,
2052 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2057 assert(scope < _UNIT_FILE_SCOPE_MAX);
2060 if (root_dir && scope != UNIT_FILE_SYSTEM)
2063 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2067 STRV_FOREACH(i, paths.unit_path) {
2068 _cleanup_closedir_ DIR *d = NULL;
2069 _cleanup_free_ char *buf = NULL;
2070 const char *units_dir;
2072 if (!isempty(root_dir)) {
2073 buf = strjoin(root_dir, "/", *i, NULL);
2081 d = opendir(units_dir);
2083 if (errno == ENOENT)
2090 _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
2095 if (!de && errno != 0)
2101 if (ignore_file(de->d_name))
2104 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2107 if (hashmap_get(h, de->d_name))
2110 dirent_ensure_type(d, de);
2112 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2115 f = new0(UnitFileList, 1);
2119 f->path = path_make_absolute(de->d_name, units_dir);
2123 r = null_or_empty_path(f->path);
2124 if (r < 0 && r != -ENOENT)
2128 path_startswith(*i, "/run") ?
2129 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2133 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2137 f->state = UNIT_FILE_ENABLED;
2141 r = unit_file_can_install(&paths, root_dir, f->path, true);
2142 if (r == -EINVAL || /* Invalid setting? */
2143 r == -EBADMSG || /* Invalid format? */
2144 r == -ENOENT /* Included file not found? */)
2145 f->state = UNIT_FILE_INVALID;
2149 f->state = UNIT_FILE_DISABLED;
2151 f->state = UNIT_FILE_STATIC;
2154 r = hashmap_put(h, basename(f->path), f);
2157 f = NULL; /* prevent cleanup */
2164 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2165 [UNIT_FILE_ENABLED] = "enabled",
2166 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2167 [UNIT_FILE_LINKED] = "linked",
2168 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2169 [UNIT_FILE_MASKED] = "masked",
2170 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2171 [UNIT_FILE_STATIC] = "static",
2172 [UNIT_FILE_DISABLED] = "disabled",
2173 [UNIT_FILE_INVALID] = "invalid",
2176 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2178 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2179 [UNIT_FILE_SYMLINK] = "symlink",
2180 [UNIT_FILE_UNLINK] = "unlink",
2183 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2185 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = {
2186 [UNIT_FILE_PRESET_FULL] = "full",
2187 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2188 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2191 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);