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);
822 free(i->default_instance);
826 static void install_info_hashmap_free(Hashmap *m) {
832 while ((i = hashmap_steal_first(m)))
833 install_info_free(i);
838 static void install_context_done(InstallContext *c) {
841 install_info_hashmap_free(c->will_install);
842 install_info_hashmap_free(c->have_installed);
844 c->will_install = c->have_installed = NULL;
847 static int install_info_add(
851 InstallInfo *i = NULL;
855 assert(name || path);
858 name = basename(path);
860 if (!unit_name_is_valid(name, TEMPLATE_VALID))
863 if (hashmap_get(c->have_installed, name) ||
864 hashmap_get(c->will_install, name))
867 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
871 i = new0(InstallInfo, 1);
875 i->name = strdup(name);
882 i->path = strdup(path);
889 r = hashmap_put(c->will_install, i->name, i);
897 install_info_free(i);
902 static int install_info_add_auto(
904 const char *name_or_path) {
907 assert(name_or_path);
909 if (path_is_absolute(name_or_path))
910 return install_info_add(c, NULL, name_or_path);
912 return install_info_add(c, name_or_path, NULL);
915 static int config_parse_also(
917 const char *filename,
920 unsigned section_line,
930 InstallContext *c = data;
936 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
937 _cleanup_free_ char *n;
944 r = install_info_add(c, n, NULL);
952 static int config_parse_user(
954 const char *filename,
957 unsigned section_line,
964 InstallInfo *i = data;
972 r = install_full_printf(i, rvalue, &printed);
982 static int config_parse_default_instance(
984 const char *filename,
987 unsigned section_line,
994 InstallInfo *i = data;
1002 r = install_full_printf(i, rvalue, &printed);
1006 if (!unit_instance_is_valid(printed))
1009 free(i->default_instance);
1010 i->default_instance = printed;
1015 static int unit_file_load(
1019 bool allow_symlink) {
1021 const ConfigTableItem items[] = {
1022 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
1023 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1024 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1025 { "Install", "DefaultInstance", config_parse_default_instance, 0, info },
1026 { "Install", "Also", config_parse_also, 0, c },
1027 { "Exec", "User", config_parse_user, 0, info },
1032 _cleanup_fclose_ FILE *f = NULL;
1039 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1043 f = fdopen(fd, "re");
1049 r = config_parse(NULL, path, f, NULL, config_item_table_lookup, (void*) items, true, true, info);
1054 (int) strv_length(info->aliases) +
1055 (int) strv_length(info->wanted_by) +
1056 (int) strv_length(info->required_by);
1059 static int unit_file_search(
1063 const char *root_dir,
1064 bool allow_symlink) {
1076 if (isempty(root_dir))
1079 path = strappenda(root_dir, info->path);
1081 return unit_file_load(c, info, path, allow_symlink);
1086 STRV_FOREACH(p, paths->unit_path) {
1087 _cleanup_free_ char *path = NULL;
1089 if (isempty(root_dir))
1090 path = strjoin(*p, "/", info->name, NULL);
1092 path = strjoin(root_dir, "/", *p, "/", info->name, NULL);
1096 r = unit_file_load(c, info, path, allow_symlink);
1102 if (r != -ENOENT && r != -ELOOP)
1106 if (unit_name_is_instance(info->name)) {
1108 /* Unit file doesn't exist, however instance
1109 * enablement was requested. We will check if it is
1110 * possible to load template unit file. */
1112 _cleanup_free_ char *template = NULL, *template_dir = NULL;
1114 template = unit_name_template(info->name);
1118 STRV_FOREACH(p, paths->unit_path) {
1119 _cleanup_free_ char *path = NULL;
1121 if (isempty(root_dir))
1122 path = strjoin(*p, "/", template, NULL);
1124 path = strjoin(root_dir, "/", *p, "/", template, NULL);
1128 r = unit_file_load(c, info, path, allow_symlink);
1134 if (r != -ENOENT && r != -ELOOP)
1142 static int unit_file_can_install(
1144 const char *root_dir,
1146 bool allow_symlink) {
1148 _cleanup_install_context_done_ InstallContext c = {};
1155 r = install_info_add_auto(&c, name);
1159 assert_se(i = hashmap_first(c.will_install));
1161 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1165 (int) strv_length(i->aliases) +
1166 (int) strv_length(i->wanted_by) +
1167 (int) strv_length(i->required_by);
1172 static int create_symlink(
1173 const char *old_path,
1174 const char *new_path,
1176 UnitFileChange **changes,
1177 unsigned *n_changes) {
1179 _cleanup_free_ char *dest = NULL;
1185 mkdir_parents_label(new_path, 0755);
1187 if (symlink(old_path, new_path) >= 0) {
1188 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1192 if (errno != EEXIST)
1195 r = readlink_and_make_absolute(new_path, &dest);
1199 if (path_equal(dest, old_path))
1205 r = symlink_atomic(old_path, new_path);
1209 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1210 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1215 static int install_info_symlink_alias(
1217 const char *config_path,
1219 UnitFileChange **changes,
1220 unsigned *n_changes) {
1226 assert(config_path);
1228 STRV_FOREACH(s, i->aliases) {
1229 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1231 q = install_full_printf(i, *s, &dst);
1235 alias_path = path_make_absolute(dst, config_path);
1239 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1247 static int install_info_symlink_wants(
1249 const char *config_path,
1253 UnitFileChange **changes,
1254 unsigned *n_changes) {
1256 _cleanup_free_ char *buf = NULL;
1262 assert(config_path);
1264 if (unit_name_is_template(i->name) && i->default_instance) {
1265 buf = unit_name_replace_instance(i->name, i->default_instance);
1273 STRV_FOREACH(s, list) {
1274 _cleanup_free_ char *path = NULL, *dst = NULL;
1276 q = install_full_printf(i, *s, &dst);
1280 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1285 path = strjoin(config_path, "/", dst, suffix, n, NULL);
1289 q = create_symlink(i->path, path, force, changes, n_changes);
1297 static int install_info_symlink_link(
1300 const char *config_path,
1302 UnitFileChange **changes,
1303 unsigned *n_changes) {
1305 _cleanup_free_ char *path = NULL;
1310 assert(config_path);
1313 r = in_search_path(i->path, paths->unit_path);
1317 path = strjoin(config_path, "/", i->name, NULL);
1321 return create_symlink(i->path, path, force, changes, n_changes);
1324 static int install_info_apply(
1327 const char *config_path,
1329 UnitFileChange **changes,
1330 unsigned *n_changes) {
1336 assert(config_path);
1338 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1340 q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes);
1344 q = install_info_symlink_wants(i, config_path, i->required_by, ".requires/", force, changes, n_changes);
1348 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1355 static int install_context_apply(
1358 const char *config_path,
1359 const char *root_dir,
1361 UnitFileChange **changes,
1362 unsigned *n_changes) {
1369 assert(config_path);
1371 while ((i = hashmap_first(c->will_install))) {
1373 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1377 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1379 q = unit_file_search(c, i, paths, root_dir, false);
1388 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1389 if (r >= 0 && q < 0)
1396 static int install_context_mark_for_removal(
1399 Set **remove_symlinks_to,
1400 const char *config_path,
1401 const char *root_dir) {
1408 assert(config_path);
1410 /* Marks all items for removal */
1412 while ((i = hashmap_first(c->will_install))) {
1414 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1418 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1420 q = unit_file_search(c, i, paths, root_dir, false);
1431 if (unit_name_is_instance(i->name)) {
1435 unit_file = basename(i->path);
1437 if (unit_name_is_instance(unit_file))
1438 /* unit file named as instance exists, thus all symlinks
1439 * pointing to it will be removed */
1440 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1442 /* does not exist, thus we will mark for removal symlinks
1443 * to template unit file */
1444 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1446 /* If i->path is not set, it means that we didn't actually find
1447 * the unit file. But we can still remove symlinks to the
1448 * nonexistent template. */
1449 unit_file = unit_name_template(i->name);
1453 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1457 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1459 if (r >= 0 && q < 0)
1466 int unit_file_enable(
1467 UnitFileScope scope,
1469 const char *root_dir,
1472 UnitFileChange **changes,
1473 unsigned *n_changes) {
1475 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1476 _cleanup_install_context_done_ InstallContext c = {};
1478 _cleanup_free_ char *config_path = NULL;
1482 assert(scope < _UNIT_FILE_SCOPE_MAX);
1484 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1488 r = get_config_path(scope, runtime, root_dir, &config_path);
1492 STRV_FOREACH(i, files) {
1493 r = install_info_add_auto(&c, *i);
1498 /* This will return the number of symlink rules that were
1499 supposed to be created, not the ones actually created. This is
1500 useful to determine whether the passed files had any
1501 installation data at all. */
1503 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1506 int unit_file_disable(
1507 UnitFileScope scope,
1509 const char *root_dir,
1511 UnitFileChange **changes,
1512 unsigned *n_changes) {
1514 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1515 _cleanup_install_context_done_ InstallContext c = {};
1517 _cleanup_free_ char *config_path = NULL;
1518 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1522 assert(scope < _UNIT_FILE_SCOPE_MAX);
1524 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1528 r = get_config_path(scope, runtime, root_dir, &config_path);
1532 STRV_FOREACH(i, files) {
1533 r = install_info_add_auto(&c, *i);
1538 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1540 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1547 int unit_file_reenable(
1548 UnitFileScope scope,
1550 const char *root_dir,
1553 UnitFileChange **changes,
1554 unsigned *n_changes) {
1557 r = unit_file_disable(scope, runtime, root_dir, files,
1558 changes, n_changes);
1562 return unit_file_enable(scope, runtime, root_dir, files, force,
1563 changes, n_changes);
1566 int unit_file_set_default(
1567 UnitFileScope scope,
1568 const char *root_dir,
1571 UnitFileChange **changes,
1572 unsigned *n_changes) {
1574 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1575 _cleanup_install_context_done_ InstallContext c = {};
1576 _cleanup_free_ char *config_path = NULL;
1579 InstallInfo *i = NULL;
1582 assert(scope < _UNIT_FILE_SCOPE_MAX);
1585 if (unit_name_to_type(file) != UNIT_TARGET)
1588 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1592 r = get_config_path(scope, false, root_dir, &config_path);
1596 r = install_info_add_auto(&c, file);
1600 assert_se(i = hashmap_first(c.will_install));
1602 r = unit_file_search(&c, i, &paths, root_dir, false);
1606 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1608 r = create_symlink(i->path, path, force, changes, n_changes);
1615 int unit_file_get_default(
1616 UnitFileScope scope,
1617 const char *root_dir,
1620 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1625 assert(scope < _UNIT_FILE_SCOPE_MAX);
1628 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1632 STRV_FOREACH(p, paths.unit_path) {
1633 _cleanup_free_ char *path = NULL, *tmp = NULL;
1636 if (isempty(root_dir))
1637 path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
1639 path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
1644 r = readlink_malloc(path, &tmp);
1647 else if (r == -EINVAL)
1649 n = strdup(SPECIAL_DEFAULT_TARGET);
1653 n = strdup(basename(tmp));
1665 UnitFileState unit_file_get_state(
1666 UnitFileScope scope,
1667 const char *root_dir,
1670 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1671 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1673 _cleanup_free_ char *path = NULL;
1677 assert(scope < _UNIT_FILE_SCOPE_MAX);
1680 if (root_dir && scope != UNIT_FILE_SYSTEM)
1683 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1686 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1690 STRV_FOREACH(i, paths.unit_path) {
1698 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1700 asprintf(&path, "%s/%s", *i, name);
1705 partial = path + strlen(root_dir) + 1;
1710 * Search for a unit file in our default paths, to
1711 * be sure, that there are no broken symlinks.
1713 if (lstat(path, &st) < 0) {
1715 if (errno != ENOENT)
1718 if (!unit_name_is_instance(name))
1721 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1724 r = null_or_empty_path(path);
1725 if (r < 0 && r != -ENOENT)
1728 state = path_startswith(*i, "/run") ?
1729 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1734 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1740 r = unit_file_can_install(&paths, root_dir, partial, true);
1741 if (r < 0 && errno != ENOENT)
1744 return UNIT_FILE_DISABLED;
1746 return UNIT_FILE_STATIC;
1749 return r < 0 ? r : state;
1752 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
1753 _cleanup_strv_free_ char **files = NULL;
1758 assert(scope < _UNIT_FILE_SCOPE_MAX);
1761 if (scope == UNIT_FILE_SYSTEM)
1762 r = conf_files_list(&files, ".preset", root_dir,
1763 "/etc/systemd/system-preset",
1764 "/usr/local/lib/systemd/system-preset",
1765 "/usr/lib/systemd/system-preset",
1766 #ifdef HAVE_SPLIT_USR
1767 "/lib/systemd/system-preset",
1770 else if (scope == UNIT_FILE_GLOBAL)
1771 r = conf_files_list(&files, ".preset", root_dir,
1772 "/etc/systemd/user-preset",
1773 "/usr/local/lib/systemd/user-preset",
1774 "/usr/lib/systemd/user-preset",
1782 STRV_FOREACH(i, files) {
1783 _cleanup_free_ char *buf = NULL;
1784 _cleanup_fclose_ FILE *f;
1788 p = buf = strjoin(root_dir, "/", *i, NULL);
1794 if (errno == ENOENT)
1801 char line[LINE_MAX], *l;
1803 if (!fgets(line, sizeof(line), f))
1810 if (strchr(COMMENTS "\n", *l))
1813 if (first_word(l, "enable")) {
1815 l += strspn(l, WHITESPACE);
1817 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1818 log_debug("Preset file says enable %s.", name);
1822 } else if (first_word(l, "disable")) {
1824 l += strspn(l, WHITESPACE);
1826 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1827 log_debug("Preset file says disable %s.", name);
1832 log_debug("Couldn't parse line '%s'", l);
1836 /* Default is "enable" */
1837 log_debug("Preset file doesn't say anything about %s, enabling.", name);
1841 int unit_file_preset(
1842 UnitFileScope scope,
1844 const char *root_dir,
1846 UnitFilePresetMode mode,
1848 UnitFileChange **changes,
1849 unsigned *n_changes) {
1851 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1852 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1853 _cleanup_free_ char *config_path = NULL;
1858 assert(scope < _UNIT_FILE_SCOPE_MAX);
1859 assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
1861 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1865 r = get_config_path(scope, runtime, root_dir, &config_path);
1869 STRV_FOREACH(i, files) {
1871 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1874 r = unit_file_query_preset(scope, root_dir, *i);
1878 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1879 r = install_info_add_auto(&plus, *i);
1880 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1881 r = install_info_add_auto(&minus, *i);
1890 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1891 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1893 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1895 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1900 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1901 /* Returns number of symlinks that where supposed to be installed. */
1902 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1910 int unit_file_preset_all(
1911 UnitFileScope scope,
1913 const char *root_dir,
1914 UnitFilePresetMode mode,
1916 UnitFileChange **changes,
1917 unsigned *n_changes) {
1919 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1920 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1921 _cleanup_free_ char *config_path = NULL;
1926 assert(scope < _UNIT_FILE_SCOPE_MAX);
1927 assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
1929 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1933 r = get_config_path(scope, runtime, root_dir, &config_path);
1937 STRV_FOREACH(i, paths.unit_path) {
1938 _cleanup_closedir_ DIR *d = NULL;
1939 _cleanup_free_ char *buf = NULL;
1940 const char *units_dir;
1942 if (!isempty(root_dir)) {
1943 buf = strjoin(root_dir, "/", *i, NULL);
1951 d = opendir(units_dir);
1953 if (errno == ENOENT)
1964 if (!de && errno != 0)
1970 if (ignore_file(de->d_name))
1973 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1976 dirent_ensure_type(d, de);
1978 if (de->d_type != DT_REG)
1981 r = unit_file_query_preset(scope, root_dir, de->d_name);
1985 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1986 r = install_info_add_auto(&plus, de->d_name);
1987 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1988 r = install_info_add_auto(&minus, de->d_name);
1998 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1999 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2001 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
2003 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
2008 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2009 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2017 static void unitfilelist_free(UnitFileList **f) {
2024 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
2026 int unit_file_get_list(
2027 UnitFileScope scope,
2028 const char *root_dir,
2031 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2036 assert(scope < _UNIT_FILE_SCOPE_MAX);
2039 if (root_dir && scope != UNIT_FILE_SYSTEM)
2042 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2046 STRV_FOREACH(i, paths.unit_path) {
2047 _cleanup_closedir_ DIR *d = NULL;
2048 _cleanup_free_ char *buf = NULL;
2049 const char *units_dir;
2051 if (!isempty(root_dir)) {
2052 buf = strjoin(root_dir, "/", *i, NULL);
2060 d = opendir(units_dir);
2062 if (errno == ENOENT)
2069 _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
2074 if (!de && errno != 0)
2080 if (ignore_file(de->d_name))
2083 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2086 if (hashmap_get(h, de->d_name))
2089 dirent_ensure_type(d, de);
2091 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2094 f = new0(UnitFileList, 1);
2098 f->path = path_make_absolute(de->d_name, units_dir);
2102 r = null_or_empty_path(f->path);
2103 if (r < 0 && r != -ENOENT)
2107 path_startswith(*i, "/run") ?
2108 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2112 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2116 f->state = UNIT_FILE_ENABLED;
2120 r = unit_file_can_install(&paths, root_dir, f->path, true);
2121 if (r == -EINVAL || /* Invalid setting? */
2122 r == -EBADMSG || /* Invalid format? */
2123 r == -ENOENT /* Included file not found? */)
2124 f->state = UNIT_FILE_INVALID;
2128 f->state = UNIT_FILE_DISABLED;
2130 f->state = UNIT_FILE_STATIC;
2133 r = hashmap_put(h, basename(f->path), f);
2136 f = NULL; /* prevent cleanup */
2143 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2144 [UNIT_FILE_ENABLED] = "enabled",
2145 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2146 [UNIT_FILE_LINKED] = "linked",
2147 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2148 [UNIT_FILE_MASKED] = "masked",
2149 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2150 [UNIT_FILE_STATIC] = "static",
2151 [UNIT_FILE_DISABLED] = "disabled",
2152 [UNIT_FILE_INVALID] = "invalid",
2155 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2157 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2158 [UNIT_FILE_SYMLINK] = "symlink",
2159 [UNIT_FILE_UNLINK] = "unlink",
2162 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2164 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MODE_MAX] = {
2165 [UNIT_FILE_PRESET_FULL] = "full",
2166 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2167 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2170 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);