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, const char *root_dir) {
51 _cleanup_free_ char *parent = NULL;
57 r = path_get_parent(path, &parent);
61 STRV_FOREACH(i, search) {
62 _cleanup_free_ char *buf = NULL;
66 buf = strjoin(root_dir, "/", *i, NULL);
74 if (path_equal(parent, p))
81 static int lookup_paths_init_from_scope(LookupPaths *paths,
83 const char *root_dir) {
86 assert(scope < _UNIT_FILE_SCOPE_MAX);
90 return lookup_paths_init(paths,
91 scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
92 scope == UNIT_FILE_USER,
97 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
102 assert(scope < _UNIT_FILE_SCOPE_MAX);
107 case UNIT_FILE_SYSTEM:
109 if (root_dir && runtime)
110 asprintf(&p, "%s/run/systemd/system", root_dir);
112 p = strdup("/run/systemd/system");
114 asprintf(&p, "%s/%s", root_dir, SYSTEM_CONFIG_UNIT_PATH);
116 p = strdup(SYSTEM_CONFIG_UNIT_PATH);
120 case UNIT_FILE_GLOBAL:
126 p = strdup("/run/systemd/user");
128 p = strdup(USER_CONFIG_UNIT_PATH);
133 if (root_dir || runtime)
136 r = user_config_home(&p);
138 return r < 0 ? r : -ENOENT;
143 assert_not_reached("Bad scope");
153 static int add_file_change(
154 UnitFileChange **changes,
156 UnitFileChangeType type,
158 const char *source) {
164 assert(!changes == !n_changes);
169 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
177 c[i].path = strdup(path);
182 c[i].source = strdup(source);
194 static int mark_symlink_for_removal(
195 Set **remove_symlinks_to,
203 r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
211 path_kill_slashes(n);
213 r = set_consume(*remove_symlinks_to, n);
215 return r == -EEXIST ? 0 : r;
220 static int remove_marked_symlinks_fd(
221 Set *remove_symlinks_to,
224 const char *config_path,
226 UnitFileChange **changes,
228 char** instance_whitelist) {
230 _cleanup_closedir_ DIR *d = NULL;
233 assert(remove_symlinks_to);
252 if (!de && errno != 0) {
260 if (ignore_file(de->d_name))
263 dirent_ensure_type(d, de);
265 if (de->d_type == DT_DIR) {
267 _cleanup_free_ char *p = NULL;
269 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
279 p = path_make_absolute(de->d_name, path);
285 /* This will close nfd, regardless whether it succeeds or not */
286 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, instance_whitelist);
290 } else if (de->d_type == DT_LNK) {
291 _cleanup_free_ char *p = NULL, *dest = NULL;
295 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
298 if (unit_name_is_instance(de->d_name) &&
299 instance_whitelist &&
300 !strv_contains(instance_whitelist, de->d_name)) {
302 _cleanup_free_ char *w;
304 /* OK, the file is not listed directly
305 * in the whitelist, so let's check if
306 * the template of it might be
309 w = unit_name_template(de->d_name);
313 if (!strv_contains(instance_whitelist, w))
317 p = path_make_absolute(de->d_name, path);
321 q = readlink_and_canonicalize(p, &dest);
332 set_get(remove_symlinks_to, dest) ||
333 set_get(remove_symlinks_to, basename(dest));
338 if (unlink(p) < 0 && errno != ENOENT) {
344 path_kill_slashes(p);
345 rmdir_parents(p, config_path);
346 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
348 if (!set_get(remove_symlinks_to, p)) {
350 q = mark_symlink_for_removal(&remove_symlinks_to, p);
363 static int remove_marked_symlinks(
364 Set *remove_symlinks_to,
365 const char *config_path,
366 UnitFileChange **changes,
368 char** instance_whitelist) {
370 _cleanup_close_ int fd = -1;
376 if (set_size(remove_symlinks_to) <= 0)
379 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
387 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
393 /* This takes possession of cfd and closes it */
394 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist);
402 static int find_symlinks_fd(
406 const char *config_path,
407 bool *same_name_link) {
410 _cleanup_closedir_ DIR *d = NULL;
416 assert(same_name_link);
429 if (!de && errno != 0)
435 if (ignore_file(de->d_name))
438 dirent_ensure_type(d, de);
440 if (de->d_type == DT_DIR) {
442 _cleanup_free_ char *p = NULL;
444 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
454 p = path_make_absolute(de->d_name, path);
460 /* This will close nfd, regardless whether it succeeds or not */
461 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
467 } else if (de->d_type == DT_LNK) {
468 _cleanup_free_ char *p = NULL, *dest = NULL;
469 bool found_path, found_dest, b = false;
472 /* Acquire symlink name */
473 p = path_make_absolute(de->d_name, path);
477 /* Acquire symlink destination */
478 q = readlink_and_canonicalize(p, &dest);
488 /* Check if the symlink itself matches what we
490 if (path_is_absolute(name))
491 found_path = path_equal(p, name);
493 found_path = streq(de->d_name, name);
495 /* Check if what the symlink points to
496 * matches what we are looking for */
497 if (path_is_absolute(name))
498 found_dest = path_equal(dest, name);
500 found_dest = streq(basename(dest), name);
502 if (found_path && found_dest) {
503 _cleanup_free_ char *t = NULL;
505 /* Filter out same name links in the main
507 t = path_make_absolute(name, config_path);
511 b = path_equal(t, p);
515 *same_name_link = true;
516 else if (found_path || found_dest)
522 static int find_symlinks(
524 const char *config_path,
525 bool *same_name_link) {
531 assert(same_name_link);
533 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
540 /* This takes possession of fd and closes it */
541 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
544 static int find_symlinks_in_scope(
546 const char *root_dir,
548 UnitFileState *state) {
551 _cleanup_free_ char *path2 = NULL;
552 bool same_name_link_runtime = false, same_name_link = false;
555 assert(scope < _UNIT_FILE_SCOPE_MAX);
558 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
559 _cleanup_free_ char *path = NULL;
561 /* First look in runtime config path */
562 r = get_config_path(scope, true, root_dir, &path);
566 r = find_symlinks(name, path, &same_name_link_runtime);
570 *state = UNIT_FILE_ENABLED_RUNTIME;
575 /* Then look in the normal config path */
576 r = get_config_path(scope, false, root_dir, &path2);
580 r = find_symlinks(name, path2, &same_name_link);
584 *state = UNIT_FILE_ENABLED;
588 /* Hmm, we didn't find it, but maybe we found the same name
590 if (same_name_link_runtime) {
591 *state = UNIT_FILE_LINKED_RUNTIME;
593 } else if (same_name_link) {
594 *state = UNIT_FILE_LINKED;
604 const char *root_dir,
607 UnitFileChange **changes,
608 unsigned *n_changes) {
611 _cleanup_free_ char *prefix = NULL;
615 assert(scope < _UNIT_FILE_SCOPE_MAX);
617 r = get_config_path(scope, runtime, root_dir, &prefix);
621 STRV_FOREACH(i, files) {
622 _cleanup_free_ char *path = NULL;
624 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
630 path = path_make_absolute(*i, prefix);
636 if (symlink("/dev/null", path) >= 0) {
637 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
641 if (errno == EEXIST) {
643 if (null_or_empty_path(path) > 0)
647 if (symlink_atomic("/dev/null", path) >= 0) {
648 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
649 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
665 int unit_file_unmask(
668 const char *root_dir,
670 UnitFileChange **changes,
671 unsigned *n_changes) {
673 char **i, *config_path = NULL;
675 Set *remove_symlinks_to = NULL;
678 assert(scope < _UNIT_FILE_SCOPE_MAX);
680 r = get_config_path(scope, runtime, root_dir, &config_path);
684 STRV_FOREACH(i, files) {
687 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
693 path = path_make_absolute(*i, config_path);
699 q = null_or_empty_path(path);
701 if (unlink(path) >= 0) {
702 mark_symlink_for_removal(&remove_symlinks_to, path);
703 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
712 if (q != -ENOENT && r == 0)
720 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
724 set_free_free(remove_symlinks_to);
733 const char *root_dir,
736 UnitFileChange **changes,
737 unsigned *n_changes) {
739 _cleanup_lookup_paths_free_ LookupPaths paths = {};
741 _cleanup_free_ char *config_path = NULL;
745 assert(scope < _UNIT_FILE_SCOPE_MAX);
747 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
751 r = get_config_path(scope, runtime, root_dir, &config_path);
755 STRV_FOREACH(i, files) {
756 _cleanup_free_ char *path = NULL;
762 if (!path_is_absolute(*i) ||
763 !unit_name_is_valid(fn, TEMPLATE_VALID)) {
769 if (lstat(*i, &st) < 0) {
775 if (!S_ISREG(st.st_mode)) {
780 q = in_search_path(*i, paths.unit_path, root_dir);
787 path = path_make_absolute(fn, config_path);
791 if (symlink(*i, path) >= 0) {
792 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
796 if (errno == EEXIST) {
797 _cleanup_free_ char *dest = NULL;
799 q = readlink_and_make_absolute(path, &dest);
800 if (q < 0 && errno != ENOENT) {
806 if (q >= 0 && path_equal(dest, *i))
810 if (symlink_atomic(*i, path) >= 0) {
811 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
812 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
828 void unit_file_list_free(Hashmap *h) {
831 while ((i = hashmap_steal_first(h))) {
839 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
842 assert(changes || n_changes == 0);
847 for (i = 0; i < n_changes; i++) {
848 free(changes[i].path);
849 free(changes[i].source);
855 static void install_info_free(InstallInfo *i) {
860 strv_free(i->aliases);
861 strv_free(i->wanted_by);
862 strv_free(i->required_by);
863 free(i->default_instance);
867 static void install_info_hashmap_free(Hashmap *m) {
873 while ((i = hashmap_steal_first(m)))
874 install_info_free(i);
879 static void install_context_done(InstallContext *c) {
882 install_info_hashmap_free(c->will_install);
883 install_info_hashmap_free(c->have_installed);
885 c->will_install = c->have_installed = NULL;
888 static int install_info_add(
892 InstallInfo *i = NULL;
896 assert(name || path);
899 name = basename(path);
901 if (!unit_name_is_valid(name, TEMPLATE_VALID))
904 if (hashmap_get(c->have_installed, name) ||
905 hashmap_get(c->will_install, name))
908 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
912 i = new0(InstallInfo, 1);
916 i->name = strdup(name);
923 i->path = strdup(path);
930 r = hashmap_put(c->will_install, i->name, i);
938 install_info_free(i);
943 static int install_info_add_auto(
945 const char *name_or_path) {
948 assert(name_or_path);
950 if (path_is_absolute(name_or_path))
951 return install_info_add(c, NULL, name_or_path);
953 return install_info_add(c, name_or_path, NULL);
956 static int config_parse_also(
958 const char *filename,
961 unsigned section_line,
971 InstallContext *c = data;
977 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
978 _cleanup_free_ char *n;
985 r = install_info_add(c, n, NULL);
993 static int config_parse_user(
995 const char *filename,
998 unsigned section_line,
1005 InstallInfo *i = data;
1013 r = install_full_printf(i, rvalue, &printed);
1023 static int config_parse_default_instance(
1025 const char *filename,
1027 const char *section,
1028 unsigned section_line,
1035 InstallInfo *i = data;
1043 r = install_full_printf(i, rvalue, &printed);
1047 if (!unit_instance_is_valid(printed))
1050 free(i->default_instance);
1051 i->default_instance = printed;
1056 static int unit_file_load(
1060 bool allow_symlink) {
1062 const ConfigTableItem items[] = {
1063 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
1064 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1065 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1066 { "Install", "DefaultInstance", config_parse_default_instance, 0, info },
1067 { "Install", "Also", config_parse_also, 0, c },
1068 { "Exec", "User", config_parse_user, 0, info },
1073 _cleanup_fclose_ FILE *f = NULL;
1080 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1084 f = fdopen(fd, "re");
1090 r = config_parse(NULL, path, f, NULL, config_item_table_lookup, (void*) items, true, true, info);
1095 (int) strv_length(info->aliases) +
1096 (int) strv_length(info->wanted_by) +
1097 (int) strv_length(info->required_by);
1100 static int unit_file_search(
1104 const char *root_dir,
1105 bool allow_symlink) {
1117 if (isempty(root_dir))
1120 path = strappenda(root_dir, info->path);
1122 return unit_file_load(c, info, path, allow_symlink);
1127 STRV_FOREACH(p, paths->unit_path) {
1128 _cleanup_free_ char *path = NULL;
1130 if (isempty(root_dir))
1131 path = strjoin(*p, "/", info->name, NULL);
1133 path = strjoin(root_dir, "/", *p, "/", info->name, NULL);
1137 r = unit_file_load(c, info, path, allow_symlink);
1143 if (r != -ENOENT && r != -ELOOP)
1147 if (unit_name_is_instance(info->name)) {
1149 /* Unit file doesn't exist, however instance
1150 * enablement was requested. We will check if it is
1151 * possible to load template unit file. */
1153 _cleanup_free_ char *template = NULL, *template_dir = NULL;
1155 template = unit_name_template(info->name);
1159 STRV_FOREACH(p, paths->unit_path) {
1160 _cleanup_free_ char *path = NULL;
1162 if (isempty(root_dir))
1163 path = strjoin(*p, "/", template, NULL);
1165 path = strjoin(root_dir, "/", *p, "/", template, NULL);
1169 r = unit_file_load(c, info, path, allow_symlink);
1175 if (r != -ENOENT && r != -ELOOP)
1183 static int unit_file_can_install(
1185 const char *root_dir,
1187 bool allow_symlink) {
1189 _cleanup_install_context_done_ InstallContext c = {};
1196 r = install_info_add_auto(&c, name);
1200 assert_se(i = hashmap_first(c.will_install));
1202 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1206 (int) strv_length(i->aliases) +
1207 (int) strv_length(i->wanted_by) +
1208 (int) strv_length(i->required_by);
1213 static int create_symlink(
1214 const char *old_path,
1215 const char *new_path,
1217 UnitFileChange **changes,
1218 unsigned *n_changes) {
1220 _cleanup_free_ char *dest = NULL;
1226 mkdir_parents_label(new_path, 0755);
1228 if (symlink(old_path, new_path) >= 0) {
1229 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1233 if (errno != EEXIST)
1236 r = readlink_and_make_absolute(new_path, &dest);
1240 if (path_equal(dest, old_path))
1246 r = symlink_atomic(old_path, new_path);
1250 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1251 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1256 static int install_info_symlink_alias(
1258 const char *config_path,
1260 UnitFileChange **changes,
1261 unsigned *n_changes) {
1267 assert(config_path);
1269 STRV_FOREACH(s, i->aliases) {
1270 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1272 q = install_full_printf(i, *s, &dst);
1276 alias_path = path_make_absolute(dst, config_path);
1280 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1288 static int install_info_symlink_wants(
1290 const char *config_path,
1294 UnitFileChange **changes,
1295 unsigned *n_changes) {
1297 _cleanup_free_ char *buf = NULL;
1303 assert(config_path);
1305 if (unit_name_is_template(i->name)) {
1307 /* Don't install any symlink if there's no default
1308 * instance configured */
1310 if (!i->default_instance)
1313 buf = unit_name_replace_instance(i->name, i->default_instance);
1321 STRV_FOREACH(s, list) {
1322 _cleanup_free_ char *path = NULL, *dst = NULL;
1324 q = install_full_printf(i, *s, &dst);
1328 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1333 path = strjoin(config_path, "/", dst, suffix, n, NULL);
1337 q = create_symlink(i->path, path, force, changes, n_changes);
1345 static int install_info_symlink_link(
1348 const char *config_path,
1349 const char *root_dir,
1351 UnitFileChange **changes,
1352 unsigned *n_changes) {
1354 _cleanup_free_ char *path = NULL;
1359 assert(config_path);
1362 r = in_search_path(i->path, paths->unit_path, root_dir);
1366 path = strjoin(config_path, "/", i->name, NULL);
1370 return create_symlink(i->path, path, force, changes, n_changes);
1373 static int install_info_apply(
1376 const char *config_path,
1377 const char *root_dir,
1379 UnitFileChange **changes,
1380 unsigned *n_changes) {
1386 assert(config_path);
1388 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1390 q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes);
1394 q = install_info_symlink_wants(i, config_path, i->required_by, ".requires/", force, changes, n_changes);
1398 q = install_info_symlink_link(i, paths, config_path, root_dir, force, changes, n_changes);
1405 static int install_context_apply(
1408 const char *config_path,
1409 const char *root_dir,
1411 UnitFileChange **changes,
1412 unsigned *n_changes) {
1419 assert(config_path);
1421 while ((i = hashmap_first(c->will_install))) {
1423 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1427 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1429 q = unit_file_search(c, i, paths, root_dir, false);
1438 q = install_info_apply(i, paths, config_path, root_dir, force, changes, n_changes);
1439 if (r >= 0 && q < 0)
1446 static int install_context_mark_for_removal(
1449 Set **remove_symlinks_to,
1450 const char *config_path,
1451 const char *root_dir) {
1458 assert(config_path);
1460 /* Marks all items for removal */
1462 while ((i = hashmap_first(c->will_install))) {
1464 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1468 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1470 q = unit_file_search(c, i, paths, root_dir, false);
1481 if (unit_name_is_instance(i->name)) {
1485 unit_file = basename(i->path);
1487 if (unit_name_is_instance(unit_file))
1488 /* unit file named as instance exists, thus all symlinks
1489 * pointing to it will be removed */
1490 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1492 /* does not exist, thus we will mark for removal symlinks
1493 * to template unit file */
1494 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1496 /* If i->path is not set, it means that we didn't actually find
1497 * the unit file. But we can still remove symlinks to the
1498 * nonexistent template. */
1499 unit_file = unit_name_template(i->name);
1503 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1507 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1509 if (r >= 0 && q < 0)
1516 int unit_file_enable(
1517 UnitFileScope scope,
1519 const char *root_dir,
1522 UnitFileChange **changes,
1523 unsigned *n_changes) {
1525 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1526 _cleanup_install_context_done_ InstallContext c = {};
1528 _cleanup_free_ char *config_path = NULL;
1532 assert(scope < _UNIT_FILE_SCOPE_MAX);
1534 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1538 r = get_config_path(scope, runtime, root_dir, &config_path);
1542 STRV_FOREACH(i, files) {
1543 r = install_info_add_auto(&c, *i);
1548 /* This will return the number of symlink rules that were
1549 supposed to be created, not the ones actually created. This is
1550 useful to determine whether the passed files had any
1551 installation data at all. */
1553 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1556 int unit_file_disable(
1557 UnitFileScope scope,
1559 const char *root_dir,
1561 UnitFileChange **changes,
1562 unsigned *n_changes) {
1564 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1565 _cleanup_install_context_done_ InstallContext c = {};
1567 _cleanup_free_ char *config_path = NULL;
1568 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1572 assert(scope < _UNIT_FILE_SCOPE_MAX);
1574 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1578 r = get_config_path(scope, runtime, root_dir, &config_path);
1582 STRV_FOREACH(i, files) {
1583 r = install_info_add_auto(&c, *i);
1588 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1590 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1597 int unit_file_reenable(
1598 UnitFileScope scope,
1600 const char *root_dir,
1603 UnitFileChange **changes,
1604 unsigned *n_changes) {
1607 r = unit_file_disable(scope, runtime, root_dir, files,
1608 changes, n_changes);
1612 return unit_file_enable(scope, runtime, root_dir, files, force,
1613 changes, n_changes);
1616 int unit_file_set_default(
1617 UnitFileScope scope,
1618 const char *root_dir,
1621 UnitFileChange **changes,
1622 unsigned *n_changes) {
1624 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1625 _cleanup_install_context_done_ InstallContext c = {};
1626 _cleanup_free_ char *config_path = NULL;
1629 InstallInfo *i = NULL;
1632 assert(scope < _UNIT_FILE_SCOPE_MAX);
1635 if (unit_name_to_type(file) != UNIT_TARGET)
1638 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1642 r = get_config_path(scope, false, root_dir, &config_path);
1646 r = install_info_add_auto(&c, file);
1650 assert_se(i = hashmap_first(c.will_install));
1652 r = unit_file_search(&c, i, &paths, root_dir, false);
1656 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1658 r = create_symlink(i->path, path, force, changes, n_changes);
1665 int unit_file_get_default(
1666 UnitFileScope scope,
1667 const char *root_dir,
1670 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1675 assert(scope < _UNIT_FILE_SCOPE_MAX);
1678 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1682 STRV_FOREACH(p, paths.unit_path) {
1683 _cleanup_free_ char *path = NULL, *tmp = NULL;
1686 if (isempty(root_dir))
1687 path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
1689 path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
1694 r = readlink_malloc(path, &tmp);
1697 else if (r == -EINVAL)
1699 n = strdup(SPECIAL_DEFAULT_TARGET);
1703 n = strdup(basename(tmp));
1715 UnitFileState unit_file_get_state(
1716 UnitFileScope scope,
1717 const char *root_dir,
1720 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1721 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1723 _cleanup_free_ char *path = NULL;
1727 assert(scope < _UNIT_FILE_SCOPE_MAX);
1730 if (root_dir && scope != UNIT_FILE_SYSTEM)
1733 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1736 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1740 STRV_FOREACH(i, paths.unit_path) {
1748 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1750 asprintf(&path, "%s/%s", *i, name);
1755 partial = path + strlen(root_dir) + 1;
1760 * Search for a unit file in our default paths, to
1761 * be sure, that there are no broken symlinks.
1763 if (lstat(path, &st) < 0) {
1765 if (errno != ENOENT)
1768 if (!unit_name_is_instance(name))
1771 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1774 r = null_or_empty_path(path);
1775 if (r < 0 && r != -ENOENT)
1778 state = path_startswith(*i, "/run") ?
1779 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1784 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1790 r = unit_file_can_install(&paths, root_dir, partial, true);
1791 if (r < 0 && errno != ENOENT)
1794 return UNIT_FILE_DISABLED;
1796 return UNIT_FILE_STATIC;
1799 return r < 0 ? r : state;
1802 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
1803 _cleanup_strv_free_ char **files = NULL;
1808 assert(scope < _UNIT_FILE_SCOPE_MAX);
1811 if (scope == UNIT_FILE_SYSTEM)
1812 r = conf_files_list(&files, ".preset", root_dir,
1813 "/etc/systemd/system-preset",
1814 "/usr/local/lib/systemd/system-preset",
1815 "/usr/lib/systemd/system-preset",
1816 #ifdef HAVE_SPLIT_USR
1817 "/lib/systemd/system-preset",
1820 else if (scope == UNIT_FILE_GLOBAL)
1821 r = conf_files_list(&files, ".preset", root_dir,
1822 "/etc/systemd/user-preset",
1823 "/usr/local/lib/systemd/user-preset",
1824 "/usr/lib/systemd/user-preset",
1832 STRV_FOREACH(i, files) {
1833 _cleanup_free_ char *buf = NULL;
1834 _cleanup_fclose_ FILE *f;
1838 p = buf = strjoin(root_dir, "/", *i, NULL);
1844 if (errno == ENOENT)
1851 char line[LINE_MAX], *l;
1853 if (!fgets(line, sizeof(line), f))
1860 if (strchr(COMMENTS "\n", *l))
1863 if (first_word(l, "enable")) {
1865 l += strspn(l, WHITESPACE);
1867 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1868 log_debug("Preset file says enable %s.", name);
1872 } else if (first_word(l, "disable")) {
1874 l += strspn(l, WHITESPACE);
1876 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1877 log_debug("Preset file says disable %s.", name);
1882 log_debug("Couldn't parse line '%s'", l);
1886 /* Default is "enable" */
1887 log_debug("Preset file doesn't say anything about %s, enabling.", name);
1891 int unit_file_preset(
1892 UnitFileScope scope,
1894 const char *root_dir,
1896 UnitFilePresetMode mode,
1898 UnitFileChange **changes,
1899 unsigned *n_changes) {
1901 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1902 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1903 _cleanup_free_ char *config_path = NULL;
1908 assert(scope < _UNIT_FILE_SCOPE_MAX);
1909 assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
1911 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1915 r = get_config_path(scope, runtime, root_dir, &config_path);
1919 STRV_FOREACH(i, files) {
1921 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1924 r = unit_file_query_preset(scope, root_dir, *i);
1928 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1929 r = install_info_add_auto(&plus, *i);
1930 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1931 r = install_info_add_auto(&minus, *i);
1940 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1941 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1943 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1945 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1950 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1951 /* Returns number of symlinks that where supposed to be installed. */
1952 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1960 int unit_file_preset_all(
1961 UnitFileScope scope,
1963 const char *root_dir,
1964 UnitFilePresetMode mode,
1966 UnitFileChange **changes,
1967 unsigned *n_changes) {
1969 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1970 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1971 _cleanup_free_ char *config_path = NULL;
1976 assert(scope < _UNIT_FILE_SCOPE_MAX);
1977 assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
1979 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1983 r = get_config_path(scope, runtime, root_dir, &config_path);
1987 STRV_FOREACH(i, paths.unit_path) {
1988 _cleanup_closedir_ DIR *d = NULL;
1989 _cleanup_free_ char *buf = NULL;
1990 const char *units_dir;
1992 if (!isempty(root_dir)) {
1993 buf = strjoin(root_dir, "/", *i, NULL);
2001 d = opendir(units_dir);
2003 if (errno == ENOENT)
2014 if (!de && errno != 0)
2020 if (ignore_file(de->d_name))
2023 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2026 dirent_ensure_type(d, de);
2028 if (de->d_type != DT_REG)
2031 r = unit_file_query_preset(scope, root_dir, de->d_name);
2035 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
2036 r = install_info_add_auto(&plus, de->d_name);
2037 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
2038 r = install_info_add_auto(&minus, de->d_name);
2048 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2049 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2051 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
2053 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
2058 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2059 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2067 static void unitfilelist_free(UnitFileList **f) {
2074 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
2076 int unit_file_get_list(
2077 UnitFileScope scope,
2078 const char *root_dir,
2081 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2086 assert(scope < _UNIT_FILE_SCOPE_MAX);
2089 if (root_dir && scope != UNIT_FILE_SYSTEM)
2092 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2096 STRV_FOREACH(i, paths.unit_path) {
2097 _cleanup_closedir_ DIR *d = NULL;
2098 _cleanup_free_ char *buf = NULL;
2099 const char *units_dir;
2101 if (!isempty(root_dir)) {
2102 buf = strjoin(root_dir, "/", *i, NULL);
2110 d = opendir(units_dir);
2112 if (errno == ENOENT)
2119 _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
2124 if (!de && errno != 0)
2130 if (ignore_file(de->d_name))
2133 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2136 if (hashmap_get(h, de->d_name))
2139 dirent_ensure_type(d, de);
2141 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2144 f = new0(UnitFileList, 1);
2148 f->path = path_make_absolute(de->d_name, units_dir);
2152 r = null_or_empty_path(f->path);
2153 if (r < 0 && r != -ENOENT)
2157 path_startswith(*i, "/run") ?
2158 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2162 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2166 f->state = UNIT_FILE_ENABLED;
2170 r = unit_file_can_install(&paths, root_dir, f->path, true);
2171 if (r == -EINVAL || /* Invalid setting? */
2172 r == -EBADMSG || /* Invalid format? */
2173 r == -ENOENT /* Included file not found? */)
2174 f->state = UNIT_FILE_INVALID;
2178 f->state = UNIT_FILE_DISABLED;
2180 f->state = UNIT_FILE_STATIC;
2183 r = hashmap_put(h, basename(f->path), f);
2186 f = NULL; /* prevent cleanup */
2193 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2194 [UNIT_FILE_ENABLED] = "enabled",
2195 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2196 [UNIT_FILE_LINKED] = "linked",
2197 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2198 [UNIT_FILE_MASKED] = "masked",
2199 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2200 [UNIT_FILE_STATIC] = "static",
2201 [UNIT_FILE_DISABLED] = "disabled",
2202 [UNIT_FILE_INVALID] = "invalid",
2205 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2207 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2208 [UNIT_FILE_SYMLINK] = "symlink",
2209 [UNIT_FILE_UNLINK] = "unlink",
2212 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2214 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MODE_MAX] = {
2215 [UNIT_FILE_PRESET_FULL] = "full",
2216 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2217 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2220 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);