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 "install-printf.h"
43 OrderedHashmap *will_install;
44 OrderedHashmap *have_installed;
47 static int in_search_path(const char *path, char **search) {
48 _cleanup_free_ char *parent = NULL;
53 r = path_get_parent(path, &parent);
57 return strv_contains(search, parent);
60 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
65 assert(scope < _UNIT_FILE_SCOPE_MAX);
70 case UNIT_FILE_SYSTEM:
73 p = path_join(root_dir, "/run/systemd/system", NULL);
75 p = path_join(root_dir, SYSTEM_CONFIG_UNIT_PATH, NULL);
78 case UNIT_FILE_GLOBAL:
84 p = strdup("/run/systemd/user");
86 p = strdup(USER_CONFIG_UNIT_PATH);
95 r = user_runtime_dir(&p);
97 r = user_config_home(&p);
100 return r < 0 ? r : -ENOENT;
105 assert_not_reached("Bad scope");
115 static int mark_symlink_for_removal(
116 Set **remove_symlinks_to,
124 r = set_ensure_allocated(remove_symlinks_to, &string_hash_ops);
132 path_kill_slashes(n);
134 r = set_consume(*remove_symlinks_to, n);
136 return r == -EEXIST ? 0 : r;
141 static int remove_marked_symlinks_fd(
142 Set *remove_symlinks_to,
145 const char *config_path,
147 UnitFileChange **changes,
149 char** instance_whitelist) {
151 _cleanup_closedir_ DIR *d = NULL;
154 assert(remove_symlinks_to);
173 if (!de && errno != 0) {
181 if (hidden_file(de->d_name))
184 dirent_ensure_type(d, de);
186 if (de->d_type == DT_DIR) {
188 _cleanup_free_ char *p = NULL;
190 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
200 p = path_make_absolute(de->d_name, path);
206 /* This will close nfd, regardless whether it succeeds or not */
207 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, instance_whitelist);
211 } else if (de->d_type == DT_LNK) {
212 _cleanup_free_ char *p = NULL, *dest = NULL;
216 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
219 if (unit_name_is_valid(de->d_name, UNIT_NAME_INSTANCE) &&
220 instance_whitelist &&
221 !strv_contains(instance_whitelist, de->d_name)) {
223 _cleanup_free_ char *w = NULL;
225 /* OK, the file is not listed directly
226 * in the whitelist, so let's check if
227 * the template of it might be
230 r = unit_name_template(de->d_name, &w);
234 if (!strv_contains(instance_whitelist, w))
238 p = path_make_absolute(de->d_name, path);
242 q = readlink_and_canonicalize(p, &dest);
253 set_get(remove_symlinks_to, dest) ||
254 set_get(remove_symlinks_to, basename(dest));
259 if (unlink(p) < 0 && errno != ENOENT) {
265 path_kill_slashes(p);
266 rmdir_parents(p, config_path);
267 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
269 if (!set_get(remove_symlinks_to, p)) {
271 q = mark_symlink_for_removal(&remove_symlinks_to, p);
284 static int remove_marked_symlinks(
285 Set *remove_symlinks_to,
286 const char *config_path,
287 UnitFileChange **changes,
289 char** instance_whitelist) {
291 _cleanup_close_ int fd = -1;
297 if (set_size(remove_symlinks_to) <= 0)
300 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
308 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
314 /* This takes possession of cfd and closes it */
315 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist);
323 static int find_symlinks_fd(
327 const char *config_path,
328 bool *same_name_link) {
331 _cleanup_closedir_ DIR *d = NULL;
337 assert(same_name_link);
350 if (!de && errno != 0)
356 if (hidden_file(de->d_name))
359 dirent_ensure_type(d, de);
361 if (de->d_type == DT_DIR) {
363 _cleanup_free_ char *p = NULL;
365 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
375 p = path_make_absolute(de->d_name, path);
381 /* This will close nfd, regardless whether it succeeds or not */
382 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
388 } else if (de->d_type == DT_LNK) {
389 _cleanup_free_ char *p = NULL, *dest = NULL;
390 bool found_path, found_dest, b = false;
393 /* Acquire symlink name */
394 p = path_make_absolute(de->d_name, path);
398 /* Acquire symlink destination */
399 q = readlink_and_canonicalize(p, &dest);
409 /* Check if the symlink itself matches what we
411 if (path_is_absolute(name))
412 found_path = path_equal(p, name);
414 found_path = streq(de->d_name, name);
416 /* Check if what the symlink points to
417 * matches what we are looking for */
418 if (path_is_absolute(name))
419 found_dest = path_equal(dest, name);
421 found_dest = streq(basename(dest), name);
423 if (found_path && found_dest) {
424 _cleanup_free_ char *t = NULL;
426 /* Filter out same name links in the main
428 t = path_make_absolute(name, config_path);
432 b = path_equal(t, p);
436 *same_name_link = true;
437 else if (found_path || found_dest)
443 static int find_symlinks(
445 const char *config_path,
446 bool *same_name_link) {
452 assert(same_name_link);
454 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
461 /* This takes possession of fd and closes it */
462 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
465 static int find_symlinks_in_scope(
467 const char *root_dir,
469 UnitFileState *state) {
472 _cleanup_free_ char *normal_path = NULL, *runtime_path = NULL;
473 bool same_name_link_runtime = false, same_name_link = false;
476 assert(scope < _UNIT_FILE_SCOPE_MAX);
479 /* First look in runtime config path */
480 r = get_config_path(scope, true, root_dir, &normal_path);
484 r = find_symlinks(name, normal_path, &same_name_link_runtime);
488 *state = UNIT_FILE_ENABLED_RUNTIME;
492 /* Then look in the normal config path */
493 r = get_config_path(scope, false, root_dir, &runtime_path);
497 r = find_symlinks(name, runtime_path, &same_name_link);
501 *state = UNIT_FILE_ENABLED;
505 /* Hmm, we didn't find it, but maybe we found the same name
507 if (same_name_link_runtime) {
508 *state = UNIT_FILE_LINKED_RUNTIME;
510 } else if (same_name_link) {
511 *state = UNIT_FILE_LINKED;
521 const char *root_dir,
524 UnitFileChange **changes,
525 unsigned *n_changes) {
528 _cleanup_free_ char *prefix = NULL;
532 assert(scope < _UNIT_FILE_SCOPE_MAX);
534 r = get_config_path(scope, runtime, root_dir, &prefix);
538 STRV_FOREACH(i, files) {
539 _cleanup_free_ char *path = NULL;
541 if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) {
547 path = path_make_absolute(*i, prefix);
553 if (symlink("/dev/null", path) >= 0) {
554 unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
558 if (errno == EEXIST) {
560 if (null_or_empty_path(path) > 0)
564 if (symlink_atomic("/dev/null", path) >= 0) {
565 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
566 unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
582 int unit_file_unmask(
585 const char *root_dir,
587 UnitFileChange **changes,
588 unsigned *n_changes) {
590 char **i, *config_path = NULL;
592 Set *remove_symlinks_to = NULL;
595 assert(scope < _UNIT_FILE_SCOPE_MAX);
597 r = get_config_path(scope, runtime, root_dir, &config_path);
601 STRV_FOREACH(i, files) {
602 _cleanup_free_ char *path = NULL;
604 if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) {
610 path = path_make_absolute(*i, config_path);
616 q = null_or_empty_path(path);
618 if (unlink(path) < 0)
621 q = mark_symlink_for_removal(&remove_symlinks_to, path);
622 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
626 if (q != -ENOENT && r == 0)
632 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
636 set_free_free(remove_symlinks_to);
645 const char *root_dir,
648 UnitFileChange **changes,
649 unsigned *n_changes) {
651 _cleanup_lookup_paths_free_ LookupPaths paths = {};
653 _cleanup_free_ char *config_path = NULL;
657 assert(scope < _UNIT_FILE_SCOPE_MAX);
659 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
663 r = get_config_path(scope, runtime, root_dir, &config_path);
667 STRV_FOREACH(i, files) {
668 _cleanup_free_ char *path = NULL;
674 if (!path_is_absolute(*i) ||
675 !unit_name_is_valid(fn, UNIT_NAME_ANY)) {
681 if (lstat(*i, &st) < 0) {
687 if (!S_ISREG(st.st_mode)) {
692 q = in_search_path(*i, paths.unit_path);
699 path = path_make_absolute(fn, config_path);
703 if (symlink(*i, path) >= 0) {
704 unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
708 if (errno == EEXIST) {
709 _cleanup_free_ char *dest = NULL;
711 q = readlink_and_make_absolute(path, &dest);
712 if (q < 0 && errno != ENOENT) {
718 if (q >= 0 && path_equal(dest, *i))
722 if (symlink_atomic(*i, path) >= 0) {
723 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
724 unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
740 void unit_file_list_free(Hashmap *h) {
743 while ((i = hashmap_steal_first(h))) {
751 int unit_file_changes_add(
752 UnitFileChange **changes,
754 UnitFileChangeType type,
756 const char *source) {
762 assert(!changes == !n_changes);
767 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
775 c[i].path = strdup(path);
779 path_kill_slashes(c[i].path);
782 c[i].source = strdup(source);
788 path_kill_slashes(c[i].path);
796 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
799 assert(changes || n_changes == 0);
804 for (i = 0; i < n_changes; i++) {
805 free(changes[i].path);
806 free(changes[i].source);
812 static void install_info_free(UnitFileInstallInfo *i) {
817 strv_free(i->aliases);
818 strv_free(i->wanted_by);
819 strv_free(i->required_by);
821 free(i->default_instance);
825 static void install_info_hashmap_free(OrderedHashmap *m) {
826 UnitFileInstallInfo *i;
831 while ((i = ordered_hashmap_steal_first(m)))
832 install_info_free(i);
834 ordered_hashmap_free(m);
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 UnitFileInstallInfo *i = NULL;
854 assert(name || path);
857 name = basename(path);
859 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
862 if (ordered_hashmap_get(c->have_installed, name) ||
863 ordered_hashmap_get(c->will_install, name))
866 r = ordered_hashmap_ensure_allocated(&c->will_install, &string_hash_ops);
870 i = new0(UnitFileInstallInfo, 1);
874 i->name = strdup(name);
881 i->path = strdup(path);
888 r = ordered_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(
916 const char *filename,
919 unsigned section_line,
927 const char *word, *state;
928 InstallContext *c = data;
929 UnitFileInstallInfo *i = userdata;
935 FOREACH_WORD_QUOTED(word, l, rvalue, state) {
936 _cleanup_free_ char *n;
939 n = strndup(word, l);
943 r = install_info_add(c, n, NULL);
947 r = strv_extend(&i->also, n);
952 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
953 "Trailing garbage, ignoring.");
958 static int config_parse_user(
960 const char *filename,
963 unsigned section_line,
970 UnitFileInstallInfo *i = data;
978 r = install_full_printf(i, rvalue, &printed);
988 static int config_parse_default_instance(
990 const char *filename,
993 unsigned section_line,
1000 UnitFileInstallInfo *i = data;
1008 r = install_full_printf(i, rvalue, &printed);
1012 if (!unit_instance_is_valid(printed)) {
1017 free(i->default_instance);
1018 i->default_instance = printed;
1023 static int unit_file_load(
1025 UnitFileInstallInfo *info,
1027 const char *root_dir,
1032 const ConfigTableItem items[] = {
1033 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
1034 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1035 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1036 { "Install", "DefaultInstance", config_parse_default_instance, 0, info },
1037 { "Install", "Also", config_parse_also, 0, c },
1038 { "Exec", "User", config_parse_user, 0, info },
1042 _cleanup_fclose_ FILE *f = NULL;
1049 if (!isempty(root_dir))
1050 path = strjoina(root_dir, "/", path);
1053 r = access(path, F_OK) ? -errno : 0;
1057 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1061 f = fdopen(fd, "re");
1067 r = config_parse(NULL, path, f,
1069 config_item_table_lookup, items,
1070 true, true, false, info);
1075 *also = !strv_isempty(info->also);
1078 (int) strv_length(info->aliases) +
1079 (int) strv_length(info->wanted_by) +
1080 (int) strv_length(info->required_by);
1083 static int unit_file_search(
1085 UnitFileInstallInfo *info,
1086 const LookupPaths *paths,
1087 const char *root_dir,
1100 return unit_file_load(c, info, info->path, root_dir, allow_symlink, load, also);
1104 STRV_FOREACH(p, paths->unit_path) {
1105 _cleanup_free_ char *path = NULL;
1107 path = strjoin(*p, "/", info->name, NULL);
1111 r = unit_file_load(c, info, path, root_dir, allow_symlink, load, also);
1117 if (r != -ENOENT && r != -ELOOP)
1121 if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
1123 /* Unit file doesn't exist, however instance
1124 * enablement was requested. We will check if it is
1125 * possible to load template unit file. */
1127 _cleanup_free_ char *template = NULL;
1129 r = unit_name_template(info->name, &template);
1133 STRV_FOREACH(p, paths->unit_path) {
1134 _cleanup_free_ char *path = NULL;
1136 path = strjoin(*p, "/", template, NULL);
1140 r = unit_file_load(c, info, path, root_dir, allow_symlink, load, also);
1146 if (r != -ENOENT && r != -ELOOP)
1154 static int unit_file_can_install(
1155 const LookupPaths *paths,
1156 const char *root_dir,
1161 _cleanup_(install_context_done) InstallContext c = {};
1162 UnitFileInstallInfo *i;
1168 r = install_info_add_auto(&c, name);
1172 assert_se(i = ordered_hashmap_first(c.will_install));
1174 r = unit_file_search(&c, i, paths, root_dir, allow_symlink, true, also);
1178 (int) strv_length(i->aliases) +
1179 (int) strv_length(i->wanted_by) +
1180 (int) strv_length(i->required_by);
1185 static int create_symlink(
1186 const char *old_path,
1187 const char *new_path,
1189 UnitFileChange **changes,
1190 unsigned *n_changes) {
1192 _cleanup_free_ char *dest = NULL;
1198 mkdir_parents_label(new_path, 0755);
1200 if (symlink(old_path, new_path) >= 0) {
1201 unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1205 if (errno != EEXIST)
1208 r = readlink_and_make_absolute(new_path, &dest);
1212 if (path_equal(dest, old_path))
1218 r = symlink_atomic(old_path, new_path);
1222 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1223 unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1228 static int install_info_symlink_alias(
1229 UnitFileInstallInfo *i,
1230 const char *config_path,
1232 UnitFileChange **changes,
1233 unsigned *n_changes) {
1239 assert(config_path);
1241 STRV_FOREACH(s, i->aliases) {
1242 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1244 q = install_full_printf(i, *s, &dst);
1248 alias_path = path_make_absolute(dst, config_path);
1252 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1260 static int install_info_symlink_wants(
1261 UnitFileInstallInfo *i,
1262 const char *config_path,
1266 UnitFileChange **changes,
1267 unsigned *n_changes) {
1269 _cleanup_free_ char *buf = NULL;
1275 assert(config_path);
1277 if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE)) {
1279 /* Don't install any symlink if there's no default
1280 * instance configured */
1282 if (!i->default_instance)
1285 r = unit_name_replace_instance(i->name, i->default_instance, &buf);
1293 STRV_FOREACH(s, list) {
1294 _cleanup_free_ char *path = NULL, *dst = NULL;
1296 q = install_full_printf(i, *s, &dst);
1300 if (!unit_name_is_valid(dst, UNIT_NAME_ANY)) {
1305 path = strjoin(config_path, "/", dst, suffix, n, NULL);
1309 q = create_symlink(i->path, path, force, changes, n_changes);
1317 static int install_info_symlink_link(
1318 UnitFileInstallInfo *i,
1319 const LookupPaths *paths,
1320 const char *config_path,
1321 const char *root_dir,
1323 UnitFileChange **changes,
1324 unsigned *n_changes) {
1326 _cleanup_free_ char *path = NULL;
1331 assert(config_path);
1334 r = in_search_path(i->path, paths->unit_path);
1338 path = strjoin(config_path, "/", i->name, NULL);
1342 return create_symlink(i->path, path, force, changes, n_changes);
1345 static int install_info_apply(
1346 UnitFileInstallInfo *i,
1347 const LookupPaths *paths,
1348 const char *config_path,
1349 const char *root_dir,
1351 UnitFileChange **changes,
1352 unsigned *n_changes) {
1358 assert(config_path);
1360 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1362 q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes);
1366 q = install_info_symlink_wants(i, config_path, i->required_by, ".requires/", force, changes, n_changes);
1370 q = install_info_symlink_link(i, paths, config_path, root_dir, force, changes, n_changes);
1377 static int install_context_apply(
1379 const LookupPaths *paths,
1380 const char *config_path,
1381 const char *root_dir,
1383 UnitFileChange **changes,
1384 unsigned *n_changes) {
1386 UnitFileInstallInfo *i;
1391 assert(config_path);
1393 if (!ordered_hashmap_isempty(c->will_install)) {
1394 r = ordered_hashmap_ensure_allocated(&c->have_installed, &string_hash_ops);
1398 r = ordered_hashmap_reserve(c->have_installed, ordered_hashmap_size(c->will_install));
1404 while ((i = ordered_hashmap_first(c->will_install))) {
1405 assert_se(ordered_hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1407 q = unit_file_search(c, i, paths, root_dir, false, true, NULL);
1416 q = install_info_apply(i, paths, config_path, root_dir, force, changes, n_changes);
1417 if (r >= 0 && q < 0)
1424 static int install_context_mark_for_removal(
1426 const LookupPaths *paths,
1427 Set **remove_symlinks_to,
1428 const char *config_path,
1429 const char *root_dir) {
1431 UnitFileInstallInfo *i;
1436 assert(config_path);
1438 /* Marks all items for removal */
1440 if (!ordered_hashmap_isempty(c->will_install)) {
1441 r = ordered_hashmap_ensure_allocated(&c->have_installed, &string_hash_ops);
1445 r = ordered_hashmap_reserve(c->have_installed, ordered_hashmap_size(c->will_install));
1451 while ((i = ordered_hashmap_first(c->will_install))) {
1452 assert_se(ordered_hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1454 q = unit_file_search(c, i, paths, root_dir, false, true, NULL);
1465 if (unit_name_is_valid(i->name, UNIT_NAME_INSTANCE)) {
1469 unit_file = basename(i->path);
1471 if (unit_name_is_valid(unit_file, UNIT_NAME_INSTANCE))
1472 /* unit file named as instance exists, thus all symlinks
1473 * pointing to it will be removed */
1474 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1476 /* does not exist, thus we will mark for removal symlinks
1477 * to template unit file */
1478 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1480 /* If i->path is not set, it means that we didn't actually find
1481 * the unit file. But we can still remove symlinks to the
1482 * nonexistent template. */
1483 r = unit_name_template(i->name, &unit_file);
1487 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1491 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1493 if (r >= 0 && q < 0)
1500 int unit_file_add_dependency(
1501 UnitFileScope scope,
1503 const char *root_dir,
1508 UnitFileChange **changes,
1509 unsigned *n_changes) {
1511 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1512 _cleanup_(install_context_done) InstallContext c = {};
1513 _cleanup_free_ char *config_path = NULL;
1516 UnitFileInstallInfo *info;
1519 assert(scope < _UNIT_FILE_SCOPE_MAX);
1521 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1525 r = get_config_path(scope, runtime, root_dir, &config_path);
1529 STRV_FOREACH(i, files) {
1530 UnitFileState state;
1532 state = unit_file_get_state(scope, root_dir, *i);
1534 return log_error_errno(state, "Failed to get unit file state for %s: %m", *i);
1536 if (state == UNIT_FILE_MASKED || state == UNIT_FILE_MASKED_RUNTIME) {
1537 log_error("Failed to enable unit: Unit %s is masked", *i);
1541 r = install_info_add_auto(&c, *i);
1546 if (!ordered_hashmap_isempty(c.will_install)) {
1547 r = ordered_hashmap_ensure_allocated(&c.have_installed, &string_hash_ops);
1551 r = ordered_hashmap_reserve(c.have_installed, ordered_hashmap_size(c.will_install));
1556 while ((info = ordered_hashmap_first(c.will_install))) {
1557 assert_se(ordered_hashmap_move_one(c.have_installed, c.will_install, info->name) == 0);
1559 r = unit_file_search(&c, info, &paths, root_dir, false, false, NULL);
1563 if (dep == UNIT_WANTS)
1564 r = strv_extend(&info->wanted_by, target);
1565 else if (dep == UNIT_REQUIRES)
1566 r = strv_extend(&info->required_by, target);
1573 r = install_info_apply(info, &paths, config_path, root_dir, force, changes, n_changes);
1581 int unit_file_enable(
1582 UnitFileScope scope,
1584 const char *root_dir,
1587 UnitFileChange **changes,
1588 unsigned *n_changes) {
1590 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1591 _cleanup_(install_context_done) InstallContext c = {};
1593 _cleanup_free_ char *config_path = NULL;
1597 assert(scope < _UNIT_FILE_SCOPE_MAX);
1599 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1603 r = get_config_path(scope, runtime, root_dir, &config_path);
1607 STRV_FOREACH(i, files) {
1608 UnitFileState state;
1610 /* We only want to know if this unit is masked, so we ignore
1611 * errors from unit_file_get_state, deferring other checks.
1612 * This allows templated units to be enabled on the fly. */
1613 state = unit_file_get_state(scope, root_dir, *i);
1614 if (state == UNIT_FILE_MASKED || state == UNIT_FILE_MASKED_RUNTIME) {
1615 log_error("Failed to enable unit: Unit %s is masked", *i);
1619 r = install_info_add_auto(&c, *i);
1624 /* This will return the number of symlink rules that were
1625 supposed to be created, not the ones actually created. This is
1626 useful to determine whether the passed files had any
1627 installation data at all. */
1629 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1632 int unit_file_disable(
1633 UnitFileScope scope,
1635 const char *root_dir,
1637 UnitFileChange **changes,
1638 unsigned *n_changes) {
1640 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1641 _cleanup_(install_context_done) InstallContext c = {};
1643 _cleanup_free_ char *config_path = NULL;
1644 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1648 assert(scope < _UNIT_FILE_SCOPE_MAX);
1650 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1654 r = get_config_path(scope, runtime, root_dir, &config_path);
1658 STRV_FOREACH(i, files) {
1659 r = install_info_add_auto(&c, *i);
1664 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1666 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1673 int unit_file_reenable(
1674 UnitFileScope scope,
1676 const char *root_dir,
1679 UnitFileChange **changes,
1680 unsigned *n_changes) {
1683 r = unit_file_disable(scope, runtime, root_dir, files,
1684 changes, n_changes);
1688 return unit_file_enable(scope, runtime, root_dir, files, force,
1689 changes, n_changes);
1692 int unit_file_set_default(
1693 UnitFileScope scope,
1694 const char *root_dir,
1697 UnitFileChange **changes,
1698 unsigned *n_changes) {
1700 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1701 _cleanup_(install_context_done) InstallContext c = {};
1702 _cleanup_free_ char *config_path = NULL;
1705 UnitFileInstallInfo *i = NULL;
1708 assert(scope < _UNIT_FILE_SCOPE_MAX);
1711 if (unit_name_to_type(file) != UNIT_TARGET)
1714 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1718 r = get_config_path(scope, false, root_dir, &config_path);
1722 r = install_info_add_auto(&c, file);
1726 assert_se(i = ordered_hashmap_first(c.will_install));
1728 r = unit_file_search(&c, i, &paths, root_dir, false, true, NULL);
1732 path = strjoina(config_path, "/" SPECIAL_DEFAULT_TARGET);
1734 r = create_symlink(i->path, path, force, changes, n_changes);
1741 int unit_file_get_default(
1742 UnitFileScope scope,
1743 const char *root_dir,
1746 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1751 assert(scope < _UNIT_FILE_SCOPE_MAX);
1754 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1758 STRV_FOREACH(p, paths.unit_path) {
1759 _cleanup_free_ char *path = NULL, *tmp = NULL;
1762 path = path_join(root_dir, *p, SPECIAL_DEFAULT_TARGET);
1766 r = readlink_malloc(path, &tmp);
1769 else if (r == -EINVAL)
1771 n = strdup(SPECIAL_DEFAULT_TARGET);
1775 n = strdup(basename(tmp));
1787 UnitFileState unit_file_lookup_state(
1788 UnitFileScope scope,
1789 const char *root_dir,
1790 const LookupPaths *paths,
1793 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1795 _cleanup_free_ char *path = NULL;
1800 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
1803 STRV_FOREACH(i, paths->unit_path) {
1809 path = path_join(root_dir, *i, name);
1814 partial = path + strlen(root_dir);
1819 * Search for a unit file in our default paths, to
1820 * be sure, that there are no broken symlinks.
1822 if (lstat(path, &st) < 0) {
1824 if (errno != ENOENT)
1827 if (!unit_name_is_valid(name, UNIT_NAME_INSTANCE))
1830 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1833 r = null_or_empty_path(path);
1834 if (r < 0 && r != -ENOENT)
1837 state = path_startswith(*i, "/run") ? UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1842 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1848 r = unit_file_can_install(paths, root_dir, partial, true, &also);
1849 if (r < 0 && errno != ENOENT)
1852 return UNIT_FILE_DISABLED;
1855 return UNIT_FILE_INDIRECT;
1856 return UNIT_FILE_STATIC;
1860 return r < 0 ? r : state;
1863 UnitFileState unit_file_get_state(
1864 UnitFileScope scope,
1865 const char *root_dir,
1868 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1872 assert(scope < _UNIT_FILE_SCOPE_MAX);
1875 if (root_dir && scope != UNIT_FILE_SYSTEM)
1878 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1882 return unit_file_lookup_state(scope, root_dir, &paths, name);
1885 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
1886 _cleanup_strv_free_ char **files = NULL;
1891 assert(scope < _UNIT_FILE_SCOPE_MAX);
1894 if (scope == UNIT_FILE_SYSTEM)
1895 r = conf_files_list(&files, ".preset", root_dir,
1896 "/etc/systemd/system-preset",
1897 "/usr/local/lib/systemd/system-preset",
1898 "/usr/lib/systemd/system-preset",
1899 #ifdef HAVE_SPLIT_USR
1900 "/lib/systemd/system-preset",
1903 else if (scope == UNIT_FILE_GLOBAL)
1904 r = conf_files_list(&files, ".preset", root_dir,
1905 "/etc/systemd/user-preset",
1906 "/usr/local/lib/systemd/user-preset",
1907 "/usr/lib/systemd/user-preset",
1915 STRV_FOREACH(p, files) {
1916 _cleanup_fclose_ FILE *f;
1918 f = fopen(*p, "re");
1920 if (errno == ENOENT)
1927 char line[LINE_MAX], *l;
1929 if (!fgets(line, sizeof(line), f))
1936 if (strchr(COMMENTS "\n", *l))
1939 if (first_word(l, "enable")) {
1941 l += strspn(l, WHITESPACE);
1943 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1944 log_debug("Preset file says enable %s.", name);
1948 } else if (first_word(l, "disable")) {
1950 l += strspn(l, WHITESPACE);
1952 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1953 log_debug("Preset file says disable %s.", name);
1958 log_debug("Couldn't parse line '%s'", l);
1962 /* Default is "enable" */
1963 log_debug("Preset file doesn't say anything about %s, enabling.", name);
1967 int unit_file_preset(
1968 UnitFileScope scope,
1970 const char *root_dir,
1972 UnitFilePresetMode mode,
1974 UnitFileChange **changes,
1975 unsigned *n_changes) {
1977 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
1978 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1979 _cleanup_free_ char *config_path = NULL;
1984 assert(scope < _UNIT_FILE_SCOPE_MAX);
1985 assert(mode < _UNIT_FILE_PRESET_MAX);
1987 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1991 r = get_config_path(scope, runtime, root_dir, &config_path);
1995 STRV_FOREACH(i, files) {
1997 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
2000 r = unit_file_query_preset(scope, root_dir, *i);
2004 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
2005 r = install_info_add_auto(&plus, *i);
2006 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
2007 r = install_info_add_auto(&minus, *i);
2016 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2017 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2019 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
2021 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
2026 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2027 /* Returns number of symlinks that where supposed to be installed. */
2028 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2036 int unit_file_preset_all(
2037 UnitFileScope scope,
2039 const char *root_dir,
2040 UnitFilePresetMode mode,
2042 UnitFileChange **changes,
2043 unsigned *n_changes) {
2045 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
2046 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2047 _cleanup_free_ char *config_path = NULL;
2052 assert(scope < _UNIT_FILE_SCOPE_MAX);
2053 assert(mode < _UNIT_FILE_PRESET_MAX);
2055 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2059 r = get_config_path(scope, runtime, root_dir, &config_path);
2063 STRV_FOREACH(i, paths.unit_path) {
2064 _cleanup_closedir_ DIR *d = NULL;
2065 _cleanup_free_ char *units_dir;
2067 units_dir = path_join(root_dir, *i, NULL);
2071 d = opendir(units_dir);
2073 if (errno == ENOENT)
2084 if (!de && errno != 0)
2090 if (hidden_file(de->d_name))
2093 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
2096 dirent_ensure_type(d, de);
2098 if (de->d_type != DT_REG)
2101 r = unit_file_query_preset(scope, root_dir, de->d_name);
2105 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
2106 r = install_info_add_auto(&plus, de->d_name);
2107 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
2108 r = install_info_add_auto(&minus, de->d_name);
2118 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2119 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2121 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
2123 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
2128 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2129 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2137 static void unit_file_list_free_one(UnitFileList *f) {
2145 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one);
2147 int unit_file_get_list(
2148 UnitFileScope scope,
2149 const char *root_dir,
2152 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2157 assert(scope < _UNIT_FILE_SCOPE_MAX);
2160 if (root_dir && scope != UNIT_FILE_SYSTEM)
2164 r = access(root_dir, F_OK);
2169 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2173 STRV_FOREACH(i, paths.unit_path) {
2174 _cleanup_closedir_ DIR *d = NULL;
2175 _cleanup_free_ char *units_dir;
2177 units_dir = path_join(root_dir, *i, NULL);
2181 d = opendir(units_dir);
2183 if (errno == ENOENT)
2190 _cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL;
2192 _cleanup_free_ char *path = NULL;
2197 if (!de && errno != 0)
2203 if (hidden_file(de->d_name))
2206 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
2209 if (hashmap_get(h, de->d_name))
2212 dirent_ensure_type(d, de);
2214 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2217 f = new0(UnitFileList, 1);
2221 f->path = path_make_absolute(de->d_name, units_dir);
2225 r = null_or_empty_path(f->path);
2226 if (r < 0 && r != -ENOENT)
2230 path_startswith(*i, "/run") ?
2231 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2235 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2239 f->state = UNIT_FILE_ENABLED;
2243 path = path_make_absolute(de->d_name, *i);
2247 r = unit_file_can_install(&paths, root_dir, path, true, &also);
2248 if (r == -EINVAL || /* Invalid setting? */
2249 r == -EBADMSG || /* Invalid format? */
2250 r == -ENOENT /* Included file not found? */)
2251 f->state = UNIT_FILE_INVALID;
2255 f->state = UNIT_FILE_DISABLED;
2257 f->state = also ? UNIT_FILE_INDIRECT : UNIT_FILE_STATIC;
2260 r = hashmap_put(h, basename(f->path), f);
2263 f = NULL; /* prevent cleanup */
2270 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2271 [UNIT_FILE_ENABLED] = "enabled",
2272 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2273 [UNIT_FILE_LINKED] = "linked",
2274 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2275 [UNIT_FILE_MASKED] = "masked",
2276 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2277 [UNIT_FILE_STATIC] = "static",
2278 [UNIT_FILE_DISABLED] = "disabled",
2279 [UNIT_FILE_INDIRECT] = "indirect",
2280 [UNIT_FILE_INVALID] = "invalid",
2283 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2285 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2286 [UNIT_FILE_SYMLINK] = "symlink",
2287 [UNIT_FILE_UNLINK] = "unlink",
2290 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2292 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = {
2293 [UNIT_FILE_PRESET_FULL] = "full",
2294 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2295 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2298 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);