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 #define _cleanup_install_context_done_ _cleanup_(install_context_done)
50 static int lookup_paths_init_from_scope(LookupPaths *paths,
52 const char *root_dir) {
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,
66 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
71 assert(scope < _UNIT_FILE_SCOPE_MAX);
76 case UNIT_FILE_SYSTEM:
78 if (root_dir && runtime)
79 asprintf(&p, "%s/run/systemd/system", root_dir);
81 p = strdup("/run/systemd/system");
83 asprintf(&p, "%s/%s", root_dir, SYSTEM_CONFIG_UNIT_PATH);
85 p = strdup(SYSTEM_CONFIG_UNIT_PATH);
89 case UNIT_FILE_GLOBAL:
95 p = strdup("/run/systemd/user");
97 p = strdup(USER_CONFIG_UNIT_PATH);
102 if (root_dir || runtime)
105 r = user_config_home(&p);
107 return r < 0 ? r : -ENOENT;
112 assert_not_reached("Bad scope");
122 static int add_file_change(
123 UnitFileChange **changes,
125 UnitFileChangeType type,
127 const char *source) {
133 assert(!changes == !n_changes);
138 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
146 c[i].path = strdup(path);
151 c[i].source = strdup(source);
163 static int mark_symlink_for_removal(
164 Set **remove_symlinks_to,
172 r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
180 path_kill_slashes(n);
182 r = set_consume(*remove_symlinks_to, n);
184 return r == -EEXIST ? 0 : r;
189 static int remove_marked_symlinks_fd(
190 Set *remove_symlinks_to,
193 const char *config_path,
195 UnitFileChange **changes,
197 char** instance_whitelist) {
199 _cleanup_closedir_ DIR *d = NULL;
202 assert(remove_symlinks_to);
221 if (!de && errno != 0) {
229 if (ignore_file(de->d_name))
232 dirent_ensure_type(d, de);
234 if (de->d_type == DT_DIR) {
236 _cleanup_free_ char *p = NULL;
238 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
248 p = path_make_absolute(de->d_name, path);
254 /* This will close nfd, regardless whether it succeeds or not */
255 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, instance_whitelist);
259 } else if (de->d_type == DT_LNK) {
260 _cleanup_free_ char *p = NULL, *dest = NULL;
264 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
267 if (unit_name_is_instance(de->d_name) &&
268 instance_whitelist &&
269 !strv_contains(instance_whitelist, de->d_name))
272 p = path_make_absolute(de->d_name, path);
276 q = readlink_and_canonicalize(p, &dest);
287 set_get(remove_symlinks_to, dest) ||
288 set_get(remove_symlinks_to, basename(dest));
294 if (unlink(p) < 0 && errno != ENOENT) {
301 rmdir_parents(p, config_path);
303 path_kill_slashes(p);
305 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
307 if (!set_get(remove_symlinks_to, p)) {
309 q = mark_symlink_for_removal(&remove_symlinks_to, p);
322 static int remove_marked_symlinks(
323 Set *remove_symlinks_to,
324 const char *config_path,
325 UnitFileChange **changes,
327 char** instance_whitelist) {
329 _cleanup_close_ int fd = -1;
335 if (set_size(remove_symlinks_to) <= 0)
338 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
346 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
352 /* This takes possession of cfd and closes it */
353 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist);
361 static int find_symlinks_fd(
365 const char *config_path,
366 bool *same_name_link) {
369 _cleanup_closedir_ DIR *d = NULL;
375 assert(same_name_link);
388 if (!de && errno != 0)
394 if (ignore_file(de->d_name))
397 dirent_ensure_type(d, de);
399 if (de->d_type == DT_DIR) {
401 _cleanup_free_ char *p = NULL;
403 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
413 p = path_make_absolute(de->d_name, path);
419 /* This will close nfd, regardless whether it succeeds or not */
420 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
426 } else if (de->d_type == DT_LNK) {
427 _cleanup_free_ char *p = NULL, *dest = NULL;
428 bool found_path, found_dest, b = false;
431 /* Acquire symlink name */
432 p = path_make_absolute(de->d_name, path);
436 /* Acquire symlink destination */
437 q = readlink_and_canonicalize(p, &dest);
447 /* Check if the symlink itself matches what we
449 if (path_is_absolute(name))
450 found_path = path_equal(p, name);
452 found_path = streq(de->d_name, name);
454 /* Check if what the symlink points to
455 * matches what we are looking for */
456 if (path_is_absolute(name))
457 found_dest = path_equal(dest, name);
459 found_dest = streq(basename(dest), name);
461 if (found_path && found_dest) {
462 _cleanup_free_ char *t = NULL;
464 /* Filter out same name links in the main
466 t = path_make_absolute(name, config_path);
470 b = path_equal(t, p);
474 *same_name_link = true;
475 else if (found_path || found_dest)
481 static int find_symlinks(
483 const char *config_path,
484 bool *same_name_link) {
490 assert(same_name_link);
492 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
499 /* This takes possession of fd and closes it */
500 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
503 static int find_symlinks_in_scope(
505 const char *root_dir,
507 UnitFileState *state) {
510 _cleanup_free_ char *path2 = NULL;
511 bool same_name_link_runtime = false, same_name_link = false;
514 assert(scope < _UNIT_FILE_SCOPE_MAX);
517 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
518 _cleanup_free_ char *path = NULL;
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, &path2);
539 r = find_symlinks(name, path2, &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 = NULL;
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, TEMPLATE_VALID)) {
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");
600 if (errno == EEXIST) {
602 if (null_or_empty_path(path) > 0)
606 if (symlink_atomic("/dev/null", path) >= 0) {
607 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
608 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
624 int unit_file_unmask(
627 const char *root_dir,
629 UnitFileChange **changes,
630 unsigned *n_changes) {
632 char **i, *config_path = NULL;
634 Set *remove_symlinks_to = NULL;
637 assert(scope < _UNIT_FILE_SCOPE_MAX);
639 r = get_config_path(scope, runtime, root_dir, &config_path);
643 STRV_FOREACH(i, files) {
646 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
652 path = path_make_absolute(*i, config_path);
658 q = null_or_empty_path(path);
660 if (unlink(path) >= 0) {
661 mark_symlink_for_removal(&remove_symlinks_to, path);
662 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
671 if (q != -ENOENT && r == 0)
679 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
683 set_free_free(remove_symlinks_to);
692 const char *root_dir,
695 UnitFileChange **changes,
696 unsigned *n_changes) {
698 _cleanup_lookup_paths_free_ LookupPaths paths = {};
700 _cleanup_free_ char *config_path = NULL;
704 assert(scope < _UNIT_FILE_SCOPE_MAX);
706 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
710 r = get_config_path(scope, runtime, root_dir, &config_path);
714 STRV_FOREACH(i, files) {
715 _cleanup_free_ char *path = NULL;
721 if (!path_is_absolute(*i) ||
722 !unit_name_is_valid(fn, TEMPLATE_VALID)) {
728 if (lstat(*i, &st) < 0) {
734 if (!S_ISREG(st.st_mode)) {
739 q = in_search_path(*i, paths.unit_path);
746 path = path_make_absolute(fn, config_path);
750 if (symlink(*i, path) >= 0) {
751 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
755 if (errno == EEXIST) {
756 _cleanup_free_ char *dest = NULL;
758 q = readlink_and_make_absolute(path, &dest);
759 if (q < 0 && errno != ENOENT) {
765 if (q >= 0 && path_equal(dest, *i))
769 if (symlink_atomic(*i, path) >= 0) {
770 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
771 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
787 void unit_file_list_free(Hashmap *h) {
790 while ((i = hashmap_steal_first(h))) {
798 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
801 assert(changes || n_changes == 0);
806 for (i = 0; i < n_changes; i++) {
807 free(changes[i].path);
808 free(changes[i].source);
814 static void install_info_free(InstallInfo *i) {
819 strv_free(i->aliases);
820 strv_free(i->wanted_by);
821 strv_free(i->required_by);
825 static void install_info_hashmap_free(Hashmap *m) {
831 while ((i = hashmap_steal_first(m)))
832 install_info_free(i);
837 static void install_context_done(InstallContext *c) {
840 install_info_hashmap_free(c->will_install);
841 install_info_hashmap_free(c->have_installed);
843 c->will_install = c->have_installed = NULL;
846 static int install_info_add(
850 InstallInfo *i = NULL;
854 assert(name || path);
857 name = basename(path);
859 if (!unit_name_is_valid(name, TEMPLATE_VALID))
862 if (hashmap_get(c->have_installed, name) ||
863 hashmap_get(c->will_install, name))
866 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
870 i = new0(InstallInfo, 1);
874 i->name = strdup(name);
881 i->path = strdup(path);
888 r = hashmap_put(c->will_install, i->name, i);
896 install_info_free(i);
901 static int install_info_add_auto(
903 const char *name_or_path) {
906 assert(name_or_path);
908 if (path_is_absolute(name_or_path))
909 return install_info_add(c, NULL, name_or_path);
911 return install_info_add(c, name_or_path, NULL);
914 static int config_parse_also(const char *unit,
915 const char *filename,
918 unsigned section_line,
928 InstallContext *c = data;
934 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
935 _cleanup_free_ char *n;
942 r = install_info_add(c, n, NULL);
950 static int config_parse_user(const char *unit,
951 const char *filename,
954 unsigned section_line,
961 InstallInfo *i = data;
969 r = install_full_printf(i, rvalue, &printed);
979 static int unit_file_load(
983 bool allow_symlink) {
985 const ConfigTableItem items[] = {
986 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
987 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
988 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
989 { "Install", "Also", config_parse_also, 0, c },
990 { "Exec", "User", config_parse_user, 0, info },
991 { NULL, NULL, NULL, 0, NULL }
995 _cleanup_fclose_ FILE *f = NULL;
1002 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1006 f = fdopen(fd, "re");
1012 r = config_parse(NULL, path, f, NULL,
1013 config_item_table_lookup, (void*) items, true, true, info);
1018 (int) strv_length(info->aliases) +
1019 (int) strv_length(info->wanted_by) +
1020 (int) strv_length(info->required_by);
1023 static int unit_file_search(
1027 const char *root_dir,
1028 bool allow_symlink) {
1038 char *full_path = NULL;
1040 if (!isempty(root_dir))
1041 full_path = strappenda(root_dir, info->path);
1043 return unit_file_load(c, info, full_path ?: info->path, allow_symlink);
1048 STRV_FOREACH(p, paths->unit_path) {
1049 _cleanup_free_ char *path = NULL, *full_path = NULL;
1051 path = strjoin(*p, "/", info->name, NULL);
1055 if (!isempty(root_dir)) {
1056 full_path = strappend(root_dir, path);
1061 r = unit_file_load(c, info, full_path ?: path, allow_symlink);
1065 } else if (r == -ENOENT && unit_name_is_instance(info->name)) {
1066 /* Unit file doesn't exist, however instance enablement was requested.
1067 * We will check if it is possible to load template unit file. */
1068 _cleanup_free_ char *template = NULL, *template_dir = NULL;
1070 template = unit_name_template(info->name);
1074 /* We will reuse path variable since we don't need it anymore. */
1075 template_dir = path;
1076 *(strrchr(template_dir, '/') + 1) = '\0';
1078 path = strappend(template_dir, template);
1082 if (!isempty(root_dir)) {
1084 full_path = strappend(root_dir, path);
1089 /* Let's try to load template unit. */
1090 r = unit_file_load(c, info, full_path ?: path, allow_symlink);
1097 if (r != -ENOENT && r != -ELOOP)
1104 static int unit_file_can_install(
1106 const char *root_dir,
1108 bool allow_symlink) {
1110 _cleanup_install_context_done_ InstallContext c = {};
1117 r = install_info_add_auto(&c, name);
1121 assert_se(i = hashmap_first(c.will_install));
1123 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1127 (int) strv_length(i->aliases) +
1128 (int) strv_length(i->wanted_by) +
1129 (int) strv_length(i->required_by);
1134 static int create_symlink(
1135 const char *old_path,
1136 const char *new_path,
1138 UnitFileChange **changes,
1139 unsigned *n_changes) {
1141 _cleanup_free_ char *dest = NULL;
1147 mkdir_parents_label(new_path, 0755);
1149 if (symlink(old_path, new_path) >= 0) {
1150 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1154 if (errno != EEXIST)
1157 r = readlink_and_make_absolute(new_path, &dest);
1161 if (path_equal(dest, old_path))
1167 r = symlink_atomic(old_path, new_path);
1171 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1172 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1177 static int install_info_symlink_alias(
1179 const char *config_path,
1181 UnitFileChange **changes,
1182 unsigned *n_changes) {
1188 assert(config_path);
1190 STRV_FOREACH(s, i->aliases) {
1191 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1193 q = install_full_printf(i, *s, &dst);
1197 alias_path = path_make_absolute(dst, config_path);
1201 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1209 static int install_info_symlink_wants(
1211 const char *config_path,
1213 UnitFileChange **changes,
1214 unsigned *n_changes) {
1220 assert(config_path);
1222 STRV_FOREACH(s, i->wanted_by) {
1223 _cleanup_free_ char *path = NULL, *dst = NULL;
1225 q = install_full_printf(i, *s, &dst);
1229 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1234 if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
1237 q = create_symlink(i->path, path, force, changes, n_changes);
1246 static int install_info_symlink_requires(
1248 const char *config_path,
1250 UnitFileChange **changes,
1251 unsigned *n_changes) {
1257 assert(config_path);
1259 STRV_FOREACH(s, i->required_by) {
1260 _cleanup_free_ char *path = NULL, *dst = NULL;
1262 q = install_full_printf(i, *s, &dst);
1266 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1271 if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
1274 q = create_symlink(i->path, path, force, changes, n_changes);
1283 static int install_info_symlink_link(
1286 const char *config_path,
1288 UnitFileChange **changes,
1289 unsigned *n_changes) {
1291 _cleanup_free_ char *path = NULL;
1296 assert(config_path);
1299 r = in_search_path(i->path, paths->unit_path);
1303 path = strjoin(config_path, "/", i->name, NULL);
1307 return create_symlink(i->path, path, force, changes, n_changes);
1310 static int install_info_apply(
1313 const char *config_path,
1315 UnitFileChange **changes,
1316 unsigned *n_changes) {
1322 assert(config_path);
1324 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1326 q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1330 q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1334 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1341 static int install_context_apply(
1344 const char *config_path,
1345 const char *root_dir,
1347 UnitFileChange **changes,
1348 unsigned *n_changes) {
1355 assert(config_path);
1357 while ((i = hashmap_first(c->will_install))) {
1359 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1363 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1365 q = unit_file_search(c, i, paths, root_dir, false);
1374 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1375 if (r >= 0 && q < 0)
1382 static int install_context_mark_for_removal(
1385 Set **remove_symlinks_to,
1386 const char *config_path,
1387 const char *root_dir) {
1394 assert(config_path);
1396 /* Marks all items for removal */
1398 while ((i = hashmap_first(c->will_install))) {
1400 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1404 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1406 q = unit_file_search(c, i, paths, root_dir, false);
1417 if (unit_name_is_instance(i->name)) {
1421 unit_file = basename(i->path);
1423 if (unit_name_is_instance(unit_file))
1424 /* unit file named as instance exists, thus all symlinks
1425 * pointing to it will be removed */
1426 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1428 /* does not exist, thus we will mark for removal symlinks
1429 * to template unit file */
1430 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1432 /* If i->path is not set, it means that we didn't actually find
1433 * the unit file. But we can still remove symlinks to the
1434 * nonexistent template. */
1435 unit_file = unit_name_template(i->name);
1439 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1443 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1445 if (r >= 0 && q < 0)
1452 int unit_file_enable(
1453 UnitFileScope scope,
1455 const char *root_dir,
1458 UnitFileChange **changes,
1459 unsigned *n_changes) {
1461 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1462 _cleanup_install_context_done_ InstallContext c = {};
1464 _cleanup_free_ char *config_path = NULL;
1468 assert(scope < _UNIT_FILE_SCOPE_MAX);
1470 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1474 r = get_config_path(scope, runtime, root_dir, &config_path);
1478 STRV_FOREACH(i, files) {
1479 r = install_info_add_auto(&c, *i);
1484 /* This will return the number of symlink rules that were
1485 supposed to be created, not the ones actually created. This is
1486 useful to determine whether the passed files had any
1487 installation data at all. */
1489 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1492 int unit_file_disable(
1493 UnitFileScope scope,
1495 const char *root_dir,
1497 UnitFileChange **changes,
1498 unsigned *n_changes) {
1500 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1501 _cleanup_install_context_done_ InstallContext c = {};
1503 _cleanup_free_ char *config_path = NULL;
1504 _cleanup_set_free_free_ Set *remove_symlinks_to = 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 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1526 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1533 int unit_file_reenable(
1534 UnitFileScope scope,
1536 const char *root_dir,
1539 UnitFileChange **changes,
1540 unsigned *n_changes) {
1543 r = unit_file_disable(scope, runtime, root_dir, files,
1544 changes, n_changes);
1548 return unit_file_enable(scope, runtime, root_dir, files, force,
1549 changes, n_changes);
1552 int unit_file_set_default(
1553 UnitFileScope scope,
1554 const char *root_dir,
1557 UnitFileChange **changes,
1558 unsigned *n_changes) {
1560 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1561 _cleanup_install_context_done_ InstallContext c = {};
1562 _cleanup_free_ char *config_path = NULL;
1565 InstallInfo *i = NULL;
1568 assert(scope < _UNIT_FILE_SCOPE_MAX);
1571 if (unit_name_to_type(file) != UNIT_TARGET)
1574 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1578 r = get_config_path(scope, false, root_dir, &config_path);
1582 r = install_info_add_auto(&c, file);
1586 assert_se(i = hashmap_first(c.will_install));
1588 r = unit_file_search(&c, i, &paths, root_dir, false);
1592 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1594 r = create_symlink(i->path, path, force, changes, n_changes);
1601 int unit_file_get_default(
1602 UnitFileScope scope,
1603 const char *root_dir,
1606 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1611 assert(scope < _UNIT_FILE_SCOPE_MAX);
1614 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1618 STRV_FOREACH(p, paths.unit_path) {
1619 _cleanup_free_ char *path = NULL, *tmp = NULL;
1622 if (isempty(root_dir))
1623 path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
1625 path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
1630 r = readlink_malloc(path, &tmp);
1633 else if (r == -EINVAL)
1635 n = strdup(SPECIAL_DEFAULT_TARGET);
1639 n = strdup(basename(tmp));
1651 UnitFileState unit_file_get_state(
1652 UnitFileScope scope,
1653 const char *root_dir,
1656 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1657 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1659 _cleanup_free_ char *path = NULL;
1663 assert(scope < _UNIT_FILE_SCOPE_MAX);
1666 if (root_dir && scope != UNIT_FILE_SYSTEM)
1669 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1672 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1676 STRV_FOREACH(i, paths.unit_path) {
1684 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1686 asprintf(&path, "%s/%s", *i, name);
1691 partial = path + strlen(root_dir) + 1;
1696 * Search for a unit file in our default paths, to
1697 * be sure, that there are no broken symlinks.
1699 if (lstat(path, &st) < 0) {
1701 if (errno != ENOENT)
1704 if (!unit_name_is_instance(name))
1707 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1710 r = null_or_empty_path(path);
1711 if (r < 0 && r != -ENOENT)
1714 state = path_startswith(*i, "/run") ?
1715 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1720 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1726 r = unit_file_can_install(&paths, root_dir, partial, true);
1727 if (r < 0 && errno != ENOENT)
1730 return UNIT_FILE_DISABLED;
1732 return UNIT_FILE_STATIC;
1735 return r < 0 ? r : state;
1738 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
1739 _cleanup_strv_free_ char **files = NULL;
1744 assert(scope < _UNIT_FILE_SCOPE_MAX);
1747 if (scope == UNIT_FILE_SYSTEM)
1748 r = conf_files_list(&files, ".preset", root_dir,
1749 "/etc/systemd/system-preset",
1750 "/usr/local/lib/systemd/system-preset",
1751 "/usr/lib/systemd/system-preset",
1752 #ifdef HAVE_SPLIT_USR
1753 "/lib/systemd/system-preset",
1756 else if (scope == UNIT_FILE_GLOBAL)
1757 r = conf_files_list(&files, ".preset", root_dir,
1758 "/etc/systemd/user-preset",
1759 "/usr/local/lib/systemd/user-preset",
1760 "/usr/lib/systemd/user-preset",
1768 STRV_FOREACH(i, files) {
1769 _cleanup_free_ char *buf = NULL;
1770 _cleanup_fclose_ FILE *f;
1774 p = buf = strjoin(root_dir, "/", *i, NULL);
1780 if (errno == ENOENT)
1787 char line[LINE_MAX], *l;
1789 if (!fgets(line, sizeof(line), f))
1796 if (strchr(COMMENTS "\n", *l))
1799 if (first_word(l, "enable")) {
1801 l += strspn(l, WHITESPACE);
1803 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1804 log_debug("Preset file says enable %s.", name);
1808 } else if (first_word(l, "disable")) {
1810 l += strspn(l, WHITESPACE);
1812 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1813 log_debug("Preset file says disable %s.", name);
1818 log_debug("Couldn't parse line '%s'", l);
1822 /* Default is "enable" */
1823 log_debug("Preset file doesn't say anything about %s, enabling.", name);
1827 int unit_file_preset(
1828 UnitFileScope scope,
1830 const char *root_dir,
1832 UnitFilePresetMode mode,
1834 UnitFileChange **changes,
1835 unsigned *n_changes) {
1837 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1838 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1839 _cleanup_free_ char *config_path = NULL;
1844 assert(scope < _UNIT_FILE_SCOPE_MAX);
1845 assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
1847 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1851 r = get_config_path(scope, runtime, root_dir, &config_path);
1855 STRV_FOREACH(i, files) {
1857 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1860 r = unit_file_query_preset(scope, root_dir, *i);
1864 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1865 r = install_info_add_auto(&plus, *i);
1866 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1867 r = install_info_add_auto(&minus, *i);
1876 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1877 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1879 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1881 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1886 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1887 /* Returns number of symlinks that where supposed to be installed. */
1888 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1896 int unit_file_preset_all(
1897 UnitFileScope scope,
1899 const char *root_dir,
1900 UnitFilePresetMode mode,
1902 UnitFileChange **changes,
1903 unsigned *n_changes) {
1905 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1906 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1907 _cleanup_free_ char *config_path = NULL;
1912 assert(scope < _UNIT_FILE_SCOPE_MAX);
1913 assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
1915 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1919 r = get_config_path(scope, runtime, root_dir, &config_path);
1923 STRV_FOREACH(i, paths.unit_path) {
1924 _cleanup_closedir_ DIR *d = NULL;
1925 _cleanup_free_ char *buf = NULL;
1926 const char *units_dir;
1928 if (!isempty(root_dir)) {
1929 buf = strjoin(root_dir, "/", *i, NULL);
1937 d = opendir(units_dir);
1939 if (errno == ENOENT)
1950 if (!de && errno != 0)
1956 if (ignore_file(de->d_name))
1959 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1962 dirent_ensure_type(d, de);
1964 if (de->d_type != DT_REG)
1967 r = unit_file_query_preset(scope, root_dir, de->d_name);
1971 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1972 r = install_info_add_auto(&plus, de->d_name);
1973 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1974 r = install_info_add_auto(&minus, de->d_name);
1984 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1985 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1987 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1989 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
1994 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1995 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2003 static void unitfilelist_free(UnitFileList **f) {
2010 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
2012 int unit_file_get_list(
2013 UnitFileScope scope,
2014 const char *root_dir,
2017 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2022 assert(scope < _UNIT_FILE_SCOPE_MAX);
2025 if (root_dir && scope != UNIT_FILE_SYSTEM)
2028 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2032 STRV_FOREACH(i, paths.unit_path) {
2033 _cleanup_closedir_ DIR *d = NULL;
2034 _cleanup_free_ char *buf = NULL;
2035 const char *units_dir;
2037 if (!isempty(root_dir)) {
2038 buf = strjoin(root_dir, "/", *i, NULL);
2046 d = opendir(units_dir);
2048 if (errno == ENOENT)
2055 _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
2060 if (!de && errno != 0)
2066 if (ignore_file(de->d_name))
2069 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2072 if (hashmap_get(h, de->d_name))
2075 dirent_ensure_type(d, de);
2077 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2080 f = new0(UnitFileList, 1);
2084 f->path = path_make_absolute(de->d_name, units_dir);
2088 r = null_or_empty_path(f->path);
2089 if (r < 0 && r != -ENOENT)
2093 path_startswith(*i, "/run") ?
2094 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2098 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2102 f->state = UNIT_FILE_ENABLED;
2106 r = unit_file_can_install(&paths, root_dir, f->path, true);
2107 if (r == -EINVAL || /* Invalid setting? */
2108 r == -EBADMSG || /* Invalid format? */
2109 r == -ENOENT /* Included file not found? */)
2110 f->state = UNIT_FILE_INVALID;
2114 f->state = UNIT_FILE_DISABLED;
2116 f->state = UNIT_FILE_STATIC;
2119 r = hashmap_put(h, basename(f->path), f);
2122 f = NULL; /* prevent cleanup */
2129 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2130 [UNIT_FILE_ENABLED] = "enabled",
2131 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2132 [UNIT_FILE_LINKED] = "linked",
2133 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2134 [UNIT_FILE_MASKED] = "masked",
2135 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2136 [UNIT_FILE_STATIC] = "static",
2137 [UNIT_FILE_DISABLED] = "disabled",
2138 [UNIT_FILE_INVALID] = "invalid",
2141 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2143 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2144 [UNIT_FILE_SYMLINK] = "symlink",
2145 [UNIT_FILE_UNLINK] = "unlink",
2148 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2150 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MODE_MAX] = {
2151 [UNIT_FILE_PRESET_FULL] = "full",
2152 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2153 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2156 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);