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"
50 Hashmap *will_install;
51 Hashmap *have_installed;
54 static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope) {
57 assert(scope < _UNIT_FILE_SCOPE_MAX);
61 return lookup_paths_init(paths,
62 scope == UNIT_FILE_SYSTEM ? MANAGER_SYSTEM : MANAGER_USER,
63 scope == UNIT_FILE_USER,
67 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
72 assert(scope < _UNIT_FILE_SCOPE_MAX);
77 case UNIT_FILE_SYSTEM:
79 if (root_dir && runtime)
80 asprintf(&p, "%s/run/systemd/system", root_dir);
82 p = strdup("/run/systemd/system");
84 asprintf(&p, "%s/%s", root_dir, SYSTEM_CONFIG_UNIT_PATH);
86 p = strdup(SYSTEM_CONFIG_UNIT_PATH);
90 case UNIT_FILE_GLOBAL:
96 p = strdup("/run/systemd/user");
98 p = strdup(USER_CONFIG_UNIT_PATH);
103 if (root_dir || runtime)
106 r = user_config_home(&p);
108 return r < 0 ? r : -ENOENT;
113 assert_not_reached("Bad scope");
123 static int add_file_change(
124 UnitFileChange **changes,
126 UnitFileChangeType type,
128 const char *source) {
134 assert(!changes == !n_changes);
139 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
147 c[i].path = strdup(path);
152 c[i].source = strdup(source);
164 static int mark_symlink_for_removal(
165 Set **remove_symlinks_to,
173 r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
181 path_kill_slashes(n);
183 r = set_put(*remove_symlinks_to, n);
186 return r == -EEXIST ? 0 : r;
192 static int remove_marked_symlinks_fd(
193 Set *remove_symlinks_to,
196 const char *config_path,
198 UnitFileChange **changes,
204 struct dirent buffer, *de;
206 assert(remove_symlinks_to);
214 close_nointr_nofail(fd);
223 k = readdir_r(d, &buffer, &de);
232 if (ignore_file(de->d_name))
235 dirent_ensure_type(d, de);
237 if (de->d_type == DT_DIR) {
241 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
251 p = path_make_absolute(de->d_name, path);
253 close_nointr_nofail(nfd);
258 /* This will close nfd, regardless whether it succeeds or not */
259 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, files);
265 } else if (de->d_type == DT_LNK) {
270 p = path_make_absolute(de->d_name, path);
276 q = readlink_and_canonicalize(p, &dest);
289 set_get(remove_symlinks_to, dest) ||
290 set_get(remove_symlinks_to, path_get_file_name(dest));
292 if (unit_name_is_instance(p))
293 found = found && strv_contains(files, path_get_file_name(p));
297 if (unlink(p) < 0 && errno != ENOENT) {
302 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);
329 static int remove_marked_symlinks(
330 Set *remove_symlinks_to,
331 const char *config_path,
332 UnitFileChange **changes,
341 if (set_size(remove_symlinks_to) <= 0)
344 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
358 /* This takes possession of cfd and closes it */
359 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, files);
364 close_nointr_nofail(fd);
369 static int find_symlinks_fd(
373 const char *config_path,
374 bool *same_name_link) {
378 struct dirent buffer, *de;
384 assert(same_name_link);
388 close_nointr_nofail(fd);
395 k = readdir_r(d, &buffer, &de);
404 if (ignore_file(de->d_name))
407 dirent_ensure_type(d, de);
409 if (de->d_type == DT_DIR) {
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);
425 close_nointr_nofail(nfd);
430 /* This will close nfd, regardless whether it succeeds or not */
431 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
442 } else if (de->d_type == DT_LNK) {
444 bool found_path, found_dest, b = false;
447 /* Acquire symlink name */
448 p = path_make_absolute(de->d_name, path);
454 /* Acquire symlink destination */
455 q = readlink_and_canonicalize(p, &dest);
467 /* Check if the symlink itself matches what we
469 if (path_is_absolute(name))
470 found_path = path_equal(p, name);
472 found_path = streq(de->d_name, name);
474 /* Check if what the symlink points to
475 * matches what we are looking for */
476 if (path_is_absolute(name))
477 found_dest = path_equal(dest, name);
479 found_dest = streq(path_get_file_name(dest), name);
483 if (found_path && found_dest) {
486 /* Filter out same name links in the main
488 t = path_make_absolute(name, config_path);
495 b = path_equal(t, p);
502 *same_name_link = true;
503 else if (found_path || found_dest) {
515 static int find_symlinks(
517 const char *config_path,
518 bool *same_name_link) {
524 assert(same_name_link);
526 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
533 /* This takes possession of fd and closes it */
534 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
537 static int find_symlinks_in_scope(
539 const char *root_dir,
541 UnitFileState *state) {
544 char _cleanup_free_ *path = NULL;
545 bool same_name_link_runtime = false, same_name_link = false;
548 assert(scope < _UNIT_FILE_SCOPE_MAX);
551 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
553 /* First look in runtime config path */
554 r = get_config_path(scope, true, root_dir, &path);
558 r = find_symlinks(name, path, &same_name_link_runtime);
562 *state = UNIT_FILE_ENABLED_RUNTIME;
567 /* Then look in the normal config path */
568 r = get_config_path(scope, false, root_dir, &path);
572 r = find_symlinks(name, path, &same_name_link);
576 *state = UNIT_FILE_ENABLED;
580 /* Hmm, we didn't find it, but maybe we found the same name
582 if (same_name_link_runtime) {
583 *state = UNIT_FILE_LINKED_RUNTIME;
585 } else if (same_name_link) {
586 *state = UNIT_FILE_LINKED;
596 const char *root_dir,
599 UnitFileChange **changes,
600 unsigned *n_changes) {
603 char _cleanup_free_ *prefix;
607 assert(scope < _UNIT_FILE_SCOPE_MAX);
609 r = get_config_path(scope, runtime, root_dir, &prefix);
613 STRV_FOREACH(i, files) {
614 char _cleanup_free_ *path = NULL;
616 if (!unit_name_is_valid(*i, true)) {
622 path = path_make_absolute(*i, prefix);
628 if (symlink("/dev/null", path) >= 0) {
629 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
634 if (errno == EEXIST) {
636 if (null_or_empty_path(path) > 0)
642 if (symlink("/dev/null", path) >= 0) {
644 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
645 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
662 int unit_file_unmask(
665 const char *root_dir,
667 UnitFileChange **changes,
668 unsigned *n_changes) {
670 char **i, *config_path = NULL;
672 Set *remove_symlinks_to = NULL;
675 assert(scope < _UNIT_FILE_SCOPE_MAX);
677 r = get_config_path(scope, runtime, root_dir, &config_path);
681 STRV_FOREACH(i, files) {
684 if (!unit_name_is_valid(*i, true)) {
690 path = path_make_absolute(*i, config_path);
696 q = null_or_empty_path(path);
698 if (unlink(path) >= 0) {
699 mark_symlink_for_removal(&remove_symlinks_to, path);
700 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
709 if (q != -ENOENT && r == 0)
717 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
721 set_free_free(remove_symlinks_to);
730 const char *root_dir,
733 UnitFileChange **changes,
734 unsigned *n_changes) {
737 char **i, *config_path = NULL;
741 assert(scope < _UNIT_FILE_SCOPE_MAX);
745 r = lookup_paths_init_from_scope(&paths, scope);
749 r = get_config_path(scope, runtime, root_dir, &config_path);
753 STRV_FOREACH(i, files) {
757 fn = path_get_file_name(*i);
759 if (!path_is_absolute(*i) ||
760 !unit_name_is_valid(fn, true)) {
766 if (lstat(*i, &st) < 0) {
772 if (!S_ISREG(st.st_mode)) {
777 q = in_search_path(*i, paths.unit_path);
786 path = path_make_absolute(fn, config_path);
792 if (symlink(*i, path) >= 0) {
793 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
799 if (errno == EEXIST) {
802 q = readlink_and_make_absolute(path, &dest);
804 if (q < 0 && errno != ENOENT) {
813 if (q >= 0 && path_equal(dest, *i)) {
824 if (symlink(*i, path) >= 0) {
826 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
827 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
845 lookup_paths_free(&paths);
851 void unit_file_list_free(Hashmap *h) {
854 while ((i = hashmap_steal_first(h))) {
862 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
865 assert(changes || n_changes == 0);
870 for (i = 0; i < n_changes; i++) {
871 free(changes[i].path);
872 free(changes[i].source);
878 static void install_info_free(InstallInfo *i) {
883 strv_free(i->aliases);
884 strv_free(i->wanted_by);
885 strv_free(i->required_by);
889 static void install_info_hashmap_free(Hashmap *m) {
895 while ((i = hashmap_steal_first(m)))
896 install_info_free(i);
901 static void install_context_done(InstallContext *c) {
904 install_info_hashmap_free(c->will_install);
905 install_info_hashmap_free(c->have_installed);
907 c->will_install = c->have_installed = NULL;
910 static int install_info_add(
914 InstallInfo *i = NULL;
918 assert(name || path);
921 name = path_get_file_name(path);
923 if (!unit_name_is_valid(name, true))
926 if (hashmap_get(c->have_installed, name) ||
927 hashmap_get(c->will_install, name))
930 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
934 i = new0(InstallInfo, 1);
938 i->name = strdup(name);
945 i->path = strdup(path);
952 r = hashmap_put(c->will_install, i->name, i);
960 install_info_free(i);
965 static int install_info_add_auto(
967 const char *name_or_path) {
970 assert(name_or_path);
972 if (path_is_absolute(name_or_path))
973 return install_info_add(c, NULL, name_or_path);
975 return install_info_add(c, name_or_path, NULL);
978 static int config_parse_also(
979 const char *filename,
991 InstallContext *c = data;
997 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1005 r = install_info_add(c, n, NULL);
1017 static int unit_file_load(
1021 bool allow_symlink) {
1023 const ConfigTableItem items[] = {
1024 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
1025 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1026 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1027 { "Install", "Also", config_parse_also, 0, c },
1028 { NULL, NULL, NULL, 0, NULL }
1039 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1043 f = fdopen(fd, "re");
1045 close_nointr_nofail(fd);
1049 r = config_parse(path, f, NULL, config_item_table_lookup, (void*) items, true, info);
1055 strv_length(info->aliases) +
1056 strv_length(info->wanted_by) +
1057 strv_length(info->required_by);
1060 static int unit_file_search(
1064 const char *root_dir,
1065 bool allow_symlink) {
1075 return unit_file_load(c, info, info->path, allow_symlink);
1079 STRV_FOREACH(p, paths->unit_path) {
1082 if (isempty(root_dir))
1083 asprintf(&path, "%s/%s", *p, info->name);
1085 asprintf(&path, "%s/%s/%s", root_dir, *p, info->name);
1090 r = unit_file_load(c, info, path, allow_symlink);
1095 if (r == -ENOENT && unit_name_is_instance(info->name)) {
1096 /* unit file doesn't exist, however instance enablement was request */
1097 /* we will check if it is possible to load template unit file */
1098 char *template = NULL,
1099 *template_path = NULL,
1100 *template_dir = NULL;
1102 template = unit_name_template(info->name);
1108 /* we will reuse path variable since we don't need it anymore */
1109 template_dir = path;
1110 *(strrchr(path, '/') + 1) = '\0';
1112 template_path = strjoin(template_dir, template, NULL);
1113 if (!template_path) {
1119 /* let's try to load template unit */
1120 r = unit_file_load(c, info, template_path, allow_symlink);
1122 info->path = strdup(template_path);
1126 free(template_path);
1132 free(template_path);
1137 if (r != -ENOENT && r != -ELOOP)
1144 static int unit_file_can_install(
1146 const char *root_dir,
1148 bool allow_symlink) {
1159 r = install_info_add_auto(&c, name);
1163 assert_se(i = hashmap_first(c.will_install));
1165 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1169 strv_length(i->aliases) +
1170 strv_length(i->wanted_by) +
1171 strv_length(i->required_by);
1173 install_context_done(&c);
1178 static int create_symlink(
1179 const char *old_path,
1180 const char *new_path,
1182 UnitFileChange **changes,
1183 unsigned *n_changes) {
1191 mkdir_parents_label(new_path, 0755);
1193 if (symlink(old_path, new_path) >= 0) {
1194 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1198 if (errno != EEXIST)
1201 r = readlink_and_make_absolute(new_path, &dest);
1205 if (path_equal(dest, old_path)) {
1217 if (symlink(old_path, new_path) >= 0) {
1218 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1219 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1226 static int install_info_symlink_alias(
1228 const char *config_path,
1230 UnitFileChange **changes,
1231 unsigned *n_changes) {
1237 assert(config_path);
1239 STRV_FOREACH(s, i->aliases) {
1242 alias_path = path_make_absolute(*s, config_path);
1247 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1257 static int install_info_symlink_wants(
1259 const char *config_path,
1261 UnitFileChange **changes,
1262 unsigned *n_changes) {
1268 assert(config_path);
1270 STRV_FOREACH(s, i->wanted_by) {
1273 if (!unit_name_is_valid(*s, true)) {
1278 if (asprintf(&path, "%s/%s.wants/%s", config_path, *s, i->name) < 0)
1281 q = create_symlink(i->path, path, force, changes, n_changes);
1291 static int install_info_symlink_requires(
1293 const char *config_path,
1295 UnitFileChange **changes,
1296 unsigned *n_changes) {
1302 assert(config_path);
1304 STRV_FOREACH(s, i->required_by) {
1307 if (!unit_name_is_valid(*s, true)) {
1312 if (asprintf(&path, "%s/%s.requires/%s", config_path, *s, i->name) < 0)
1315 q = create_symlink(i->path, path, force, changes, n_changes);
1325 static int install_info_symlink_link(
1328 const char *config_path,
1330 UnitFileChange **changes,
1331 unsigned *n_changes) {
1338 assert(config_path);
1341 r = in_search_path(i->path, paths->unit_path);
1345 if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1348 r = create_symlink(i->path, path, force, changes, n_changes);
1354 static int install_info_apply(
1357 const char *config_path,
1359 UnitFileChange **changes,
1360 unsigned *n_changes) {
1366 assert(config_path);
1368 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1370 q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1374 q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1378 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1385 static int install_context_apply(
1388 const char *config_path,
1389 const char *root_dir,
1391 UnitFileChange **changes,
1392 unsigned *n_changes) {
1399 assert(config_path);
1401 while ((i = hashmap_first(c->will_install))) {
1403 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1407 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1409 q = unit_file_search(c, i, paths, root_dir, false);
1418 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1419 if (r >= 0 && q < 0)
1426 static int install_context_mark_for_removal(
1429 Set **remove_symlinks_to,
1430 const char *config_path,
1431 const char *root_dir) {
1438 assert(config_path);
1440 /* Marks all items for removal */
1442 while ((i = hashmap_first(c->will_install))) {
1444 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1448 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1450 q = unit_file_search(c, i, paths, root_dir, false);
1459 if (unit_name_is_instance(i->name)) {
1460 char *unit_file = NULL;
1462 unit_file = path_get_file_name(i->path);
1464 if (unit_name_is_instance(unit_file))
1465 /* unit file named as instance exists, thus all symlinks pointing to it, will be removed */
1466 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1468 /* does not exist, thus we will mark for removal symlinks to template unit file */
1469 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1471 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1473 if (r >= 0 && q < 0)
1480 int unit_file_enable(
1481 UnitFileScope scope,
1483 const char *root_dir,
1486 UnitFileChange **changes,
1487 unsigned *n_changes) {
1491 char **i, *config_path = NULL;
1495 assert(scope < _UNIT_FILE_SCOPE_MAX);
1500 r = lookup_paths_init_from_scope(&paths, scope);
1504 r = get_config_path(scope, runtime, root_dir, &config_path);
1508 STRV_FOREACH(i, files) {
1509 r = install_info_add_auto(&c, *i);
1514 /* This will return the number of symlink rules that were
1515 supposed to be created, not the ones actually created. This is
1516 useful to determine whether the passed files hat any
1517 installation data at all. */
1518 r = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1521 install_context_done(&c);
1522 lookup_paths_free(&paths);
1528 int unit_file_disable(
1529 UnitFileScope scope,
1531 const char *root_dir,
1533 UnitFileChange **changes,
1534 unsigned *n_changes) {
1538 char **i, *config_path = NULL;
1539 Set *remove_symlinks_to = NULL;
1543 assert(scope < _UNIT_FILE_SCOPE_MAX);
1548 r = lookup_paths_init_from_scope(&paths, scope);
1552 r = get_config_path(scope, runtime, root_dir, &config_path);
1556 STRV_FOREACH(i, files) {
1557 r = install_info_add_auto(&c, *i);
1562 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1564 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1569 install_context_done(&c);
1570 lookup_paths_free(&paths);
1571 set_free_free(remove_symlinks_to);
1577 int unit_file_reenable(
1578 UnitFileScope scope,
1580 const char *root_dir,
1583 UnitFileChange **changes,
1584 unsigned *n_changes) {
1588 char **i, *config_path = NULL;
1589 Set *remove_symlinks_to = NULL;
1593 assert(scope < _UNIT_FILE_SCOPE_MAX);
1598 r = lookup_paths_init_from_scope(&paths, scope);
1602 r = get_config_path(scope, runtime, root_dir, &config_path);
1606 STRV_FOREACH(i, files) {
1607 r = mark_symlink_for_removal(&remove_symlinks_to, *i);
1611 r = install_info_add_auto(&c, *i);
1616 r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1618 /* Returns number of symlinks that where supposed to be installed. */
1619 q = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1624 lookup_paths_free(&paths);
1625 install_context_done(&c);
1626 set_free_free(remove_symlinks_to);
1632 UnitFileState unit_file_get_state(
1633 UnitFileScope scope,
1634 const char *root_dir,
1638 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1639 char **i, *path = NULL;
1643 assert(scope < _UNIT_FILE_SCOPE_MAX);
1648 if (root_dir && scope != UNIT_FILE_SYSTEM)
1651 if (!unit_name_is_valid(name, true))
1654 r = lookup_paths_init_from_scope(&paths, scope);
1658 STRV_FOREACH(i, paths.unit_path) {
1665 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1667 asprintf(&path, "%s/%s", *i, name);
1674 if (lstat(path, &st) < 0) {
1676 if (errno == ENOENT)
1682 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {
1687 r = null_or_empty_path(path);
1688 if (r < 0 && r != -ENOENT)
1691 state = path_startswith(*i, "/run") ?
1692 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1697 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1705 r = unit_file_can_install(&paths, root_dir, path, true);
1706 if (r < 0 && errno != -ENOENT)
1709 state = UNIT_FILE_DISABLED;
1712 } else if (r == 0) {
1713 state = UNIT_FILE_STATIC;
1720 lookup_paths_free(&paths);
1723 return r < 0 ? r : state;
1726 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1731 assert(scope < _UNIT_FILE_SCOPE_MAX);
1734 if (scope == UNIT_FILE_SYSTEM)
1735 r = conf_files_list(&files, ".preset",
1736 "/etc/systemd/system-preset",
1737 "/usr/local/lib/systemd/system-preset",
1738 "/usr/lib/systemd/system-preset",
1739 #ifdef HAVE_SPLIT_USR
1740 "/lib/systemd/system-preset",
1743 else if (scope == UNIT_FILE_GLOBAL)
1744 r = conf_files_list(&files, ".preset",
1745 "/etc/systemd/user-preset",
1746 "/usr/local/lib/systemd/user-preset",
1747 "/usr/lib/systemd/user-preset",
1755 STRV_FOREACH(i, files) {
1758 f = fopen(*i, "re");
1760 if (errno == ENOENT)
1768 char line[LINE_MAX], *l;
1770 if (!fgets(line, sizeof(line), f))
1777 if (strchr(COMMENTS, *l))
1780 if (first_word(l, "enable")) {
1782 l += strspn(l, WHITESPACE);
1784 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1789 } else if (first_word(l, "disable")) {
1791 l += strspn(l, WHITESPACE);
1793 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1799 log_debug("Couldn't parse line '%s'", l);
1805 /* Default is "enable" */
1814 int unit_file_preset(
1815 UnitFileScope scope,
1817 const char *root_dir,
1820 UnitFileChange **changes,
1821 unsigned *n_changes) {
1824 InstallContext plus, minus;
1825 char **i, *config_path = NULL;
1826 Set *remove_symlinks_to = NULL;
1830 assert(scope < _UNIT_FILE_SCOPE_MAX);
1836 r = lookup_paths_init_from_scope(&paths, scope);
1840 r = get_config_path(scope, runtime, root_dir, &config_path);
1844 STRV_FOREACH(i, files) {
1846 if (!unit_name_is_valid(*i, true)) {
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, config_path, root_dir);
1866 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1870 /* Returns number of symlinks that where supposed to be installed. */
1871 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1876 lookup_paths_free(&paths);
1877 install_context_done(&plus);
1878 install_context_done(&minus);
1879 set_free_free(remove_symlinks_to);
1885 int unit_file_get_list(
1886 UnitFileScope scope,
1887 const char *root_dir,
1891 char **i, *buf = NULL;
1896 assert(scope < _UNIT_FILE_SCOPE_MAX);
1901 if (root_dir && scope != UNIT_FILE_SYSTEM)
1904 r = lookup_paths_init_from_scope(&paths, scope);
1908 STRV_FOREACH(i, paths.unit_path) {
1909 struct dirent buffer, *de;
1910 const char *units_dir;
1916 if (asprintf(&buf, "%s/%s", root_dir, *i) < 0) {
1927 d = opendir(units_dir);
1929 if (errno == ENOENT)
1939 r = readdir_r(d, &buffer, &de);
1948 if (ignore_file(de->d_name))
1951 if (!unit_name_is_valid(de->d_name, true))
1954 if (hashmap_get(h, de->d_name))
1957 r = dirent_ensure_type(d, de);
1965 if (de->d_type != DT_LNK && de->d_type != DT_REG)
1968 f = new0(UnitFileList, 1);
1974 f->path = path_make_absolute(de->d_name, units_dir);
1981 r = null_or_empty_path(f->path);
1982 if (r < 0 && r != -ENOENT) {
1988 path_startswith(*i, "/run") ?
1989 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1993 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
1999 f->state = UNIT_FILE_ENABLED;
2003 r = unit_file_can_install(&paths, root_dir, f->path, true);
2004 if (r == -EINVAL || /* Invalid setting? */
2005 r == -EBADMSG || /* Invalid format? */
2006 r == -ENOENT /* Included file not found? */)
2007 f->state = UNIT_FILE_INVALID;
2013 f->state = UNIT_FILE_DISABLED;
2015 f->state = UNIT_FILE_STATIC;
2018 r = hashmap_put(h, path_get_file_name(f->path), f);
2028 lookup_paths_free(&paths);
2037 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2038 [UNIT_FILE_ENABLED] = "enabled",
2039 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2040 [UNIT_FILE_LINKED] = "linked",
2041 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2042 [UNIT_FILE_MASKED] = "masked",
2043 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2044 [UNIT_FILE_STATIC] = "static",
2045 [UNIT_FILE_DISABLED] = "disabled",
2046 [UNIT_FILE_INVALID] = "invalid",
2049 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2051 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2052 [UNIT_FILE_SYMLINK] = "symlink",
2053 [UNIT_FILE_UNLINK] = "unlink",
2056 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);