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) {
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);
564 *state = UNIT_FILE_ENABLED_RUNTIME;
569 /* Then look in the normal config path */
570 r = get_config_path(scope, false, root_dir, &path);
574 r = find_symlinks(name, path, &same_name_link);
580 *state = UNIT_FILE_ENABLED;
584 /* Hmm, we didn't find it, but maybe we found the same name
586 if (same_name_link_runtime) {
587 *state = UNIT_FILE_LINKED_RUNTIME;
589 } else if (same_name_link) {
590 *state = UNIT_FILE_LINKED;
600 const char *root_dir,
603 UnitFileChange **changes,
604 unsigned *n_changes) {
610 assert(scope < _UNIT_FILE_SCOPE_MAX);
612 r = get_config_path(scope, runtime, root_dir, &prefix);
616 STRV_FOREACH(i, files) {
619 if (!unit_name_is_valid(*i, true)) {
625 path = path_make_absolute(*i, prefix);
631 if (symlink("/dev/null", path) >= 0) {
632 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
638 if (errno == EEXIST) {
640 if (null_or_empty_path(path) > 0) {
648 if (symlink("/dev/null", path) >= 0) {
650 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
651 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
673 int unit_file_unmask(
676 const char *root_dir,
678 UnitFileChange **changes,
679 unsigned *n_changes) {
681 char **i, *config_path = NULL;
683 Set *remove_symlinks_to = NULL;
686 assert(scope < _UNIT_FILE_SCOPE_MAX);
688 r = get_config_path(scope, runtime, root_dir, &config_path);
692 STRV_FOREACH(i, files) {
695 if (!unit_name_is_valid(*i, true)) {
701 path = path_make_absolute(*i, config_path);
707 q = null_or_empty_path(path);
709 if (unlink(path) >= 0) {
710 mark_symlink_for_removal(&remove_symlinks_to, path);
711 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
720 if (q != -ENOENT && r == 0)
728 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
732 set_free_free(remove_symlinks_to);
741 const char *root_dir,
744 UnitFileChange **changes,
745 unsigned *n_changes) {
748 char **i, *config_path = NULL;
752 assert(scope < _UNIT_FILE_SCOPE_MAX);
756 r = lookup_paths_init_from_scope(&paths, scope);
760 r = get_config_path(scope, runtime, root_dir, &config_path);
764 STRV_FOREACH(i, files) {
768 fn = path_get_file_name(*i);
770 if (!path_is_absolute(*i) ||
771 !unit_name_is_valid(fn, true)) {
777 if (lstat(*i, &st) < 0) {
783 if (!S_ISREG(st.st_mode)) {
788 q = in_search_path(*i, paths.unit_path);
797 path = path_make_absolute(fn, config_path);
803 if (symlink(*i, path) >= 0) {
804 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
810 if (errno == EEXIST) {
813 q = readlink_and_make_absolute(path, &dest);
815 if (q < 0 && errno != ENOENT) {
824 if (q >= 0 && path_equal(dest, *i)) {
835 if (symlink(*i, path) >= 0) {
837 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
838 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
856 lookup_paths_free(&paths);
862 void unit_file_list_free(Hashmap *h) {
865 while ((i = hashmap_steal_first(h))) {
873 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
876 assert(changes || n_changes == 0);
881 for (i = 0; i < n_changes; i++) {
882 free(changes[i].path);
883 free(changes[i].source);
889 static void install_info_free(InstallInfo *i) {
894 strv_free(i->aliases);
895 strv_free(i->wanted_by);
896 strv_free(i->required_by);
900 static void install_info_hashmap_free(Hashmap *m) {
906 while ((i = hashmap_steal_first(m)))
907 install_info_free(i);
912 static void install_context_done(InstallContext *c) {
915 install_info_hashmap_free(c->will_install);
916 install_info_hashmap_free(c->have_installed);
918 c->will_install = c->have_installed = NULL;
921 static int install_info_add(
925 InstallInfo *i = NULL;
929 assert(name || path);
932 name = path_get_file_name(path);
934 if (!unit_name_is_valid(name, true))
937 if (hashmap_get(c->have_installed, name) ||
938 hashmap_get(c->will_install, name))
941 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
945 i = new0(InstallInfo, 1);
949 i->name = strdup(name);
956 i->path = strdup(path);
963 r = hashmap_put(c->will_install, i->name, i);
971 install_info_free(i);
976 static int install_info_add_auto(
978 const char *name_or_path) {
981 assert(name_or_path);
983 if (path_is_absolute(name_or_path))
984 return install_info_add(c, NULL, name_or_path);
986 return install_info_add(c, name_or_path, NULL);
989 static int config_parse_also(
990 const char *filename,
1002 InstallContext *c = data;
1008 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1016 r = install_info_add(c, n, NULL);
1028 static int unit_file_load(
1032 bool allow_symlink) {
1034 const ConfigTableItem items[] = {
1035 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
1036 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1037 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1038 { "Install", "Also", config_parse_also, 0, c },
1039 { NULL, NULL, NULL, 0, NULL }
1050 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1054 f = fdopen(fd, "re");
1056 close_nointr_nofail(fd);
1060 r = config_parse(path, f, NULL, config_item_table_lookup, (void*) items, true, info);
1066 strv_length(info->aliases) +
1067 strv_length(info->wanted_by) +
1068 strv_length(info->required_by);
1071 static int unit_file_search(
1075 const char *root_dir,
1076 bool allow_symlink) {
1086 return unit_file_load(c, info, info->path, allow_symlink);
1090 STRV_FOREACH(p, paths->unit_path) {
1093 if (isempty(root_dir))
1094 asprintf(&path, "%s/%s", *p, info->name);
1096 asprintf(&path, "%s/%s/%s", root_dir, *p, info->name);
1101 r = unit_file_load(c, info, path, allow_symlink);
1106 if (r == -ENOENT && unit_name_is_instance(info->name)) {
1107 /* unit file doesn't exist, however instance enablement was request */
1108 /* we will check if it is possible to load template unit file */
1109 char *template = NULL,
1110 *template_path = NULL,
1111 *template_dir = NULL;
1113 template = unit_name_template(info->name);
1119 /* we will reuse path variable since we don't need it anymore */
1120 template_dir = path;
1121 *(strrchr(path, '/') + 1) = '\0';
1123 template_path = strjoin(template_dir, template, NULL);
1124 if (!template_path) {
1130 /* let's try to load template unit */
1131 r = unit_file_load(c, info, template_path, allow_symlink);
1133 info->path = strdup(template_path);
1137 free(template_path);
1143 free(template_path);
1148 if (r != -ENOENT && r != -ELOOP)
1155 static int unit_file_can_install(
1157 const char *root_dir,
1159 bool allow_symlink) {
1170 r = install_info_add_auto(&c, name);
1174 assert_se(i = hashmap_first(c.will_install));
1176 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1180 strv_length(i->aliases) +
1181 strv_length(i->wanted_by) +
1182 strv_length(i->required_by);
1184 install_context_done(&c);
1189 static int create_symlink(
1190 const char *old_path,
1191 const char *new_path,
1193 UnitFileChange **changes,
1194 unsigned *n_changes) {
1202 mkdir_parents_label(new_path, 0755);
1204 if (symlink(old_path, new_path) >= 0) {
1205 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1209 if (errno != EEXIST)
1212 r = readlink_and_make_absolute(new_path, &dest);
1216 if (path_equal(dest, old_path)) {
1228 if (symlink(old_path, new_path) >= 0) {
1229 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1230 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1237 static int install_info_symlink_alias(
1239 const char *config_path,
1241 UnitFileChange **changes,
1242 unsigned *n_changes) {
1248 assert(config_path);
1250 STRV_FOREACH(s, i->aliases) {
1253 alias_path = path_make_absolute(*s, config_path);
1258 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1268 static int install_info_symlink_wants(
1270 const char *config_path,
1272 UnitFileChange **changes,
1273 unsigned *n_changes) {
1279 assert(config_path);
1281 STRV_FOREACH(s, i->wanted_by) {
1284 if (!unit_name_is_valid(*s, true)) {
1289 if (asprintf(&path, "%s/%s.wants/%s", config_path, *s, i->name) < 0)
1292 q = create_symlink(i->path, path, force, changes, n_changes);
1302 static int install_info_symlink_requires(
1304 const char *config_path,
1306 UnitFileChange **changes,
1307 unsigned *n_changes) {
1313 assert(config_path);
1315 STRV_FOREACH(s, i->required_by) {
1318 if (!unit_name_is_valid(*s, true)) {
1323 if (asprintf(&path, "%s/%s.requires/%s", config_path, *s, i->name) < 0)
1326 q = create_symlink(i->path, path, force, changes, n_changes);
1336 static int install_info_symlink_link(
1339 const char *config_path,
1341 UnitFileChange **changes,
1342 unsigned *n_changes) {
1349 assert(config_path);
1352 r = in_search_path(i->path, paths->unit_path);
1356 if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1359 r = create_symlink(i->path, path, force, changes, n_changes);
1365 static int install_info_apply(
1368 const char *config_path,
1370 UnitFileChange **changes,
1371 unsigned *n_changes) {
1377 assert(config_path);
1379 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1381 q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1385 q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1389 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1396 static int install_context_apply(
1399 const char *config_path,
1400 const char *root_dir,
1402 UnitFileChange **changes,
1403 unsigned *n_changes) {
1410 assert(config_path);
1412 while ((i = hashmap_first(c->will_install))) {
1414 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1418 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1420 q = unit_file_search(c, i, paths, root_dir, false);
1429 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1430 if (r >= 0 && q < 0)
1437 static int install_context_mark_for_removal(
1440 Set **remove_symlinks_to,
1441 const char *config_path,
1442 const char *root_dir) {
1449 assert(config_path);
1451 /* Marks all items for removal */
1453 while ((i = hashmap_first(c->will_install))) {
1455 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1459 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1461 q = unit_file_search(c, i, paths, root_dir, false);
1470 if (unit_name_is_instance(i->name)) {
1471 char *unit_file = NULL;
1473 unit_file = path_get_file_name(i->path);
1475 if (unit_name_is_instance(unit_file))
1476 /* unit file named as instance exists, thus all symlinks pointing to it, will be removed */
1477 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1479 /* does not exist, thus we will mark for removal symlinks to template unit file */
1480 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1482 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1484 if (r >= 0 && q < 0)
1491 int unit_file_enable(
1492 UnitFileScope scope,
1494 const char *root_dir,
1497 UnitFileChange **changes,
1498 unsigned *n_changes) {
1502 char **i, *config_path = NULL;
1506 assert(scope < _UNIT_FILE_SCOPE_MAX);
1511 r = lookup_paths_init_from_scope(&paths, scope);
1515 r = get_config_path(scope, runtime, root_dir, &config_path);
1519 STRV_FOREACH(i, files) {
1520 r = install_info_add_auto(&c, *i);
1525 /* This will return the number of symlink rules that were
1526 supposed to be created, not the ones actually created. This is
1527 useful to determine whether the passed files hat any
1528 installation data at all. */
1529 r = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1532 install_context_done(&c);
1533 lookup_paths_free(&paths);
1539 int unit_file_disable(
1540 UnitFileScope scope,
1542 const char *root_dir,
1544 UnitFileChange **changes,
1545 unsigned *n_changes) {
1549 char **i, *config_path = NULL;
1550 Set *remove_symlinks_to = NULL;
1554 assert(scope < _UNIT_FILE_SCOPE_MAX);
1559 r = lookup_paths_init_from_scope(&paths, scope);
1563 r = get_config_path(scope, runtime, root_dir, &config_path);
1567 STRV_FOREACH(i, files) {
1568 r = install_info_add_auto(&c, *i);
1573 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1575 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1580 install_context_done(&c);
1581 lookup_paths_free(&paths);
1582 set_free_free(remove_symlinks_to);
1588 int unit_file_reenable(
1589 UnitFileScope scope,
1591 const char *root_dir,
1594 UnitFileChange **changes,
1595 unsigned *n_changes) {
1599 char **i, *config_path = NULL;
1600 Set *remove_symlinks_to = NULL;
1604 assert(scope < _UNIT_FILE_SCOPE_MAX);
1609 r = lookup_paths_init_from_scope(&paths, scope);
1613 r = get_config_path(scope, runtime, root_dir, &config_path);
1617 STRV_FOREACH(i, files) {
1618 r = mark_symlink_for_removal(&remove_symlinks_to, *i);
1622 r = install_info_add_auto(&c, *i);
1627 r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1629 /* Returns number of symlinks that where supposed to be installed. */
1630 q = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1635 lookup_paths_free(&paths);
1636 install_context_done(&c);
1637 set_free_free(remove_symlinks_to);
1643 UnitFileState unit_file_get_state(
1644 UnitFileScope scope,
1645 const char *root_dir,
1649 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1650 char **i, *path = NULL;
1654 assert(scope < _UNIT_FILE_SCOPE_MAX);
1659 if (root_dir && scope != UNIT_FILE_SYSTEM)
1662 if (!unit_name_is_valid(name, true))
1665 r = lookup_paths_init_from_scope(&paths, scope);
1669 STRV_FOREACH(i, paths.unit_path) {
1676 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1678 asprintf(&path, "%s/%s", *i, name);
1685 if (lstat(path, &st) < 0) {
1687 if (errno == ENOENT)
1693 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {
1698 r = null_or_empty_path(path);
1699 if (r < 0 && r != -ENOENT)
1702 state = path_startswith(*i, "/run") ?
1703 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1708 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1716 r = unit_file_can_install(&paths, root_dir, path, true);
1717 if (r < 0 && errno != -ENOENT)
1720 state = UNIT_FILE_DISABLED;
1723 } else if (r == 0) {
1724 state = UNIT_FILE_STATIC;
1731 lookup_paths_free(&paths);
1734 return r < 0 ? r : state;
1737 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1742 assert(scope < _UNIT_FILE_SCOPE_MAX);
1745 if (scope == UNIT_FILE_SYSTEM)
1746 r = conf_files_list(&files, ".preset",
1747 "/etc/systemd/system-preset",
1748 "/usr/local/lib/systemd/system-preset",
1749 "/usr/lib/systemd/system-preset",
1750 #ifdef HAVE_SPLIT_USR
1751 "/lib/systemd/system-preset",
1754 else if (scope == UNIT_FILE_GLOBAL)
1755 r = conf_files_list(&files, ".preset",
1756 "/etc/systemd/user-preset",
1757 "/usr/local/lib/systemd/user-preset",
1758 "/usr/lib/systemd/user-preset",
1766 STRV_FOREACH(i, files) {
1769 f = fopen(*i, "re");
1771 if (errno == ENOENT)
1779 char line[LINE_MAX], *l;
1781 if (!fgets(line, sizeof(line), f))
1788 if (strchr(COMMENTS, *l))
1791 if (first_word(l, "enable")) {
1793 l += strspn(l, WHITESPACE);
1795 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) {
1810 log_debug("Couldn't parse line '%s'", l);
1816 /* Default is "enable" */
1825 int unit_file_preset(
1826 UnitFileScope scope,
1828 const char *root_dir,
1831 UnitFileChange **changes,
1832 unsigned *n_changes) {
1835 InstallContext plus, minus;
1836 char **i, *config_path = NULL;
1837 Set *remove_symlinks_to = NULL;
1841 assert(scope < _UNIT_FILE_SCOPE_MAX);
1847 r = lookup_paths_init_from_scope(&paths, scope);
1851 r = get_config_path(scope, runtime, root_dir, &config_path);
1855 STRV_FOREACH(i, files) {
1857 if (!unit_name_is_valid(*i, true)) {
1862 r = unit_file_query_preset(scope, *i);
1867 r = install_info_add_auto(&plus, *i);
1869 r = install_info_add_auto(&minus, *i);
1875 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1877 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1881 /* Returns number of symlinks that where supposed to be installed. */
1882 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1887 lookup_paths_free(&paths);
1888 install_context_done(&plus);
1889 install_context_done(&minus);
1890 set_free_free(remove_symlinks_to);
1896 int unit_file_get_list(
1897 UnitFileScope scope,
1898 const char *root_dir,
1902 char **i, *buf = NULL;
1907 assert(scope < _UNIT_FILE_SCOPE_MAX);
1912 if (root_dir && scope != UNIT_FILE_SYSTEM)
1915 r = lookup_paths_init_from_scope(&paths, scope);
1919 STRV_FOREACH(i, paths.unit_path) {
1920 struct dirent buffer, *de;
1921 const char *units_dir;
1927 if (asprintf(&buf, "%s/%s", root_dir, *i) < 0) {
1938 d = opendir(units_dir);
1940 if (errno == ENOENT)
1950 r = readdir_r(d, &buffer, &de);
1959 if (ignore_file(de->d_name))
1962 if (!unit_name_is_valid(de->d_name, true))
1965 if (hashmap_get(h, de->d_name))
1968 r = dirent_ensure_type(d, de);
1976 if (de->d_type != DT_LNK && de->d_type != DT_REG)
1979 f = new0(UnitFileList, 1);
1985 f->path = path_make_absolute(de->d_name, units_dir);
1992 r = null_or_empty_path(f->path);
1993 if (r < 0 && r != -ENOENT) {
1999 path_startswith(*i, "/run") ?
2000 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2004 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2010 f->state = UNIT_FILE_ENABLED;
2014 r = unit_file_can_install(&paths, root_dir, f->path, true);
2015 if (r == -EINVAL || /* Invalid setting? */
2016 r == -EBADMSG || /* Invalid format? */
2017 r == -ENOENT /* Included file not found? */)
2018 f->state = UNIT_FILE_INVALID;
2024 f->state = UNIT_FILE_DISABLED;
2026 f->state = UNIT_FILE_STATIC;
2029 r = hashmap_put(h, path_get_file_name(f->path), f);
2039 lookup_paths_free(&paths);
2048 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2049 [UNIT_FILE_ENABLED] = "enabled",
2050 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2051 [UNIT_FILE_LINKED] = "linked",
2052 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2053 [UNIT_FILE_MASKED] = "masked",
2054 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2055 [UNIT_FILE_STATIC] = "static",
2056 [UNIT_FILE_DISABLED] = "disabled",
2057 [UNIT_FILE_INVALID] = "invalid",
2060 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2062 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2063 [UNIT_FILE_SYMLINK] = "symlink",
2064 [UNIT_FILE_UNLINK] = "unlink",
2067 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);