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 r = install_info_add_auto(&c, *i);
1524 /* This will return the number of symlink rules that were
1525 supposed to be created, not the ones actually created. This is
1526 useful to determine whether the passed files had any
1527 installation data at all. */
1529 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1532 int unit_file_disable(
1533 UnitFileScope scope,
1535 const char *root_dir,
1537 UnitFileChange **changes,
1538 unsigned *n_changes) {
1540 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1541 _cleanup_(install_context_done) InstallContext c = {};
1543 _cleanup_free_ char *config_path = NULL;
1544 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1548 assert(scope < _UNIT_FILE_SCOPE_MAX);
1550 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
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);
1573 int unit_file_reenable(
1574 UnitFileScope scope,
1576 const char *root_dir,
1579 UnitFileChange **changes,
1580 unsigned *n_changes) {
1583 r = unit_file_disable(scope, runtime, root_dir, files,
1584 changes, n_changes);
1588 return unit_file_enable(scope, runtime, root_dir, files, force,
1589 changes, n_changes);
1592 int unit_file_set_default(
1593 UnitFileScope scope,
1594 const char *root_dir,
1597 UnitFileChange **changes,
1598 unsigned *n_changes) {
1600 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1601 _cleanup_(install_context_done) InstallContext c = {};
1602 _cleanup_free_ char *config_path = NULL;
1605 InstallInfo *i = NULL;
1608 assert(scope < _UNIT_FILE_SCOPE_MAX);
1611 if (unit_name_to_type(file) != UNIT_TARGET)
1614 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1618 r = get_config_path(scope, false, root_dir, &config_path);
1622 r = install_info_add_auto(&c, file);
1626 assert_se(i = hashmap_first(c.will_install));
1628 r = unit_file_search(&c, i, &paths, root_dir, false);
1632 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1634 r = create_symlink(i->path, path, force, changes, n_changes);
1641 int unit_file_get_default(
1642 UnitFileScope scope,
1643 const char *root_dir,
1646 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1651 assert(scope < _UNIT_FILE_SCOPE_MAX);
1654 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1658 STRV_FOREACH(p, paths.unit_path) {
1659 _cleanup_free_ char *path = NULL, *tmp = NULL;
1662 path = path_join(root_dir, *p, SPECIAL_DEFAULT_TARGET);
1666 r = readlink_malloc(path, &tmp);
1669 else if (r == -EINVAL)
1671 n = strdup(SPECIAL_DEFAULT_TARGET);
1675 n = strdup(basename(tmp));
1687 UnitFileState unit_file_get_state(
1688 UnitFileScope scope,
1689 const char *root_dir,
1692 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1693 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1695 _cleanup_free_ char *path = NULL;
1699 assert(scope < _UNIT_FILE_SCOPE_MAX);
1702 if (root_dir && scope != UNIT_FILE_SYSTEM)
1705 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1708 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1712 STRV_FOREACH(i, paths.unit_path) {
1719 path = path_join(root_dir, *i, name);
1724 partial = path + strlen(root_dir);
1729 * Search for a unit file in our default paths, to
1730 * be sure, that there are no broken symlinks.
1732 if (lstat(path, &st) < 0) {
1734 if (errno != ENOENT)
1737 if (!unit_name_is_instance(name))
1740 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1743 r = null_or_empty_path(path);
1744 if (r < 0 && r != -ENOENT)
1747 state = path_startswith(*i, "/run") ?
1748 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1753 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1759 r = unit_file_can_install(&paths, root_dir, partial, true);
1760 if (r < 0 && errno != ENOENT)
1763 return UNIT_FILE_DISABLED;
1765 return UNIT_FILE_STATIC;
1768 return r < 0 ? r : state;
1771 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
1772 _cleanup_strv_free_ char **files = NULL;
1777 assert(scope < _UNIT_FILE_SCOPE_MAX);
1780 if (scope == UNIT_FILE_SYSTEM)
1781 r = conf_files_list(&files, ".preset", root_dir,
1782 "/etc/systemd/system-preset",
1783 "/usr/local/lib/systemd/system-preset",
1784 "/usr/lib/systemd/system-preset",
1785 #ifdef HAVE_SPLIT_USR
1786 "/lib/systemd/system-preset",
1789 else if (scope == UNIT_FILE_GLOBAL)
1790 r = conf_files_list(&files, ".preset", root_dir,
1791 "/etc/systemd/user-preset",
1792 "/usr/local/lib/systemd/user-preset",
1793 "/usr/lib/systemd/user-preset",
1801 STRV_FOREACH(p, files) {
1802 _cleanup_fclose_ FILE *f;
1804 f = fopen(*p, "re");
1806 if (errno == ENOENT)
1813 char line[LINE_MAX], *l;
1815 if (!fgets(line, sizeof(line), f))
1822 if (strchr(COMMENTS "\n", *l))
1825 if (first_word(l, "enable")) {
1827 l += strspn(l, WHITESPACE);
1829 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1830 log_debug("Preset file says enable %s.", name);
1834 } else if (first_word(l, "disable")) {
1836 l += strspn(l, WHITESPACE);
1838 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1839 log_debug("Preset file says disable %s.", name);
1844 log_debug("Couldn't parse line '%s'", l);
1848 /* Default is "enable" */
1849 log_debug("Preset file doesn't say anything about %s, enabling.", name);
1853 int unit_file_preset(
1854 UnitFileScope scope,
1856 const char *root_dir,
1858 UnitFilePresetMode mode,
1860 UnitFileChange **changes,
1861 unsigned *n_changes) {
1863 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
1864 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1865 _cleanup_free_ char *config_path = NULL;
1870 assert(scope < _UNIT_FILE_SCOPE_MAX);
1871 assert(mode < _UNIT_FILE_PRESET_MAX);
1873 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1877 r = get_config_path(scope, runtime, root_dir, &config_path);
1881 STRV_FOREACH(i, files) {
1883 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1886 r = unit_file_query_preset(scope, root_dir, *i);
1890 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1891 r = install_info_add_auto(&plus, *i);
1892 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1893 r = install_info_add_auto(&minus, *i);
1902 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1903 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1905 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1907 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1912 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1913 /* Returns number of symlinks that where supposed to be installed. */
1914 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1922 int unit_file_preset_all(
1923 UnitFileScope scope,
1925 const char *root_dir,
1926 UnitFilePresetMode mode,
1928 UnitFileChange **changes,
1929 unsigned *n_changes) {
1931 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
1932 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1933 _cleanup_free_ char *config_path = NULL;
1938 assert(scope < _UNIT_FILE_SCOPE_MAX);
1939 assert(mode < _UNIT_FILE_PRESET_MAX);
1941 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1945 r = get_config_path(scope, runtime, root_dir, &config_path);
1949 STRV_FOREACH(i, paths.unit_path) {
1950 _cleanup_closedir_ DIR *d = NULL;
1951 _cleanup_free_ char *units_dir;
1953 units_dir = path_join(root_dir, *i, NULL);
1957 d = opendir(units_dir);
1959 if (errno == ENOENT)
1970 if (!de && errno != 0)
1976 if (ignore_file(de->d_name))
1979 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1982 dirent_ensure_type(d, de);
1984 if (de->d_type != DT_REG)
1987 r = unit_file_query_preset(scope, root_dir, de->d_name);
1991 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1992 r = install_info_add_auto(&plus, de->d_name);
1993 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1994 r = install_info_add_auto(&minus, de->d_name);
2004 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2005 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2007 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
2009 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
2014 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2015 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2023 static void unit_file_list_free_one(UnitFileList *f) {
2031 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one);
2033 int unit_file_get_list(
2034 UnitFileScope scope,
2035 const char *root_dir,
2038 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2043 assert(scope < _UNIT_FILE_SCOPE_MAX);
2046 if (root_dir && scope != UNIT_FILE_SYSTEM)
2050 r = access(root_dir, F_OK);
2055 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2059 STRV_FOREACH(i, paths.unit_path) {
2060 _cleanup_closedir_ DIR *d = NULL;
2061 _cleanup_free_ char *units_dir;
2063 units_dir = path_join(root_dir, *i, NULL);
2067 d = opendir(units_dir);
2069 if (errno == ENOENT)
2076 _cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL;
2078 _cleanup_free_ char *path = NULL;
2082 if (!de && errno != 0)
2088 if (ignore_file(de->d_name))
2091 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2094 if (hashmap_get(h, de->d_name))
2097 dirent_ensure_type(d, de);
2099 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2102 f = new0(UnitFileList, 1);
2106 f->path = path_make_absolute(de->d_name, units_dir);
2110 r = null_or_empty_path(f->path);
2111 if (r < 0 && r != -ENOENT)
2115 path_startswith(*i, "/run") ?
2116 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2120 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2124 f->state = UNIT_FILE_ENABLED;
2128 path = path_make_absolute(de->d_name, *i);
2132 r = unit_file_can_install(&paths, root_dir, path, true);
2133 if (r == -EINVAL || /* Invalid setting? */
2134 r == -EBADMSG || /* Invalid format? */
2135 r == -ENOENT /* Included file not found? */)
2136 f->state = UNIT_FILE_INVALID;
2140 f->state = UNIT_FILE_DISABLED;
2142 f->state = UNIT_FILE_STATIC;
2145 r = hashmap_put(h, basename(f->path), f);
2148 f = NULL; /* prevent cleanup */
2155 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2156 [UNIT_FILE_ENABLED] = "enabled",
2157 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2158 [UNIT_FILE_LINKED] = "linked",
2159 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2160 [UNIT_FILE_MASKED] = "masked",
2161 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2162 [UNIT_FILE_STATIC] = "static",
2163 [UNIT_FILE_DISABLED] = "disabled",
2164 [UNIT_FILE_INVALID] = "invalid",
2167 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2169 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2170 [UNIT_FILE_SYMLINK] = "symlink",
2171 [UNIT_FILE_UNLINK] = "unlink",
2174 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2176 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = {
2177 [UNIT_FILE_PRESET_FULL] = "full",
2178 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2179 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2182 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);