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) {
378 DIR _cleanup_closedir_ *d = NULL;
384 assert(same_name_link);
388 close_nointr_nofail(fd);
395 union dirent_storage buf;
397 k = readdir_r(d, &buf.de, &de);
404 if (ignore_file(de->d_name))
407 dirent_ensure_type(d, de);
409 if (de->d_type == DT_DIR) {
411 char _cleanup_free_ *p = NULL;
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);
429 /* This will close nfd, regardless whether it succeeds or not */
430 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
438 } else if (de->d_type == DT_LNK) {
439 char _cleanup_free_ *p = NULL, *dest = NULL;
440 bool found_path, found_dest, b = false;
443 /* Acquire symlink name */
444 p = path_make_absolute(de->d_name, path);
448 /* Acquire symlink destination */
449 q = readlink_and_canonicalize(p, &dest);
459 /* Check if the symlink itself matches what we
461 if (path_is_absolute(name))
462 found_path = path_equal(p, name);
464 found_path = streq(de->d_name, name);
466 /* Check if what the symlink points to
467 * matches what we are looking for */
468 if (path_is_absolute(name))
469 found_dest = path_equal(dest, name);
471 found_dest = streq(path_get_file_name(dest), name);
473 if (found_path && found_dest) {
474 char _cleanup_free_ *t = NULL;
476 /* Filter out same name links in the main
478 t = path_make_absolute(name, config_path);
482 b = path_equal(t, p);
486 *same_name_link = true;
487 else if (found_path || found_dest)
495 static int find_symlinks(
497 const char *config_path,
498 bool *same_name_link) {
504 assert(same_name_link);
506 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
513 /* This takes possession of fd and closes it */
514 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
517 static int find_symlinks_in_scope(
519 const char *root_dir,
521 UnitFileState *state) {
524 char _cleanup_free_ *path = NULL;
525 bool same_name_link_runtime = false, same_name_link = false;
528 assert(scope < _UNIT_FILE_SCOPE_MAX);
531 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
533 /* First look in runtime config path */
534 r = get_config_path(scope, true, root_dir, &path);
538 r = find_symlinks(name, path, &same_name_link_runtime);
542 *state = UNIT_FILE_ENABLED_RUNTIME;
547 /* Then look in the normal config path */
548 r = get_config_path(scope, false, root_dir, &path);
552 r = find_symlinks(name, path, &same_name_link);
556 *state = UNIT_FILE_ENABLED;
560 /* Hmm, we didn't find it, but maybe we found the same name
562 if (same_name_link_runtime) {
563 *state = UNIT_FILE_LINKED_RUNTIME;
565 } else if (same_name_link) {
566 *state = UNIT_FILE_LINKED;
576 const char *root_dir,
579 UnitFileChange **changes,
580 unsigned *n_changes) {
583 char _cleanup_free_ *prefix;
587 assert(scope < _UNIT_FILE_SCOPE_MAX);
589 r = get_config_path(scope, runtime, root_dir, &prefix);
593 STRV_FOREACH(i, files) {
594 char _cleanup_free_ *path = NULL;
596 if (!unit_name_is_valid(*i, true)) {
602 path = path_make_absolute(*i, prefix);
608 if (symlink("/dev/null", path) >= 0) {
609 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
614 if (errno == EEXIST) {
616 if (null_or_empty_path(path) > 0)
622 if (symlink("/dev/null", path) >= 0) {
624 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
625 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
642 int unit_file_unmask(
645 const char *root_dir,
647 UnitFileChange **changes,
648 unsigned *n_changes) {
650 char **i, *config_path = NULL;
652 Set *remove_symlinks_to = NULL;
655 assert(scope < _UNIT_FILE_SCOPE_MAX);
657 r = get_config_path(scope, runtime, root_dir, &config_path);
661 STRV_FOREACH(i, files) {
664 if (!unit_name_is_valid(*i, true)) {
670 path = path_make_absolute(*i, config_path);
676 q = null_or_empty_path(path);
678 if (unlink(path) >= 0) {
679 mark_symlink_for_removal(&remove_symlinks_to, path);
680 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
689 if (q != -ENOENT && r == 0)
697 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
701 set_free_free(remove_symlinks_to);
710 const char *root_dir,
713 UnitFileChange **changes,
714 unsigned *n_changes) {
717 char **i, *config_path = NULL;
721 assert(scope < _UNIT_FILE_SCOPE_MAX);
725 r = lookup_paths_init_from_scope(&paths, scope);
729 r = get_config_path(scope, runtime, root_dir, &config_path);
733 STRV_FOREACH(i, files) {
737 fn = path_get_file_name(*i);
739 if (!path_is_absolute(*i) ||
740 !unit_name_is_valid(fn, true)) {
746 if (lstat(*i, &st) < 0) {
752 if (!S_ISREG(st.st_mode)) {
757 q = in_search_path(*i, paths.unit_path);
766 path = path_make_absolute(fn, config_path);
772 if (symlink(*i, path) >= 0) {
773 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
779 if (errno == EEXIST) {
782 q = readlink_and_make_absolute(path, &dest);
784 if (q < 0 && errno != ENOENT) {
793 if (q >= 0 && path_equal(dest, *i)) {
804 if (symlink(*i, path) >= 0) {
806 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
807 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
825 lookup_paths_free(&paths);
831 void unit_file_list_free(Hashmap *h) {
834 while ((i = hashmap_steal_first(h))) {
842 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
845 assert(changes || n_changes == 0);
850 for (i = 0; i < n_changes; i++) {
851 free(changes[i].path);
852 free(changes[i].source);
858 static void install_info_free(InstallInfo *i) {
863 strv_free(i->aliases);
864 strv_free(i->wanted_by);
865 strv_free(i->required_by);
869 static void install_info_hashmap_free(Hashmap *m) {
875 while ((i = hashmap_steal_first(m)))
876 install_info_free(i);
881 static void install_context_done(InstallContext *c) {
884 install_info_hashmap_free(c->will_install);
885 install_info_hashmap_free(c->have_installed);
887 c->will_install = c->have_installed = NULL;
890 static int install_info_add(
894 InstallInfo *i = NULL;
898 assert(name || path);
901 name = path_get_file_name(path);
903 if (!unit_name_is_valid(name, true))
906 if (hashmap_get(c->have_installed, name) ||
907 hashmap_get(c->will_install, name))
910 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
914 i = new0(InstallInfo, 1);
918 i->name = strdup(name);
925 i->path = strdup(path);
932 r = hashmap_put(c->will_install, i->name, i);
940 install_info_free(i);
945 static int install_info_add_auto(
947 const char *name_or_path) {
950 assert(name_or_path);
952 if (path_is_absolute(name_or_path))
953 return install_info_add(c, NULL, name_or_path);
955 return install_info_add(c, name_or_path, NULL);
958 static int config_parse_also(
959 const char *filename,
971 InstallContext *c = data;
977 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
985 r = install_info_add(c, n, NULL);
997 static int unit_file_load(
1001 bool allow_symlink) {
1003 const ConfigTableItem items[] = {
1004 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
1005 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1006 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1007 { "Install", "Also", config_parse_also, 0, c },
1008 { NULL, NULL, NULL, 0, NULL }
1019 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1023 f = fdopen(fd, "re");
1025 close_nointr_nofail(fd);
1029 r = config_parse(path, f, NULL, config_item_table_lookup, (void*) items, true, info);
1035 strv_length(info->aliases) +
1036 strv_length(info->wanted_by) +
1037 strv_length(info->required_by);
1040 static int unit_file_search(
1044 const char *root_dir,
1045 bool allow_symlink) {
1055 return unit_file_load(c, info, info->path, allow_symlink);
1059 STRV_FOREACH(p, paths->unit_path) {
1062 if (isempty(root_dir))
1063 asprintf(&path, "%s/%s", *p, info->name);
1065 asprintf(&path, "%s/%s/%s", root_dir, *p, info->name);
1070 r = unit_file_load(c, info, path, allow_symlink);
1075 if (r == -ENOENT && unit_name_is_instance(info->name)) {
1076 /* unit file doesn't exist, however instance enablement was request */
1077 /* we will check if it is possible to load template unit file */
1078 char *template = NULL,
1079 *template_path = NULL,
1080 *template_dir = NULL;
1082 template = unit_name_template(info->name);
1088 /* we will reuse path variable since we don't need it anymore */
1089 template_dir = path;
1090 *(strrchr(path, '/') + 1) = '\0';
1092 template_path = strjoin(template_dir, template, NULL);
1093 if (!template_path) {
1099 /* let's try to load template unit */
1100 r = unit_file_load(c, info, template_path, allow_symlink);
1102 info->path = strdup(template_path);
1106 free(template_path);
1112 free(template_path);
1117 if (r != -ENOENT && r != -ELOOP)
1124 static int unit_file_can_install(
1126 const char *root_dir,
1128 bool allow_symlink) {
1139 r = install_info_add_auto(&c, name);
1143 assert_se(i = hashmap_first(c.will_install));
1145 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1149 strv_length(i->aliases) +
1150 strv_length(i->wanted_by) +
1151 strv_length(i->required_by);
1153 install_context_done(&c);
1158 static int create_symlink(
1159 const char *old_path,
1160 const char *new_path,
1162 UnitFileChange **changes,
1163 unsigned *n_changes) {
1171 mkdir_parents_label(new_path, 0755);
1173 if (symlink(old_path, new_path) >= 0) {
1174 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1178 if (errno != EEXIST)
1181 r = readlink_and_make_absolute(new_path, &dest);
1185 if (path_equal(dest, old_path)) {
1197 if (symlink(old_path, new_path) >= 0) {
1198 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1199 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1206 static int install_info_symlink_alias(
1208 const char *config_path,
1210 UnitFileChange **changes,
1211 unsigned *n_changes) {
1217 assert(config_path);
1219 STRV_FOREACH(s, i->aliases) {
1222 alias_path = path_make_absolute(*s, config_path);
1227 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1237 static int install_info_symlink_wants(
1239 const char *config_path,
1241 UnitFileChange **changes,
1242 unsigned *n_changes) {
1248 assert(config_path);
1250 STRV_FOREACH(s, i->wanted_by) {
1253 if (!unit_name_is_valid(*s, true)) {
1258 if (asprintf(&path, "%s/%s.wants/%s", config_path, *s, i->name) < 0)
1261 q = create_symlink(i->path, path, force, changes, n_changes);
1271 static int install_info_symlink_requires(
1273 const char *config_path,
1275 UnitFileChange **changes,
1276 unsigned *n_changes) {
1282 assert(config_path);
1284 STRV_FOREACH(s, i->required_by) {
1287 if (!unit_name_is_valid(*s, true)) {
1292 if (asprintf(&path, "%s/%s.requires/%s", config_path, *s, i->name) < 0)
1295 q = create_symlink(i->path, path, force, changes, n_changes);
1305 static int install_info_symlink_link(
1308 const char *config_path,
1310 UnitFileChange **changes,
1311 unsigned *n_changes) {
1318 assert(config_path);
1321 r = in_search_path(i->path, paths->unit_path);
1325 if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1328 r = create_symlink(i->path, path, force, changes, n_changes);
1334 static int install_info_apply(
1337 const char *config_path,
1339 UnitFileChange **changes,
1340 unsigned *n_changes) {
1346 assert(config_path);
1348 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1350 q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1354 q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1358 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1365 static int install_context_apply(
1368 const char *config_path,
1369 const char *root_dir,
1371 UnitFileChange **changes,
1372 unsigned *n_changes) {
1379 assert(config_path);
1381 while ((i = hashmap_first(c->will_install))) {
1383 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1387 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1389 q = unit_file_search(c, i, paths, root_dir, false);
1398 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1399 if (r >= 0 && q < 0)
1406 static int install_context_mark_for_removal(
1409 Set **remove_symlinks_to,
1410 const char *config_path,
1411 const char *root_dir) {
1418 assert(config_path);
1420 /* Marks all items for removal */
1422 while ((i = hashmap_first(c->will_install))) {
1424 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1428 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1430 q = unit_file_search(c, i, paths, root_dir, false);
1439 if (unit_name_is_instance(i->name)) {
1440 char *unit_file = NULL;
1442 unit_file = path_get_file_name(i->path);
1444 if (unit_name_is_instance(unit_file))
1445 /* unit file named as instance exists, thus all symlinks pointing to it, will be removed */
1446 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1448 /* does not exist, thus we will mark for removal symlinks to template unit file */
1449 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1451 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1453 if (r >= 0 && q < 0)
1460 int unit_file_enable(
1461 UnitFileScope scope,
1463 const char *root_dir,
1466 UnitFileChange **changes,
1467 unsigned *n_changes) {
1471 char **i, *config_path = NULL;
1475 assert(scope < _UNIT_FILE_SCOPE_MAX);
1480 r = lookup_paths_init_from_scope(&paths, scope);
1484 r = get_config_path(scope, runtime, root_dir, &config_path);
1488 STRV_FOREACH(i, files) {
1489 r = install_info_add_auto(&c, *i);
1494 /* This will return the number of symlink rules that were
1495 supposed to be created, not the ones actually created. This is
1496 useful to determine whether the passed files had any
1497 installation data at all. */
1498 r = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1501 install_context_done(&c);
1502 lookup_paths_free(&paths);
1508 int unit_file_disable(
1509 UnitFileScope scope,
1511 const char *root_dir,
1513 UnitFileChange **changes,
1514 unsigned *n_changes) {
1518 char **i, *config_path = NULL;
1519 Set *remove_symlinks_to = NULL;
1523 assert(scope < _UNIT_FILE_SCOPE_MAX);
1528 r = lookup_paths_init_from_scope(&paths, scope);
1532 r = get_config_path(scope, runtime, root_dir, &config_path);
1536 STRV_FOREACH(i, files) {
1537 r = install_info_add_auto(&c, *i);
1542 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1544 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1549 install_context_done(&c);
1550 lookup_paths_free(&paths);
1551 set_free_free(remove_symlinks_to);
1557 int unit_file_reenable(
1558 UnitFileScope scope,
1560 const char *root_dir,
1563 UnitFileChange **changes,
1564 unsigned *n_changes) {
1568 char **i, *config_path = NULL;
1569 Set *remove_symlinks_to = NULL;
1573 assert(scope < _UNIT_FILE_SCOPE_MAX);
1578 r = lookup_paths_init_from_scope(&paths, scope);
1582 r = get_config_path(scope, runtime, root_dir, &config_path);
1586 STRV_FOREACH(i, files) {
1587 r = mark_symlink_for_removal(&remove_symlinks_to, *i);
1591 r = install_info_add_auto(&c, *i);
1596 r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1598 /* Returns number of symlinks that where supposed to be installed. */
1599 q = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1604 lookup_paths_free(&paths);
1605 install_context_done(&c);
1606 set_free_free(remove_symlinks_to);
1612 UnitFileState unit_file_get_state(
1613 UnitFileScope scope,
1614 const char *root_dir,
1618 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1619 char **i, *path = NULL;
1623 assert(scope < _UNIT_FILE_SCOPE_MAX);
1628 if (root_dir && scope != UNIT_FILE_SYSTEM)
1631 if (!unit_name_is_valid(name, true))
1634 r = lookup_paths_init_from_scope(&paths, scope);
1638 STRV_FOREACH(i, paths.unit_path) {
1645 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1647 asprintf(&path, "%s/%s", *i, name);
1654 if (lstat(path, &st) < 0) {
1656 if (errno == ENOENT)
1662 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {
1667 r = null_or_empty_path(path);
1668 if (r < 0 && r != -ENOENT)
1671 state = path_startswith(*i, "/run") ?
1672 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1677 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1685 r = unit_file_can_install(&paths, root_dir, path, true);
1686 if (r < 0 && errno != -ENOENT)
1689 state = UNIT_FILE_DISABLED;
1692 } else if (r == 0) {
1693 state = UNIT_FILE_STATIC;
1700 lookup_paths_free(&paths);
1703 return r < 0 ? r : state;
1706 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1711 assert(scope < _UNIT_FILE_SCOPE_MAX);
1714 if (scope == UNIT_FILE_SYSTEM)
1715 r = conf_files_list(&files, ".preset",
1716 "/etc/systemd/system-preset",
1717 "/usr/local/lib/systemd/system-preset",
1718 "/usr/lib/systemd/system-preset",
1719 #ifdef HAVE_SPLIT_USR
1720 "/lib/systemd/system-preset",
1723 else if (scope == UNIT_FILE_GLOBAL)
1724 r = conf_files_list(&files, ".preset",
1725 "/etc/systemd/user-preset",
1726 "/usr/local/lib/systemd/user-preset",
1727 "/usr/lib/systemd/user-preset",
1735 STRV_FOREACH(i, files) {
1738 f = fopen(*i, "re");
1740 if (errno == ENOENT)
1748 char line[LINE_MAX], *l;
1750 if (!fgets(line, sizeof(line), f))
1757 if (strchr(COMMENTS, *l))
1760 if (first_word(l, "enable")) {
1762 l += strspn(l, WHITESPACE);
1764 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1769 } else if (first_word(l, "disable")) {
1771 l += strspn(l, WHITESPACE);
1773 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1779 log_debug("Couldn't parse line '%s'", l);
1785 /* Default is "enable" */
1794 int unit_file_preset(
1795 UnitFileScope scope,
1797 const char *root_dir,
1800 UnitFileChange **changes,
1801 unsigned *n_changes) {
1804 InstallContext plus, minus;
1805 char **i, *config_path = NULL;
1806 Set *remove_symlinks_to = NULL;
1810 assert(scope < _UNIT_FILE_SCOPE_MAX);
1816 r = lookup_paths_init_from_scope(&paths, scope);
1820 r = get_config_path(scope, runtime, root_dir, &config_path);
1824 STRV_FOREACH(i, files) {
1826 if (!unit_name_is_valid(*i, true)) {
1831 r = unit_file_query_preset(scope, *i);
1836 r = install_info_add_auto(&plus, *i);
1838 r = install_info_add_auto(&minus, *i);
1844 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1846 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1850 /* Returns number of symlinks that where supposed to be installed. */
1851 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1856 lookup_paths_free(&paths);
1857 install_context_done(&plus);
1858 install_context_done(&minus);
1859 set_free_free(remove_symlinks_to);
1865 int unit_file_get_list(
1866 UnitFileScope scope,
1867 const char *root_dir,
1871 char **i, *buf = NULL;
1876 assert(scope < _UNIT_FILE_SCOPE_MAX);
1881 if (root_dir && scope != UNIT_FILE_SYSTEM)
1884 r = lookup_paths_init_from_scope(&paths, scope);
1888 STRV_FOREACH(i, paths.unit_path) {
1889 const char *units_dir;
1895 if (asprintf(&buf, "%s/%s", root_dir, *i) < 0) {
1906 d = opendir(units_dir);
1908 if (errno == ENOENT)
1917 union dirent_storage buffer;
1920 r = readdir_r(d, &buffer.de, &de);
1929 if (ignore_file(de->d_name))
1932 if (!unit_name_is_valid(de->d_name, true))
1935 if (hashmap_get(h, de->d_name))
1938 r = dirent_ensure_type(d, de);
1946 if (de->d_type != DT_LNK && de->d_type != DT_REG)
1949 f = new0(UnitFileList, 1);
1955 f->path = path_make_absolute(de->d_name, units_dir);
1962 r = null_or_empty_path(f->path);
1963 if (r < 0 && r != -ENOENT) {
1969 path_startswith(*i, "/run") ?
1970 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1974 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
1980 f->state = UNIT_FILE_ENABLED;
1984 r = unit_file_can_install(&paths, root_dir, f->path, true);
1985 if (r == -EINVAL || /* Invalid setting? */
1986 r == -EBADMSG || /* Invalid format? */
1987 r == -ENOENT /* Included file not found? */)
1988 f->state = UNIT_FILE_INVALID;
1994 f->state = UNIT_FILE_DISABLED;
1996 f->state = UNIT_FILE_STATIC;
1999 r = hashmap_put(h, path_get_file_name(f->path), f);
2009 lookup_paths_free(&paths);
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);