1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty <of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
32 #include "path-util.h"
33 #include "path-lookup.h"
35 #include "unit-name.h"
37 #include "conf-parser.h"
38 #include "conf-files.h"
39 #include "specifier.h"
40 #include "install-printf.h"
43 Hashmap *will_install;
44 Hashmap *have_installed;
47 #define _cleanup_lookup_paths_free_ \
48 __attribute__((cleanup(lookup_paths_free)))
49 #define _cleanup_install_context_done_ \
50 __attribute__((cleanup(install_context_done)))
52 static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope) {
55 assert(scope < _UNIT_FILE_SCOPE_MAX);
59 return lookup_paths_init(paths,
60 scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
61 scope == UNIT_FILE_USER,
65 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
70 assert(scope < _UNIT_FILE_SCOPE_MAX);
75 case UNIT_FILE_SYSTEM:
77 if (root_dir && runtime)
78 asprintf(&p, "%s/run/systemd/system", root_dir);
80 p = strdup("/run/systemd/system");
82 asprintf(&p, "%s/%s", root_dir, SYSTEM_CONFIG_UNIT_PATH);
84 p = strdup(SYSTEM_CONFIG_UNIT_PATH);
88 case UNIT_FILE_GLOBAL:
94 p = strdup("/run/systemd/user");
96 p = strdup(USER_CONFIG_UNIT_PATH);
101 if (root_dir || runtime)
104 r = user_config_home(&p);
106 return r < 0 ? r : -ENOENT;
111 assert_not_reached("Bad scope");
121 static int add_file_change(
122 UnitFileChange **changes,
124 UnitFileChangeType type,
126 const char *source) {
132 assert(!changes == !n_changes);
137 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
145 c[i].path = strdup(path);
150 c[i].source = strdup(source);
162 static int mark_symlink_for_removal(
163 Set **remove_symlinks_to,
171 r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
179 path_kill_slashes(n);
181 r = set_put(*remove_symlinks_to, n);
184 return r == -EEXIST ? 0 : r;
190 static int remove_marked_symlinks_fd(
191 Set *remove_symlinks_to,
194 const char *config_path,
196 UnitFileChange **changes,
201 _cleanup_closedir_ DIR *d = NULL;
203 assert(remove_symlinks_to);
211 close_nointr_nofail(fd);
219 union dirent_storage buf;
222 k = readdir_r(d, &buf.de, &de);
231 if (ignore_file(de->d_name))
234 dirent_ensure_type(d, de);
236 if (de->d_type == DT_DIR) {
238 _cleanup_free_ char *p = NULL;
240 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
250 p = path_make_absolute(de->d_name, path);
252 close_nointr_nofail(nfd);
256 /* This will close nfd, regardless whether it succeeds or not */
257 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, files);
262 } else if (de->d_type == DT_LNK) {
263 _cleanup_free_ char *p = NULL, *dest = NULL;
267 p = path_make_absolute(de->d_name, path);
271 q = readlink_and_canonicalize(p, &dest);
282 set_get(remove_symlinks_to, dest) ||
283 set_get(remove_symlinks_to, path_get_file_name(dest));
285 if (unit_name_is_instance(p))
286 found = found && strv_contains(files, path_get_file_name(p));
290 if (unlink(p) < 0 && errno != ENOENT) {
295 rmdir_parents(p, config_path);
296 path_kill_slashes(p);
298 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
300 if (!set_get(remove_symlinks_to, p)) {
302 q = mark_symlink_for_removal(&remove_symlinks_to, p);
317 static int remove_marked_symlinks(
318 Set *remove_symlinks_to,
319 const char *config_path,
320 UnitFileChange **changes,
329 if (set_size(remove_symlinks_to) <= 0)
332 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
346 /* This takes possession of cfd and closes it */
347 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, files);
352 close_nointr_nofail(fd);
357 static int find_symlinks_fd(
361 const char *config_path,
362 bool *same_name_link) {
365 _cleanup_closedir_ DIR *d = NULL;
371 assert(same_name_link);
375 close_nointr_nofail(fd);
382 union dirent_storage buf;
384 k = readdir_r(d, &buf.de, &de);
391 if (ignore_file(de->d_name))
394 dirent_ensure_type(d, de);
396 if (de->d_type == DT_DIR) {
398 _cleanup_free_ char *p = NULL;
400 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
410 p = path_make_absolute(de->d_name, path);
412 close_nointr_nofail(nfd);
416 /* This will close nfd, regardless whether it succeeds or not */
417 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
425 } else if (de->d_type == DT_LNK) {
426 _cleanup_free_ char *p = NULL, *dest = NULL;
427 bool found_path, found_dest, b = false;
430 /* Acquire symlink name */
431 p = path_make_absolute(de->d_name, path);
435 /* Acquire symlink destination */
436 q = readlink_and_canonicalize(p, &dest);
446 /* Check if the symlink itself matches what we
448 if (path_is_absolute(name))
449 found_path = path_equal(p, name);
451 found_path = streq(de->d_name, name);
453 /* Check if what the symlink points to
454 * matches what we are looking for */
455 if (path_is_absolute(name))
456 found_dest = path_equal(dest, name);
458 found_dest = streq(path_get_file_name(dest), name);
460 if (found_path && found_dest) {
461 _cleanup_free_ char *t = NULL;
463 /* Filter out same name links in the main
465 t = path_make_absolute(name, config_path);
469 b = path_equal(t, p);
473 *same_name_link = true;
474 else if (found_path || found_dest)
482 static int find_symlinks(
484 const char *config_path,
485 bool *same_name_link) {
491 assert(same_name_link);
493 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
500 /* This takes possession of fd and closes it */
501 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
504 static int find_symlinks_in_scope(
506 const char *root_dir,
508 UnitFileState *state) {
511 _cleanup_free_ char *path = NULL;
512 bool same_name_link_runtime = false, same_name_link = false;
515 assert(scope < _UNIT_FILE_SCOPE_MAX);
518 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
520 /* First look in runtime config path */
521 r = get_config_path(scope, true, root_dir, &path);
525 r = find_symlinks(name, path, &same_name_link_runtime);
529 *state = UNIT_FILE_ENABLED_RUNTIME;
534 /* Then look in the normal config path */
535 r = get_config_path(scope, false, root_dir, &path);
539 r = find_symlinks(name, path, &same_name_link);
543 *state = UNIT_FILE_ENABLED;
547 /* Hmm, we didn't find it, but maybe we found the same name
549 if (same_name_link_runtime) {
550 *state = UNIT_FILE_LINKED_RUNTIME;
552 } else if (same_name_link) {
553 *state = UNIT_FILE_LINKED;
563 const char *root_dir,
566 UnitFileChange **changes,
567 unsigned *n_changes) {
570 _cleanup_free_ char *prefix;
574 assert(scope < _UNIT_FILE_SCOPE_MAX);
576 r = get_config_path(scope, runtime, root_dir, &prefix);
580 STRV_FOREACH(i, files) {
581 _cleanup_free_ char *path = NULL;
583 if (!unit_name_is_valid(*i, true)) {
589 path = path_make_absolute(*i, prefix);
595 if (symlink("/dev/null", path) >= 0) {
596 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
601 if (errno == EEXIST) {
603 if (null_or_empty_path(path) > 0)
609 if (symlink("/dev/null", path) >= 0) {
611 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
612 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
629 int unit_file_unmask(
632 const char *root_dir,
634 UnitFileChange **changes,
635 unsigned *n_changes) {
637 char **i, *config_path = NULL;
639 Set *remove_symlinks_to = NULL;
642 assert(scope < _UNIT_FILE_SCOPE_MAX);
644 r = get_config_path(scope, runtime, root_dir, &config_path);
648 STRV_FOREACH(i, files) {
651 if (!unit_name_is_valid(*i, true)) {
657 path = path_make_absolute(*i, config_path);
663 q = null_or_empty_path(path);
665 if (unlink(path) >= 0) {
666 mark_symlink_for_removal(&remove_symlinks_to, path);
667 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
676 if (q != -ENOENT && r == 0)
684 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
688 set_free_free(remove_symlinks_to);
697 const char *root_dir,
700 UnitFileChange **changes,
701 unsigned *n_changes) {
703 _cleanup_lookup_paths_free_ LookupPaths paths = {};
705 _cleanup_free_ char *config_path = NULL;
709 assert(scope < _UNIT_FILE_SCOPE_MAX);
711 r = lookup_paths_init_from_scope(&paths, scope);
715 r = get_config_path(scope, runtime, root_dir, &config_path);
719 STRV_FOREACH(i, files) {
720 _cleanup_free_ char *path = NULL;
724 fn = path_get_file_name(*i);
726 if (!path_is_absolute(*i) ||
727 !unit_name_is_valid(fn, true)) {
733 if (lstat(*i, &st) < 0) {
739 if (!S_ISREG(st.st_mode)) {
744 q = in_search_path(*i, paths.unit_path);
751 path = path_make_absolute(fn, config_path);
755 if (symlink(*i, path) >= 0) {
756 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
760 if (errno == EEXIST) {
761 _cleanup_free_ char *dest = NULL;
763 q = readlink_and_make_absolute(path, &dest);
765 if (q < 0 && errno != ENOENT) {
771 if (q >= 0 && path_equal(dest, *i))
777 if (symlink(*i, path) >= 0) {
779 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
780 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
797 void unit_file_list_free(Hashmap *h) {
800 while ((i = hashmap_steal_first(h))) {
808 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
811 assert(changes || n_changes == 0);
816 for (i = 0; i < n_changes; i++) {
817 free(changes[i].path);
818 free(changes[i].source);
824 static void install_info_free(InstallInfo *i) {
829 strv_free(i->aliases);
830 strv_free(i->wanted_by);
831 strv_free(i->required_by);
835 static void install_info_hashmap_free(Hashmap *m) {
841 while ((i = hashmap_steal_first(m)))
842 install_info_free(i);
847 static void install_context_done(InstallContext *c) {
850 install_info_hashmap_free(c->will_install);
851 install_info_hashmap_free(c->have_installed);
853 c->will_install = c->have_installed = NULL;
856 static int install_info_add(
860 InstallInfo *i = NULL;
864 assert(name || path);
867 name = path_get_file_name(path);
869 if (!unit_name_is_valid(name, true))
872 if (hashmap_get(c->have_installed, name) ||
873 hashmap_get(c->will_install, name))
876 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
880 i = new0(InstallInfo, 1);
884 i->name = strdup(name);
891 i->path = strdup(path);
898 r = hashmap_put(c->will_install, i->name, i);
906 install_info_free(i);
911 static int install_info_add_auto(
913 const char *name_or_path) {
916 assert(name_or_path);
918 if (path_is_absolute(name_or_path))
919 return install_info_add(c, NULL, name_or_path);
921 return install_info_add(c, name_or_path, NULL);
924 static int config_parse_also(const char *unit,
925 const char *filename,
937 InstallContext *c = data;
943 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
944 _cleanup_free_ char *n;
951 r = install_info_add(c, n, NULL);
959 static int config_parse_user(const char *unit,
960 const char *filename,
969 InstallInfo *i = data;
976 printed = install_full_printf(i, rvalue);
986 static int unit_file_load(
990 bool allow_symlink) {
992 const ConfigTableItem items[] = {
993 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
994 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
995 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
996 { "Install", "Also", config_parse_also, 0, c },
997 { "Exec", "User", config_parse_user, 0, info },
998 { NULL, NULL, NULL, 0, NULL }
1002 _cleanup_fclose_ FILE *f = NULL;
1009 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1013 f = fdopen(fd, "re");
1015 close_nointr_nofail(fd);
1019 r = config_parse(NULL, path, f, NULL,
1020 config_item_table_lookup, (void*) items, true, info);
1025 strv_length(info->aliases) +
1026 strv_length(info->wanted_by) +
1027 strv_length(info->required_by);
1030 static int unit_file_search(
1034 const char *root_dir,
1035 bool allow_symlink) {
1045 return unit_file_load(c, info, info->path, allow_symlink);
1049 STRV_FOREACH(p, paths->unit_path) {
1052 if (isempty(root_dir))
1053 asprintf(&path, "%s/%s", *p, info->name);
1055 asprintf(&path, "%s/%s/%s", root_dir, *p, info->name);
1060 r = unit_file_load(c, info, path, allow_symlink);
1065 if (r == -ENOENT && unit_name_is_instance(info->name)) {
1066 /* unit file doesn't exist, however instance enablement was request */
1067 /* we will check if it is possible to load template unit file */
1068 char *template = NULL,
1069 *template_path = NULL,
1070 *template_dir = NULL;
1072 template = unit_name_template(info->name);
1078 /* we will reuse path variable since we don't need it anymore */
1079 template_dir = path;
1080 *(strrchr(path, '/') + 1) = '\0';
1082 template_path = strjoin(template_dir, template, NULL);
1083 if (!template_path) {
1089 /* let's try to load template unit */
1090 r = unit_file_load(c, info, template_path, allow_symlink);
1092 info->path = strdup(template_path);
1096 free(template_path);
1102 free(template_path);
1107 if (r != -ENOENT && r != -ELOOP)
1114 static int unit_file_can_install(
1116 const char *root_dir,
1118 bool allow_symlink) {
1120 _cleanup_install_context_done_ InstallContext c = {};
1127 r = install_info_add_auto(&c, name);
1131 assert_se(i = hashmap_first(c.will_install));
1133 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1137 strv_length(i->aliases) +
1138 strv_length(i->wanted_by) +
1139 strv_length(i->required_by);
1144 static int create_symlink(
1145 const char *old_path,
1146 const char *new_path,
1148 UnitFileChange **changes,
1149 unsigned *n_changes) {
1151 _cleanup_free_ char *dest = NULL;
1157 mkdir_parents_label(new_path, 0755);
1159 if (symlink(old_path, new_path) >= 0) {
1160 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1164 if (errno != EEXIST)
1167 r = readlink_and_make_absolute(new_path, &dest);
1171 if (path_equal(dest, old_path))
1179 if (symlink(old_path, new_path) >= 0) {
1180 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1181 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1188 static int install_info_symlink_alias(
1190 const char *config_path,
1192 UnitFileChange **changes,
1193 unsigned *n_changes) {
1199 assert(config_path);
1201 STRV_FOREACH(s, i->aliases) {
1202 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1204 dst = install_full_printf(i, *s);
1208 alias_path = path_make_absolute(dst, config_path);
1212 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1220 static int install_info_symlink_wants(
1222 const char *config_path,
1224 UnitFileChange **changes,
1225 unsigned *n_changes) {
1231 assert(config_path);
1233 STRV_FOREACH(s, i->wanted_by) {
1234 _cleanup_free_ char *path = NULL, *dst = NULL;
1236 dst = install_full_printf(i, *s);
1240 if (!unit_name_is_valid(dst, true)) {
1245 if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
1248 q = create_symlink(i->path, path, force, changes, n_changes);
1257 static int install_info_symlink_requires(
1259 const char *config_path,
1261 UnitFileChange **changes,
1262 unsigned *n_changes) {
1268 assert(config_path);
1270 STRV_FOREACH(s, i->required_by) {
1271 _cleanup_free_ char *path = NULL, *dst = NULL;
1273 dst = install_full_printf(i, *s);
1277 if (!unit_name_is_valid(dst, true)) {
1282 if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
1285 q = create_symlink(i->path, path, force, changes, n_changes);
1294 static int install_info_symlink_link(
1297 const char *config_path,
1299 UnitFileChange **changes,
1300 unsigned *n_changes) {
1303 _cleanup_free_ char *path = NULL;
1307 assert(config_path);
1310 r = in_search_path(i->path, paths->unit_path);
1314 if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1317 r = create_symlink(i->path, path, force, changes, n_changes);
1321 static int install_info_apply(
1324 const char *config_path,
1326 UnitFileChange **changes,
1327 unsigned *n_changes) {
1333 assert(config_path);
1335 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1337 q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1341 q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1345 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1352 static int install_context_apply(
1355 const char *config_path,
1356 const char *root_dir,
1358 UnitFileChange **changes,
1359 unsigned *n_changes) {
1366 assert(config_path);
1368 while ((i = hashmap_first(c->will_install))) {
1370 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1374 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1376 q = unit_file_search(c, i, paths, root_dir, false);
1385 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1386 if (r >= 0 && q < 0)
1393 static int install_context_mark_for_removal(
1396 Set **remove_symlinks_to,
1397 const char *config_path,
1398 const char *root_dir) {
1405 assert(config_path);
1407 /* Marks all items for removal */
1409 while ((i = hashmap_first(c->will_install))) {
1411 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1415 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1417 q = unit_file_search(c, i, paths, root_dir, false);
1426 if (unit_name_is_instance(i->name)) {
1427 char *unit_file = NULL;
1429 unit_file = path_get_file_name(i->path);
1431 if (unit_name_is_instance(unit_file))
1432 /* unit file named as instance exists, thus all symlinks pointing to it, will be removed */
1433 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1435 /* does not exist, thus we will mark for removal symlinks to template unit file */
1436 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1438 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1440 if (r >= 0 && q < 0)
1447 int unit_file_enable(
1448 UnitFileScope scope,
1450 const char *root_dir,
1453 UnitFileChange **changes,
1454 unsigned *n_changes) {
1456 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1457 _cleanup_install_context_done_ InstallContext c = {};
1459 _cleanup_free_ char *config_path = NULL;
1463 assert(scope < _UNIT_FILE_SCOPE_MAX);
1465 r = lookup_paths_init_from_scope(&paths, scope);
1469 r = get_config_path(scope, runtime, root_dir, &config_path);
1473 STRV_FOREACH(i, files) {
1474 r = install_info_add_auto(&c, *i);
1479 /* This will return the number of symlink rules that were
1480 supposed to be created, not the ones actually created. This is
1481 useful to determine whether the passed files had any
1482 installation data at all. */
1483 r = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1487 int unit_file_disable(
1488 UnitFileScope scope,
1490 const char *root_dir,
1492 UnitFileChange **changes,
1493 unsigned *n_changes) {
1495 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1496 _cleanup_install_context_done_ InstallContext c = {};
1498 _cleanup_free_ char *config_path = NULL;
1499 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1503 assert(scope < _UNIT_FILE_SCOPE_MAX);
1505 r = lookup_paths_init_from_scope(&paths, scope);
1509 r = get_config_path(scope, runtime, root_dir, &config_path);
1513 STRV_FOREACH(i, files) {
1514 r = install_info_add_auto(&c, *i);
1519 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1521 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1528 int unit_file_reenable(
1529 UnitFileScope scope,
1531 const char *root_dir,
1534 UnitFileChange **changes,
1535 unsigned *n_changes) {
1537 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1538 _cleanup_install_context_done_ InstallContext c = {};
1540 _cleanup_free_ char *config_path = NULL;
1541 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1545 assert(scope < _UNIT_FILE_SCOPE_MAX);
1547 r = lookup_paths_init_from_scope(&paths, scope);
1551 r = get_config_path(scope, runtime, root_dir, &config_path);
1555 STRV_FOREACH(i, files) {
1556 r = mark_symlink_for_removal(&remove_symlinks_to, *i);
1560 r = install_info_add_auto(&c, *i);
1565 r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1567 /* Returns number of symlinks that where supposed to be installed. */
1568 q = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1575 UnitFileState unit_file_get_state(
1576 UnitFileScope scope,
1577 const char *root_dir,
1580 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1581 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1583 _cleanup_free_ char *path = NULL;
1587 assert(scope < _UNIT_FILE_SCOPE_MAX);
1590 if (root_dir && scope != UNIT_FILE_SYSTEM)
1593 if (!unit_name_is_valid(name, true))
1596 r = lookup_paths_init_from_scope(&paths, scope);
1600 STRV_FOREACH(i, paths.unit_path) {
1607 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1609 asprintf(&path, "%s/%s", *i, name);
1614 if (lstat(path, &st) < 0) {
1616 if (errno == ENOENT)
1622 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1625 r = null_or_empty_path(path);
1626 if (r < 0 && r != -ENOENT)
1629 state = path_startswith(*i, "/run") ?
1630 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1634 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1640 r = unit_file_can_install(&paths, root_dir, path, true);
1641 if (r < 0 && errno != ENOENT)
1644 return UNIT_FILE_DISABLED;
1646 return UNIT_FILE_STATIC;
1649 return r < 0 ? r : state;
1652 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1653 _cleanup_strv_free_ char **files = NULL;
1658 assert(scope < _UNIT_FILE_SCOPE_MAX);
1661 if (scope == UNIT_FILE_SYSTEM)
1662 r = conf_files_list(&files, ".preset", NULL,
1663 "/etc/systemd/system-preset",
1664 "/usr/local/lib/systemd/system-preset",
1665 "/usr/lib/systemd/system-preset",
1666 #ifdef HAVE_SPLIT_USR
1667 "/lib/systemd/system-preset",
1670 else if (scope == UNIT_FILE_GLOBAL)
1671 r = conf_files_list(&files, ".preset", NULL,
1672 "/etc/systemd/user-preset",
1673 "/usr/local/lib/systemd/user-preset",
1674 "/usr/lib/systemd/user-preset",
1682 STRV_FOREACH(i, files) {
1683 _cleanup_fclose_ FILE *f;
1685 f = fopen(*i, "re");
1687 if (errno == ENOENT)
1694 char line[LINE_MAX], *l;
1696 if (!fgets(line, sizeof(line), f))
1703 if (strchr(COMMENTS "\n", *l))
1706 if (first_word(l, "enable")) {
1708 l += strspn(l, WHITESPACE);
1710 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1713 } else if (first_word(l, "disable")) {
1715 l += strspn(l, WHITESPACE);
1717 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1721 log_debug("Couldn't parse line '%s'", l);
1725 /* Default is "enable" */
1729 int unit_file_preset(
1730 UnitFileScope scope,
1732 const char *root_dir,
1735 UnitFileChange **changes,
1736 unsigned *n_changes) {
1738 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1739 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1741 _cleanup_free_ char *config_path = NULL;
1742 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1746 assert(scope < _UNIT_FILE_SCOPE_MAX);
1748 r = lookup_paths_init_from_scope(&paths, scope);
1752 r = get_config_path(scope, runtime, root_dir, &config_path);
1756 STRV_FOREACH(i, files) {
1758 if (!unit_name_is_valid(*i, true))
1761 r = unit_file_query_preset(scope, *i);
1766 r = install_info_add_auto(&plus, *i);
1768 r = install_info_add_auto(&minus, *i);
1774 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to,
1775 config_path, root_dir);
1777 q = remove_marked_symlinks(remove_symlinks_to, config_path,
1778 changes, n_changes, files);
1782 /* Returns number of symlinks that where supposed to be installed. */
1783 q = install_context_apply(&plus, &paths, config_path, root_dir, force,
1784 changes, n_changes);
1791 static void unitfilelist_free(UnitFileList **f) {
1799 int unit_file_get_list(
1800 UnitFileScope scope,
1801 const char *root_dir,
1804 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1806 _cleanup_free_ char *buf = NULL;
1807 _cleanup_closedir_ DIR *d = NULL;
1811 assert(scope < _UNIT_FILE_SCOPE_MAX);
1814 if (root_dir && scope != UNIT_FILE_SYSTEM)
1817 r = lookup_paths_init_from_scope(&paths, scope);
1821 STRV_FOREACH(i, paths.unit_path) {
1822 const char *units_dir;
1828 if (asprintf(&buf, "%s/%s", root_dir, *i) < 0)
1838 d = opendir(units_dir);
1840 if (errno == ENOENT)
1848 union dirent_storage buffer;
1849 UnitFileList __attribute__((cleanup(unitfilelist_free)))
1852 r = readdir_r(d, &buffer.de, &de);
1859 if (ignore_file(de->d_name))
1862 if (!unit_name_is_valid(de->d_name, true))
1865 if (hashmap_get(h, de->d_name))
1868 r = dirent_ensure_type(d, de);
1876 if (de->d_type != DT_LNK && de->d_type != DT_REG)
1879 f = new0(UnitFileList, 1);
1883 f->path = path_make_absolute(de->d_name, units_dir);
1887 r = null_or_empty_path(f->path);
1888 if (r < 0 && r != -ENOENT)
1892 path_startswith(*i, "/run") ?
1893 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1897 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
1901 f->state = UNIT_FILE_ENABLED;
1905 r = unit_file_can_install(&paths, root_dir, f->path, true);
1906 if (r == -EINVAL || /* Invalid setting? */
1907 r == -EBADMSG || /* Invalid format? */
1908 r == -ENOENT /* Included file not found? */)
1909 f->state = UNIT_FILE_INVALID;
1913 f->state = UNIT_FILE_DISABLED;
1915 f->state = UNIT_FILE_STATIC;
1918 r = hashmap_put(h, path_get_file_name(f->path), f);
1921 f = NULL; /* prevent cleanup */
1928 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
1929 [UNIT_FILE_ENABLED] = "enabled",
1930 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
1931 [UNIT_FILE_LINKED] = "linked",
1932 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
1933 [UNIT_FILE_MASKED] = "masked",
1934 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
1935 [UNIT_FILE_STATIC] = "static",
1936 [UNIT_FILE_DISABLED] = "disabled",
1937 [UNIT_FILE_INVALID] = "invalid",
1940 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
1942 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
1943 [UNIT_FILE_SYMLINK] = "symlink",
1944 [UNIT_FILE_UNLINK] = "unlink",
1947 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);