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 lookup_paths_init_from_scope(LookupPaths *paths,
52 const char *root_dir) {
55 assert(scope < _UNIT_FILE_SCOPE_MAX);
59 return lookup_paths_init(paths,
60 scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
61 scope == UNIT_FILE_USER,
66 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
71 assert(scope < _UNIT_FILE_SCOPE_MAX);
76 case UNIT_FILE_SYSTEM:
78 if (root_dir && runtime)
79 asprintf(&p, "%s/run/systemd/system", root_dir);
81 p = strdup("/run/systemd/system");
83 asprintf(&p, "%s/%s", root_dir, SYSTEM_CONFIG_UNIT_PATH);
85 p = strdup(SYSTEM_CONFIG_UNIT_PATH);
89 case UNIT_FILE_GLOBAL:
95 p = strdup("/run/systemd/user");
97 p = strdup(USER_CONFIG_UNIT_PATH);
102 if (root_dir || runtime)
105 r = user_config_home(&p);
107 return r < 0 ? r : -ENOENT;
112 assert_not_reached("Bad scope");
122 static int add_file_change(
123 UnitFileChange **changes,
125 UnitFileChangeType type,
127 const char *source) {
133 assert(!changes == !n_changes);
138 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
146 c[i].path = strdup(path);
151 c[i].source = strdup(source);
163 static int mark_symlink_for_removal(
164 Set **remove_symlinks_to,
172 r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
180 path_kill_slashes(n);
182 r = set_consume(*remove_symlinks_to, n);
184 return r == -EEXIST ? 0 : r;
189 static int remove_marked_symlinks_fd(
190 Set *remove_symlinks_to,
193 const char *config_path,
195 UnitFileChange **changes,
197 char** instance_whitelist) {
199 _cleanup_closedir_ DIR *d = NULL;
202 assert(remove_symlinks_to);
221 if (!de && errno != 0) {
229 if (ignore_file(de->d_name))
232 dirent_ensure_type(d, de);
234 if (de->d_type == DT_DIR) {
236 _cleanup_free_ char *p = NULL;
238 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
248 p = path_make_absolute(de->d_name, path);
254 /* This will close nfd, regardless whether it succeeds or not */
255 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, instance_whitelist);
259 } else if (de->d_type == DT_LNK) {
260 _cleanup_free_ char *p = NULL, *dest = NULL;
264 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
267 if (unit_name_is_instance(de->d_name) &&
268 instance_whitelist &&
269 !strv_contains(instance_whitelist, de->d_name)) {
271 _cleanup_free_ char *w;
273 /* OK, the file is not listed directly
274 * in the whitelist, so let's check if
275 * the template of it might be
278 w = unit_name_template(de->d_name);
282 if (!strv_contains(instance_whitelist, w))
286 p = path_make_absolute(de->d_name, path);
290 q = readlink_and_canonicalize(p, &dest);
301 set_get(remove_symlinks_to, dest) ||
302 set_get(remove_symlinks_to, basename(dest));
307 if (unlink(p) < 0 && errno != ENOENT) {
313 path_kill_slashes(p);
314 rmdir_parents(p, config_path);
315 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
317 if (!set_get(remove_symlinks_to, p)) {
319 q = mark_symlink_for_removal(&remove_symlinks_to, p);
332 static int remove_marked_symlinks(
333 Set *remove_symlinks_to,
334 const char *config_path,
335 UnitFileChange **changes,
337 char** instance_whitelist) {
339 _cleanup_close_ int fd = -1;
345 if (set_size(remove_symlinks_to) <= 0)
348 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
356 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
362 /* This takes possession of cfd and closes it */
363 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist);
371 static int find_symlinks_fd(
375 const char *config_path,
376 bool *same_name_link) {
379 _cleanup_closedir_ DIR *d = NULL;
385 assert(same_name_link);
398 if (!de && errno != 0)
404 if (ignore_file(de->d_name))
407 dirent_ensure_type(d, de);
409 if (de->d_type == DT_DIR) {
411 _cleanup_free_ char *p = NULL;
413 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
423 p = path_make_absolute(de->d_name, path);
429 /* This will close nfd, regardless whether it succeeds or not */
430 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
436 } else if (de->d_type == DT_LNK) {
437 _cleanup_free_ char *p = NULL, *dest = NULL;
438 bool found_path, found_dest, b = false;
441 /* Acquire symlink name */
442 p = path_make_absolute(de->d_name, path);
446 /* Acquire symlink destination */
447 q = readlink_and_canonicalize(p, &dest);
457 /* Check if the symlink itself matches what we
459 if (path_is_absolute(name))
460 found_path = path_equal(p, name);
462 found_path = streq(de->d_name, name);
464 /* Check if what the symlink points to
465 * matches what we are looking for */
466 if (path_is_absolute(name))
467 found_dest = path_equal(dest, name);
469 found_dest = streq(basename(dest), name);
471 if (found_path && found_dest) {
472 _cleanup_free_ char *t = NULL;
474 /* Filter out same name links in the main
476 t = path_make_absolute(name, config_path);
480 b = path_equal(t, p);
484 *same_name_link = true;
485 else if (found_path || found_dest)
491 static int find_symlinks(
493 const char *config_path,
494 bool *same_name_link) {
500 assert(same_name_link);
502 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
509 /* This takes possession of fd and closes it */
510 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
513 static int find_symlinks_in_scope(
515 const char *root_dir,
517 UnitFileState *state) {
520 _cleanup_free_ char *path2 = NULL;
521 bool same_name_link_runtime = false, same_name_link = false;
524 assert(scope < _UNIT_FILE_SCOPE_MAX);
527 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
528 _cleanup_free_ char *path = NULL;
530 /* First look in runtime config path */
531 r = get_config_path(scope, true, root_dir, &path);
535 r = find_symlinks(name, path, &same_name_link_runtime);
539 *state = UNIT_FILE_ENABLED_RUNTIME;
544 /* Then look in the normal config path */
545 r = get_config_path(scope, false, root_dir, &path2);
549 r = find_symlinks(name, path2, &same_name_link);
553 *state = UNIT_FILE_ENABLED;
557 /* Hmm, we didn't find it, but maybe we found the same name
559 if (same_name_link_runtime) {
560 *state = UNIT_FILE_LINKED_RUNTIME;
562 } else if (same_name_link) {
563 *state = UNIT_FILE_LINKED;
573 const char *root_dir,
576 UnitFileChange **changes,
577 unsigned *n_changes) {
580 _cleanup_free_ char *prefix = NULL;
584 assert(scope < _UNIT_FILE_SCOPE_MAX);
586 r = get_config_path(scope, runtime, root_dir, &prefix);
590 STRV_FOREACH(i, files) {
591 _cleanup_free_ char *path = NULL;
593 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
599 path = path_make_absolute(*i, prefix);
605 if (symlink("/dev/null", path) >= 0) {
606 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
610 if (errno == EEXIST) {
612 if (null_or_empty_path(path) > 0)
616 if (symlink_atomic("/dev/null", path) >= 0) {
617 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
618 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
634 int unit_file_unmask(
637 const char *root_dir,
639 UnitFileChange **changes,
640 unsigned *n_changes) {
642 char **i, *config_path = NULL;
644 Set *remove_symlinks_to = NULL;
647 assert(scope < _UNIT_FILE_SCOPE_MAX);
649 r = get_config_path(scope, runtime, root_dir, &config_path);
653 STRV_FOREACH(i, files) {
656 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
662 path = path_make_absolute(*i, config_path);
668 q = null_or_empty_path(path);
670 if (unlink(path) >= 0) {
671 mark_symlink_for_removal(&remove_symlinks_to, path);
672 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
681 if (q != -ENOENT && r == 0)
689 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
693 set_free_free(remove_symlinks_to);
702 const char *root_dir,
705 UnitFileChange **changes,
706 unsigned *n_changes) {
708 _cleanup_lookup_paths_free_ LookupPaths paths = {};
710 _cleanup_free_ char *config_path = NULL;
714 assert(scope < _UNIT_FILE_SCOPE_MAX);
716 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
720 r = get_config_path(scope, runtime, root_dir, &config_path);
724 STRV_FOREACH(i, files) {
725 _cleanup_free_ char *path = NULL;
731 if (!path_is_absolute(*i) ||
732 !unit_name_is_valid(fn, TEMPLATE_VALID)) {
738 if (lstat(*i, &st) < 0) {
744 if (!S_ISREG(st.st_mode)) {
749 q = in_search_path(*i, paths.unit_path);
756 path = path_make_absolute(fn, config_path);
760 if (symlink(*i, path) >= 0) {
761 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
765 if (errno == EEXIST) {
766 _cleanup_free_ char *dest = NULL;
768 q = readlink_and_make_absolute(path, &dest);
769 if (q < 0 && errno != ENOENT) {
775 if (q >= 0 && path_equal(dest, *i))
779 if (symlink_atomic(*i, path) >= 0) {
780 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
781 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
797 void unit_file_list_free(Hashmap *h) {
800 while ((i = hashmap_steal_first(h))) {
808 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
811 assert(changes || n_changes == 0);
816 for (i = 0; i < n_changes; i++) {
817 free(changes[i].path);
818 free(changes[i].source);
824 static void install_info_free(InstallInfo *i) {
829 strv_free(i->aliases);
830 strv_free(i->wanted_by);
831 strv_free(i->required_by);
832 free(i->default_instance);
836 static void install_info_hashmap_free(Hashmap *m) {
842 while ((i = hashmap_steal_first(m)))
843 install_info_free(i);
848 static void install_context_done(InstallContext *c) {
851 install_info_hashmap_free(c->will_install);
852 install_info_hashmap_free(c->have_installed);
854 c->will_install = c->have_installed = NULL;
857 static int install_info_add(
861 InstallInfo *i = NULL;
865 assert(name || path);
868 name = basename(path);
870 if (!unit_name_is_valid(name, TEMPLATE_VALID))
873 if (hashmap_get(c->have_installed, name) ||
874 hashmap_get(c->will_install, name))
877 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
881 i = new0(InstallInfo, 1);
885 i->name = strdup(name);
892 i->path = strdup(path);
899 r = hashmap_put(c->will_install, i->name, i);
907 install_info_free(i);
912 static int install_info_add_auto(
914 const char *name_or_path) {
917 assert(name_or_path);
919 if (path_is_absolute(name_or_path))
920 return install_info_add(c, NULL, name_or_path);
922 return install_info_add(c, name_or_path, NULL);
925 static int config_parse_also(
927 const char *filename,
930 unsigned section_line,
940 InstallContext *c = data;
946 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
947 _cleanup_free_ char *n;
954 r = install_info_add(c, n, NULL);
962 static int config_parse_user(
964 const char *filename,
967 unsigned section_line,
974 InstallInfo *i = data;
982 r = install_full_printf(i, rvalue, &printed);
992 static int config_parse_default_instance(
994 const char *filename,
997 unsigned section_line,
1004 InstallInfo *i = data;
1012 r = install_full_printf(i, rvalue, &printed);
1016 if (!unit_instance_is_valid(printed))
1019 free(i->default_instance);
1020 i->default_instance = printed;
1025 static int unit_file_load(
1029 bool allow_symlink) {
1031 const ConfigTableItem items[] = {
1032 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
1033 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1034 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1035 { "Install", "DefaultInstance", config_parse_default_instance, 0, info },
1036 { "Install", "Also", config_parse_also, 0, c },
1037 { "Exec", "User", config_parse_user, 0, info },
1042 _cleanup_fclose_ FILE *f = NULL;
1049 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1053 f = fdopen(fd, "re");
1059 r = config_parse(NULL, path, f, NULL, config_item_table_lookup, (void*) items, true, true, info);
1064 (int) strv_length(info->aliases) +
1065 (int) strv_length(info->wanted_by) +
1066 (int) strv_length(info->required_by);
1069 static int unit_file_search(
1073 const char *root_dir,
1074 bool allow_symlink) {
1086 if (isempty(root_dir))
1089 path = strappenda(root_dir, info->path);
1091 return unit_file_load(c, info, path, allow_symlink);
1096 STRV_FOREACH(p, paths->unit_path) {
1097 _cleanup_free_ char *path = NULL;
1099 if (isempty(root_dir))
1100 path = strjoin(*p, "/", info->name, NULL);
1102 path = strjoin(root_dir, "/", *p, "/", info->name, NULL);
1106 r = unit_file_load(c, info, path, allow_symlink);
1112 if (r != -ENOENT && r != -ELOOP)
1116 if (unit_name_is_instance(info->name)) {
1118 /* Unit file doesn't exist, however instance
1119 * enablement was requested. We will check if it is
1120 * possible to load template unit file. */
1122 _cleanup_free_ char *template = NULL, *template_dir = NULL;
1124 template = unit_name_template(info->name);
1128 STRV_FOREACH(p, paths->unit_path) {
1129 _cleanup_free_ char *path = NULL;
1131 if (isempty(root_dir))
1132 path = strjoin(*p, "/", template, NULL);
1134 path = strjoin(root_dir, "/", *p, "/", template, NULL);
1138 r = unit_file_load(c, info, path, allow_symlink);
1144 if (r != -ENOENT && r != -ELOOP)
1152 static int unit_file_can_install(
1154 const char *root_dir,
1156 bool allow_symlink) {
1158 _cleanup_install_context_done_ InstallContext c = {};
1165 r = install_info_add_auto(&c, name);
1169 assert_se(i = hashmap_first(c.will_install));
1171 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1175 (int) strv_length(i->aliases) +
1176 (int) strv_length(i->wanted_by) +
1177 (int) strv_length(i->required_by);
1182 static int create_symlink(
1183 const char *old_path,
1184 const char *new_path,
1186 UnitFileChange **changes,
1187 unsigned *n_changes) {
1189 _cleanup_free_ char *dest = NULL;
1195 mkdir_parents_label(new_path, 0755);
1197 if (symlink(old_path, new_path) >= 0) {
1198 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1202 if (errno != EEXIST)
1205 r = readlink_and_make_absolute(new_path, &dest);
1209 if (path_equal(dest, old_path))
1215 r = symlink_atomic(old_path, new_path);
1219 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1220 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1225 static int install_info_symlink_alias(
1227 const char *config_path,
1229 UnitFileChange **changes,
1230 unsigned *n_changes) {
1236 assert(config_path);
1238 STRV_FOREACH(s, i->aliases) {
1239 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1241 q = install_full_printf(i, *s, &dst);
1245 alias_path = path_make_absolute(dst, config_path);
1249 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1257 static int install_info_symlink_wants(
1259 const char *config_path,
1263 UnitFileChange **changes,
1264 unsigned *n_changes) {
1266 _cleanup_free_ char *buf = NULL;
1272 assert(config_path);
1274 if (unit_name_is_template(i->name) && i->default_instance) {
1275 buf = unit_name_replace_instance(i->name, i->default_instance);
1283 STRV_FOREACH(s, list) {
1284 _cleanup_free_ char *path = NULL, *dst = NULL;
1286 q = install_full_printf(i, *s, &dst);
1290 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1295 path = strjoin(config_path, "/", dst, suffix, n, NULL);
1299 q = create_symlink(i->path, path, force, changes, n_changes);
1307 static int install_info_symlink_link(
1310 const char *config_path,
1312 UnitFileChange **changes,
1313 unsigned *n_changes) {
1315 _cleanup_free_ char *path = NULL;
1320 assert(config_path);
1323 r = in_search_path(i->path, paths->unit_path);
1327 path = strjoin(config_path, "/", i->name, NULL);
1331 return create_symlink(i->path, path, force, changes, n_changes);
1334 static int install_info_apply(
1337 const char *config_path,
1339 UnitFileChange **changes,
1340 unsigned *n_changes) {
1346 assert(config_path);
1348 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1350 q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes);
1354 q = install_info_symlink_wants(i, config_path, i->required_by, ".requires/", force, changes, n_changes);
1358 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1365 static int install_context_apply(
1368 const char *config_path,
1369 const char *root_dir,
1371 UnitFileChange **changes,
1372 unsigned *n_changes) {
1379 assert(config_path);
1381 while ((i = hashmap_first(c->will_install))) {
1383 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1387 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1389 q = unit_file_search(c, i, paths, root_dir, false);
1398 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1399 if (r >= 0 && q < 0)
1406 static int install_context_mark_for_removal(
1409 Set **remove_symlinks_to,
1410 const char *config_path,
1411 const char *root_dir) {
1418 assert(config_path);
1420 /* Marks all items for removal */
1422 while ((i = hashmap_first(c->will_install))) {
1424 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1428 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1430 q = unit_file_search(c, i, paths, root_dir, false);
1441 if (unit_name_is_instance(i->name)) {
1445 unit_file = basename(i->path);
1447 if (unit_name_is_instance(unit_file))
1448 /* unit file named as instance exists, thus all symlinks
1449 * pointing to it will be removed */
1450 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1452 /* does not exist, thus we will mark for removal symlinks
1453 * to template unit file */
1454 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1456 /* If i->path is not set, it means that we didn't actually find
1457 * the unit file. But we can still remove symlinks to the
1458 * nonexistent template. */
1459 unit_file = unit_name_template(i->name);
1463 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1467 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1469 if (r >= 0 && q < 0)
1476 int unit_file_enable(
1477 UnitFileScope scope,
1479 const char *root_dir,
1482 UnitFileChange **changes,
1483 unsigned *n_changes) {
1485 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1486 _cleanup_install_context_done_ InstallContext c = {};
1488 _cleanup_free_ char *config_path = NULL;
1492 assert(scope < _UNIT_FILE_SCOPE_MAX);
1494 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1498 r = get_config_path(scope, runtime, root_dir, &config_path);
1502 STRV_FOREACH(i, files) {
1503 r = install_info_add_auto(&c, *i);
1508 /* This will return the number of symlink rules that were
1509 supposed to be created, not the ones actually created. This is
1510 useful to determine whether the passed files had any
1511 installation data at all. */
1513 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1516 int unit_file_disable(
1517 UnitFileScope scope,
1519 const char *root_dir,
1521 UnitFileChange **changes,
1522 unsigned *n_changes) {
1524 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1525 _cleanup_install_context_done_ InstallContext c = {};
1527 _cleanup_free_ char *config_path = NULL;
1528 _cleanup_set_free_free_ Set *remove_symlinks_to = 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 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1550 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1557 int unit_file_reenable(
1558 UnitFileScope scope,
1560 const char *root_dir,
1563 UnitFileChange **changes,
1564 unsigned *n_changes) {
1567 r = unit_file_disable(scope, runtime, root_dir, files,
1568 changes, n_changes);
1572 return unit_file_enable(scope, runtime, root_dir, files, force,
1573 changes, n_changes);
1576 int unit_file_set_default(
1577 UnitFileScope scope,
1578 const char *root_dir,
1581 UnitFileChange **changes,
1582 unsigned *n_changes) {
1584 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1585 _cleanup_install_context_done_ InstallContext c = {};
1586 _cleanup_free_ char *config_path = NULL;
1589 InstallInfo *i = NULL;
1592 assert(scope < _UNIT_FILE_SCOPE_MAX);
1595 if (unit_name_to_type(file) != UNIT_TARGET)
1598 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1602 r = get_config_path(scope, false, root_dir, &config_path);
1606 r = install_info_add_auto(&c, file);
1610 assert_se(i = hashmap_first(c.will_install));
1612 r = unit_file_search(&c, i, &paths, root_dir, false);
1616 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1618 r = create_symlink(i->path, path, force, changes, n_changes);
1625 int unit_file_get_default(
1626 UnitFileScope scope,
1627 const char *root_dir,
1630 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1635 assert(scope < _UNIT_FILE_SCOPE_MAX);
1638 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1642 STRV_FOREACH(p, paths.unit_path) {
1643 _cleanup_free_ char *path = NULL, *tmp = NULL;
1646 if (isempty(root_dir))
1647 path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
1649 path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
1654 r = readlink_malloc(path, &tmp);
1657 else if (r == -EINVAL)
1659 n = strdup(SPECIAL_DEFAULT_TARGET);
1663 n = strdup(basename(tmp));
1675 UnitFileState unit_file_get_state(
1676 UnitFileScope scope,
1677 const char *root_dir,
1680 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1681 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1683 _cleanup_free_ char *path = NULL;
1687 assert(scope < _UNIT_FILE_SCOPE_MAX);
1690 if (root_dir && scope != UNIT_FILE_SYSTEM)
1693 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1696 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1700 STRV_FOREACH(i, paths.unit_path) {
1708 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1710 asprintf(&path, "%s/%s", *i, name);
1715 partial = path + strlen(root_dir) + 1;
1720 * Search for a unit file in our default paths, to
1721 * be sure, that there are no broken symlinks.
1723 if (lstat(path, &st) < 0) {
1725 if (errno != ENOENT)
1728 if (!unit_name_is_instance(name))
1731 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1734 r = null_or_empty_path(path);
1735 if (r < 0 && r != -ENOENT)
1738 state = path_startswith(*i, "/run") ?
1739 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1744 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1750 r = unit_file_can_install(&paths, root_dir, partial, true);
1751 if (r < 0 && errno != ENOENT)
1754 return UNIT_FILE_DISABLED;
1756 return UNIT_FILE_STATIC;
1759 return r < 0 ? r : state;
1762 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
1763 _cleanup_strv_free_ char **files = NULL;
1768 assert(scope < _UNIT_FILE_SCOPE_MAX);
1771 if (scope == UNIT_FILE_SYSTEM)
1772 r = conf_files_list(&files, ".preset", root_dir,
1773 "/etc/systemd/system-preset",
1774 "/usr/local/lib/systemd/system-preset",
1775 "/usr/lib/systemd/system-preset",
1776 #ifdef HAVE_SPLIT_USR
1777 "/lib/systemd/system-preset",
1780 else if (scope == UNIT_FILE_GLOBAL)
1781 r = conf_files_list(&files, ".preset", root_dir,
1782 "/etc/systemd/user-preset",
1783 "/usr/local/lib/systemd/user-preset",
1784 "/usr/lib/systemd/user-preset",
1792 STRV_FOREACH(i, files) {
1793 _cleanup_free_ char *buf = NULL;
1794 _cleanup_fclose_ FILE *f;
1798 p = buf = strjoin(root_dir, "/", *i, NULL);
1804 if (errno == ENOENT)
1811 char line[LINE_MAX], *l;
1813 if (!fgets(line, sizeof(line), f))
1820 if (strchr(COMMENTS "\n", *l))
1823 if (first_word(l, "enable")) {
1825 l += strspn(l, WHITESPACE);
1827 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1828 log_debug("Preset file says enable %s.", name);
1832 } else if (first_word(l, "disable")) {
1834 l += strspn(l, WHITESPACE);
1836 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1837 log_debug("Preset file says disable %s.", name);
1842 log_debug("Couldn't parse line '%s'", l);
1846 /* Default is "enable" */
1847 log_debug("Preset file doesn't say anything about %s, enabling.", name);
1851 int unit_file_preset(
1852 UnitFileScope scope,
1854 const char *root_dir,
1856 UnitFilePresetMode mode,
1858 UnitFileChange **changes,
1859 unsigned *n_changes) {
1861 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1862 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1863 _cleanup_free_ char *config_path = NULL;
1868 assert(scope < _UNIT_FILE_SCOPE_MAX);
1869 assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
1871 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1875 r = get_config_path(scope, runtime, root_dir, &config_path);
1879 STRV_FOREACH(i, files) {
1881 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1884 r = unit_file_query_preset(scope, root_dir, *i);
1888 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1889 r = install_info_add_auto(&plus, *i);
1890 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1891 r = install_info_add_auto(&minus, *i);
1900 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1901 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1903 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1905 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1910 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1911 /* Returns number of symlinks that where supposed to be installed. */
1912 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1920 int unit_file_preset_all(
1921 UnitFileScope scope,
1923 const char *root_dir,
1924 UnitFilePresetMode mode,
1926 UnitFileChange **changes,
1927 unsigned *n_changes) {
1929 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1930 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1931 _cleanup_free_ char *config_path = NULL;
1936 assert(scope < _UNIT_FILE_SCOPE_MAX);
1937 assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
1939 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1943 r = get_config_path(scope, runtime, root_dir, &config_path);
1947 STRV_FOREACH(i, paths.unit_path) {
1948 _cleanup_closedir_ DIR *d = NULL;
1949 _cleanup_free_ char *buf = NULL;
1950 const char *units_dir;
1952 if (!isempty(root_dir)) {
1953 buf = strjoin(root_dir, "/", *i, NULL);
1961 d = opendir(units_dir);
1963 if (errno == ENOENT)
1974 if (!de && errno != 0)
1980 if (ignore_file(de->d_name))
1983 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1986 dirent_ensure_type(d, de);
1988 if (de->d_type != DT_REG)
1991 r = unit_file_query_preset(scope, root_dir, de->d_name);
1995 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1996 r = install_info_add_auto(&plus, de->d_name);
1997 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1998 r = install_info_add_auto(&minus, de->d_name);
2008 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2009 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2011 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
2013 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
2018 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2019 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2027 static void unitfilelist_free(UnitFileList **f) {
2034 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
2036 int unit_file_get_list(
2037 UnitFileScope scope,
2038 const char *root_dir,
2041 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2046 assert(scope < _UNIT_FILE_SCOPE_MAX);
2049 if (root_dir && scope != UNIT_FILE_SYSTEM)
2052 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2056 STRV_FOREACH(i, paths.unit_path) {
2057 _cleanup_closedir_ DIR *d = NULL;
2058 _cleanup_free_ char *buf = NULL;
2059 const char *units_dir;
2061 if (!isempty(root_dir)) {
2062 buf = strjoin(root_dir, "/", *i, NULL);
2070 d = opendir(units_dir);
2072 if (errno == ENOENT)
2079 _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
2084 if (!de && errno != 0)
2090 if (ignore_file(de->d_name))
2093 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2096 if (hashmap_get(h, de->d_name))
2099 dirent_ensure_type(d, de);
2101 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2104 f = new0(UnitFileList, 1);
2108 f->path = path_make_absolute(de->d_name, units_dir);
2112 r = null_or_empty_path(f->path);
2113 if (r < 0 && r != -ENOENT)
2117 path_startswith(*i, "/run") ?
2118 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2122 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2126 f->state = UNIT_FILE_ENABLED;
2130 r = unit_file_can_install(&paths, root_dir, f->path, true);
2131 if (r == -EINVAL || /* Invalid setting? */
2132 r == -EBADMSG || /* Invalid format? */
2133 r == -ENOENT /* Included file not found? */)
2134 f->state = UNIT_FILE_INVALID;
2138 f->state = UNIT_FILE_DISABLED;
2140 f->state = UNIT_FILE_STATIC;
2143 r = hashmap_put(h, basename(f->path), f);
2146 f = NULL; /* prevent cleanup */
2153 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2154 [UNIT_FILE_ENABLED] = "enabled",
2155 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2156 [UNIT_FILE_LINKED] = "linked",
2157 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2158 [UNIT_FILE_MASKED] = "masked",
2159 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2160 [UNIT_FILE_STATIC] = "static",
2161 [UNIT_FILE_DISABLED] = "disabled",
2162 [UNIT_FILE_INVALID] = "invalid",
2165 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2167 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2168 [UNIT_FILE_SYMLINK] = "symlink",
2169 [UNIT_FILE_UNLINK] = "unlink",
2172 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2174 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MODE_MAX] = {
2175 [UNIT_FILE_PRESET_FULL] = "full",
2176 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2177 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2180 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);