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))
272 p = path_make_absolute(de->d_name, path);
276 q = readlink_and_canonicalize(p, &dest);
287 set_get(remove_symlinks_to, dest) ||
288 set_get(remove_symlinks_to, basename(dest));
294 if (unlink(p) < 0 && errno != ENOENT) {
301 rmdir_parents(p, config_path);
303 path_kill_slashes(p);
305 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
307 if (!set_get(remove_symlinks_to, p)) {
309 q = mark_symlink_for_removal(&remove_symlinks_to, p);
322 static int remove_marked_symlinks(
323 Set *remove_symlinks_to,
324 const char *config_path,
325 UnitFileChange **changes,
327 char** instance_whitelist) {
329 _cleanup_close_ int fd = -1;
335 if (set_size(remove_symlinks_to) <= 0)
338 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
346 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
352 /* This takes possession of cfd and closes it */
353 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist);
361 static int find_symlinks_fd(
365 const char *config_path,
366 bool *same_name_link) {
369 _cleanup_closedir_ DIR *d = NULL;
375 assert(same_name_link);
388 if (!de && errno != 0)
394 if (ignore_file(de->d_name))
397 dirent_ensure_type(d, de);
399 if (de->d_type == DT_DIR) {
401 _cleanup_free_ char *p = NULL;
403 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
413 p = path_make_absolute(de->d_name, path);
419 /* This will close nfd, regardless whether it succeeds or not */
420 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
426 } else if (de->d_type == DT_LNK) {
427 _cleanup_free_ char *p = NULL, *dest = NULL;
428 bool found_path, found_dest, b = false;
431 /* Acquire symlink name */
432 p = path_make_absolute(de->d_name, path);
436 /* Acquire symlink destination */
437 q = readlink_and_canonicalize(p, &dest);
447 /* Check if the symlink itself matches what we
449 if (path_is_absolute(name))
450 found_path = path_equal(p, name);
452 found_path = streq(de->d_name, name);
454 /* Check if what the symlink points to
455 * matches what we are looking for */
456 if (path_is_absolute(name))
457 found_dest = path_equal(dest, name);
459 found_dest = streq(basename(dest), name);
461 if (found_path && found_dest) {
462 _cleanup_free_ char *t = NULL;
464 /* Filter out same name links in the main
466 t = path_make_absolute(name, config_path);
470 b = path_equal(t, p);
474 *same_name_link = true;
475 else if (found_path || found_dest)
481 static int find_symlinks(
483 const char *config_path,
484 bool *same_name_link) {
490 assert(same_name_link);
492 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
499 /* This takes possession of fd and closes it */
500 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
503 static int find_symlinks_in_scope(
505 const char *root_dir,
507 UnitFileState *state) {
510 _cleanup_free_ char *path2 = NULL;
511 bool same_name_link_runtime = false, same_name_link = false;
514 assert(scope < _UNIT_FILE_SCOPE_MAX);
517 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
518 _cleanup_free_ char *path = NULL;
520 /* First look in runtime config path */
521 r = get_config_path(scope, true, root_dir, &path);
525 r = find_symlinks(name, path, &same_name_link_runtime);
529 *state = UNIT_FILE_ENABLED_RUNTIME;
534 /* Then look in the normal config path */
535 r = get_config_path(scope, false, root_dir, &path2);
539 r = find_symlinks(name, path2, &same_name_link);
543 *state = UNIT_FILE_ENABLED;
547 /* Hmm, we didn't find it, but maybe we found the same name
549 if (same_name_link_runtime) {
550 *state = UNIT_FILE_LINKED_RUNTIME;
552 } else if (same_name_link) {
553 *state = UNIT_FILE_LINKED;
563 const char *root_dir,
566 UnitFileChange **changes,
567 unsigned *n_changes) {
570 _cleanup_free_ char *prefix = NULL;
574 assert(scope < _UNIT_FILE_SCOPE_MAX);
576 r = get_config_path(scope, runtime, root_dir, &prefix);
580 STRV_FOREACH(i, files) {
581 _cleanup_free_ char *path = NULL;
583 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
589 path = path_make_absolute(*i, prefix);
595 if (symlink("/dev/null", path) >= 0) {
596 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
600 if (errno == EEXIST) {
602 if (null_or_empty_path(path) > 0)
606 if (symlink_atomic("/dev/null", path) >= 0) {
607 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
608 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
624 int unit_file_unmask(
627 const char *root_dir,
629 UnitFileChange **changes,
630 unsigned *n_changes) {
632 char **i, *config_path = NULL;
634 Set *remove_symlinks_to = NULL;
637 assert(scope < _UNIT_FILE_SCOPE_MAX);
639 r = get_config_path(scope, runtime, root_dir, &config_path);
643 STRV_FOREACH(i, files) {
646 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
652 path = path_make_absolute(*i, config_path);
658 q = null_or_empty_path(path);
660 if (unlink(path) >= 0) {
661 mark_symlink_for_removal(&remove_symlinks_to, path);
662 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
671 if (q != -ENOENT && r == 0)
679 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
683 set_free_free(remove_symlinks_to);
692 const char *root_dir,
695 UnitFileChange **changes,
696 unsigned *n_changes) {
698 _cleanup_lookup_paths_free_ LookupPaths paths = {};
700 _cleanup_free_ char *config_path = NULL;
704 assert(scope < _UNIT_FILE_SCOPE_MAX);
706 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
710 r = get_config_path(scope, runtime, root_dir, &config_path);
714 STRV_FOREACH(i, files) {
715 _cleanup_free_ char *path = NULL;
721 if (!path_is_absolute(*i) ||
722 !unit_name_is_valid(fn, TEMPLATE_VALID)) {
728 if (lstat(*i, &st) < 0) {
734 if (!S_ISREG(st.st_mode)) {
739 q = in_search_path(*i, paths.unit_path);
746 path = path_make_absolute(fn, config_path);
750 if (symlink(*i, path) >= 0) {
751 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
755 if (errno == EEXIST) {
756 _cleanup_free_ char *dest = NULL;
758 q = readlink_and_make_absolute(path, &dest);
759 if (q < 0 && errno != ENOENT) {
765 if (q >= 0 && path_equal(dest, *i))
769 if (symlink_atomic(*i, path) >= 0) {
770 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
771 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
787 void unit_file_list_free(Hashmap *h) {
790 while ((i = hashmap_steal_first(h))) {
798 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
801 assert(changes || n_changes == 0);
806 for (i = 0; i < n_changes; i++) {
807 free(changes[i].path);
808 free(changes[i].source);
814 static void install_info_free(InstallInfo *i) {
819 strv_free(i->aliases);
820 strv_free(i->wanted_by);
821 strv_free(i->required_by);
825 static void install_info_hashmap_free(Hashmap *m) {
831 while ((i = hashmap_steal_first(m)))
832 install_info_free(i);
837 static void install_context_done(InstallContext *c) {
840 install_info_hashmap_free(c->will_install);
841 install_info_hashmap_free(c->have_installed);
843 c->will_install = c->have_installed = NULL;
846 static int install_info_add(
850 InstallInfo *i = NULL;
854 assert(name || path);
857 name = basename(path);
859 if (!unit_name_is_valid(name, TEMPLATE_VALID))
862 if (hashmap_get(c->have_installed, name) ||
863 hashmap_get(c->will_install, name))
866 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
870 i = new0(InstallInfo, 1);
874 i->name = strdup(name);
881 i->path = strdup(path);
888 r = hashmap_put(c->will_install, i->name, i);
896 install_info_free(i);
901 static int install_info_add_auto(
903 const char *name_or_path) {
906 assert(name_or_path);
908 if (path_is_absolute(name_or_path))
909 return install_info_add(c, NULL, name_or_path);
911 return install_info_add(c, name_or_path, NULL);
914 static int config_parse_also(const char *unit,
915 const char *filename,
918 unsigned section_line,
928 InstallContext *c = data;
934 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
935 _cleanup_free_ char *n;
942 r = install_info_add(c, n, NULL);
950 static int config_parse_user(const char *unit,
951 const char *filename,
954 unsigned section_line,
961 InstallInfo *i = data;
969 r = install_full_printf(i, rvalue, &printed);
979 static int unit_file_load(
983 bool allow_symlink) {
985 const ConfigTableItem items[] = {
986 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
987 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
988 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
989 { "Install", "Also", config_parse_also, 0, c },
990 { "Exec", "User", config_parse_user, 0, info },
991 { NULL, NULL, NULL, 0, NULL }
995 _cleanup_fclose_ FILE *f = NULL;
1002 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1006 f = fdopen(fd, "re");
1012 r = config_parse(NULL, path, f, NULL,
1013 config_item_table_lookup, (void*) items, true, true, info);
1018 (int) strv_length(info->aliases) +
1019 (int) strv_length(info->wanted_by) +
1020 (int) strv_length(info->required_by);
1023 static int unit_file_search(
1027 const char *root_dir,
1028 bool allow_symlink) {
1040 if (isempty(root_dir))
1043 path = strappenda(root_dir, info->path);
1045 return unit_file_load(c, info, path, allow_symlink);
1050 STRV_FOREACH(p, paths->unit_path) {
1051 _cleanup_free_ char *path = NULL;
1053 if (isempty(root_dir))
1054 path = strjoin(*p, "/", info->name, NULL);
1056 path = strjoin(root_dir, "/", *p, "/", info->name, NULL);
1060 r = unit_file_load(c, info, path, allow_symlink);
1066 if (r != -ENOENT && r != -ELOOP)
1070 if (unit_name_is_instance(info->name)) {
1072 /* Unit file doesn't exist, however instance
1073 * enablement was requested. We will check if it is
1074 * possible to load template unit file. */
1076 _cleanup_free_ char *template = NULL, *template_dir = NULL;
1078 template = unit_name_template(info->name);
1082 STRV_FOREACH(p, paths->unit_path) {
1083 _cleanup_free_ char *path = NULL;
1085 if (isempty(root_dir))
1086 path = strjoin(*p, "/", template, NULL);
1088 path = strjoin(root_dir, "/", *p, "/", template, NULL);
1092 r = unit_file_load(c, info, path, allow_symlink);
1098 if (r != -ENOENT && r != -ELOOP)
1106 static int unit_file_can_install(
1108 const char *root_dir,
1110 bool allow_symlink) {
1112 _cleanup_install_context_done_ InstallContext c = {};
1119 r = install_info_add_auto(&c, name);
1123 assert_se(i = hashmap_first(c.will_install));
1125 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1129 (int) strv_length(i->aliases) +
1130 (int) strv_length(i->wanted_by) +
1131 (int) strv_length(i->required_by);
1136 static int create_symlink(
1137 const char *old_path,
1138 const char *new_path,
1140 UnitFileChange **changes,
1141 unsigned *n_changes) {
1143 _cleanup_free_ char *dest = NULL;
1149 mkdir_parents_label(new_path, 0755);
1151 if (symlink(old_path, new_path) >= 0) {
1152 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1156 if (errno != EEXIST)
1159 r = readlink_and_make_absolute(new_path, &dest);
1163 if (path_equal(dest, old_path))
1169 r = symlink_atomic(old_path, new_path);
1173 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1174 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1179 static int install_info_symlink_alias(
1181 const char *config_path,
1183 UnitFileChange **changes,
1184 unsigned *n_changes) {
1190 assert(config_path);
1192 STRV_FOREACH(s, i->aliases) {
1193 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1195 q = install_full_printf(i, *s, &dst);
1199 alias_path = path_make_absolute(dst, config_path);
1203 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1211 static int install_info_symlink_wants(
1213 const char *config_path,
1215 UnitFileChange **changes,
1216 unsigned *n_changes) {
1222 assert(config_path);
1224 STRV_FOREACH(s, i->wanted_by) {
1225 _cleanup_free_ char *path = NULL, *dst = NULL;
1227 q = install_full_printf(i, *s, &dst);
1231 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1236 if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
1239 q = create_symlink(i->path, path, force, changes, n_changes);
1248 static int install_info_symlink_requires(
1250 const char *config_path,
1252 UnitFileChange **changes,
1253 unsigned *n_changes) {
1259 assert(config_path);
1261 STRV_FOREACH(s, i->required_by) {
1262 _cleanup_free_ char *path = NULL, *dst = NULL;
1264 q = install_full_printf(i, *s, &dst);
1268 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1273 if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
1276 q = create_symlink(i->path, path, force, changes, n_changes);
1285 static int install_info_symlink_link(
1288 const char *config_path,
1290 UnitFileChange **changes,
1291 unsigned *n_changes) {
1293 _cleanup_free_ char *path = NULL;
1298 assert(config_path);
1301 r = in_search_path(i->path, paths->unit_path);
1305 path = strjoin(config_path, "/", i->name, NULL);
1309 return create_symlink(i->path, path, force, changes, n_changes);
1312 static int install_info_apply(
1315 const char *config_path,
1317 UnitFileChange **changes,
1318 unsigned *n_changes) {
1324 assert(config_path);
1326 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1328 q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1332 q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1336 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1343 static int install_context_apply(
1346 const char *config_path,
1347 const char *root_dir,
1349 UnitFileChange **changes,
1350 unsigned *n_changes) {
1357 assert(config_path);
1359 while ((i = hashmap_first(c->will_install))) {
1361 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1365 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1367 q = unit_file_search(c, i, paths, root_dir, false);
1376 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1377 if (r >= 0 && q < 0)
1384 static int install_context_mark_for_removal(
1387 Set **remove_symlinks_to,
1388 const char *config_path,
1389 const char *root_dir) {
1396 assert(config_path);
1398 /* Marks all items for removal */
1400 while ((i = hashmap_first(c->will_install))) {
1402 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1406 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1408 q = unit_file_search(c, i, paths, root_dir, false);
1419 if (unit_name_is_instance(i->name)) {
1423 unit_file = basename(i->path);
1425 if (unit_name_is_instance(unit_file))
1426 /* unit file named as instance exists, thus all symlinks
1427 * pointing to it will be removed */
1428 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1430 /* does not exist, thus we will mark for removal symlinks
1431 * to template unit file */
1432 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1434 /* If i->path is not set, it means that we didn't actually find
1435 * the unit file. But we can still remove symlinks to the
1436 * nonexistent template. */
1437 unit_file = unit_name_template(i->name);
1441 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1445 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1447 if (r >= 0 && q < 0)
1454 int unit_file_enable(
1455 UnitFileScope scope,
1457 const char *root_dir,
1460 UnitFileChange **changes,
1461 unsigned *n_changes) {
1463 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1464 _cleanup_install_context_done_ InstallContext c = {};
1466 _cleanup_free_ char *config_path = NULL;
1470 assert(scope < _UNIT_FILE_SCOPE_MAX);
1472 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1476 r = get_config_path(scope, runtime, root_dir, &config_path);
1480 STRV_FOREACH(i, files) {
1481 r = install_info_add_auto(&c, *i);
1486 /* This will return the number of symlink rules that were
1487 supposed to be created, not the ones actually created. This is
1488 useful to determine whether the passed files had any
1489 installation data at all. */
1491 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1494 int unit_file_disable(
1495 UnitFileScope scope,
1497 const char *root_dir,
1499 UnitFileChange **changes,
1500 unsigned *n_changes) {
1502 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1503 _cleanup_install_context_done_ InstallContext c = {};
1505 _cleanup_free_ char *config_path = NULL;
1506 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1510 assert(scope < _UNIT_FILE_SCOPE_MAX);
1512 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1516 r = get_config_path(scope, runtime, root_dir, &config_path);
1520 STRV_FOREACH(i, files) {
1521 r = install_info_add_auto(&c, *i);
1526 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1528 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1535 int unit_file_reenable(
1536 UnitFileScope scope,
1538 const char *root_dir,
1541 UnitFileChange **changes,
1542 unsigned *n_changes) {
1545 r = unit_file_disable(scope, runtime, root_dir, files,
1546 changes, n_changes);
1550 return unit_file_enable(scope, runtime, root_dir, files, force,
1551 changes, n_changes);
1554 int unit_file_set_default(
1555 UnitFileScope scope,
1556 const char *root_dir,
1559 UnitFileChange **changes,
1560 unsigned *n_changes) {
1562 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1563 _cleanup_install_context_done_ InstallContext c = {};
1564 _cleanup_free_ char *config_path = NULL;
1567 InstallInfo *i = NULL;
1570 assert(scope < _UNIT_FILE_SCOPE_MAX);
1573 if (unit_name_to_type(file) != UNIT_TARGET)
1576 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1580 r = get_config_path(scope, false, root_dir, &config_path);
1584 r = install_info_add_auto(&c, file);
1588 assert_se(i = hashmap_first(c.will_install));
1590 r = unit_file_search(&c, i, &paths, root_dir, false);
1594 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1596 r = create_symlink(i->path, path, force, changes, n_changes);
1603 int unit_file_get_default(
1604 UnitFileScope scope,
1605 const char *root_dir,
1608 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1613 assert(scope < _UNIT_FILE_SCOPE_MAX);
1616 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1620 STRV_FOREACH(p, paths.unit_path) {
1621 _cleanup_free_ char *path = NULL, *tmp = NULL;
1624 if (isempty(root_dir))
1625 path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
1627 path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
1632 r = readlink_malloc(path, &tmp);
1635 else if (r == -EINVAL)
1637 n = strdup(SPECIAL_DEFAULT_TARGET);
1641 n = strdup(basename(tmp));
1653 UnitFileState unit_file_get_state(
1654 UnitFileScope scope,
1655 const char *root_dir,
1658 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1659 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1661 _cleanup_free_ char *path = NULL;
1665 assert(scope < _UNIT_FILE_SCOPE_MAX);
1668 if (root_dir && scope != UNIT_FILE_SYSTEM)
1671 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1674 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1678 STRV_FOREACH(i, paths.unit_path) {
1686 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1688 asprintf(&path, "%s/%s", *i, name);
1693 partial = path + strlen(root_dir) + 1;
1698 * Search for a unit file in our default paths, to
1699 * be sure, that there are no broken symlinks.
1701 if (lstat(path, &st) < 0) {
1703 if (errno != ENOENT)
1706 if (!unit_name_is_instance(name))
1709 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1712 r = null_or_empty_path(path);
1713 if (r < 0 && r != -ENOENT)
1716 state = path_startswith(*i, "/run") ?
1717 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1722 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1728 r = unit_file_can_install(&paths, root_dir, partial, true);
1729 if (r < 0 && errno != ENOENT)
1732 return UNIT_FILE_DISABLED;
1734 return UNIT_FILE_STATIC;
1737 return r < 0 ? r : state;
1740 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
1741 _cleanup_strv_free_ char **files = NULL;
1746 assert(scope < _UNIT_FILE_SCOPE_MAX);
1749 if (scope == UNIT_FILE_SYSTEM)
1750 r = conf_files_list(&files, ".preset", root_dir,
1751 "/etc/systemd/system-preset",
1752 "/usr/local/lib/systemd/system-preset",
1753 "/usr/lib/systemd/system-preset",
1754 #ifdef HAVE_SPLIT_USR
1755 "/lib/systemd/system-preset",
1758 else if (scope == UNIT_FILE_GLOBAL)
1759 r = conf_files_list(&files, ".preset", root_dir,
1760 "/etc/systemd/user-preset",
1761 "/usr/local/lib/systemd/user-preset",
1762 "/usr/lib/systemd/user-preset",
1770 STRV_FOREACH(i, files) {
1771 _cleanup_free_ char *buf = NULL;
1772 _cleanup_fclose_ FILE *f;
1776 p = buf = strjoin(root_dir, "/", *i, NULL);
1782 if (errno == ENOENT)
1789 char line[LINE_MAX], *l;
1791 if (!fgets(line, sizeof(line), f))
1798 if (strchr(COMMENTS "\n", *l))
1801 if (first_word(l, "enable")) {
1803 l += strspn(l, WHITESPACE);
1805 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1806 log_debug("Preset file says enable %s.", name);
1810 } else if (first_word(l, "disable")) {
1812 l += strspn(l, WHITESPACE);
1814 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1815 log_debug("Preset file says disable %s.", name);
1820 log_debug("Couldn't parse line '%s'", l);
1824 /* Default is "enable" */
1825 log_debug("Preset file doesn't say anything about %s, enabling.", name);
1829 int unit_file_preset(
1830 UnitFileScope scope,
1832 const char *root_dir,
1834 UnitFilePresetMode mode,
1836 UnitFileChange **changes,
1837 unsigned *n_changes) {
1839 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1840 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1841 _cleanup_free_ char *config_path = NULL;
1846 assert(scope < _UNIT_FILE_SCOPE_MAX);
1847 assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
1849 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1853 r = get_config_path(scope, runtime, root_dir, &config_path);
1857 STRV_FOREACH(i, files) {
1859 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1862 r = unit_file_query_preset(scope, root_dir, *i);
1866 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1867 r = install_info_add_auto(&plus, *i);
1868 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1869 r = install_info_add_auto(&minus, *i);
1878 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1879 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1881 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1883 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1888 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1889 /* Returns number of symlinks that where supposed to be installed. */
1890 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1898 int unit_file_preset_all(
1899 UnitFileScope scope,
1901 const char *root_dir,
1902 UnitFilePresetMode mode,
1904 UnitFileChange **changes,
1905 unsigned *n_changes) {
1907 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1908 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1909 _cleanup_free_ char *config_path = NULL;
1914 assert(scope < _UNIT_FILE_SCOPE_MAX);
1915 assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
1917 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1921 r = get_config_path(scope, runtime, root_dir, &config_path);
1925 STRV_FOREACH(i, paths.unit_path) {
1926 _cleanup_closedir_ DIR *d = NULL;
1927 _cleanup_free_ char *buf = NULL;
1928 const char *units_dir;
1930 if (!isempty(root_dir)) {
1931 buf = strjoin(root_dir, "/", *i, NULL);
1939 d = opendir(units_dir);
1941 if (errno == ENOENT)
1952 if (!de && errno != 0)
1958 if (ignore_file(de->d_name))
1961 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1964 dirent_ensure_type(d, de);
1966 if (de->d_type != DT_REG)
1969 r = unit_file_query_preset(scope, root_dir, de->d_name);
1973 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1974 r = install_info_add_auto(&plus, de->d_name);
1975 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1976 r = install_info_add_auto(&minus, de->d_name);
1986 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1987 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1989 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1991 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
1996 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1997 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2005 static void unitfilelist_free(UnitFileList **f) {
2012 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
2014 int unit_file_get_list(
2015 UnitFileScope scope,
2016 const char *root_dir,
2019 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2024 assert(scope < _UNIT_FILE_SCOPE_MAX);
2027 if (root_dir && scope != UNIT_FILE_SYSTEM)
2030 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2034 STRV_FOREACH(i, paths.unit_path) {
2035 _cleanup_closedir_ DIR *d = NULL;
2036 _cleanup_free_ char *buf = NULL;
2037 const char *units_dir;
2039 if (!isempty(root_dir)) {
2040 buf = strjoin(root_dir, "/", *i, NULL);
2048 d = opendir(units_dir);
2050 if (errno == ENOENT)
2057 _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
2062 if (!de && errno != 0)
2068 if (ignore_file(de->d_name))
2071 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2074 if (hashmap_get(h, de->d_name))
2077 dirent_ensure_type(d, de);
2079 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2082 f = new0(UnitFileList, 1);
2086 f->path = path_make_absolute(de->d_name, units_dir);
2090 r = null_or_empty_path(f->path);
2091 if (r < 0 && r != -ENOENT)
2095 path_startswith(*i, "/run") ?
2096 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2100 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2104 f->state = UNIT_FILE_ENABLED;
2108 r = unit_file_can_install(&paths, root_dir, f->path, true);
2109 if (r == -EINVAL || /* Invalid setting? */
2110 r == -EBADMSG || /* Invalid format? */
2111 r == -ENOENT /* Included file not found? */)
2112 f->state = UNIT_FILE_INVALID;
2116 f->state = UNIT_FILE_DISABLED;
2118 f->state = UNIT_FILE_STATIC;
2121 r = hashmap_put(h, basename(f->path), f);
2124 f = NULL; /* prevent cleanup */
2131 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2132 [UNIT_FILE_ENABLED] = "enabled",
2133 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2134 [UNIT_FILE_LINKED] = "linked",
2135 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2136 [UNIT_FILE_MASKED] = "masked",
2137 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2138 [UNIT_FILE_STATIC] = "static",
2139 [UNIT_FILE_DISABLED] = "disabled",
2140 [UNIT_FILE_INVALID] = "invalid",
2143 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2145 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2146 [UNIT_FILE_SYMLINK] = "symlink",
2147 [UNIT_FILE_UNLINK] = "unlink",
2150 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2152 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MODE_MAX] = {
2153 [UNIT_FILE_PRESET_FULL] = "full",
2154 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2155 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2158 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);