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, NULL, config_item_table_lookup, (void*) items, true, true, info);
1084 (int) strv_length(info->aliases) +
1085 (int) strv_length(info->wanted_by) +
1086 (int) strv_length(info->required_by);
1089 static int unit_file_search(
1093 const char *root_dir,
1094 bool allow_symlink) {
1104 return unit_file_load(c, info, info->path, root_dir, allow_symlink);
1108 STRV_FOREACH(p, paths->unit_path) {
1109 _cleanup_free_ char *path = NULL;
1111 path = strjoin(*p, "/", info->name, NULL);
1115 r = unit_file_load(c, info, path, root_dir, allow_symlink);
1121 if (r != -ENOENT && r != -ELOOP)
1125 if (unit_name_is_instance(info->name)) {
1127 /* Unit file doesn't exist, however instance
1128 * enablement was requested. We will check if it is
1129 * possible to load template unit file. */
1131 _cleanup_free_ char *template = NULL;
1133 template = unit_name_template(info->name);
1137 STRV_FOREACH(p, paths->unit_path) {
1138 _cleanup_free_ char *path = NULL;
1140 path = strjoin(*p, "/", template, NULL);
1144 r = unit_file_load(c, info, path, root_dir, allow_symlink);
1150 if (r != -ENOENT && r != -ELOOP)
1158 static int unit_file_can_install(
1160 const char *root_dir,
1162 bool allow_symlink) {
1164 _cleanup_install_context_done_ InstallContext c = {};
1171 r = install_info_add_auto(&c, name);
1175 assert_se(i = hashmap_first(c.will_install));
1177 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1181 (int) strv_length(i->aliases) +
1182 (int) strv_length(i->wanted_by) +
1183 (int) strv_length(i->required_by);
1188 static int create_symlink(
1189 const char *old_path,
1190 const char *new_path,
1192 UnitFileChange **changes,
1193 unsigned *n_changes) {
1195 _cleanup_free_ char *dest = NULL;
1201 mkdir_parents_label(new_path, 0755);
1203 if (symlink(old_path, new_path) >= 0) {
1204 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1208 if (errno != EEXIST)
1211 r = readlink_and_make_absolute(new_path, &dest);
1215 if (path_equal(dest, old_path))
1221 r = symlink_atomic(old_path, new_path);
1225 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1226 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1231 static int install_info_symlink_alias(
1233 const char *config_path,
1235 UnitFileChange **changes,
1236 unsigned *n_changes) {
1242 assert(config_path);
1244 STRV_FOREACH(s, i->aliases) {
1245 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1247 q = install_full_printf(i, *s, &dst);
1251 alias_path = path_make_absolute(dst, config_path);
1255 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1263 static int install_info_symlink_wants(
1265 const char *config_path,
1269 UnitFileChange **changes,
1270 unsigned *n_changes) {
1272 _cleanup_free_ char *buf = NULL;
1278 assert(config_path);
1280 if (unit_name_is_template(i->name)) {
1282 /* Don't install any symlink if there's no default
1283 * instance configured */
1285 if (!i->default_instance)
1288 buf = unit_name_replace_instance(i->name, i->default_instance);
1296 STRV_FOREACH(s, list) {
1297 _cleanup_free_ char *path = NULL, *dst = NULL;
1299 q = install_full_printf(i, *s, &dst);
1303 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1308 path = strjoin(config_path, "/", dst, suffix, n, NULL);
1312 q = create_symlink(i->path, path, force, changes, n_changes);
1320 static int install_info_symlink_link(
1323 const char *config_path,
1324 const char *root_dir,
1326 UnitFileChange **changes,
1327 unsigned *n_changes) {
1329 _cleanup_free_ char *path = NULL;
1334 assert(config_path);
1337 r = in_search_path(i->path, paths->unit_path);
1341 path = strjoin(config_path, "/", i->name, NULL);
1345 return create_symlink(i->path, path, force, changes, n_changes);
1348 static int install_info_apply(
1351 const char *config_path,
1352 const char *root_dir,
1354 UnitFileChange **changes,
1355 unsigned *n_changes) {
1361 assert(config_path);
1363 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1365 q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes);
1369 q = install_info_symlink_wants(i, config_path, i->required_by, ".requires/", force, changes, n_changes);
1373 q = install_info_symlink_link(i, paths, config_path, root_dir, force, changes, n_changes);
1380 static int install_context_apply(
1383 const char *config_path,
1384 const char *root_dir,
1386 UnitFileChange **changes,
1387 unsigned *n_changes) {
1394 assert(config_path);
1396 while ((i = hashmap_first(c->will_install))) {
1398 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1402 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1404 q = unit_file_search(c, i, paths, root_dir, false);
1413 q = install_info_apply(i, paths, config_path, root_dir, force, changes, n_changes);
1414 if (r >= 0 && q < 0)
1421 static int install_context_mark_for_removal(
1424 Set **remove_symlinks_to,
1425 const char *config_path,
1426 const char *root_dir) {
1433 assert(config_path);
1435 /* Marks all items for removal */
1437 while ((i = hashmap_first(c->will_install))) {
1439 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1443 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1445 q = unit_file_search(c, i, paths, root_dir, false);
1456 if (unit_name_is_instance(i->name)) {
1460 unit_file = basename(i->path);
1462 if (unit_name_is_instance(unit_file))
1463 /* unit file named as instance exists, thus all symlinks
1464 * pointing to it will be removed */
1465 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1467 /* does not exist, thus we will mark for removal symlinks
1468 * to template unit file */
1469 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1471 /* If i->path is not set, it means that we didn't actually find
1472 * the unit file. But we can still remove symlinks to the
1473 * nonexistent template. */
1474 unit_file = unit_name_template(i->name);
1478 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1482 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1484 if (r >= 0 && q < 0)
1491 int unit_file_enable(
1492 UnitFileScope scope,
1494 const char *root_dir,
1497 UnitFileChange **changes,
1498 unsigned *n_changes) {
1500 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1501 _cleanup_install_context_done_ InstallContext c = {};
1503 _cleanup_free_ char *config_path = NULL;
1507 assert(scope < _UNIT_FILE_SCOPE_MAX);
1509 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1513 r = get_config_path(scope, runtime, root_dir, &config_path);
1517 STRV_FOREACH(i, files) {
1518 r = install_info_add_auto(&c, *i);
1523 /* This will return the number of symlink rules that were
1524 supposed to be created, not the ones actually created. This is
1525 useful to determine whether the passed files had any
1526 installation data at all. */
1528 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1531 int unit_file_disable(
1532 UnitFileScope scope,
1534 const char *root_dir,
1536 UnitFileChange **changes,
1537 unsigned *n_changes) {
1539 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1540 _cleanup_install_context_done_ InstallContext c = {};
1542 _cleanup_free_ char *config_path = NULL;
1543 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1547 assert(scope < _UNIT_FILE_SCOPE_MAX);
1549 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1553 r = get_config_path(scope, runtime, root_dir, &config_path);
1557 STRV_FOREACH(i, files) {
1558 r = install_info_add_auto(&c, *i);
1563 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1565 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1572 int unit_file_reenable(
1573 UnitFileScope scope,
1575 const char *root_dir,
1578 UnitFileChange **changes,
1579 unsigned *n_changes) {
1582 r = unit_file_disable(scope, runtime, root_dir, files,
1583 changes, n_changes);
1587 return unit_file_enable(scope, runtime, root_dir, files, force,
1588 changes, n_changes);
1591 int unit_file_set_default(
1592 UnitFileScope scope,
1593 const char *root_dir,
1596 UnitFileChange **changes,
1597 unsigned *n_changes) {
1599 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1600 _cleanup_install_context_done_ InstallContext c = {};
1601 _cleanup_free_ char *config_path = NULL;
1604 InstallInfo *i = NULL;
1607 assert(scope < _UNIT_FILE_SCOPE_MAX);
1610 if (unit_name_to_type(file) != UNIT_TARGET)
1613 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1617 r = get_config_path(scope, false, root_dir, &config_path);
1621 r = install_info_add_auto(&c, file);
1625 assert_se(i = hashmap_first(c.will_install));
1627 r = unit_file_search(&c, i, &paths, root_dir, false);
1631 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1633 r = create_symlink(i->path, path, force, changes, n_changes);
1640 int unit_file_get_default(
1641 UnitFileScope scope,
1642 const char *root_dir,
1645 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1650 assert(scope < _UNIT_FILE_SCOPE_MAX);
1653 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1657 STRV_FOREACH(p, paths.unit_path) {
1658 _cleanup_free_ char *path = NULL, *tmp = NULL;
1661 if (isempty(root_dir))
1662 path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
1664 path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
1669 r = readlink_malloc(path, &tmp);
1672 else if (r == -EINVAL)
1674 n = strdup(SPECIAL_DEFAULT_TARGET);
1678 n = strdup(basename(tmp));
1690 UnitFileState unit_file_get_state(
1691 UnitFileScope scope,
1692 const char *root_dir,
1695 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1696 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1698 _cleanup_free_ char *path = NULL;
1702 assert(scope < _UNIT_FILE_SCOPE_MAX);
1705 if (root_dir && scope != UNIT_FILE_SYSTEM)
1708 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1711 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1715 STRV_FOREACH(i, paths.unit_path) {
1723 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1725 asprintf(&path, "%s/%s", *i, name);
1730 partial = path + strlen(root_dir) + 1;
1735 * Search for a unit file in our default paths, to
1736 * be sure, that there are no broken symlinks.
1738 if (lstat(path, &st) < 0) {
1740 if (errno != ENOENT)
1743 if (!unit_name_is_instance(name))
1746 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1749 r = null_or_empty_path(path);
1750 if (r < 0 && r != -ENOENT)
1753 state = path_startswith(*i, "/run") ?
1754 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1759 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1765 r = unit_file_can_install(&paths, root_dir, partial, true);
1766 if (r < 0 && errno != ENOENT)
1769 return UNIT_FILE_DISABLED;
1771 return UNIT_FILE_STATIC;
1774 return r < 0 ? r : state;
1777 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
1778 _cleanup_strv_free_ char **files = NULL;
1783 assert(scope < _UNIT_FILE_SCOPE_MAX);
1786 if (scope == UNIT_FILE_SYSTEM)
1787 r = conf_files_list(&files, ".preset", root_dir,
1788 "/etc/systemd/system-preset",
1789 "/usr/local/lib/systemd/system-preset",
1790 "/usr/lib/systemd/system-preset",
1791 #ifdef HAVE_SPLIT_USR
1792 "/lib/systemd/system-preset",
1795 else if (scope == UNIT_FILE_GLOBAL)
1796 r = conf_files_list(&files, ".preset", root_dir,
1797 "/etc/systemd/user-preset",
1798 "/usr/local/lib/systemd/user-preset",
1799 "/usr/lib/systemd/user-preset",
1807 STRV_FOREACH(i, files) {
1808 _cleanup_free_ char *buf = NULL;
1809 _cleanup_fclose_ FILE *f;
1813 p = buf = strjoin(root_dir, "/", *i, NULL);
1819 if (errno == ENOENT)
1826 char line[LINE_MAX], *l;
1828 if (!fgets(line, sizeof(line), f))
1835 if (strchr(COMMENTS "\n", *l))
1838 if (first_word(l, "enable")) {
1840 l += strspn(l, WHITESPACE);
1842 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1843 log_debug("Preset file says enable %s.", name);
1847 } else if (first_word(l, "disable")) {
1849 l += strspn(l, WHITESPACE);
1851 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1852 log_debug("Preset file says disable %s.", name);
1857 log_debug("Couldn't parse line '%s'", l);
1861 /* Default is "enable" */
1862 log_debug("Preset file doesn't say anything about %s, enabling.", name);
1866 int unit_file_preset(
1867 UnitFileScope scope,
1869 const char *root_dir,
1871 UnitFilePresetMode mode,
1873 UnitFileChange **changes,
1874 unsigned *n_changes) {
1876 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1877 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1878 _cleanup_free_ char *config_path = NULL;
1883 assert(scope < _UNIT_FILE_SCOPE_MAX);
1884 assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
1886 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1890 r = get_config_path(scope, runtime, root_dir, &config_path);
1894 STRV_FOREACH(i, files) {
1896 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1899 r = unit_file_query_preset(scope, root_dir, *i);
1903 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1904 r = install_info_add_auto(&plus, *i);
1905 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1906 r = install_info_add_auto(&minus, *i);
1915 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1916 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1918 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1920 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1925 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1926 /* Returns number of symlinks that where supposed to be installed. */
1927 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1935 int unit_file_preset_all(
1936 UnitFileScope scope,
1938 const char *root_dir,
1939 UnitFilePresetMode mode,
1941 UnitFileChange **changes,
1942 unsigned *n_changes) {
1944 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1945 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1946 _cleanup_free_ char *config_path = NULL;
1951 assert(scope < _UNIT_FILE_SCOPE_MAX);
1952 assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
1954 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1958 r = get_config_path(scope, runtime, root_dir, &config_path);
1962 STRV_FOREACH(i, paths.unit_path) {
1963 _cleanup_closedir_ DIR *d = NULL;
1964 _cleanup_free_ char *buf = NULL;
1965 const char *units_dir;
1967 if (!isempty(root_dir)) {
1968 buf = strjoin(root_dir, "/", *i, NULL);
1976 d = opendir(units_dir);
1978 if (errno == ENOENT)
1989 if (!de && errno != 0)
1995 if (ignore_file(de->d_name))
1998 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2001 dirent_ensure_type(d, de);
2003 if (de->d_type != DT_REG)
2006 r = unit_file_query_preset(scope, root_dir, de->d_name);
2010 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
2011 r = install_info_add_auto(&plus, de->d_name);
2012 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
2013 r = install_info_add_auto(&minus, de->d_name);
2023 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2024 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2026 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
2028 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
2033 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2034 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2042 static void unitfilelist_free(UnitFileList **f) {
2049 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
2051 int unit_file_get_list(
2052 UnitFileScope scope,
2053 const char *root_dir,
2056 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2061 assert(scope < _UNIT_FILE_SCOPE_MAX);
2064 if (root_dir && scope != UNIT_FILE_SYSTEM)
2067 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2071 STRV_FOREACH(i, paths.unit_path) {
2072 _cleanup_closedir_ DIR *d = NULL;
2073 _cleanup_free_ char *buf = NULL;
2074 const char *units_dir;
2076 if (!isempty(root_dir)) {
2077 buf = strjoin(root_dir, "/", *i, NULL);
2085 d = opendir(units_dir);
2087 if (errno == ENOENT)
2094 _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
2099 if (!de && errno != 0)
2105 if (ignore_file(de->d_name))
2108 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2111 if (hashmap_get(h, de->d_name))
2114 dirent_ensure_type(d, de);
2116 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2119 f = new0(UnitFileList, 1);
2123 f->path = path_make_absolute(de->d_name, units_dir);
2127 r = null_or_empty_path(f->path);
2128 if (r < 0 && r != -ENOENT)
2132 path_startswith(*i, "/run") ?
2133 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2137 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2141 f->state = UNIT_FILE_ENABLED;
2145 r = unit_file_can_install(&paths, root_dir, f->path, true);
2146 if (r == -EINVAL || /* Invalid setting? */
2147 r == -EBADMSG || /* Invalid format? */
2148 r == -ENOENT /* Included file not found? */)
2149 f->state = UNIT_FILE_INVALID;
2153 f->state = UNIT_FILE_DISABLED;
2155 f->state = UNIT_FILE_STATIC;
2158 r = hashmap_put(h, basename(f->path), f);
2161 f = NULL; /* prevent cleanup */
2168 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2169 [UNIT_FILE_ENABLED] = "enabled",
2170 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2171 [UNIT_FILE_LINKED] = "linked",
2172 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2173 [UNIT_FILE_MASKED] = "masked",
2174 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2175 [UNIT_FILE_STATIC] = "static",
2176 [UNIT_FILE_DISABLED] = "disabled",
2177 [UNIT_FILE_INVALID] = "invalid",
2180 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2182 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2183 [UNIT_FILE_SYMLINK] = "symlink",
2184 [UNIT_FILE_UNLINK] = "unlink",
2187 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2189 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MODE_MAX] = {
2190 [UNIT_FILE_PRESET_FULL] = "full",
2191 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2192 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2195 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);