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"
44 Hashmap *will_install;
45 Hashmap *have_installed;
48 static int in_search_path(const char *path, char **search) {
49 _cleanup_free_ char *parent = NULL;
54 r = path_get_parent(path, &parent);
58 return strv_contains(search, parent);
61 static int lookup_paths_init_from_scope(LookupPaths *paths,
63 const char *root_dir) {
66 assert(scope < _UNIT_FILE_SCOPE_MAX);
70 return lookup_paths_init(paths,
71 scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
72 scope == UNIT_FILE_USER,
77 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
82 assert(scope < _UNIT_FILE_SCOPE_MAX);
87 case UNIT_FILE_SYSTEM:
90 p = path_join(root_dir, "/run/systemd/system", NULL);
92 p = path_join(root_dir, SYSTEM_CONFIG_UNIT_PATH, NULL);
95 case UNIT_FILE_GLOBAL:
101 p = strdup("/run/systemd/user");
103 p = strdup(USER_CONFIG_UNIT_PATH);
112 r = user_runtime_dir(&p);
114 r = user_config_home(&p);
117 return r < 0 ? r : -ENOENT;
122 assert_not_reached("Bad scope");
132 static int add_file_change(
133 UnitFileChange **changes,
135 UnitFileChangeType type,
137 const char *source) {
143 assert(!changes == !n_changes);
148 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
156 c[i].path = strdup(path);
160 path_kill_slashes(c[i].path);
163 c[i].source = strdup(source);
169 path_kill_slashes(c[i].path);
177 static int mark_symlink_for_removal(
178 Set **remove_symlinks_to,
186 r = set_ensure_allocated(remove_symlinks_to, &string_hash_ops);
194 path_kill_slashes(n);
196 r = set_consume(*remove_symlinks_to, n);
198 return r == -EEXIST ? 0 : r;
203 static int remove_marked_symlinks_fd(
204 Set *remove_symlinks_to,
207 const char *config_path,
209 UnitFileChange **changes,
211 char** instance_whitelist) {
213 _cleanup_closedir_ DIR *d = NULL;
216 assert(remove_symlinks_to);
235 if (!de && errno != 0) {
243 if (ignore_file(de->d_name))
246 dirent_ensure_type(d, de);
248 if (de->d_type == DT_DIR) {
250 _cleanup_free_ char *p = NULL;
252 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
262 p = path_make_absolute(de->d_name, path);
268 /* This will close nfd, regardless whether it succeeds or not */
269 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, instance_whitelist);
273 } else if (de->d_type == DT_LNK) {
274 _cleanup_free_ char *p = NULL, *dest = NULL;
278 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
281 if (unit_name_is_instance(de->d_name) &&
282 instance_whitelist &&
283 !strv_contains(instance_whitelist, de->d_name)) {
285 _cleanup_free_ char *w;
287 /* OK, the file is not listed directly
288 * in the whitelist, so let's check if
289 * the template of it might be
292 w = unit_name_template(de->d_name);
296 if (!strv_contains(instance_whitelist, w))
300 p = path_make_absolute(de->d_name, path);
304 q = readlink_and_canonicalize(p, &dest);
315 set_get(remove_symlinks_to, dest) ||
316 set_get(remove_symlinks_to, basename(dest));
321 if (unlink(p) < 0 && errno != ENOENT) {
327 path_kill_slashes(p);
328 rmdir_parents(p, config_path);
329 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
331 if (!set_get(remove_symlinks_to, p)) {
333 q = mark_symlink_for_removal(&remove_symlinks_to, p);
346 static int remove_marked_symlinks(
347 Set *remove_symlinks_to,
348 const char *config_path,
349 UnitFileChange **changes,
351 char** instance_whitelist) {
353 _cleanup_close_ int fd = -1;
359 if (set_size(remove_symlinks_to) <= 0)
362 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
370 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
376 /* This takes possession of cfd and closes it */
377 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist);
385 static int find_symlinks_fd(
389 const char *config_path,
390 bool *same_name_link) {
393 _cleanup_closedir_ DIR *d = NULL;
399 assert(same_name_link);
412 if (!de && errno != 0)
418 if (ignore_file(de->d_name))
421 dirent_ensure_type(d, de);
423 if (de->d_type == DT_DIR) {
425 _cleanup_free_ char *p = NULL;
427 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
437 p = path_make_absolute(de->d_name, path);
443 /* This will close nfd, regardless whether it succeeds or not */
444 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
450 } else if (de->d_type == DT_LNK) {
451 _cleanup_free_ char *p = NULL, *dest = NULL;
452 bool found_path, found_dest, b = false;
455 /* Acquire symlink name */
456 p = path_make_absolute(de->d_name, path);
460 /* Acquire symlink destination */
461 q = readlink_and_canonicalize(p, &dest);
471 /* Check if the symlink itself matches what we
473 if (path_is_absolute(name))
474 found_path = path_equal(p, name);
476 found_path = streq(de->d_name, name);
478 /* Check if what the symlink points to
479 * matches what we are looking for */
480 if (path_is_absolute(name))
481 found_dest = path_equal(dest, name);
483 found_dest = streq(basename(dest), name);
485 if (found_path && found_dest) {
486 _cleanup_free_ char *t = NULL;
488 /* Filter out same name links in the main
490 t = path_make_absolute(name, config_path);
494 b = path_equal(t, p);
498 *same_name_link = true;
499 else if (found_path || found_dest)
505 static int find_symlinks(
507 const char *config_path,
508 bool *same_name_link) {
514 assert(same_name_link);
516 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
523 /* This takes possession of fd and closes it */
524 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
527 static int find_symlinks_in_scope(
529 const char *root_dir,
531 UnitFileState *state) {
534 _cleanup_free_ char *path = NULL;
535 bool same_name_link_runtime = false, same_name_link = false;
538 assert(scope < _UNIT_FILE_SCOPE_MAX);
542 /* First look in runtime config path */
543 r = get_config_path(scope, true, root_dir, &path);
547 r = find_symlinks(name, path, &same_name_link_runtime);
551 *state = UNIT_FILE_ENABLED_RUNTIME;
555 /* Then look in the normal config path */
556 r = get_config_path(scope, false, root_dir, &path);
560 r = find_symlinks(name, path, &same_name_link);
564 *state = UNIT_FILE_ENABLED;
568 /* Hmm, we didn't find it, but maybe we found the same name
570 if (same_name_link_runtime) {
571 *state = UNIT_FILE_LINKED_RUNTIME;
573 } else if (same_name_link) {
574 *state = UNIT_FILE_LINKED;
584 const char *root_dir,
587 UnitFileChange **changes,
588 unsigned *n_changes) {
591 _cleanup_free_ char *prefix = NULL;
595 assert(scope < _UNIT_FILE_SCOPE_MAX);
597 r = get_config_path(scope, runtime, root_dir, &prefix);
601 STRV_FOREACH(i, files) {
602 _cleanup_free_ char *path = NULL;
604 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
610 path = path_make_absolute(*i, prefix);
616 if (symlink("/dev/null", path) >= 0) {
617 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
621 if (errno == EEXIST) {
623 if (null_or_empty_path(path) > 0)
627 if (symlink_atomic("/dev/null", path) >= 0) {
628 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
629 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
645 int unit_file_unmask(
648 const char *root_dir,
650 UnitFileChange **changes,
651 unsigned *n_changes) {
653 char **i, *config_path = NULL;
655 Set *remove_symlinks_to = NULL;
658 assert(scope < _UNIT_FILE_SCOPE_MAX);
660 r = get_config_path(scope, runtime, root_dir, &config_path);
664 STRV_FOREACH(i, files) {
667 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
673 path = path_make_absolute(*i, config_path);
679 q = null_or_empty_path(path);
681 if (unlink(path) >= 0) {
682 mark_symlink_for_removal(&remove_symlinks_to, path);
683 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
692 if (q != -ENOENT && r == 0)
700 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
704 set_free_free(remove_symlinks_to);
713 const char *root_dir,
716 UnitFileChange **changes,
717 unsigned *n_changes) {
719 _cleanup_lookup_paths_free_ LookupPaths paths = {};
721 _cleanup_free_ char *config_path = NULL;
725 assert(scope < _UNIT_FILE_SCOPE_MAX);
727 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
731 r = get_config_path(scope, runtime, root_dir, &config_path);
735 STRV_FOREACH(i, files) {
736 _cleanup_free_ char *path = NULL;
742 if (!path_is_absolute(*i) ||
743 !unit_name_is_valid(fn, TEMPLATE_VALID)) {
749 if (lstat(*i, &st) < 0) {
755 if (!S_ISREG(st.st_mode)) {
760 q = in_search_path(*i, paths.unit_path);
767 path = path_make_absolute(fn, config_path);
771 if (symlink(*i, path) >= 0) {
772 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
776 if (errno == EEXIST) {
777 _cleanup_free_ char *dest = NULL;
779 q = readlink_and_make_absolute(path, &dest);
780 if (q < 0 && errno != ENOENT) {
786 if (q >= 0 && path_equal(dest, *i))
790 if (symlink_atomic(*i, path) >= 0) {
791 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
792 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
808 void unit_file_list_free(Hashmap *h) {
811 while ((i = hashmap_steal_first(h))) {
819 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
822 assert(changes || n_changes == 0);
827 for (i = 0; i < n_changes; i++) {
828 free(changes[i].path);
829 free(changes[i].source);
835 static void install_info_free(InstallInfo *i) {
840 strv_free(i->aliases);
841 strv_free(i->wanted_by);
842 strv_free(i->required_by);
843 free(i->default_instance);
847 static void install_info_hashmap_free(Hashmap *m) {
853 while ((i = hashmap_steal_first(m)))
854 install_info_free(i);
859 static void install_context_done(InstallContext *c) {
862 install_info_hashmap_free(c->will_install);
863 install_info_hashmap_free(c->have_installed);
865 c->will_install = c->have_installed = NULL;
868 static int install_info_add(
872 InstallInfo *i = NULL;
876 assert(name || path);
879 name = basename(path);
881 if (!unit_name_is_valid(name, TEMPLATE_VALID))
884 if (hashmap_get(c->have_installed, name) ||
885 hashmap_get(c->will_install, name))
888 r = hashmap_ensure_allocated(&c->will_install, &string_hash_ops);
892 i = new0(InstallInfo, 1);
896 i->name = strdup(name);
903 i->path = strdup(path);
910 r = hashmap_put(c->will_install, i->name, i);
918 install_info_free(i);
923 static int install_info_add_auto(
925 const char *name_or_path) {
928 assert(name_or_path);
930 if (path_is_absolute(name_or_path))
931 return install_info_add(c, NULL, name_or_path);
933 return install_info_add(c, name_or_path, NULL);
936 static int config_parse_also(
938 const char *filename,
941 unsigned section_line,
949 const char *word, *state;
950 InstallContext *c = data;
956 FOREACH_WORD_QUOTED(word, l, rvalue, state) {
957 _cleanup_free_ char *n;
960 n = strndup(word, l);
964 r = install_info_add(c, n, NULL);
969 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
970 "Trailing garbage, ignoring.");
975 static int config_parse_user(
977 const char *filename,
980 unsigned section_line,
987 InstallInfo *i = data;
995 r = install_full_printf(i, rvalue, &printed);
1005 static int config_parse_default_instance(
1007 const char *filename,
1009 const char *section,
1010 unsigned section_line,
1017 InstallInfo *i = data;
1025 r = install_full_printf(i, rvalue, &printed);
1029 if (!unit_instance_is_valid(printed)) {
1034 free(i->default_instance);
1035 i->default_instance = printed;
1040 static int unit_file_load(
1044 const char *root_dir,
1045 bool allow_symlink) {
1047 const ConfigTableItem items[] = {
1048 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
1049 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1050 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1051 { "Install", "DefaultInstance", config_parse_default_instance, 0, info },
1052 { "Install", "Also", config_parse_also, 0, c },
1053 { "Exec", "User", config_parse_user, 0, info },
1057 _cleanup_fclose_ FILE *f = NULL;
1064 if (!isempty(root_dir))
1065 path = strappenda(root_dir, "/", path);
1067 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1071 f = fdopen(fd, "re");
1077 r = config_parse(NULL, path, f,
1079 config_item_table_lookup, items,
1080 true, true, false, info);
1085 (int) strv_length(info->aliases) +
1086 (int) strv_length(info->wanted_by) +
1087 (int) strv_length(info->required_by);
1090 static int unit_file_search(
1094 const char *root_dir,
1095 bool allow_symlink) {
1105 return unit_file_load(c, info, info->path, root_dir, allow_symlink);
1109 STRV_FOREACH(p, paths->unit_path) {
1110 _cleanup_free_ char *path = NULL;
1112 path = strjoin(*p, "/", info->name, NULL);
1116 r = unit_file_load(c, info, path, root_dir, allow_symlink);
1122 if (r != -ENOENT && r != -ELOOP)
1126 if (unit_name_is_instance(info->name)) {
1128 /* Unit file doesn't exist, however instance
1129 * enablement was requested. We will check if it is
1130 * possible to load template unit file. */
1132 _cleanup_free_ char *template = NULL;
1134 template = unit_name_template(info->name);
1138 STRV_FOREACH(p, paths->unit_path) {
1139 _cleanup_free_ char *path = NULL;
1141 path = strjoin(*p, "/", template, NULL);
1145 r = unit_file_load(c, info, path, root_dir, allow_symlink);
1151 if (r != -ENOENT && r != -ELOOP)
1159 static int unit_file_can_install(
1161 const char *root_dir,
1163 bool allow_symlink) {
1165 _cleanup_(install_context_done) InstallContext c = {};
1172 r = install_info_add_auto(&c, name);
1176 assert_se(i = hashmap_first(c.will_install));
1178 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1182 (int) strv_length(i->aliases) +
1183 (int) strv_length(i->wanted_by) +
1184 (int) strv_length(i->required_by);
1189 static int create_symlink(
1190 const char *old_path,
1191 const char *new_path,
1193 UnitFileChange **changes,
1194 unsigned *n_changes) {
1196 _cleanup_free_ char *dest = NULL;
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))
1222 r = symlink_atomic(old_path, new_path);
1226 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1227 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1232 static int install_info_symlink_alias(
1234 const char *config_path,
1236 UnitFileChange **changes,
1237 unsigned *n_changes) {
1243 assert(config_path);
1245 STRV_FOREACH(s, i->aliases) {
1246 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1248 q = install_full_printf(i, *s, &dst);
1252 alias_path = path_make_absolute(dst, config_path);
1256 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1264 static int install_info_symlink_wants(
1266 const char *config_path,
1270 UnitFileChange **changes,
1271 unsigned *n_changes) {
1273 _cleanup_free_ char *buf = NULL;
1279 assert(config_path);
1281 if (unit_name_is_template(i->name)) {
1283 /* Don't install any symlink if there's no default
1284 * instance configured */
1286 if (!i->default_instance)
1289 buf = unit_name_replace_instance(i->name, i->default_instance);
1297 STRV_FOREACH(s, list) {
1298 _cleanup_free_ char *path = NULL, *dst = NULL;
1300 q = install_full_printf(i, *s, &dst);
1304 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1309 path = strjoin(config_path, "/", dst, suffix, n, NULL);
1313 q = create_symlink(i->path, path, force, changes, n_changes);
1321 static int install_info_symlink_link(
1324 const char *config_path,
1325 const char *root_dir,
1327 UnitFileChange **changes,
1328 unsigned *n_changes) {
1330 _cleanup_free_ char *path = NULL;
1335 assert(config_path);
1338 r = in_search_path(i->path, paths->unit_path);
1342 path = strjoin(config_path, "/", i->name, NULL);
1346 return create_symlink(i->path, path, force, changes, n_changes);
1349 static int install_info_apply(
1352 const char *config_path,
1353 const char *root_dir,
1355 UnitFileChange **changes,
1356 unsigned *n_changes) {
1362 assert(config_path);
1364 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1366 q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes);
1370 q = install_info_symlink_wants(i, config_path, i->required_by, ".requires/", force, changes, n_changes);
1374 q = install_info_symlink_link(i, paths, config_path, root_dir, force, changes, n_changes);
1381 static int install_context_apply(
1384 const char *config_path,
1385 const char *root_dir,
1387 UnitFileChange **changes,
1388 unsigned *n_changes) {
1395 assert(config_path);
1397 while ((i = hashmap_first(c->will_install))) {
1399 q = hashmap_ensure_allocated(&c->have_installed, &string_hash_ops);
1403 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1405 q = unit_file_search(c, i, paths, root_dir, false);
1414 q = install_info_apply(i, paths, config_path, root_dir, force, changes, n_changes);
1415 if (r >= 0 && q < 0)
1422 static int install_context_mark_for_removal(
1425 Set **remove_symlinks_to,
1426 const char *config_path,
1427 const char *root_dir) {
1434 assert(config_path);
1436 /* Marks all items for removal */
1438 while ((i = hashmap_first(c->will_install))) {
1440 q = hashmap_ensure_allocated(&c->have_installed, &string_hash_ops);
1444 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1446 q = unit_file_search(c, i, paths, root_dir, false);
1457 if (unit_name_is_instance(i->name)) {
1461 unit_file = basename(i->path);
1463 if (unit_name_is_instance(unit_file))
1464 /* unit file named as instance exists, thus all symlinks
1465 * pointing to it will be removed */
1466 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1468 /* does not exist, thus we will mark for removal symlinks
1469 * to template unit file */
1470 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1472 /* If i->path is not set, it means that we didn't actually find
1473 * the unit file. But we can still remove symlinks to the
1474 * nonexistent template. */
1475 unit_file = unit_name_template(i->name);
1479 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1483 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1485 if (r >= 0 && q < 0)
1492 int unit_file_enable(
1493 UnitFileScope scope,
1495 const char *root_dir,
1498 UnitFileChange **changes,
1499 unsigned *n_changes) {
1501 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1502 _cleanup_(install_context_done) InstallContext c = {};
1504 _cleanup_free_ char *config_path = NULL;
1508 assert(scope < _UNIT_FILE_SCOPE_MAX);
1510 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1514 r = get_config_path(scope, runtime, root_dir, &config_path);
1518 STRV_FOREACH(i, files) {
1519 UnitFileState state;
1521 state = unit_file_get_state(scope, root_dir, *i);
1523 log_error("Failed to get unit file state for %s: %s", *i, strerror(-state));
1527 if (state == UNIT_FILE_MASKED || state == UNIT_FILE_MASKED_RUNTIME) {
1528 log_error("Failed to enable unit: Unit %s is masked", *i);
1532 r = install_info_add_auto(&c, *i);
1537 /* This will return the number of symlink rules that were
1538 supposed to be created, not the ones actually created. This is
1539 useful to determine whether the passed files had any
1540 installation data at all. */
1542 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1545 int unit_file_disable(
1546 UnitFileScope scope,
1548 const char *root_dir,
1550 UnitFileChange **changes,
1551 unsigned *n_changes) {
1553 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1554 _cleanup_(install_context_done) InstallContext c = {};
1556 _cleanup_free_ char *config_path = NULL;
1557 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1561 assert(scope < _UNIT_FILE_SCOPE_MAX);
1563 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1567 r = get_config_path(scope, runtime, root_dir, &config_path);
1571 STRV_FOREACH(i, files) {
1572 r = install_info_add_auto(&c, *i);
1577 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1579 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1586 int unit_file_reenable(
1587 UnitFileScope scope,
1589 const char *root_dir,
1592 UnitFileChange **changes,
1593 unsigned *n_changes) {
1596 r = unit_file_disable(scope, runtime, root_dir, files,
1597 changes, n_changes);
1601 return unit_file_enable(scope, runtime, root_dir, files, force,
1602 changes, n_changes);
1605 int unit_file_set_default(
1606 UnitFileScope scope,
1607 const char *root_dir,
1610 UnitFileChange **changes,
1611 unsigned *n_changes) {
1613 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1614 _cleanup_(install_context_done) InstallContext c = {};
1615 _cleanup_free_ char *config_path = NULL;
1618 InstallInfo *i = NULL;
1621 assert(scope < _UNIT_FILE_SCOPE_MAX);
1624 if (unit_name_to_type(file) != UNIT_TARGET)
1627 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1631 r = get_config_path(scope, false, root_dir, &config_path);
1635 r = install_info_add_auto(&c, file);
1639 assert_se(i = hashmap_first(c.will_install));
1641 r = unit_file_search(&c, i, &paths, root_dir, false);
1645 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1647 r = create_symlink(i->path, path, force, changes, n_changes);
1654 int unit_file_get_default(
1655 UnitFileScope scope,
1656 const char *root_dir,
1659 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1664 assert(scope < _UNIT_FILE_SCOPE_MAX);
1667 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1671 STRV_FOREACH(p, paths.unit_path) {
1672 _cleanup_free_ char *path = NULL, *tmp = NULL;
1675 path = path_join(root_dir, *p, SPECIAL_DEFAULT_TARGET);
1679 r = readlink_malloc(path, &tmp);
1682 else if (r == -EINVAL)
1684 n = strdup(SPECIAL_DEFAULT_TARGET);
1688 n = strdup(basename(tmp));
1700 UnitFileState unit_file_get_state(
1701 UnitFileScope scope,
1702 const char *root_dir,
1705 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1706 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1708 _cleanup_free_ char *path = NULL;
1712 assert(scope < _UNIT_FILE_SCOPE_MAX);
1715 if (root_dir && scope != UNIT_FILE_SYSTEM)
1718 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1721 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1725 STRV_FOREACH(i, paths.unit_path) {
1732 path = path_join(root_dir, *i, name);
1737 partial = path + strlen(root_dir);
1742 * Search for a unit file in our default paths, to
1743 * be sure, that there are no broken symlinks.
1745 if (lstat(path, &st) < 0) {
1747 if (errno != ENOENT)
1750 if (!unit_name_is_instance(name))
1753 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1756 r = null_or_empty_path(path);
1757 if (r < 0 && r != -ENOENT)
1760 state = path_startswith(*i, "/run") ?
1761 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1766 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1772 r = unit_file_can_install(&paths, root_dir, partial, true);
1773 if (r < 0 && errno != ENOENT)
1776 return UNIT_FILE_DISABLED;
1778 return UNIT_FILE_STATIC;
1781 return r < 0 ? r : state;
1784 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
1785 _cleanup_strv_free_ char **files = NULL;
1790 assert(scope < _UNIT_FILE_SCOPE_MAX);
1793 if (scope == UNIT_FILE_SYSTEM)
1794 r = conf_files_list(&files, ".preset", root_dir,
1795 "/etc/systemd/system-preset",
1796 "/usr/local/lib/systemd/system-preset",
1797 "/usr/lib/systemd/system-preset",
1798 #ifdef HAVE_SPLIT_USR
1799 "/lib/systemd/system-preset",
1802 else if (scope == UNIT_FILE_GLOBAL)
1803 r = conf_files_list(&files, ".preset", root_dir,
1804 "/etc/systemd/user-preset",
1805 "/usr/local/lib/systemd/user-preset",
1806 "/usr/lib/systemd/user-preset",
1814 STRV_FOREACH(p, files) {
1815 _cleanup_fclose_ FILE *f;
1817 f = fopen(*p, "re");
1819 if (errno == ENOENT)
1826 char line[LINE_MAX], *l;
1828 if (!fgets(line, sizeof(line), f))
1835 if (strchr(COMMENTS "\n", *l))
1838 if (first_word(l, "enable")) {
1840 l += strspn(l, WHITESPACE);
1842 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1843 log_debug("Preset file says enable %s.", name);
1847 } else if (first_word(l, "disable")) {
1849 l += strspn(l, WHITESPACE);
1851 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1852 log_debug("Preset file says disable %s.", name);
1857 log_debug("Couldn't parse line '%s'", l);
1861 /* Default is "enable" */
1862 log_debug("Preset file doesn't say anything about %s, enabling.", name);
1866 int unit_file_preset(
1867 UnitFileScope scope,
1869 const char *root_dir,
1871 UnitFilePresetMode mode,
1873 UnitFileChange **changes,
1874 unsigned *n_changes) {
1876 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
1877 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1878 _cleanup_free_ char *config_path = NULL;
1883 assert(scope < _UNIT_FILE_SCOPE_MAX);
1884 assert(mode < _UNIT_FILE_PRESET_MAX);
1886 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1890 r = get_config_path(scope, runtime, root_dir, &config_path);
1894 STRV_FOREACH(i, files) {
1896 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1899 r = unit_file_query_preset(scope, root_dir, *i);
1903 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1904 r = install_info_add_auto(&plus, *i);
1905 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1906 r = install_info_add_auto(&minus, *i);
1915 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1916 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1918 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1920 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1925 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1926 /* Returns number of symlinks that where supposed to be installed. */
1927 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1935 int unit_file_preset_all(
1936 UnitFileScope scope,
1938 const char *root_dir,
1939 UnitFilePresetMode mode,
1941 UnitFileChange **changes,
1942 unsigned *n_changes) {
1944 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
1945 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1946 _cleanup_free_ char *config_path = NULL;
1951 assert(scope < _UNIT_FILE_SCOPE_MAX);
1952 assert(mode < _UNIT_FILE_PRESET_MAX);
1954 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1958 r = get_config_path(scope, runtime, root_dir, &config_path);
1962 STRV_FOREACH(i, paths.unit_path) {
1963 _cleanup_closedir_ DIR *d = NULL;
1964 _cleanup_free_ char *units_dir;
1966 units_dir = path_join(root_dir, *i, NULL);
1970 d = opendir(units_dir);
1972 if (errno == ENOENT)
1983 if (!de && errno != 0)
1989 if (ignore_file(de->d_name))
1992 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1995 dirent_ensure_type(d, de);
1997 if (de->d_type != DT_REG)
2000 r = unit_file_query_preset(scope, root_dir, de->d_name);
2004 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
2005 r = install_info_add_auto(&plus, de->d_name);
2006 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
2007 r = install_info_add_auto(&minus, de->d_name);
2017 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2018 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2020 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
2022 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
2027 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2028 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2036 static void unit_file_list_free_one(UnitFileList *f) {
2044 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one);
2046 int unit_file_get_list(
2047 UnitFileScope scope,
2048 const char *root_dir,
2051 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2056 assert(scope < _UNIT_FILE_SCOPE_MAX);
2059 if (root_dir && scope != UNIT_FILE_SYSTEM)
2063 r = access(root_dir, F_OK);
2068 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2072 STRV_FOREACH(i, paths.unit_path) {
2073 _cleanup_closedir_ DIR *d = NULL;
2074 _cleanup_free_ char *units_dir;
2076 units_dir = path_join(root_dir, *i, NULL);
2080 d = opendir(units_dir);
2082 if (errno == ENOENT)
2089 _cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL;
2091 _cleanup_free_ char *path = NULL;
2095 if (!de && errno != 0)
2101 if (ignore_file(de->d_name))
2104 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2107 if (hashmap_get(h, de->d_name))
2110 dirent_ensure_type(d, de);
2112 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2115 f = new0(UnitFileList, 1);
2119 f->path = path_make_absolute(de->d_name, units_dir);
2123 r = null_or_empty_path(f->path);
2124 if (r < 0 && r != -ENOENT)
2128 path_startswith(*i, "/run") ?
2129 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2133 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2137 f->state = UNIT_FILE_ENABLED;
2141 path = path_make_absolute(de->d_name, *i);
2145 r = unit_file_can_install(&paths, root_dir, path, true);
2146 if (r == -EINVAL || /* Invalid setting? */
2147 r == -EBADMSG || /* Invalid format? */
2148 r == -ENOENT /* Included file not found? */)
2149 f->state = UNIT_FILE_INVALID;
2153 f->state = UNIT_FILE_DISABLED;
2155 f->state = UNIT_FILE_STATIC;
2158 r = hashmap_put(h, basename(f->path), f);
2161 f = NULL; /* prevent cleanup */
2168 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2169 [UNIT_FILE_ENABLED] = "enabled",
2170 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2171 [UNIT_FILE_LINKED] = "linked",
2172 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2173 [UNIT_FILE_MASKED] = "masked",
2174 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2175 [UNIT_FILE_STATIC] = "static",
2176 [UNIT_FILE_DISABLED] = "disabled",
2177 [UNIT_FILE_INVALID] = "invalid",
2180 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2182 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2183 [UNIT_FILE_SYMLINK] = "symlink",
2184 [UNIT_FILE_UNLINK] = "unlink",
2187 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2189 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = {
2190 [UNIT_FILE_PRESET_FULL] = "full",
2191 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2192 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2195 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);