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, UnitFileScope scope) {
53 assert(scope < _UNIT_FILE_SCOPE_MAX);
57 return lookup_paths_init(paths,
58 scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
59 scope == UNIT_FILE_USER,
63 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
68 assert(scope < _UNIT_FILE_SCOPE_MAX);
73 case UNIT_FILE_SYSTEM:
75 if (root_dir && runtime)
76 asprintf(&p, "%s/run/systemd/system", root_dir);
78 p = strdup("/run/systemd/system");
80 asprintf(&p, "%s/%s", root_dir, SYSTEM_CONFIG_UNIT_PATH);
82 p = strdup(SYSTEM_CONFIG_UNIT_PATH);
86 case UNIT_FILE_GLOBAL:
92 p = strdup("/run/systemd/user");
94 p = strdup(USER_CONFIG_UNIT_PATH);
99 if (root_dir || runtime)
102 r = user_config_home(&p);
104 return r < 0 ? r : -ENOENT;
109 assert_not_reached("Bad scope");
119 static int add_file_change(
120 UnitFileChange **changes,
122 UnitFileChangeType type,
124 const char *source) {
130 assert(!changes == !n_changes);
135 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
143 c[i].path = strdup(path);
148 c[i].source = strdup(source);
160 static int mark_symlink_for_removal(
161 Set **remove_symlinks_to,
169 r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
177 path_kill_slashes(n);
179 r = set_consume(*remove_symlinks_to, n);
181 return r == -EEXIST ? 0 : r;
186 static int remove_marked_symlinks_fd(
187 Set *remove_symlinks_to,
190 const char *config_path,
192 UnitFileChange **changes,
197 _cleanup_closedir_ DIR *d = NULL;
199 assert(remove_symlinks_to);
218 if (!de && errno != 0) {
226 if (ignore_file(de->d_name))
229 dirent_ensure_type(d, de);
231 if (de->d_type == DT_DIR) {
233 _cleanup_free_ char *p = NULL;
235 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
245 p = path_make_absolute(de->d_name, path);
251 /* This will close nfd, regardless whether it succeeds or not */
252 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, files);
257 } else if (de->d_type == DT_LNK) {
258 _cleanup_free_ char *p = NULL, *dest = NULL;
262 p = path_make_absolute(de->d_name, path);
266 q = readlink_and_canonicalize(p, &dest);
277 set_get(remove_symlinks_to, dest) ||
278 set_get(remove_symlinks_to, basename(dest));
280 if (unit_name_is_instance(p))
281 found = found && strv_contains(files, basename(p));
285 if (unlink(p) < 0 && errno != ENOENT) {
290 rmdir_parents(p, config_path);
291 path_kill_slashes(p);
293 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
295 if (!set_get(remove_symlinks_to, p)) {
297 q = mark_symlink_for_removal(&remove_symlinks_to, p);
312 static int remove_marked_symlinks(
313 Set *remove_symlinks_to,
314 const char *config_path,
315 UnitFileChange **changes,
324 if (set_size(remove_symlinks_to) <= 0)
327 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
335 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
341 /* This takes possession of cfd and closes it */
342 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, files);
352 static int find_symlinks_fd(
356 const char *config_path,
357 bool *same_name_link) {
360 _cleanup_closedir_ DIR *d = NULL;
366 assert(same_name_link);
379 if (!de && errno != 0)
385 if (ignore_file(de->d_name))
388 dirent_ensure_type(d, de);
390 if (de->d_type == DT_DIR) {
392 _cleanup_free_ char *p = NULL;
394 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
404 p = path_make_absolute(de->d_name, path);
410 /* This will close nfd, regardless whether it succeeds or not */
411 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
419 } else if (de->d_type == DT_LNK) {
420 _cleanup_free_ char *p = NULL, *dest = NULL;
421 bool found_path, found_dest, b = false;
424 /* Acquire symlink name */
425 p = path_make_absolute(de->d_name, path);
429 /* Acquire symlink destination */
430 q = readlink_and_canonicalize(p, &dest);
440 /* Check if the symlink itself matches what we
442 if (path_is_absolute(name))
443 found_path = path_equal(p, name);
445 found_path = streq(de->d_name, name);
447 /* Check if what the symlink points to
448 * matches what we are looking for */
449 if (path_is_absolute(name))
450 found_dest = path_equal(dest, name);
452 found_dest = streq(basename(dest), name);
454 if (found_path && found_dest) {
455 _cleanup_free_ char *t = NULL;
457 /* Filter out same name links in the main
459 t = path_make_absolute(name, config_path);
463 b = path_equal(t, p);
467 *same_name_link = true;
468 else if (found_path || found_dest)
474 static int find_symlinks(
476 const char *config_path,
477 bool *same_name_link) {
483 assert(same_name_link);
485 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
492 /* This takes possession of fd and closes it */
493 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
496 static int find_symlinks_in_scope(
498 const char *root_dir,
500 UnitFileState *state) {
503 _cleanup_free_ char *path2 = NULL;
504 bool same_name_link_runtime = false, same_name_link = false;
507 assert(scope < _UNIT_FILE_SCOPE_MAX);
510 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
511 _cleanup_free_ char *path = NULL;
513 /* First look in runtime config path */
514 r = get_config_path(scope, true, root_dir, &path);
518 r = find_symlinks(name, path, &same_name_link_runtime);
522 *state = UNIT_FILE_ENABLED_RUNTIME;
527 /* Then look in the normal config path */
528 r = get_config_path(scope, false, root_dir, &path2);
532 r = find_symlinks(name, path2, &same_name_link);
536 *state = UNIT_FILE_ENABLED;
540 /* Hmm, we didn't find it, but maybe we found the same name
542 if (same_name_link_runtime) {
543 *state = UNIT_FILE_LINKED_RUNTIME;
545 } else if (same_name_link) {
546 *state = UNIT_FILE_LINKED;
556 const char *root_dir,
559 UnitFileChange **changes,
560 unsigned *n_changes) {
563 _cleanup_free_ char *prefix;
567 assert(scope < _UNIT_FILE_SCOPE_MAX);
569 r = get_config_path(scope, runtime, root_dir, &prefix);
573 STRV_FOREACH(i, files) {
574 _cleanup_free_ char *path = NULL;
576 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
582 path = path_make_absolute(*i, prefix);
588 if (symlink("/dev/null", path) >= 0) {
589 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
594 if (errno == EEXIST) {
596 if (null_or_empty_path(path) > 0)
602 if (symlink("/dev/null", path) >= 0) {
604 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
605 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
622 int unit_file_unmask(
625 const char *root_dir,
627 UnitFileChange **changes,
628 unsigned *n_changes) {
630 char **i, *config_path = NULL;
632 Set *remove_symlinks_to = NULL;
635 assert(scope < _UNIT_FILE_SCOPE_MAX);
637 r = get_config_path(scope, runtime, root_dir, &config_path);
641 STRV_FOREACH(i, files) {
644 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
650 path = path_make_absolute(*i, config_path);
656 q = null_or_empty_path(path);
658 if (unlink(path) >= 0) {
659 mark_symlink_for_removal(&remove_symlinks_to, path);
660 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
669 if (q != -ENOENT && r == 0)
677 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
681 set_free_free(remove_symlinks_to);
690 const char *root_dir,
693 UnitFileChange **changes,
694 unsigned *n_changes) {
696 _cleanup_lookup_paths_free_ LookupPaths paths = {};
698 _cleanup_free_ char *config_path = NULL;
702 assert(scope < _UNIT_FILE_SCOPE_MAX);
704 r = lookup_paths_init_from_scope(&paths, scope);
708 r = get_config_path(scope, runtime, root_dir, &config_path);
712 STRV_FOREACH(i, files) {
713 _cleanup_free_ char *path = NULL;
719 if (!path_is_absolute(*i) ||
720 !unit_name_is_valid(fn, TEMPLATE_VALID)) {
726 if (lstat(*i, &st) < 0) {
732 if (!S_ISREG(st.st_mode)) {
737 q = in_search_path(*i, paths.unit_path);
744 path = path_make_absolute(fn, config_path);
748 if (symlink(*i, path) >= 0) {
749 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
753 if (errno == EEXIST) {
754 _cleanup_free_ char *dest = NULL;
756 q = readlink_and_make_absolute(path, &dest);
758 if (q < 0 && errno != ENOENT) {
764 if (q >= 0 && path_equal(dest, *i))
770 if (symlink(*i, path) >= 0) {
772 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
773 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
790 void unit_file_list_free(Hashmap *h) {
793 while ((i = hashmap_steal_first(h))) {
801 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
804 assert(changes || n_changes == 0);
809 for (i = 0; i < n_changes; i++) {
810 free(changes[i].path);
811 free(changes[i].source);
817 static void install_info_free(InstallInfo *i) {
822 strv_free(i->aliases);
823 strv_free(i->wanted_by);
824 strv_free(i->required_by);
828 static void install_info_hashmap_free(Hashmap *m) {
834 while ((i = hashmap_steal_first(m)))
835 install_info_free(i);
840 static void install_context_done(InstallContext *c) {
843 install_info_hashmap_free(c->will_install);
844 install_info_hashmap_free(c->have_installed);
846 c->will_install = c->have_installed = NULL;
849 static int install_info_add(
853 InstallInfo *i = NULL;
857 assert(name || path);
860 name = basename(path);
862 if (!unit_name_is_valid(name, TEMPLATE_VALID))
865 if (hashmap_get(c->have_installed, name) ||
866 hashmap_get(c->will_install, name))
869 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
873 i = new0(InstallInfo, 1);
877 i->name = strdup(name);
884 i->path = strdup(path);
891 r = hashmap_put(c->will_install, i->name, i);
899 install_info_free(i);
904 static int install_info_add_auto(
906 const char *name_or_path) {
909 assert(name_or_path);
911 if (path_is_absolute(name_or_path))
912 return install_info_add(c, NULL, name_or_path);
914 return install_info_add(c, name_or_path, NULL);
917 static int config_parse_also(const char *unit,
918 const char *filename,
921 unsigned section_line,
931 InstallContext *c = data;
937 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
938 _cleanup_free_ char *n;
945 r = install_info_add(c, n, NULL);
953 static int config_parse_user(const char *unit,
954 const char *filename,
957 unsigned section_line,
964 InstallInfo *i = data;
972 r = install_full_printf(i, rvalue, &printed);
982 static int unit_file_load(
986 bool allow_symlink) {
988 const ConfigTableItem items[] = {
989 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
990 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
991 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
992 { "Install", "Also", config_parse_also, 0, c },
993 { "Exec", "User", config_parse_user, 0, info },
994 { NULL, NULL, NULL, 0, NULL }
998 _cleanup_fclose_ FILE *f = NULL;
1005 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1009 f = fdopen(fd, "re");
1015 r = config_parse(NULL, path, f, NULL,
1016 config_item_table_lookup, (void*) items, true, true, info);
1021 (int) strv_length(info->aliases) +
1022 (int) strv_length(info->wanted_by) +
1023 (int) strv_length(info->required_by);
1026 static int unit_file_search(
1030 const char *root_dir,
1031 bool allow_symlink) {
1041 char *full_path = NULL;
1043 if (!isempty(root_dir))
1044 full_path = strappenda(root_dir, info->path);
1046 return unit_file_load(c, info, full_path ?: info->path, allow_symlink);
1051 STRV_FOREACH(p, paths->unit_path) {
1052 _cleanup_free_ char *path = NULL, *full_path = NULL;
1054 path = strjoin(*p, "/", info->name, NULL);
1058 if (!isempty(root_dir)) {
1059 full_path = strappend(root_dir, path);
1064 r = unit_file_load(c, info, full_path ?: path, allow_symlink);
1068 } else if (r == -ENOENT && unit_name_is_instance(info->name)) {
1069 /* Unit file doesn't exist, however instance enablement was requested.
1070 * We will check if it is possible to load template unit file. */
1071 _cleanup_free_ char *template = NULL, *template_dir = NULL;
1073 template = unit_name_template(info->name);
1077 /* We will reuse path variable since we don't need it anymore. */
1078 template_dir = path;
1079 *(strrchr(template_dir, '/') + 1) = '\0';
1081 path = strappend(template_dir, template);
1085 if (!isempty(root_dir)) {
1087 full_path = strappend(root_dir, path);
1092 /* Let's try to load template unit. */
1093 r = unit_file_load(c, info, full_path ?: path, allow_symlink);
1100 if (r != -ENOENT && r != -ELOOP)
1107 static int unit_file_can_install(
1109 const char *root_dir,
1111 bool allow_symlink) {
1113 _cleanup_install_context_done_ InstallContext c = {};
1120 r = install_info_add_auto(&c, name);
1124 assert_se(i = hashmap_first(c.will_install));
1126 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1130 (int) strv_length(i->aliases) +
1131 (int) strv_length(i->wanted_by) +
1132 (int) strv_length(i->required_by);
1137 static int create_symlink(
1138 const char *old_path,
1139 const char *new_path,
1141 UnitFileChange **changes,
1142 unsigned *n_changes) {
1144 _cleanup_free_ char *dest = NULL;
1150 mkdir_parents_label(new_path, 0755);
1152 if (symlink(old_path, new_path) >= 0) {
1153 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1157 if (errno != EEXIST)
1160 r = readlink_and_make_absolute(new_path, &dest);
1164 if (path_equal(dest, old_path))
1170 r = unlink(new_path);
1171 if (r < 0 && errno != ENOENT)
1174 if (symlink(old_path, new_path) >= 0) {
1175 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1176 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1183 static int install_info_symlink_alias(
1185 const char *config_path,
1187 UnitFileChange **changes,
1188 unsigned *n_changes) {
1194 assert(config_path);
1196 STRV_FOREACH(s, i->aliases) {
1197 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1199 q = install_full_printf(i, *s, &dst);
1203 alias_path = path_make_absolute(dst, config_path);
1207 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1215 static int install_info_symlink_wants(
1217 const char *config_path,
1219 UnitFileChange **changes,
1220 unsigned *n_changes) {
1226 assert(config_path);
1228 STRV_FOREACH(s, i->wanted_by) {
1229 _cleanup_free_ char *path = NULL, *dst = NULL;
1231 q = install_full_printf(i, *s, &dst);
1235 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1240 if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
1243 q = create_symlink(i->path, path, force, changes, n_changes);
1252 static int install_info_symlink_requires(
1254 const char *config_path,
1256 UnitFileChange **changes,
1257 unsigned *n_changes) {
1263 assert(config_path);
1265 STRV_FOREACH(s, i->required_by) {
1266 _cleanup_free_ char *path = NULL, *dst = NULL;
1268 q = install_full_printf(i, *s, &dst);
1272 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1277 if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
1280 q = create_symlink(i->path, path, force, changes, n_changes);
1289 static int install_info_symlink_link(
1292 const char *config_path,
1294 UnitFileChange **changes,
1295 unsigned *n_changes) {
1298 _cleanup_free_ char *path = NULL;
1302 assert(config_path);
1305 r = in_search_path(i->path, paths->unit_path);
1309 if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1312 r = create_symlink(i->path, path, force, changes, n_changes);
1316 static int install_info_apply(
1319 const char *config_path,
1321 UnitFileChange **changes,
1322 unsigned *n_changes) {
1328 assert(config_path);
1330 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1332 q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1336 q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1340 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1347 static int install_context_apply(
1350 const char *config_path,
1351 const char *root_dir,
1353 UnitFileChange **changes,
1354 unsigned *n_changes) {
1361 assert(config_path);
1363 while ((i = hashmap_first(c->will_install))) {
1365 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1369 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1371 q = unit_file_search(c, i, paths, root_dir, false);
1380 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1381 if (r >= 0 && q < 0)
1388 static int install_context_mark_for_removal(
1391 Set **remove_symlinks_to,
1392 const char *config_path,
1393 const char *root_dir) {
1400 assert(config_path);
1402 /* Marks all items for removal */
1404 while ((i = hashmap_first(c->will_install))) {
1406 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1410 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1412 q = unit_file_search(c, i, paths, root_dir, false);
1423 if (unit_name_is_instance(i->name)) {
1427 unit_file = basename(i->path);
1429 if (unit_name_is_instance(unit_file))
1430 /* unit file named as instance exists, thus all symlinks
1431 * pointing to it will be removed */
1432 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1434 /* does not exist, thus we will mark for removal symlinks
1435 * to template unit file */
1436 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1438 /* If i->path is not set, it means that we didn't actually find
1439 * the unit file. But we can still remove symlinks to the
1440 * nonexistent template. */
1441 unit_file = unit_name_template(i->name);
1445 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1449 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1451 if (r >= 0 && q < 0)
1458 int unit_file_enable(
1459 UnitFileScope scope,
1461 const char *root_dir,
1464 UnitFileChange **changes,
1465 unsigned *n_changes) {
1467 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1468 _cleanup_install_context_done_ InstallContext c = {};
1470 _cleanup_free_ char *config_path = NULL;
1474 assert(scope < _UNIT_FILE_SCOPE_MAX);
1476 r = lookup_paths_init_from_scope(&paths, scope);
1480 r = get_config_path(scope, runtime, root_dir, &config_path);
1484 STRV_FOREACH(i, files) {
1485 r = install_info_add_auto(&c, *i);
1490 /* This will return the number of symlink rules that were
1491 supposed to be created, not the ones actually created. This is
1492 useful to determine whether the passed files had any
1493 installation data at all. */
1495 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1498 int unit_file_disable(
1499 UnitFileScope scope,
1501 const char *root_dir,
1503 UnitFileChange **changes,
1504 unsigned *n_changes) {
1506 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1507 _cleanup_install_context_done_ InstallContext c = {};
1509 _cleanup_free_ char *config_path = NULL;
1510 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1514 assert(scope < _UNIT_FILE_SCOPE_MAX);
1516 r = lookup_paths_init_from_scope(&paths, scope);
1520 r = get_config_path(scope, runtime, root_dir, &config_path);
1524 STRV_FOREACH(i, files) {
1525 r = install_info_add_auto(&c, *i);
1530 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1532 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1539 int unit_file_reenable(
1540 UnitFileScope scope,
1542 const char *root_dir,
1545 UnitFileChange **changes,
1546 unsigned *n_changes) {
1549 r = unit_file_disable(scope, runtime, root_dir, files,
1550 changes, n_changes);
1554 return unit_file_enable(scope, runtime, root_dir, files, force,
1555 changes, n_changes);
1558 int unit_file_set_default(
1559 UnitFileScope scope,
1560 const char *root_dir,
1563 UnitFileChange **changes,
1564 unsigned *n_changes) {
1566 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1567 _cleanup_install_context_done_ InstallContext c = {};
1568 _cleanup_free_ char *config_path = NULL;
1571 InstallInfo *i = NULL;
1574 assert(scope < _UNIT_FILE_SCOPE_MAX);
1577 if (unit_name_to_type(file) != UNIT_TARGET)
1580 r = lookup_paths_init_from_scope(&paths, scope);
1584 r = get_config_path(scope, false, root_dir, &config_path);
1588 r = install_info_add_auto(&c, file);
1592 assert_se(i = hashmap_first(c.will_install));
1594 r = unit_file_search(&c, i, &paths, root_dir, false);
1598 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1600 r = create_symlink(i->path, path, force, changes, n_changes);
1607 int unit_file_get_default(
1608 UnitFileScope scope,
1609 const char *root_dir,
1612 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1617 assert(scope < _UNIT_FILE_SCOPE_MAX);
1620 r = lookup_paths_init_from_scope(&paths, scope);
1624 STRV_FOREACH(p, paths.unit_path) {
1625 _cleanup_free_ char *path = NULL, *tmp = NULL;
1628 if (isempty(root_dir))
1629 path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
1631 path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
1636 r = readlink_malloc(path, &tmp);
1639 else if (r == -EINVAL)
1641 n = strdup(SPECIAL_DEFAULT_TARGET);
1645 n = strdup(basename(tmp));
1657 UnitFileState unit_file_get_state(
1658 UnitFileScope scope,
1659 const char *root_dir,
1662 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1663 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1665 _cleanup_free_ char *path = NULL;
1669 assert(scope < _UNIT_FILE_SCOPE_MAX);
1672 if (root_dir && scope != UNIT_FILE_SYSTEM)
1675 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1678 r = lookup_paths_init_from_scope(&paths, scope);
1682 STRV_FOREACH(i, paths.unit_path) {
1689 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1691 asprintf(&path, "%s/%s", *i, name);
1697 * Search for a unit file in our default paths, to
1698 * be sure, that there are no broken symlinks.
1700 if (lstat(path, &st) < 0) {
1702 if (errno != ENOENT)
1705 if (!unit_name_is_instance(name))
1708 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1711 r = null_or_empty_path(path);
1712 if (r < 0 && r != -ENOENT)
1715 state = path_startswith(*i, "/run") ?
1716 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1721 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1727 r = unit_file_can_install(&paths, root_dir, path, true);
1728 if (r < 0 && errno != ENOENT)
1731 return UNIT_FILE_DISABLED;
1733 return UNIT_FILE_STATIC;
1736 return r < 0 ? r : state;
1739 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1740 _cleanup_strv_free_ char **files = NULL;
1745 assert(scope < _UNIT_FILE_SCOPE_MAX);
1748 if (scope == UNIT_FILE_SYSTEM)
1749 r = conf_files_list(&files, ".preset", NULL,
1750 "/etc/systemd/system-preset",
1751 "/usr/local/lib/systemd/system-preset",
1752 "/usr/lib/systemd/system-preset",
1753 #ifdef HAVE_SPLIT_USR
1754 "/lib/systemd/system-preset",
1757 else if (scope == UNIT_FILE_GLOBAL)
1758 r = conf_files_list(&files, ".preset", NULL,
1759 "/etc/systemd/user-preset",
1760 "/usr/local/lib/systemd/user-preset",
1761 "/usr/lib/systemd/user-preset",
1769 STRV_FOREACH(i, files) {
1770 _cleanup_fclose_ FILE *f;
1772 f = fopen(*i, "re");
1774 if (errno == ENOENT)
1781 char line[LINE_MAX], *l;
1783 if (!fgets(line, sizeof(line), f))
1790 if (strchr(COMMENTS "\n", *l))
1793 if (first_word(l, "enable")) {
1795 l += strspn(l, WHITESPACE);
1797 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1800 } else if (first_word(l, "disable")) {
1802 l += strspn(l, WHITESPACE);
1804 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1808 log_debug("Couldn't parse line '%s'", l);
1812 /* Default is "enable" */
1816 int unit_file_preset(
1817 UnitFileScope scope,
1819 const char *root_dir,
1822 UnitFileChange **changes,
1823 unsigned *n_changes) {
1825 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1826 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1828 _cleanup_free_ char *config_path = NULL;
1829 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1833 assert(scope < _UNIT_FILE_SCOPE_MAX);
1835 r = lookup_paths_init_from_scope(&paths, scope);
1839 r = get_config_path(scope, runtime, root_dir, &config_path);
1843 STRV_FOREACH(i, files) {
1845 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1848 r = unit_file_query_preset(scope, *i);
1853 r = install_info_add_auto(&plus, *i);
1855 r = install_info_add_auto(&minus, *i);
1861 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to,
1862 config_path, root_dir);
1864 q = remove_marked_symlinks(remove_symlinks_to, config_path,
1865 changes, n_changes, files);
1869 /* Returns number of symlinks that where supposed to be installed. */
1870 q = install_context_apply(&plus, &paths, config_path, root_dir, force,
1871 changes, n_changes);
1878 static void unitfilelist_free(UnitFileList **f) {
1885 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
1887 int unit_file_get_list(
1888 UnitFileScope scope,
1889 const char *root_dir,
1892 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1894 _cleanup_free_ char *buf = NULL;
1895 _cleanup_closedir_ DIR *d = NULL;
1899 assert(scope < _UNIT_FILE_SCOPE_MAX);
1902 if (root_dir && scope != UNIT_FILE_SYSTEM)
1905 r = lookup_paths_init_from_scope(&paths, scope);
1909 STRV_FOREACH(i, paths.unit_path) {
1910 const char *units_dir;
1916 if (asprintf(&buf, "%s/%s", root_dir, *i) < 0)
1926 d = opendir(units_dir);
1928 if (errno == ENOENT)
1936 _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
1940 if (!de && errno != 0)
1946 if (ignore_file(de->d_name))
1949 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1952 if (hashmap_get(h, de->d_name))
1955 r = dirent_ensure_type(d, de);
1963 if (de->d_type != DT_LNK && de->d_type != DT_REG)
1966 f = new0(UnitFileList, 1);
1970 f->path = path_make_absolute(de->d_name, units_dir);
1974 r = null_or_empty_path(f->path);
1975 if (r < 0 && r != -ENOENT)
1979 path_startswith(*i, "/run") ?
1980 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1984 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
1988 f->state = UNIT_FILE_ENABLED;
1992 r = unit_file_can_install(&paths, root_dir, f->path, true);
1993 if (r == -EINVAL || /* Invalid setting? */
1994 r == -EBADMSG || /* Invalid format? */
1995 r == -ENOENT /* Included file not found? */)
1996 f->state = UNIT_FILE_INVALID;
2000 f->state = UNIT_FILE_DISABLED;
2002 f->state = UNIT_FILE_STATIC;
2005 r = hashmap_put(h, basename(f->path), f);
2008 f = NULL; /* prevent cleanup */
2015 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2016 [UNIT_FILE_ENABLED] = "enabled",
2017 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2018 [UNIT_FILE_LINKED] = "linked",
2019 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2020 [UNIT_FILE_MASKED] = "masked",
2021 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2022 [UNIT_FILE_STATIC] = "static",
2023 [UNIT_FILE_DISABLED] = "disabled",
2024 [UNIT_FILE_INVALID] = "invalid",
2027 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2029 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2030 [UNIT_FILE_SYMLINK] = "symlink",
2031 [UNIT_FILE_UNLINK] = "unlink",
2034 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);