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 ? SYSTEMD_SYSTEM : SYSTEMD_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,
205 assert(remove_symlinks_to);
213 close_nointr_nofail(fd);
221 union dirent_storage buf;
224 k = readdir_r(d, &buf.de, &de);
233 if (ignore_file(de->d_name))
236 dirent_ensure_type(d, de);
238 if (de->d_type == DT_DIR) {
242 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
252 p = path_make_absolute(de->d_name, path);
254 close_nointr_nofail(nfd);
259 /* This will close nfd, regardless whether it succeeds or not */
260 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, files);
266 } else if (de->d_type == DT_LNK) {
271 p = path_make_absolute(de->d_name, path);
277 q = readlink_and_canonicalize(p, &dest);
290 set_get(remove_symlinks_to, dest) ||
291 set_get(remove_symlinks_to, path_get_file_name(dest));
293 if (unit_name_is_instance(p))
294 found = found && strv_contains(files, path_get_file_name(p));
298 if (unlink(p) < 0 && errno != ENOENT) {
303 rmdir_parents(p, config_path);
304 path_kill_slashes(p);
306 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
308 if (!set_get(remove_symlinks_to, p)) {
310 q = mark_symlink_for_removal(&remove_symlinks_to, p);
330 static int remove_marked_symlinks(
331 Set *remove_symlinks_to,
332 const char *config_path,
333 UnitFileChange **changes,
342 if (set_size(remove_symlinks_to) <= 0)
345 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
359 /* This takes possession of cfd and closes it */
360 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, files);
365 close_nointr_nofail(fd);
370 static int find_symlinks_fd(
374 const char *config_path,
375 bool *same_name_link) {
384 assert(same_name_link);
388 close_nointr_nofail(fd);
395 union dirent_storage buf;
397 k = readdir_r(d, &buf.de, &de);
406 if (ignore_file(de->d_name))
409 dirent_ensure_type(d, de);
411 if (de->d_type == DT_DIR) {
415 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
425 p = path_make_absolute(de->d_name, path);
427 close_nointr_nofail(nfd);
432 /* This will close nfd, regardless whether it succeeds or not */
433 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
444 } else if (de->d_type == DT_LNK) {
446 bool found_path, found_dest, b = false;
449 /* Acquire symlink name */
450 p = path_make_absolute(de->d_name, path);
456 /* Acquire symlink destination */
457 q = readlink_and_canonicalize(p, &dest);
469 /* Check if the symlink itself matches what we
471 if (path_is_absolute(name))
472 found_path = path_equal(p, name);
474 found_path = streq(de->d_name, name);
476 /* Check if what the symlink points to
477 * matches what we are looking for */
478 if (path_is_absolute(name))
479 found_dest = path_equal(dest, name);
481 found_dest = streq(path_get_file_name(dest), name);
485 if (found_path && found_dest) {
488 /* Filter out same name links in the main
490 t = path_make_absolute(name, config_path);
497 b = path_equal(t, p);
504 *same_name_link = true;
505 else if (found_path || found_dest) {
517 static int find_symlinks(
519 const char *config_path,
520 bool *same_name_link) {
526 assert(same_name_link);
528 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
535 /* This takes possession of fd and closes it */
536 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
539 static int find_symlinks_in_scope(
541 const char *root_dir,
543 UnitFileState *state) {
546 char _cleanup_free_ *path = NULL;
547 bool same_name_link_runtime = false, same_name_link = false;
550 assert(scope < _UNIT_FILE_SCOPE_MAX);
553 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
555 /* First look in runtime config path */
556 r = get_config_path(scope, true, root_dir, &path);
560 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);
578 *state = UNIT_FILE_ENABLED;
582 /* Hmm, we didn't find it, but maybe we found the same name
584 if (same_name_link_runtime) {
585 *state = UNIT_FILE_LINKED_RUNTIME;
587 } else if (same_name_link) {
588 *state = UNIT_FILE_LINKED;
598 const char *root_dir,
601 UnitFileChange **changes,
602 unsigned *n_changes) {
605 char _cleanup_free_ *prefix;
609 assert(scope < _UNIT_FILE_SCOPE_MAX);
611 r = get_config_path(scope, runtime, root_dir, &prefix);
615 STRV_FOREACH(i, files) {
616 char _cleanup_free_ *path = NULL;
618 if (!unit_name_is_valid(*i, true)) {
624 path = path_make_absolute(*i, prefix);
630 if (symlink("/dev/null", path) >= 0) {
631 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
636 if (errno == EEXIST) {
638 if (null_or_empty_path(path) > 0)
644 if (symlink("/dev/null", path) >= 0) {
646 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
647 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
664 int unit_file_unmask(
667 const char *root_dir,
669 UnitFileChange **changes,
670 unsigned *n_changes) {
672 char **i, *config_path = NULL;
674 Set *remove_symlinks_to = NULL;
677 assert(scope < _UNIT_FILE_SCOPE_MAX);
679 r = get_config_path(scope, runtime, root_dir, &config_path);
683 STRV_FOREACH(i, files) {
686 if (!unit_name_is_valid(*i, true)) {
692 path = path_make_absolute(*i, config_path);
698 q = null_or_empty_path(path);
700 if (unlink(path) >= 0) {
701 mark_symlink_for_removal(&remove_symlinks_to, path);
702 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
711 if (q != -ENOENT && r == 0)
719 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
723 set_free_free(remove_symlinks_to);
732 const char *root_dir,
735 UnitFileChange **changes,
736 unsigned *n_changes) {
739 char **i, *config_path = NULL;
743 assert(scope < _UNIT_FILE_SCOPE_MAX);
747 r = lookup_paths_init_from_scope(&paths, scope);
751 r = get_config_path(scope, runtime, root_dir, &config_path);
755 STRV_FOREACH(i, files) {
759 fn = path_get_file_name(*i);
761 if (!path_is_absolute(*i) ||
762 !unit_name_is_valid(fn, true)) {
768 if (lstat(*i, &st) < 0) {
774 if (!S_ISREG(st.st_mode)) {
779 q = in_search_path(*i, paths.unit_path);
788 path = path_make_absolute(fn, config_path);
794 if (symlink(*i, path) >= 0) {
795 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
801 if (errno == EEXIST) {
804 q = readlink_and_make_absolute(path, &dest);
806 if (q < 0 && errno != ENOENT) {
815 if (q >= 0 && path_equal(dest, *i)) {
826 if (symlink(*i, path) >= 0) {
828 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
829 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
847 lookup_paths_free(&paths);
853 void unit_file_list_free(Hashmap *h) {
856 while ((i = hashmap_steal_first(h))) {
864 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
867 assert(changes || n_changes == 0);
872 for (i = 0; i < n_changes; i++) {
873 free(changes[i].path);
874 free(changes[i].source);
880 static void install_info_free(InstallInfo *i) {
885 strv_free(i->aliases);
886 strv_free(i->wanted_by);
887 strv_free(i->required_by);
891 static void install_info_hashmap_free(Hashmap *m) {
897 while ((i = hashmap_steal_first(m)))
898 install_info_free(i);
903 static void install_context_done(InstallContext *c) {
906 install_info_hashmap_free(c->will_install);
907 install_info_hashmap_free(c->have_installed);
909 c->will_install = c->have_installed = NULL;
912 static int install_info_add(
916 InstallInfo *i = NULL;
920 assert(name || path);
923 name = path_get_file_name(path);
925 if (!unit_name_is_valid(name, true))
928 if (hashmap_get(c->have_installed, name) ||
929 hashmap_get(c->will_install, name))
932 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
936 i = new0(InstallInfo, 1);
940 i->name = strdup(name);
947 i->path = strdup(path);
954 r = hashmap_put(c->will_install, i->name, i);
962 install_info_free(i);
967 static int install_info_add_auto(
969 const char *name_or_path) {
972 assert(name_or_path);
974 if (path_is_absolute(name_or_path))
975 return install_info_add(c, NULL, name_or_path);
977 return install_info_add(c, name_or_path, NULL);
980 static int config_parse_also(
981 const char *filename,
993 InstallContext *c = data;
999 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1007 r = install_info_add(c, n, NULL);
1019 static int unit_file_load(
1023 bool allow_symlink) {
1025 const ConfigTableItem items[] = {
1026 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
1027 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1028 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1029 { "Install", "Also", config_parse_also, 0, c },
1030 { NULL, NULL, NULL, 0, NULL }
1041 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1045 f = fdopen(fd, "re");
1047 close_nointr_nofail(fd);
1051 r = config_parse(path, f, NULL, config_item_table_lookup, (void*) items, true, info);
1057 strv_length(info->aliases) +
1058 strv_length(info->wanted_by) +
1059 strv_length(info->required_by);
1062 static int unit_file_search(
1066 const char *root_dir,
1067 bool allow_symlink) {
1077 return unit_file_load(c, info, info->path, allow_symlink);
1081 STRV_FOREACH(p, paths->unit_path) {
1084 if (isempty(root_dir))
1085 asprintf(&path, "%s/%s", *p, info->name);
1087 asprintf(&path, "%s/%s/%s", root_dir, *p, info->name);
1092 r = unit_file_load(c, info, path, allow_symlink);
1097 if (r == -ENOENT && unit_name_is_instance(info->name)) {
1098 /* unit file doesn't exist, however instance enablement was request */
1099 /* we will check if it is possible to load template unit file */
1100 char *template = NULL,
1101 *template_path = NULL,
1102 *template_dir = NULL;
1104 template = unit_name_template(info->name);
1110 /* we will reuse path variable since we don't need it anymore */
1111 template_dir = path;
1112 *(strrchr(path, '/') + 1) = '\0';
1114 template_path = strjoin(template_dir, template, NULL);
1115 if (!template_path) {
1121 /* let's try to load template unit */
1122 r = unit_file_load(c, info, template_path, allow_symlink);
1124 info->path = strdup(template_path);
1128 free(template_path);
1134 free(template_path);
1139 if (r != -ENOENT && r != -ELOOP)
1146 static int unit_file_can_install(
1148 const char *root_dir,
1150 bool allow_symlink) {
1161 r = install_info_add_auto(&c, name);
1165 assert_se(i = hashmap_first(c.will_install));
1167 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1171 strv_length(i->aliases) +
1172 strv_length(i->wanted_by) +
1173 strv_length(i->required_by);
1175 install_context_done(&c);
1180 static int create_symlink(
1181 const char *old_path,
1182 const char *new_path,
1184 UnitFileChange **changes,
1185 unsigned *n_changes) {
1193 mkdir_parents_label(new_path, 0755);
1195 if (symlink(old_path, new_path) >= 0) {
1196 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1200 if (errno != EEXIST)
1203 r = readlink_and_make_absolute(new_path, &dest);
1207 if (path_equal(dest, old_path)) {
1219 if (symlink(old_path, new_path) >= 0) {
1220 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1221 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1228 static int install_info_symlink_alias(
1230 const char *config_path,
1232 UnitFileChange **changes,
1233 unsigned *n_changes) {
1239 assert(config_path);
1241 STRV_FOREACH(s, i->aliases) {
1244 alias_path = path_make_absolute(*s, config_path);
1249 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1259 static int install_info_symlink_wants(
1261 const char *config_path,
1263 UnitFileChange **changes,
1264 unsigned *n_changes) {
1270 assert(config_path);
1272 STRV_FOREACH(s, i->wanted_by) {
1275 if (!unit_name_is_valid(*s, true)) {
1280 if (asprintf(&path, "%s/%s.wants/%s", config_path, *s, i->name) < 0)
1283 q = create_symlink(i->path, path, force, changes, n_changes);
1293 static int install_info_symlink_requires(
1295 const char *config_path,
1297 UnitFileChange **changes,
1298 unsigned *n_changes) {
1304 assert(config_path);
1306 STRV_FOREACH(s, i->required_by) {
1309 if (!unit_name_is_valid(*s, true)) {
1314 if (asprintf(&path, "%s/%s.requires/%s", config_path, *s, i->name) < 0)
1317 q = create_symlink(i->path, path, force, changes, n_changes);
1327 static int install_info_symlink_link(
1330 const char *config_path,
1332 UnitFileChange **changes,
1333 unsigned *n_changes) {
1340 assert(config_path);
1343 r = in_search_path(i->path, paths->unit_path);
1347 if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1350 r = create_symlink(i->path, path, force, changes, n_changes);
1356 static int install_info_apply(
1359 const char *config_path,
1361 UnitFileChange **changes,
1362 unsigned *n_changes) {
1368 assert(config_path);
1370 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1372 q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1376 q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1380 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1387 static int install_context_apply(
1390 const char *config_path,
1391 const char *root_dir,
1393 UnitFileChange **changes,
1394 unsigned *n_changes) {
1401 assert(config_path);
1403 while ((i = hashmap_first(c->will_install))) {
1405 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1409 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1411 q = unit_file_search(c, i, paths, root_dir, false);
1420 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1421 if (r >= 0 && q < 0)
1428 static int install_context_mark_for_removal(
1431 Set **remove_symlinks_to,
1432 const char *config_path,
1433 const char *root_dir) {
1440 assert(config_path);
1442 /* Marks all items for removal */
1444 while ((i = hashmap_first(c->will_install))) {
1446 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1450 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1452 q = unit_file_search(c, i, paths, root_dir, false);
1461 if (unit_name_is_instance(i->name)) {
1462 char *unit_file = NULL;
1464 unit_file = path_get_file_name(i->path);
1466 if (unit_name_is_instance(unit_file))
1467 /* unit file named as instance exists, thus all symlinks pointing to it, will be removed */
1468 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1470 /* does not exist, thus we will mark for removal symlinks to template unit file */
1471 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1473 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1475 if (r >= 0 && q < 0)
1482 int unit_file_enable(
1483 UnitFileScope scope,
1485 const char *root_dir,
1488 UnitFileChange **changes,
1489 unsigned *n_changes) {
1493 char **i, *config_path = NULL;
1497 assert(scope < _UNIT_FILE_SCOPE_MAX);
1502 r = lookup_paths_init_from_scope(&paths, scope);
1506 r = get_config_path(scope, runtime, root_dir, &config_path);
1510 STRV_FOREACH(i, files) {
1511 r = install_info_add_auto(&c, *i);
1516 /* This will return the number of symlink rules that were
1517 supposed to be created, not the ones actually created. This is
1518 useful to determine whether the passed files had any
1519 installation data at all. */
1520 r = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1523 install_context_done(&c);
1524 lookup_paths_free(&paths);
1530 int unit_file_disable(
1531 UnitFileScope scope,
1533 const char *root_dir,
1535 UnitFileChange **changes,
1536 unsigned *n_changes) {
1540 char **i, *config_path = NULL;
1541 Set *remove_symlinks_to = NULL;
1545 assert(scope < _UNIT_FILE_SCOPE_MAX);
1550 r = lookup_paths_init_from_scope(&paths, scope);
1554 r = get_config_path(scope, runtime, root_dir, &config_path);
1558 STRV_FOREACH(i, files) {
1559 r = install_info_add_auto(&c, *i);
1564 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1566 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1571 install_context_done(&c);
1572 lookup_paths_free(&paths);
1573 set_free_free(remove_symlinks_to);
1579 int unit_file_reenable(
1580 UnitFileScope scope,
1582 const char *root_dir,
1585 UnitFileChange **changes,
1586 unsigned *n_changes) {
1590 char **i, *config_path = NULL;
1591 Set *remove_symlinks_to = NULL;
1595 assert(scope < _UNIT_FILE_SCOPE_MAX);
1600 r = lookup_paths_init_from_scope(&paths, scope);
1604 r = get_config_path(scope, runtime, root_dir, &config_path);
1608 STRV_FOREACH(i, files) {
1609 r = mark_symlink_for_removal(&remove_symlinks_to, *i);
1613 r = install_info_add_auto(&c, *i);
1618 r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1620 /* Returns number of symlinks that where supposed to be installed. */
1621 q = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1626 lookup_paths_free(&paths);
1627 install_context_done(&c);
1628 set_free_free(remove_symlinks_to);
1634 UnitFileState unit_file_get_state(
1635 UnitFileScope scope,
1636 const char *root_dir,
1640 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1641 char **i, *path = NULL;
1645 assert(scope < _UNIT_FILE_SCOPE_MAX);
1650 if (root_dir && scope != UNIT_FILE_SYSTEM)
1653 if (!unit_name_is_valid(name, true))
1656 r = lookup_paths_init_from_scope(&paths, scope);
1660 STRV_FOREACH(i, paths.unit_path) {
1667 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1669 asprintf(&path, "%s/%s", *i, name);
1676 if (lstat(path, &st) < 0) {
1678 if (errno == ENOENT)
1684 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {
1689 r = null_or_empty_path(path);
1690 if (r < 0 && r != -ENOENT)
1693 state = path_startswith(*i, "/run") ?
1694 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1699 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1707 r = unit_file_can_install(&paths, root_dir, path, true);
1708 if (r < 0 && errno != -ENOENT)
1711 state = UNIT_FILE_DISABLED;
1714 } else if (r == 0) {
1715 state = UNIT_FILE_STATIC;
1722 lookup_paths_free(&paths);
1725 return r < 0 ? r : state;
1728 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1733 assert(scope < _UNIT_FILE_SCOPE_MAX);
1736 if (scope == UNIT_FILE_SYSTEM)
1737 r = conf_files_list(&files, ".preset",
1738 "/etc/systemd/system-preset",
1739 "/usr/local/lib/systemd/system-preset",
1740 "/usr/lib/systemd/system-preset",
1741 #ifdef HAVE_SPLIT_USR
1742 "/lib/systemd/system-preset",
1745 else if (scope == UNIT_FILE_GLOBAL)
1746 r = conf_files_list(&files, ".preset",
1747 "/etc/systemd/user-preset",
1748 "/usr/local/lib/systemd/user-preset",
1749 "/usr/lib/systemd/user-preset",
1757 STRV_FOREACH(i, files) {
1760 f = fopen(*i, "re");
1762 if (errno == ENOENT)
1770 char line[LINE_MAX], *l;
1772 if (!fgets(line, sizeof(line), f))
1779 if (strchr(COMMENTS, *l))
1782 if (first_word(l, "enable")) {
1784 l += strspn(l, WHITESPACE);
1786 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1791 } else if (first_word(l, "disable")) {
1793 l += strspn(l, WHITESPACE);
1795 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1801 log_debug("Couldn't parse line '%s'", l);
1807 /* Default is "enable" */
1816 int unit_file_preset(
1817 UnitFileScope scope,
1819 const char *root_dir,
1822 UnitFileChange **changes,
1823 unsigned *n_changes) {
1826 InstallContext plus, minus;
1827 char **i, *config_path = NULL;
1828 Set *remove_symlinks_to = NULL;
1832 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, true)) {
1853 r = unit_file_query_preset(scope, *i);
1858 r = install_info_add_auto(&plus, *i);
1860 r = install_info_add_auto(&minus, *i);
1866 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1868 q = remove_marked_symlinks(remove_symlinks_to, config_path, 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, changes, n_changes);
1878 lookup_paths_free(&paths);
1879 install_context_done(&plus);
1880 install_context_done(&minus);
1881 set_free_free(remove_symlinks_to);
1887 int unit_file_get_list(
1888 UnitFileScope scope,
1889 const char *root_dir,
1893 char **i, *buf = NULL;
1898 assert(scope < _UNIT_FILE_SCOPE_MAX);
1903 if (root_dir && scope != UNIT_FILE_SYSTEM)
1906 r = lookup_paths_init_from_scope(&paths, scope);
1910 STRV_FOREACH(i, paths.unit_path) {
1911 const char *units_dir;
1917 if (asprintf(&buf, "%s/%s", root_dir, *i) < 0) {
1928 d = opendir(units_dir);
1930 if (errno == ENOENT)
1939 union dirent_storage buffer;
1942 r = readdir_r(d, &buffer.de, &de);
1951 if (ignore_file(de->d_name))
1954 if (!unit_name_is_valid(de->d_name, true))
1957 if (hashmap_get(h, de->d_name))
1960 r = dirent_ensure_type(d, de);
1968 if (de->d_type != DT_LNK && de->d_type != DT_REG)
1971 f = new0(UnitFileList, 1);
1977 f->path = path_make_absolute(de->d_name, units_dir);
1984 r = null_or_empty_path(f->path);
1985 if (r < 0 && r != -ENOENT) {
1991 path_startswith(*i, "/run") ?
1992 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1996 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2002 f->state = UNIT_FILE_ENABLED;
2006 r = unit_file_can_install(&paths, root_dir, f->path, true);
2007 if (r == -EINVAL || /* Invalid setting? */
2008 r == -EBADMSG || /* Invalid format? */
2009 r == -ENOENT /* Included file not found? */)
2010 f->state = UNIT_FILE_INVALID;
2016 f->state = UNIT_FILE_DISABLED;
2018 f->state = UNIT_FILE_STATIC;
2021 r = hashmap_put(h, path_get_file_name(f->path), f);
2031 lookup_paths_free(&paths);
2040 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2041 [UNIT_FILE_ENABLED] = "enabled",
2042 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2043 [UNIT_FILE_LINKED] = "linked",
2044 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2045 [UNIT_FILE_MASKED] = "masked",
2046 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2047 [UNIT_FILE_STATIC] = "static",
2048 [UNIT_FILE_DISABLED] = "disabled",
2049 [UNIT_FILE_INVALID] = "invalid",
2052 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2054 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2055 [UNIT_FILE_SYMLINK] = "symlink",
2056 [UNIT_FILE_UNLINK] = "unlink",
2059 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);