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);
207 close_nointr_nofail(fd);
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);
247 close_nointr_nofail(nfd);
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);
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);
347 close_nointr_nofail(fd);
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);
370 close_nointr_nofail(fd);
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);
406 close_nointr_nofail(nfd);
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)
476 static int find_symlinks(
478 const char *config_path,
479 bool *same_name_link) {
485 assert(same_name_link);
487 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
494 /* This takes possession of fd and closes it */
495 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
498 static int find_symlinks_in_scope(
500 const char *root_dir,
502 UnitFileState *state) {
505 _cleanup_free_ char *path2 = NULL;
506 bool same_name_link_runtime = false, same_name_link = false;
509 assert(scope < _UNIT_FILE_SCOPE_MAX);
512 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
513 _cleanup_free_ char *path = NULL;
515 /* First look in runtime config path */
516 r = get_config_path(scope, true, root_dir, &path);
520 r = find_symlinks(name, path, &same_name_link_runtime);
524 *state = UNIT_FILE_ENABLED_RUNTIME;
529 /* Then look in the normal config path */
530 r = get_config_path(scope, false, root_dir, &path2);
534 r = find_symlinks(name, path2, &same_name_link);
538 *state = UNIT_FILE_ENABLED;
542 /* Hmm, we didn't find it, but maybe we found the same name
544 if (same_name_link_runtime) {
545 *state = UNIT_FILE_LINKED_RUNTIME;
547 } else if (same_name_link) {
548 *state = UNIT_FILE_LINKED;
558 const char *root_dir,
561 UnitFileChange **changes,
562 unsigned *n_changes) {
565 _cleanup_free_ char *prefix;
569 assert(scope < _UNIT_FILE_SCOPE_MAX);
571 r = get_config_path(scope, runtime, root_dir, &prefix);
575 STRV_FOREACH(i, files) {
576 _cleanup_free_ char *path = NULL;
578 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
584 path = path_make_absolute(*i, prefix);
590 if (symlink("/dev/null", path) >= 0) {
591 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
596 if (errno == EEXIST) {
598 if (null_or_empty_path(path) > 0)
604 if (symlink("/dev/null", path) >= 0) {
606 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
607 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);
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);
760 if (q < 0 && errno != ENOENT) {
766 if (q >= 0 && path_equal(dest, *i))
772 if (symlink(*i, path) >= 0) {
774 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
775 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
792 void unit_file_list_free(Hashmap *h) {
795 while ((i = hashmap_steal_first(h))) {
803 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
806 assert(changes || n_changes == 0);
811 for (i = 0; i < n_changes; i++) {
812 free(changes[i].path);
813 free(changes[i].source);
819 static void install_info_free(InstallInfo *i) {
824 strv_free(i->aliases);
825 strv_free(i->wanted_by);
826 strv_free(i->required_by);
830 static void install_info_hashmap_free(Hashmap *m) {
836 while ((i = hashmap_steal_first(m)))
837 install_info_free(i);
842 static void install_context_done(InstallContext *c) {
845 install_info_hashmap_free(c->will_install);
846 install_info_hashmap_free(c->have_installed);
848 c->will_install = c->have_installed = NULL;
851 static int install_info_add(
855 InstallInfo *i = NULL;
859 assert(name || path);
862 name = basename(path);
864 if (!unit_name_is_valid(name, TEMPLATE_VALID))
867 if (hashmap_get(c->have_installed, name) ||
868 hashmap_get(c->will_install, name))
871 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
875 i = new0(InstallInfo, 1);
879 i->name = strdup(name);
886 i->path = strdup(path);
893 r = hashmap_put(c->will_install, i->name, i);
901 install_info_free(i);
906 static int install_info_add_auto(
908 const char *name_or_path) {
911 assert(name_or_path);
913 if (path_is_absolute(name_or_path))
914 return install_info_add(c, NULL, name_or_path);
916 return install_info_add(c, name_or_path, NULL);
919 static int config_parse_also(const char *unit,
920 const char *filename,
923 unsigned section_line,
933 InstallContext *c = data;
939 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
940 _cleanup_free_ char *n;
947 r = install_info_add(c, n, NULL);
955 static int config_parse_user(const char *unit,
956 const char *filename,
959 unsigned section_line,
966 InstallInfo *i = data;
974 r = install_full_printf(i, rvalue, &printed);
984 static int unit_file_load(
988 bool allow_symlink) {
990 const ConfigTableItem items[] = {
991 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
992 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
993 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
994 { "Install", "Also", config_parse_also, 0, c },
995 { "Exec", "User", config_parse_user, 0, info },
996 { NULL, NULL, NULL, 0, NULL }
1000 _cleanup_fclose_ FILE *f = NULL;
1007 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1011 f = fdopen(fd, "re");
1013 close_nointr_nofail(fd);
1017 r = config_parse(NULL, path, f, NULL,
1018 config_item_table_lookup, (void*) items, true, true, info);
1023 (int) strv_length(info->aliases) +
1024 (int) strv_length(info->wanted_by) +
1025 (int) strv_length(info->required_by);
1028 static int unit_file_search(
1032 const char *root_dir,
1033 bool allow_symlink) {
1043 return unit_file_load(c, info, info->path, allow_symlink);
1047 STRV_FOREACH(p, paths->unit_path) {
1050 if (isempty(root_dir))
1051 asprintf(&path, "%s/%s", *p, info->name);
1053 asprintf(&path, "%s/%s/%s", root_dir, *p, info->name);
1058 r = unit_file_load(c, info, path, allow_symlink);
1063 if (r == -ENOENT && unit_name_is_instance(info->name)) {
1064 /* Unit file doesn't exist, however instance enablement was requested.
1065 * We will check if it is possible to load template unit file. */
1066 char *template = NULL,
1067 *template_path = NULL,
1068 *template_dir = NULL;
1070 template = unit_name_template(info->name);
1076 /* We will reuse path variable since we don't need it anymore. */
1077 template_dir = path;
1078 *(strrchr(path, '/') + 1) = '\0';
1080 template_path = strjoin(template_dir, template, NULL);
1081 if (!template_path) {
1087 /* Let's try to load template unit. */
1088 r = unit_file_load(c, info, template_path, allow_symlink);
1090 info->path = strdup(template_path);
1094 free(template_path);
1100 free(template_path);
1105 if (r != -ENOENT && r != -ELOOP)
1112 static int unit_file_can_install(
1114 const char *root_dir,
1116 bool allow_symlink) {
1118 _cleanup_install_context_done_ InstallContext c = {};
1125 r = install_info_add_auto(&c, name);
1129 assert_se(i = hashmap_first(c.will_install));
1131 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1135 (int) strv_length(i->aliases) +
1136 (int) strv_length(i->wanted_by) +
1137 (int) strv_length(i->required_by);
1142 static int create_symlink(
1143 const char *old_path,
1144 const char *new_path,
1146 UnitFileChange **changes,
1147 unsigned *n_changes) {
1149 _cleanup_free_ char *dest = NULL;
1155 mkdir_parents_label(new_path, 0755);
1157 if (symlink(old_path, new_path) >= 0) {
1158 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1162 if (errno != EEXIST)
1165 r = readlink_and_make_absolute(new_path, &dest);
1169 if (path_equal(dest, old_path))
1177 if (symlink(old_path, new_path) >= 0) {
1178 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1179 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1186 static int install_info_symlink_alias(
1188 const char *config_path,
1190 UnitFileChange **changes,
1191 unsigned *n_changes) {
1197 assert(config_path);
1199 STRV_FOREACH(s, i->aliases) {
1200 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1202 q = install_full_printf(i, *s, &dst);
1206 alias_path = path_make_absolute(dst, config_path);
1210 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1218 static int install_info_symlink_wants(
1220 const char *config_path,
1222 UnitFileChange **changes,
1223 unsigned *n_changes) {
1229 assert(config_path);
1231 STRV_FOREACH(s, i->wanted_by) {
1232 _cleanup_free_ char *path = NULL, *dst = NULL;
1234 q = install_full_printf(i, *s, &dst);
1238 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1243 if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
1246 q = create_symlink(i->path, path, force, changes, n_changes);
1255 static int install_info_symlink_requires(
1257 const char *config_path,
1259 UnitFileChange **changes,
1260 unsigned *n_changes) {
1266 assert(config_path);
1268 STRV_FOREACH(s, i->required_by) {
1269 _cleanup_free_ char *path = NULL, *dst = NULL;
1271 q = install_full_printf(i, *s, &dst);
1275 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1280 if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
1283 q = create_symlink(i->path, path, force, changes, n_changes);
1292 static int install_info_symlink_link(
1295 const char *config_path,
1297 UnitFileChange **changes,
1298 unsigned *n_changes) {
1301 _cleanup_free_ char *path = NULL;
1305 assert(config_path);
1308 r = in_search_path(i->path, paths->unit_path);
1312 if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1315 r = create_symlink(i->path, path, force, changes, n_changes);
1319 static int install_info_apply(
1322 const char *config_path,
1324 UnitFileChange **changes,
1325 unsigned *n_changes) {
1331 assert(config_path);
1333 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1335 q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1339 q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1343 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1350 static int install_context_apply(
1353 const char *config_path,
1354 const char *root_dir,
1356 UnitFileChange **changes,
1357 unsigned *n_changes) {
1364 assert(config_path);
1366 while ((i = hashmap_first(c->will_install))) {
1368 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1372 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1374 q = unit_file_search(c, i, paths, root_dir, false);
1383 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1384 if (r >= 0 && q < 0)
1391 static int install_context_mark_for_removal(
1394 Set **remove_symlinks_to,
1395 const char *config_path,
1396 const char *root_dir) {
1403 assert(config_path);
1405 /* Marks all items for removal */
1407 while ((i = hashmap_first(c->will_install))) {
1409 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1413 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1415 q = unit_file_search(c, i, paths, root_dir, false);
1426 if (unit_name_is_instance(i->name)) {
1430 unit_file = basename(i->path);
1432 if (unit_name_is_instance(unit_file))
1433 /* unit file named as instance exists, thus all symlinks
1434 * pointing to it will be removed */
1435 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1437 /* does not exist, thus we will mark for removal symlinks
1438 * to template unit file */
1439 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1441 /* If i->path is not set, it means that we didn't actually find
1442 * the unit file. But we can still remove symlinks to the
1443 * nonexistent template. */
1444 unit_file = unit_name_template(i->name);
1448 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1452 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1454 if (r >= 0 && q < 0)
1461 int unit_file_enable(
1462 UnitFileScope scope,
1464 const char *root_dir,
1467 UnitFileChange **changes,
1468 unsigned *n_changes) {
1470 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1471 _cleanup_install_context_done_ InstallContext c = {};
1473 _cleanup_free_ char *config_path = NULL;
1477 assert(scope < _UNIT_FILE_SCOPE_MAX);
1479 r = lookup_paths_init_from_scope(&paths, scope);
1483 r = get_config_path(scope, runtime, root_dir, &config_path);
1487 STRV_FOREACH(i, files) {
1488 r = install_info_add_auto(&c, *i);
1493 /* This will return the number of symlink rules that were
1494 supposed to be created, not the ones actually created. This is
1495 useful to determine whether the passed files had any
1496 installation data at all. */
1497 r = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1501 int unit_file_disable(
1502 UnitFileScope scope,
1504 const char *root_dir,
1506 UnitFileChange **changes,
1507 unsigned *n_changes) {
1509 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1510 _cleanup_install_context_done_ InstallContext c = {};
1512 _cleanup_free_ char *config_path = NULL;
1513 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1517 assert(scope < _UNIT_FILE_SCOPE_MAX);
1519 r = lookup_paths_init_from_scope(&paths, scope);
1523 r = get_config_path(scope, runtime, root_dir, &config_path);
1527 STRV_FOREACH(i, files) {
1528 r = install_info_add_auto(&c, *i);
1533 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1535 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1542 int unit_file_reenable(
1543 UnitFileScope scope,
1545 const char *root_dir,
1548 UnitFileChange **changes,
1549 unsigned *n_changes) {
1552 r = unit_file_disable(scope, runtime, root_dir, files,
1553 changes, n_changes);
1557 return unit_file_enable(scope, runtime, root_dir, files, force,
1558 changes, n_changes);
1561 int unit_file_set_default(
1562 UnitFileScope scope,
1563 const char *root_dir,
1566 UnitFileChange **changes,
1567 unsigned *n_changes) {
1569 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1570 _cleanup_install_context_done_ InstallContext c = {};
1571 _cleanup_free_ char *config_path = NULL;
1574 InstallInfo *i = NULL;
1577 assert(scope < _UNIT_FILE_SCOPE_MAX);
1580 if (unit_name_to_type(file) != UNIT_TARGET)
1583 r = lookup_paths_init_from_scope(&paths, scope);
1587 r = get_config_path(scope, false, root_dir, &config_path);
1591 r = install_info_add_auto(&c, file);
1595 assert_se(i = hashmap_first(c.will_install));
1597 r = unit_file_search(&c, i, &paths, root_dir, false);
1601 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1603 r = create_symlink(i->path, path, force, changes, n_changes);
1610 int unit_file_get_default(
1611 UnitFileScope scope,
1612 const char *root_dir,
1615 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1620 assert(scope < _UNIT_FILE_SCOPE_MAX);
1623 r = lookup_paths_init_from_scope(&paths, scope);
1627 STRV_FOREACH(p, paths.unit_path) {
1628 _cleanup_free_ char *path = NULL, *tmp = NULL;
1631 if (isempty(root_dir))
1632 path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
1634 path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
1639 r = readlink_malloc(path, &tmp);
1642 else if (r == -EINVAL)
1644 n = strdup(SPECIAL_DEFAULT_TARGET);
1648 n = strdup(basename(tmp));
1660 UnitFileState unit_file_get_state(
1661 UnitFileScope scope,
1662 const char *root_dir,
1665 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1666 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1668 _cleanup_free_ char *path = NULL;
1672 assert(scope < _UNIT_FILE_SCOPE_MAX);
1675 if (root_dir && scope != UNIT_FILE_SYSTEM)
1678 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1681 r = lookup_paths_init_from_scope(&paths, scope);
1685 STRV_FOREACH(i, paths.unit_path) {
1692 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1694 asprintf(&path, "%s/%s", *i, name);
1700 * Search for a unit file in our default paths, to
1701 * be sure, that there are no broken symlinks.
1703 if (lstat(path, &st) < 0) {
1705 if (errno != ENOENT)
1708 if (!unit_name_is_instance(name))
1711 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1714 r = null_or_empty_path(path);
1715 if (r < 0 && r != -ENOENT)
1718 state = path_startswith(*i, "/run") ?
1719 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1724 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1730 r = unit_file_can_install(&paths, root_dir, path, true);
1731 if (r < 0 && errno != ENOENT)
1734 return UNIT_FILE_DISABLED;
1736 return UNIT_FILE_STATIC;
1739 return r < 0 ? r : state;
1742 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1743 _cleanup_strv_free_ char **files = NULL;
1748 assert(scope < _UNIT_FILE_SCOPE_MAX);
1751 if (scope == UNIT_FILE_SYSTEM)
1752 r = conf_files_list(&files, ".preset", NULL,
1753 "/etc/systemd/system-preset",
1754 "/usr/local/lib/systemd/system-preset",
1755 "/usr/lib/systemd/system-preset",
1756 #ifdef HAVE_SPLIT_USR
1757 "/lib/systemd/system-preset",
1760 else if (scope == UNIT_FILE_GLOBAL)
1761 r = conf_files_list(&files, ".preset", NULL,
1762 "/etc/systemd/user-preset",
1763 "/usr/local/lib/systemd/user-preset",
1764 "/usr/lib/systemd/user-preset",
1772 STRV_FOREACH(i, files) {
1773 _cleanup_fclose_ FILE *f;
1775 f = fopen(*i, "re");
1777 if (errno == ENOENT)
1784 char line[LINE_MAX], *l;
1786 if (!fgets(line, sizeof(line), f))
1793 if (strchr(COMMENTS "\n", *l))
1796 if (first_word(l, "enable")) {
1798 l += strspn(l, WHITESPACE);
1800 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1803 } else if (first_word(l, "disable")) {
1805 l += strspn(l, WHITESPACE);
1807 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1811 log_debug("Couldn't parse line '%s'", l);
1815 /* Default is "enable" */
1819 int unit_file_preset(
1820 UnitFileScope scope,
1822 const char *root_dir,
1825 UnitFileChange **changes,
1826 unsigned *n_changes) {
1828 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1829 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1831 _cleanup_free_ char *config_path = NULL;
1832 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1836 assert(scope < _UNIT_FILE_SCOPE_MAX);
1838 r = lookup_paths_init_from_scope(&paths, scope);
1842 r = get_config_path(scope, runtime, root_dir, &config_path);
1846 STRV_FOREACH(i, files) {
1848 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1851 r = unit_file_query_preset(scope, *i);
1856 r = install_info_add_auto(&plus, *i);
1858 r = install_info_add_auto(&minus, *i);
1864 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to,
1865 config_path, root_dir);
1867 q = remove_marked_symlinks(remove_symlinks_to, config_path,
1868 changes, n_changes, files);
1872 /* Returns number of symlinks that where supposed to be installed. */
1873 q = install_context_apply(&plus, &paths, config_path, root_dir, force,
1874 changes, n_changes);
1881 static void unitfilelist_free(UnitFileList **f) {
1888 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
1890 int unit_file_get_list(
1891 UnitFileScope scope,
1892 const char *root_dir,
1895 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1897 _cleanup_free_ char *buf = NULL;
1898 _cleanup_closedir_ DIR *d = NULL;
1902 assert(scope < _UNIT_FILE_SCOPE_MAX);
1905 if (root_dir && scope != UNIT_FILE_SYSTEM)
1908 r = lookup_paths_init_from_scope(&paths, scope);
1912 STRV_FOREACH(i, paths.unit_path) {
1913 const char *units_dir;
1919 if (asprintf(&buf, "%s/%s", root_dir, *i) < 0)
1929 d = opendir(units_dir);
1931 if (errno == ENOENT)
1939 _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
1943 if (!de && errno != 0)
1949 if (ignore_file(de->d_name))
1952 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1955 if (hashmap_get(h, de->d_name))
1958 r = dirent_ensure_type(d, de);
1966 if (de->d_type != DT_LNK && de->d_type != DT_REG)
1969 f = new0(UnitFileList, 1);
1973 f->path = path_make_absolute(de->d_name, units_dir);
1977 r = null_or_empty_path(f->path);
1978 if (r < 0 && r != -ENOENT)
1982 path_startswith(*i, "/run") ?
1983 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1987 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
1991 f->state = UNIT_FILE_ENABLED;
1995 r = unit_file_can_install(&paths, root_dir, f->path, true);
1996 if (r == -EINVAL || /* Invalid setting? */
1997 r == -EBADMSG || /* Invalid format? */
1998 r == -ENOENT /* Included file not found? */)
1999 f->state = UNIT_FILE_INVALID;
2003 f->state = UNIT_FILE_DISABLED;
2005 f->state = UNIT_FILE_STATIC;
2008 r = hashmap_put(h, basename(f->path), f);
2011 f = NULL; /* prevent cleanup */
2018 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2019 [UNIT_FILE_ENABLED] = "enabled",
2020 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2021 [UNIT_FILE_LINKED] = "linked",
2022 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2023 [UNIT_FILE_MASKED] = "masked",
2024 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2025 [UNIT_FILE_STATIC] = "static",
2026 [UNIT_FILE_DISABLED] = "disabled",
2027 [UNIT_FILE_INVALID] = "invalid",
2030 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2032 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2033 [UNIT_FILE_SYMLINK] = "symlink",
2034 [UNIT_FILE_UNLINK] = "unlink",
2037 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);