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));
292 if (unlink(p) < 0 && errno != ENOENT) {
299 rmdir_parents(p, config_path);
301 path_kill_slashes(p);
303 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
305 if (!set_get(remove_symlinks_to, p)) {
307 q = mark_symlink_for_removal(&remove_symlinks_to, p);
321 static int remove_marked_symlinks(
322 Set *remove_symlinks_to,
323 const char *config_path,
324 UnitFileChange **changes,
326 char** instance_whitelist) {
328 _cleanup_close_ int fd = -1;
334 if (set_size(remove_symlinks_to) <= 0)
337 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
345 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
351 /* This takes possession of cfd and closes it */
352 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist);
360 static int find_symlinks_fd(
364 const char *config_path,
365 bool *same_name_link) {
368 _cleanup_closedir_ DIR *d = NULL;
374 assert(same_name_link);
387 if (!de && errno != 0)
393 if (ignore_file(de->d_name))
396 dirent_ensure_type(d, de);
398 if (de->d_type == DT_DIR) {
400 _cleanup_free_ char *p = NULL;
402 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
412 p = path_make_absolute(de->d_name, path);
418 /* This will close nfd, regardless whether it succeeds or not */
419 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
427 } else if (de->d_type == DT_LNK) {
428 _cleanup_free_ char *p = NULL, *dest = NULL;
429 bool found_path, found_dest, b = false;
432 /* Acquire symlink name */
433 p = path_make_absolute(de->d_name, path);
437 /* Acquire symlink destination */
438 q = readlink_and_canonicalize(p, &dest);
448 /* Check if the symlink itself matches what we
450 if (path_is_absolute(name))
451 found_path = path_equal(p, name);
453 found_path = streq(de->d_name, name);
455 /* Check if what the symlink points to
456 * matches what we are looking for */
457 if (path_is_absolute(name))
458 found_dest = path_equal(dest, name);
460 found_dest = streq(basename(dest), name);
462 if (found_path && found_dest) {
463 _cleanup_free_ char *t = NULL;
465 /* Filter out same name links in the main
467 t = path_make_absolute(name, config_path);
471 b = path_equal(t, p);
475 *same_name_link = true;
476 else if (found_path || found_dest)
482 static int find_symlinks(
484 const char *config_path,
485 bool *same_name_link) {
491 assert(same_name_link);
493 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
500 /* This takes possession of fd and closes it */
501 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
504 static int find_symlinks_in_scope(
506 const char *root_dir,
508 UnitFileState *state) {
511 _cleanup_free_ char *path2 = NULL;
512 bool same_name_link_runtime = false, same_name_link = false;
515 assert(scope < _UNIT_FILE_SCOPE_MAX);
518 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
519 _cleanup_free_ char *path = NULL;
521 /* First look in runtime config path */
522 r = get_config_path(scope, true, root_dir, &path);
526 r = find_symlinks(name, path, &same_name_link_runtime);
530 *state = UNIT_FILE_ENABLED_RUNTIME;
535 /* Then look in the normal config path */
536 r = get_config_path(scope, false, root_dir, &path2);
540 r = find_symlinks(name, path2, &same_name_link);
544 *state = UNIT_FILE_ENABLED;
548 /* Hmm, we didn't find it, but maybe we found the same name
550 if (same_name_link_runtime) {
551 *state = UNIT_FILE_LINKED_RUNTIME;
553 } else if (same_name_link) {
554 *state = UNIT_FILE_LINKED;
564 const char *root_dir,
567 UnitFileChange **changes,
568 unsigned *n_changes) {
571 _cleanup_free_ char *prefix = NULL;
575 assert(scope < _UNIT_FILE_SCOPE_MAX);
577 r = get_config_path(scope, runtime, root_dir, &prefix);
581 STRV_FOREACH(i, files) {
582 _cleanup_free_ char *path = NULL;
584 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
590 path = path_make_absolute(*i, prefix);
596 if (symlink("/dev/null", path) >= 0) {
597 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
602 if (errno == EEXIST) {
604 if (null_or_empty_path(path) > 0)
610 if (symlink("/dev/null", path) >= 0) {
612 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
613 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
630 int unit_file_unmask(
633 const char *root_dir,
635 UnitFileChange **changes,
636 unsigned *n_changes) {
638 char **i, *config_path = NULL;
640 Set *remove_symlinks_to = NULL;
643 assert(scope < _UNIT_FILE_SCOPE_MAX);
645 r = get_config_path(scope, runtime, root_dir, &config_path);
649 STRV_FOREACH(i, files) {
652 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
658 path = path_make_absolute(*i, config_path);
664 q = null_or_empty_path(path);
666 if (unlink(path) >= 0) {
667 mark_symlink_for_removal(&remove_symlinks_to, path);
668 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
677 if (q != -ENOENT && r == 0)
685 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
689 set_free_free(remove_symlinks_to);
698 const char *root_dir,
701 UnitFileChange **changes,
702 unsigned *n_changes) {
704 _cleanup_lookup_paths_free_ LookupPaths paths = {};
706 _cleanup_free_ char *config_path = NULL;
710 assert(scope < _UNIT_FILE_SCOPE_MAX);
712 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
716 r = get_config_path(scope, runtime, root_dir, &config_path);
720 STRV_FOREACH(i, files) {
721 _cleanup_free_ char *path = NULL;
727 if (!path_is_absolute(*i) ||
728 !unit_name_is_valid(fn, TEMPLATE_VALID)) {
734 if (lstat(*i, &st) < 0) {
740 if (!S_ISREG(st.st_mode)) {
745 q = in_search_path(*i, paths.unit_path);
752 path = path_make_absolute(fn, config_path);
756 if (symlink(*i, path) >= 0) {
757 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
761 if (errno == EEXIST) {
762 _cleanup_free_ char *dest = NULL;
764 q = readlink_and_make_absolute(path, &dest);
766 if (q < 0 && errno != ENOENT) {
772 if (q >= 0 && path_equal(dest, *i))
778 if (symlink(*i, path) >= 0) {
780 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
781 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
798 void unit_file_list_free(Hashmap *h) {
801 while ((i = hashmap_steal_first(h))) {
809 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
812 assert(changes || n_changes == 0);
817 for (i = 0; i < n_changes; i++) {
818 free(changes[i].path);
819 free(changes[i].source);
825 static void install_info_free(InstallInfo *i) {
830 strv_free(i->aliases);
831 strv_free(i->wanted_by);
832 strv_free(i->required_by);
836 static void install_info_hashmap_free(Hashmap *m) {
842 while ((i = hashmap_steal_first(m)))
843 install_info_free(i);
848 static void install_context_done(InstallContext *c) {
851 install_info_hashmap_free(c->will_install);
852 install_info_hashmap_free(c->have_installed);
854 c->will_install = c->have_installed = NULL;
857 static int install_info_add(
861 InstallInfo *i = NULL;
865 assert(name || path);
868 name = basename(path);
870 if (!unit_name_is_valid(name, TEMPLATE_VALID))
873 if (hashmap_get(c->have_installed, name) ||
874 hashmap_get(c->will_install, name))
877 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
881 i = new0(InstallInfo, 1);
885 i->name = strdup(name);
892 i->path = strdup(path);
899 r = hashmap_put(c->will_install, i->name, i);
907 install_info_free(i);
912 static int install_info_add_auto(
914 const char *name_or_path) {
917 assert(name_or_path);
919 if (path_is_absolute(name_or_path))
920 return install_info_add(c, NULL, name_or_path);
922 return install_info_add(c, name_or_path, NULL);
925 static int config_parse_also(const char *unit,
926 const char *filename,
929 unsigned section_line,
939 InstallContext *c = data;
945 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
946 _cleanup_free_ char *n;
953 r = install_info_add(c, n, NULL);
961 static int config_parse_user(const char *unit,
962 const char *filename,
965 unsigned section_line,
972 InstallInfo *i = data;
980 r = install_full_printf(i, rvalue, &printed);
990 static int unit_file_load(
994 bool allow_symlink) {
996 const ConfigTableItem items[] = {
997 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
998 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
999 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1000 { "Install", "Also", config_parse_also, 0, c },
1001 { "Exec", "User", config_parse_user, 0, info },
1002 { NULL, NULL, NULL, 0, NULL }
1006 _cleanup_fclose_ FILE *f = NULL;
1013 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1017 f = fdopen(fd, "re");
1023 r = config_parse(NULL, path, f, NULL,
1024 config_item_table_lookup, (void*) items, true, true, info);
1029 (int) strv_length(info->aliases) +
1030 (int) strv_length(info->wanted_by) +
1031 (int) strv_length(info->required_by);
1034 static int unit_file_search(
1038 const char *root_dir,
1039 bool allow_symlink) {
1049 char *full_path = NULL;
1051 if (!isempty(root_dir))
1052 full_path = strappenda(root_dir, info->path);
1054 return unit_file_load(c, info, full_path ?: info->path, allow_symlink);
1059 STRV_FOREACH(p, paths->unit_path) {
1060 _cleanup_free_ char *path = NULL, *full_path = NULL;
1062 path = strjoin(*p, "/", info->name, NULL);
1066 if (!isempty(root_dir)) {
1067 full_path = strappend(root_dir, path);
1072 r = unit_file_load(c, info, full_path ?: path, allow_symlink);
1076 } else if (r == -ENOENT && unit_name_is_instance(info->name)) {
1077 /* Unit file doesn't exist, however instance enablement was requested.
1078 * We will check if it is possible to load template unit file. */
1079 _cleanup_free_ char *template = NULL, *template_dir = NULL;
1081 template = unit_name_template(info->name);
1085 /* We will reuse path variable since we don't need it anymore. */
1086 template_dir = path;
1087 *(strrchr(template_dir, '/') + 1) = '\0';
1089 path = strappend(template_dir, template);
1093 if (!isempty(root_dir)) {
1095 full_path = strappend(root_dir, path);
1100 /* Let's try to load template unit. */
1101 r = unit_file_load(c, info, full_path ?: path, allow_symlink);
1108 if (r != -ENOENT && r != -ELOOP)
1115 static int unit_file_can_install(
1117 const char *root_dir,
1119 bool allow_symlink) {
1121 _cleanup_install_context_done_ InstallContext c = {};
1128 r = install_info_add_auto(&c, name);
1132 assert_se(i = hashmap_first(c.will_install));
1134 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1138 (int) strv_length(i->aliases) +
1139 (int) strv_length(i->wanted_by) +
1140 (int) strv_length(i->required_by);
1145 static int create_symlink(
1146 const char *old_path,
1147 const char *new_path,
1149 UnitFileChange **changes,
1150 unsigned *n_changes) {
1152 _cleanup_free_ char *dest = NULL;
1158 mkdir_parents_label(new_path, 0755);
1160 if (symlink(old_path, new_path) >= 0) {
1161 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1165 if (errno != EEXIST)
1168 r = readlink_and_make_absolute(new_path, &dest);
1172 if (path_equal(dest, old_path))
1178 r = unlink(new_path);
1179 if (r < 0 && errno != ENOENT)
1182 if (symlink(old_path, new_path) >= 0) {
1183 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1184 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1191 static int install_info_symlink_alias(
1193 const char *config_path,
1195 UnitFileChange **changes,
1196 unsigned *n_changes) {
1202 assert(config_path);
1204 STRV_FOREACH(s, i->aliases) {
1205 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1207 q = install_full_printf(i, *s, &dst);
1211 alias_path = path_make_absolute(dst, config_path);
1215 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1223 static int install_info_symlink_wants(
1225 const char *config_path,
1227 UnitFileChange **changes,
1228 unsigned *n_changes) {
1234 assert(config_path);
1236 STRV_FOREACH(s, i->wanted_by) {
1237 _cleanup_free_ char *path = NULL, *dst = NULL;
1239 q = install_full_printf(i, *s, &dst);
1243 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1248 if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
1251 q = create_symlink(i->path, path, force, changes, n_changes);
1260 static int install_info_symlink_requires(
1262 const char *config_path,
1264 UnitFileChange **changes,
1265 unsigned *n_changes) {
1271 assert(config_path);
1273 STRV_FOREACH(s, i->required_by) {
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 if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
1288 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) {
1306 _cleanup_free_ char *path = NULL;
1310 assert(config_path);
1313 r = in_search_path(i->path, paths->unit_path);
1317 if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1320 r = 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, force, changes, n_changes);
1344 q = install_info_symlink_requires(i, config_path, 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);