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);
164 c[i].source = strdup(source);
176 static int mark_symlink_for_removal(
177 Set **remove_symlinks_to,
185 r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
193 path_kill_slashes(n);
195 r = set_consume(*remove_symlinks_to, n);
197 return r == -EEXIST ? 0 : r;
202 static int remove_marked_symlinks_fd(
203 Set *remove_symlinks_to,
206 const char *config_path,
208 UnitFileChange **changes,
210 char** instance_whitelist) {
212 _cleanup_closedir_ DIR *d = NULL;
215 assert(remove_symlinks_to);
234 if (!de && errno != 0) {
242 if (ignore_file(de->d_name))
245 dirent_ensure_type(d, de);
247 if (de->d_type == DT_DIR) {
249 _cleanup_free_ char *p = NULL;
251 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
261 p = path_make_absolute(de->d_name, path);
267 /* This will close nfd, regardless whether it succeeds or not */
268 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, instance_whitelist);
272 } else if (de->d_type == DT_LNK) {
273 _cleanup_free_ char *p = NULL, *dest = NULL;
277 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
280 if (unit_name_is_instance(de->d_name) &&
281 instance_whitelist &&
282 !strv_contains(instance_whitelist, de->d_name)) {
284 _cleanup_free_ char *w;
286 /* OK, the file is not listed directly
287 * in the whitelist, so let's check if
288 * the template of it might be
291 w = unit_name_template(de->d_name);
295 if (!strv_contains(instance_whitelist, w))
299 p = path_make_absolute(de->d_name, path);
303 q = readlink_and_canonicalize(p, &dest);
314 set_get(remove_symlinks_to, dest) ||
315 set_get(remove_symlinks_to, basename(dest));
320 if (unlink(p) < 0 && errno != ENOENT) {
326 path_kill_slashes(p);
327 rmdir_parents(p, config_path);
328 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
330 if (!set_get(remove_symlinks_to, p)) {
332 q = mark_symlink_for_removal(&remove_symlinks_to, p);
345 static int remove_marked_symlinks(
346 Set *remove_symlinks_to,
347 const char *config_path,
348 UnitFileChange **changes,
350 char** instance_whitelist) {
352 _cleanup_close_ int fd = -1;
358 if (set_size(remove_symlinks_to) <= 0)
361 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
369 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
375 /* This takes possession of cfd and closes it */
376 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist);
384 static int find_symlinks_fd(
388 const char *config_path,
389 bool *same_name_link) {
392 _cleanup_closedir_ DIR *d = NULL;
398 assert(same_name_link);
411 if (!de && errno != 0)
417 if (ignore_file(de->d_name))
420 dirent_ensure_type(d, de);
422 if (de->d_type == DT_DIR) {
424 _cleanup_free_ char *p = NULL;
426 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
436 p = path_make_absolute(de->d_name, path);
442 /* This will close nfd, regardless whether it succeeds or not */
443 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
449 } else if (de->d_type == DT_LNK) {
450 _cleanup_free_ char *p = NULL, *dest = NULL;
451 bool found_path, found_dest, b = false;
454 /* Acquire symlink name */
455 p = path_make_absolute(de->d_name, path);
459 /* Acquire symlink destination */
460 q = readlink_and_canonicalize(p, &dest);
470 /* Check if the symlink itself matches what we
472 if (path_is_absolute(name))
473 found_path = path_equal(p, name);
475 found_path = streq(de->d_name, name);
477 /* Check if what the symlink points to
478 * matches what we are looking for */
479 if (path_is_absolute(name))
480 found_dest = path_equal(dest, name);
482 found_dest = streq(basename(dest), name);
484 if (found_path && found_dest) {
485 _cleanup_free_ char *t = NULL;
487 /* Filter out same name links in the main
489 t = path_make_absolute(name, config_path);
493 b = path_equal(t, p);
497 *same_name_link = true;
498 else if (found_path || found_dest)
504 static int find_symlinks(
506 const char *config_path,
507 bool *same_name_link) {
513 assert(same_name_link);
515 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
522 /* This takes possession of fd and closes it */
523 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
526 static int find_symlinks_in_scope(
528 const char *root_dir,
530 UnitFileState *state) {
533 _cleanup_free_ char *path2 = NULL;
534 bool same_name_link_runtime = false, same_name_link = false;
537 assert(scope < _UNIT_FILE_SCOPE_MAX);
540 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
541 _cleanup_free_ char *path = NULL;
543 /* First look in runtime config path */
544 r = get_config_path(scope, true, root_dir, &path);
548 r = find_symlinks(name, path, &same_name_link_runtime);
552 *state = UNIT_FILE_ENABLED_RUNTIME;
557 /* Then look in the normal config path */
558 r = get_config_path(scope, false, root_dir, &path2);
562 r = find_symlinks(name, path2, &same_name_link);
566 *state = UNIT_FILE_ENABLED;
570 /* Hmm, we didn't find it, but maybe we found the same name
572 if (same_name_link_runtime) {
573 *state = UNIT_FILE_LINKED_RUNTIME;
575 } else if (same_name_link) {
576 *state = UNIT_FILE_LINKED;
586 const char *root_dir,
589 UnitFileChange **changes,
590 unsigned *n_changes) {
593 _cleanup_free_ char *prefix = NULL;
597 assert(scope < _UNIT_FILE_SCOPE_MAX);
599 r = get_config_path(scope, runtime, root_dir, &prefix);
603 STRV_FOREACH(i, files) {
604 _cleanup_free_ char *path = NULL;
606 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
612 path = path_make_absolute(*i, prefix);
618 if (symlink("/dev/null", path) >= 0) {
619 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
623 if (errno == EEXIST) {
625 if (null_or_empty_path(path) > 0)
629 if (symlink_atomic("/dev/null", path) >= 0) {
630 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
631 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
647 int unit_file_unmask(
650 const char *root_dir,
652 UnitFileChange **changes,
653 unsigned *n_changes) {
655 char **i, *config_path = NULL;
657 Set *remove_symlinks_to = NULL;
660 assert(scope < _UNIT_FILE_SCOPE_MAX);
662 r = get_config_path(scope, runtime, root_dir, &config_path);
666 STRV_FOREACH(i, files) {
669 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
675 path = path_make_absolute(*i, config_path);
681 q = null_or_empty_path(path);
683 if (unlink(path) >= 0) {
684 mark_symlink_for_removal(&remove_symlinks_to, path);
685 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
694 if (q != -ENOENT && r == 0)
702 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
706 set_free_free(remove_symlinks_to);
715 const char *root_dir,
718 UnitFileChange **changes,
719 unsigned *n_changes) {
721 _cleanup_lookup_paths_free_ LookupPaths paths = {};
723 _cleanup_free_ char *config_path = NULL;
727 assert(scope < _UNIT_FILE_SCOPE_MAX);
729 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
733 r = get_config_path(scope, runtime, root_dir, &config_path);
737 STRV_FOREACH(i, files) {
738 _cleanup_free_ char *path = NULL;
744 if (!path_is_absolute(*i) ||
745 !unit_name_is_valid(fn, TEMPLATE_VALID)) {
751 if (lstat(*i, &st) < 0) {
757 if (!S_ISREG(st.st_mode)) {
762 q = in_search_path(*i, paths.unit_path);
769 path = path_make_absolute(fn, config_path);
773 if (symlink(*i, path) >= 0) {
774 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
778 if (errno == EEXIST) {
779 _cleanup_free_ char *dest = NULL;
781 q = readlink_and_make_absolute(path, &dest);
782 if (q < 0 && errno != ENOENT) {
788 if (q >= 0 && path_equal(dest, *i))
792 if (symlink_atomic(*i, path) >= 0) {
793 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
794 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
810 void unit_file_list_free(Hashmap *h) {
813 while ((i = hashmap_steal_first(h))) {
821 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
824 assert(changes || n_changes == 0);
829 for (i = 0; i < n_changes; i++) {
830 free(changes[i].path);
831 free(changes[i].source);
837 static void install_info_free(InstallInfo *i) {
842 strv_free(i->aliases);
843 strv_free(i->wanted_by);
844 strv_free(i->required_by);
845 free(i->default_instance);
849 static void install_info_hashmap_free(Hashmap *m) {
855 while ((i = hashmap_steal_first(m)))
856 install_info_free(i);
861 static void install_context_done(InstallContext *c) {
864 install_info_hashmap_free(c->will_install);
865 install_info_hashmap_free(c->have_installed);
867 c->will_install = c->have_installed = NULL;
870 static int install_info_add(
874 InstallInfo *i = NULL;
878 assert(name || path);
881 name = basename(path);
883 if (!unit_name_is_valid(name, TEMPLATE_VALID))
886 if (hashmap_get(c->have_installed, name) ||
887 hashmap_get(c->will_install, name))
890 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
894 i = new0(InstallInfo, 1);
898 i->name = strdup(name);
905 i->path = strdup(path);
912 r = hashmap_put(c->will_install, i->name, i);
920 install_info_free(i);
925 static int install_info_add_auto(
927 const char *name_or_path) {
930 assert(name_or_path);
932 if (path_is_absolute(name_or_path))
933 return install_info_add(c, NULL, name_or_path);
935 return install_info_add(c, name_or_path, NULL);
938 static int config_parse_also(
940 const char *filename,
943 unsigned section_line,
953 InstallContext *c = data;
959 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
960 _cleanup_free_ char *n;
967 r = install_info_add(c, n, NULL);
975 static int config_parse_user(
977 const char *filename,
980 unsigned section_line,
987 InstallInfo *i = data;
995 r = install_full_printf(i, rvalue, &printed);
1005 static int config_parse_default_instance(
1007 const char *filename,
1009 const char *section,
1010 unsigned section_line,
1017 InstallInfo *i = data;
1025 r = install_full_printf(i, rvalue, &printed);
1029 if (!unit_instance_is_valid(printed))
1032 free(i->default_instance);
1033 i->default_instance = printed;
1038 static int unit_file_load(
1042 const char *root_dir,
1043 bool allow_symlink) {
1045 const ConfigTableItem items[] = {
1046 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
1047 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1048 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1049 { "Install", "DefaultInstance", config_parse_default_instance, 0, info },
1050 { "Install", "Also", config_parse_also, 0, c },
1051 { "Exec", "User", config_parse_user, 0, info },
1055 _cleanup_fclose_ FILE *f = NULL;
1062 if (!isempty(root_dir))
1063 path = strappenda3(root_dir, "/", path);
1065 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1069 f = fdopen(fd, "re");
1075 r = config_parse(NULL, path, f, NULL, config_item_table_lookup, (void*) items, true, true, info);
1080 (int) strv_length(info->aliases) +
1081 (int) strv_length(info->wanted_by) +
1082 (int) strv_length(info->required_by);
1085 static int unit_file_search(
1089 const char *root_dir,
1090 bool allow_symlink) {
1100 return unit_file_load(c, info, info->path, root_dir, allow_symlink);
1104 STRV_FOREACH(p, paths->unit_path) {
1105 _cleanup_free_ char *path = NULL;
1107 path = strjoin(*p, "/", info->name, NULL);
1111 r = unit_file_load(c, info, path, root_dir, allow_symlink);
1117 if (r != -ENOENT && r != -ELOOP)
1121 if (unit_name_is_instance(info->name)) {
1123 /* Unit file doesn't exist, however instance
1124 * enablement was requested. We will check if it is
1125 * possible to load template unit file. */
1127 _cleanup_free_ char *template = NULL, *template_dir = NULL;
1129 template = unit_name_template(info->name);
1133 STRV_FOREACH(p, paths->unit_path) {
1134 _cleanup_free_ char *path = NULL;
1136 path = strjoin(*p, "/", template, NULL);
1140 r = unit_file_load(c, info, path, root_dir, allow_symlink);
1146 if (r != -ENOENT && r != -ELOOP)
1154 static int unit_file_can_install(
1156 const char *root_dir,
1158 bool allow_symlink) {
1160 _cleanup_install_context_done_ InstallContext c = {};
1167 r = install_info_add_auto(&c, name);
1171 assert_se(i = hashmap_first(c.will_install));
1173 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1177 (int) strv_length(i->aliases) +
1178 (int) strv_length(i->wanted_by) +
1179 (int) strv_length(i->required_by);
1184 static int create_symlink(
1185 const char *old_path,
1186 const char *new_path,
1188 UnitFileChange **changes,
1189 unsigned *n_changes) {
1191 _cleanup_free_ char *dest = NULL;
1197 mkdir_parents_label(new_path, 0755);
1199 if (symlink(old_path, new_path) >= 0) {
1200 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1204 if (errno != EEXIST)
1207 r = readlink_and_make_absolute(new_path, &dest);
1211 if (path_equal(dest, old_path))
1217 r = symlink_atomic(old_path, new_path);
1221 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1222 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1227 static int install_info_symlink_alias(
1229 const char *config_path,
1231 UnitFileChange **changes,
1232 unsigned *n_changes) {
1238 assert(config_path);
1240 STRV_FOREACH(s, i->aliases) {
1241 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1243 q = install_full_printf(i, *s, &dst);
1247 alias_path = path_make_absolute(dst, config_path);
1251 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1259 static int install_info_symlink_wants(
1261 const char *config_path,
1265 UnitFileChange **changes,
1266 unsigned *n_changes) {
1268 _cleanup_free_ char *buf = NULL;
1274 assert(config_path);
1276 if (unit_name_is_template(i->name)) {
1278 /* Don't install any symlink if there's no default
1279 * instance configured */
1281 if (!i->default_instance)
1284 buf = unit_name_replace_instance(i->name, i->default_instance);
1292 STRV_FOREACH(s, list) {
1293 _cleanup_free_ char *path = NULL, *dst = NULL;
1295 q = install_full_printf(i, *s, &dst);
1299 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1304 path = strjoin(config_path, "/", dst, suffix, n, NULL);
1308 q = create_symlink(i->path, path, force, changes, n_changes);
1316 static int install_info_symlink_link(
1319 const char *config_path,
1320 const char *root_dir,
1322 UnitFileChange **changes,
1323 unsigned *n_changes) {
1325 _cleanup_free_ char *path = NULL;
1330 assert(config_path);
1333 r = in_search_path(i->path, paths->unit_path);
1337 path = strjoin(config_path, "/", i->name, NULL);
1341 return create_symlink(i->path, path, force, changes, n_changes);
1344 static int install_info_apply(
1347 const char *config_path,
1348 const char *root_dir,
1350 UnitFileChange **changes,
1351 unsigned *n_changes) {
1357 assert(config_path);
1359 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1361 q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes);
1365 q = install_info_symlink_wants(i, config_path, i->required_by, ".requires/", force, changes, n_changes);
1369 q = install_info_symlink_link(i, paths, config_path, root_dir, force, changes, n_changes);
1376 static int install_context_apply(
1379 const char *config_path,
1380 const char *root_dir,
1382 UnitFileChange **changes,
1383 unsigned *n_changes) {
1390 assert(config_path);
1392 while ((i = hashmap_first(c->will_install))) {
1394 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1398 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1400 q = unit_file_search(c, i, paths, root_dir, false);
1409 q = install_info_apply(i, paths, config_path, root_dir, force, changes, n_changes);
1410 if (r >= 0 && q < 0)
1417 static int install_context_mark_for_removal(
1420 Set **remove_symlinks_to,
1421 const char *config_path,
1422 const char *root_dir) {
1429 assert(config_path);
1431 /* Marks all items for removal */
1433 while ((i = hashmap_first(c->will_install))) {
1435 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1439 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1441 q = unit_file_search(c, i, paths, root_dir, false);
1452 if (unit_name_is_instance(i->name)) {
1456 unit_file = basename(i->path);
1458 if (unit_name_is_instance(unit_file))
1459 /* unit file named as instance exists, thus all symlinks
1460 * pointing to it will be removed */
1461 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1463 /* does not exist, thus we will mark for removal symlinks
1464 * to template unit file */
1465 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1467 /* If i->path is not set, it means that we didn't actually find
1468 * the unit file. But we can still remove symlinks to the
1469 * nonexistent template. */
1470 unit_file = unit_name_template(i->name);
1474 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1478 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1480 if (r >= 0 && q < 0)
1487 int unit_file_enable(
1488 UnitFileScope scope,
1490 const char *root_dir,
1493 UnitFileChange **changes,
1494 unsigned *n_changes) {
1496 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1497 _cleanup_install_context_done_ InstallContext c = {};
1499 _cleanup_free_ char *config_path = NULL;
1503 assert(scope < _UNIT_FILE_SCOPE_MAX);
1505 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1509 r = get_config_path(scope, runtime, root_dir, &config_path);
1513 STRV_FOREACH(i, files) {
1514 r = install_info_add_auto(&c, *i);
1519 /* This will return the number of symlink rules that were
1520 supposed to be created, not the ones actually created. This is
1521 useful to determine whether the passed files had any
1522 installation data at all. */
1524 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1527 int unit_file_disable(
1528 UnitFileScope scope,
1530 const char *root_dir,
1532 UnitFileChange **changes,
1533 unsigned *n_changes) {
1535 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1536 _cleanup_install_context_done_ InstallContext c = {};
1538 _cleanup_free_ char *config_path = NULL;
1539 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1543 assert(scope < _UNIT_FILE_SCOPE_MAX);
1545 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1549 r = get_config_path(scope, runtime, root_dir, &config_path);
1553 STRV_FOREACH(i, files) {
1554 r = install_info_add_auto(&c, *i);
1559 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1561 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1568 int unit_file_reenable(
1569 UnitFileScope scope,
1571 const char *root_dir,
1574 UnitFileChange **changes,
1575 unsigned *n_changes) {
1578 r = unit_file_disable(scope, runtime, root_dir, files,
1579 changes, n_changes);
1583 return unit_file_enable(scope, runtime, root_dir, files, force,
1584 changes, n_changes);
1587 int unit_file_set_default(
1588 UnitFileScope scope,
1589 const char *root_dir,
1592 UnitFileChange **changes,
1593 unsigned *n_changes) {
1595 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1596 _cleanup_install_context_done_ InstallContext c = {};
1597 _cleanup_free_ char *config_path = NULL;
1600 InstallInfo *i = NULL;
1603 assert(scope < _UNIT_FILE_SCOPE_MAX);
1606 if (unit_name_to_type(file) != UNIT_TARGET)
1609 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1613 r = get_config_path(scope, false, root_dir, &config_path);
1617 r = install_info_add_auto(&c, file);
1621 assert_se(i = hashmap_first(c.will_install));
1623 r = unit_file_search(&c, i, &paths, root_dir, false);
1627 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1629 r = create_symlink(i->path, path, force, changes, n_changes);
1636 int unit_file_get_default(
1637 UnitFileScope scope,
1638 const char *root_dir,
1641 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1646 assert(scope < _UNIT_FILE_SCOPE_MAX);
1649 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1653 STRV_FOREACH(p, paths.unit_path) {
1654 _cleanup_free_ char *path = NULL, *tmp = NULL;
1657 if (isempty(root_dir))
1658 path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
1660 path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
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) {
1719 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1721 asprintf(&path, "%s/%s", *i, name);
1726 partial = path + strlen(root_dir) + 1;
1731 * Search for a unit file in our default paths, to
1732 * be sure, that there are no broken symlinks.
1734 if (lstat(path, &st) < 0) {
1736 if (errno != ENOENT)
1739 if (!unit_name_is_instance(name))
1742 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1745 r = null_or_empty_path(path);
1746 if (r < 0 && r != -ENOENT)
1749 state = path_startswith(*i, "/run") ?
1750 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1755 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1761 r = unit_file_can_install(&paths, root_dir, partial, true);
1762 if (r < 0 && errno != ENOENT)
1765 return UNIT_FILE_DISABLED;
1767 return UNIT_FILE_STATIC;
1770 return r < 0 ? r : state;
1773 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
1774 _cleanup_strv_free_ char **files = NULL;
1779 assert(scope < _UNIT_FILE_SCOPE_MAX);
1782 if (scope == UNIT_FILE_SYSTEM)
1783 r = conf_files_list(&files, ".preset", root_dir,
1784 "/etc/systemd/system-preset",
1785 "/usr/local/lib/systemd/system-preset",
1786 "/usr/lib/systemd/system-preset",
1787 #ifdef HAVE_SPLIT_USR
1788 "/lib/systemd/system-preset",
1791 else if (scope == UNIT_FILE_GLOBAL)
1792 r = conf_files_list(&files, ".preset", root_dir,
1793 "/etc/systemd/user-preset",
1794 "/usr/local/lib/systemd/user-preset",
1795 "/usr/lib/systemd/user-preset",
1803 STRV_FOREACH(i, files) {
1804 _cleanup_free_ char *buf = NULL;
1805 _cleanup_fclose_ FILE *f;
1809 p = buf = strjoin(root_dir, "/", *i, NULL);
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_MODE_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_MODE_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_MODE_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);