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"
43 Hashmap *will_install;
44 Hashmap *have_installed;
47 #define _cleanup_lookup_paths_free_ \
48 __attribute__((cleanup(lookup_paths_free)))
49 #define _cleanup_install_context_done_ \
50 __attribute__((cleanup(install_context_done)))
52 static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope) {
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,
65 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
70 assert(scope < _UNIT_FILE_SCOPE_MAX);
75 case UNIT_FILE_SYSTEM:
77 if (root_dir && runtime)
78 asprintf(&p, "%s/run/systemd/system", root_dir);
80 p = strdup("/run/systemd/system");
82 asprintf(&p, "%s/%s", root_dir, SYSTEM_CONFIG_UNIT_PATH);
84 p = strdup(SYSTEM_CONFIG_UNIT_PATH);
88 case UNIT_FILE_GLOBAL:
94 p = strdup("/run/systemd/user");
96 p = strdup(USER_CONFIG_UNIT_PATH);
101 if (root_dir || runtime)
104 r = user_config_home(&p);
106 return r < 0 ? r : -ENOENT;
111 assert_not_reached("Bad scope");
121 static int add_file_change(
122 UnitFileChange **changes,
124 UnitFileChangeType type,
126 const char *source) {
132 assert(!changes == !n_changes);
137 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
145 c[i].path = strdup(path);
150 c[i].source = strdup(source);
162 static int mark_symlink_for_removal(
163 Set **remove_symlinks_to,
171 r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
179 path_kill_slashes(n);
181 r = set_consume(*remove_symlinks_to, n);
183 return r == -EEXIST ? 0 : r;
188 static int remove_marked_symlinks_fd(
189 Set *remove_symlinks_to,
192 const char *config_path,
194 UnitFileChange **changes,
199 _cleanup_closedir_ DIR *d = NULL;
201 assert(remove_symlinks_to);
209 close_nointr_nofail(fd);
217 union dirent_storage buf;
220 k = readdir_r(d, &buf.de, &de);
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);
250 close_nointr_nofail(nfd);
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, files);
260 } else if (de->d_type == DT_LNK) {
261 _cleanup_free_ char *p = NULL, *dest = NULL;
265 p = path_make_absolute(de->d_name, path);
269 q = readlink_and_canonicalize(p, &dest);
280 set_get(remove_symlinks_to, dest) ||
281 set_get(remove_symlinks_to, path_get_file_name(dest));
283 if (unit_name_is_instance(p))
284 found = found && strv_contains(files, path_get_file_name(p));
288 if (unlink(p) < 0 && errno != ENOENT) {
293 rmdir_parents(p, config_path);
294 path_kill_slashes(p);
296 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
298 if (!set_get(remove_symlinks_to, p)) {
300 q = mark_symlink_for_removal(&remove_symlinks_to, p);
315 static int remove_marked_symlinks(
316 Set *remove_symlinks_to,
317 const char *config_path,
318 UnitFileChange **changes,
327 if (set_size(remove_symlinks_to) <= 0)
330 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
344 /* This takes possession of cfd and closes it */
345 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, files);
350 close_nointr_nofail(fd);
355 static int find_symlinks_fd(
359 const char *config_path,
360 bool *same_name_link) {
363 _cleanup_closedir_ DIR *d = NULL;
369 assert(same_name_link);
373 close_nointr_nofail(fd);
380 union dirent_storage buf;
382 k = readdir_r(d, &buf.de, &de);
389 if (ignore_file(de->d_name))
392 dirent_ensure_type(d, de);
394 if (de->d_type == DT_DIR) {
396 _cleanup_free_ char *p = NULL;
398 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
408 p = path_make_absolute(de->d_name, path);
410 close_nointr_nofail(nfd);
414 /* This will close nfd, regardless whether it succeeds or not */
415 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
423 } else if (de->d_type == DT_LNK) {
424 _cleanup_free_ char *p = NULL, *dest = NULL;
425 bool found_path, found_dest, b = false;
428 /* Acquire symlink name */
429 p = path_make_absolute(de->d_name, path);
433 /* Acquire symlink destination */
434 q = readlink_and_canonicalize(p, &dest);
444 /* Check if the symlink itself matches what we
446 if (path_is_absolute(name))
447 found_path = path_equal(p, name);
449 found_path = streq(de->d_name, name);
451 /* Check if what the symlink points to
452 * matches what we are looking for */
453 if (path_is_absolute(name))
454 found_dest = path_equal(dest, name);
456 found_dest = streq(path_get_file_name(dest), name);
458 if (found_path && found_dest) {
459 _cleanup_free_ char *t = NULL;
461 /* Filter out same name links in the main
463 t = path_make_absolute(name, config_path);
467 b = path_equal(t, p);
471 *same_name_link = true;
472 else if (found_path || found_dest)
480 static int find_symlinks(
482 const char *config_path,
483 bool *same_name_link) {
489 assert(same_name_link);
491 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
498 /* This takes possession of fd and closes it */
499 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
502 static int find_symlinks_in_scope(
504 const char *root_dir,
506 UnitFileState *state) {
509 _cleanup_free_ char *path2 = NULL;
510 bool same_name_link_runtime = false, same_name_link = false;
513 assert(scope < _UNIT_FILE_SCOPE_MAX);
516 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
517 _cleanup_free_ char *path = NULL;
519 /* First look in runtime config path */
520 r = get_config_path(scope, true, root_dir, &path);
524 r = find_symlinks(name, path, &same_name_link_runtime);
528 *state = UNIT_FILE_ENABLED_RUNTIME;
533 /* Then look in the normal config path */
534 r = get_config_path(scope, false, root_dir, &path2);
538 r = find_symlinks(name, path2, &same_name_link);
542 *state = UNIT_FILE_ENABLED;
546 /* Hmm, we didn't find it, but maybe we found the same name
548 if (same_name_link_runtime) {
549 *state = UNIT_FILE_LINKED_RUNTIME;
551 } else if (same_name_link) {
552 *state = UNIT_FILE_LINKED;
562 const char *root_dir,
565 UnitFileChange **changes,
566 unsigned *n_changes) {
569 _cleanup_free_ char *prefix;
573 assert(scope < _UNIT_FILE_SCOPE_MAX);
575 r = get_config_path(scope, runtime, root_dir, &prefix);
579 STRV_FOREACH(i, files) {
580 _cleanup_free_ char *path = NULL;
582 if (!unit_name_is_valid(*i, true)) {
588 path = path_make_absolute(*i, prefix);
594 if (symlink("/dev/null", path) >= 0) {
595 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
600 if (errno == EEXIST) {
602 if (null_or_empty_path(path) > 0)
608 if (symlink("/dev/null", path) >= 0) {
610 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
611 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
628 int unit_file_unmask(
631 const char *root_dir,
633 UnitFileChange **changes,
634 unsigned *n_changes) {
636 char **i, *config_path = NULL;
638 Set *remove_symlinks_to = NULL;
641 assert(scope < _UNIT_FILE_SCOPE_MAX);
643 r = get_config_path(scope, runtime, root_dir, &config_path);
647 STRV_FOREACH(i, files) {
650 if (!unit_name_is_valid(*i, true)) {
656 path = path_make_absolute(*i, config_path);
662 q = null_or_empty_path(path);
664 if (unlink(path) >= 0) {
665 mark_symlink_for_removal(&remove_symlinks_to, path);
666 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
675 if (q != -ENOENT && r == 0)
683 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
687 set_free_free(remove_symlinks_to);
696 const char *root_dir,
699 UnitFileChange **changes,
700 unsigned *n_changes) {
702 _cleanup_lookup_paths_free_ LookupPaths paths = {};
704 _cleanup_free_ char *config_path = NULL;
708 assert(scope < _UNIT_FILE_SCOPE_MAX);
710 r = lookup_paths_init_from_scope(&paths, scope);
714 r = get_config_path(scope, runtime, root_dir, &config_path);
718 STRV_FOREACH(i, files) {
719 _cleanup_free_ char *path = NULL;
723 fn = path_get_file_name(*i);
725 if (!path_is_absolute(*i) ||
726 !unit_name_is_valid(fn, true)) {
732 if (lstat(*i, &st) < 0) {
738 if (!S_ISREG(st.st_mode)) {
743 q = in_search_path(*i, paths.unit_path);
750 path = path_make_absolute(fn, config_path);
754 if (symlink(*i, path) >= 0) {
755 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
759 if (errno == EEXIST) {
760 _cleanup_free_ char *dest = NULL;
762 q = readlink_and_make_absolute(path, &dest);
764 if (q < 0 && errno != ENOENT) {
770 if (q >= 0 && path_equal(dest, *i))
776 if (symlink(*i, path) >= 0) {
778 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
779 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
796 void unit_file_list_free(Hashmap *h) {
799 while ((i = hashmap_steal_first(h))) {
807 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
810 assert(changes || n_changes == 0);
815 for (i = 0; i < n_changes; i++) {
816 free(changes[i].path);
817 free(changes[i].source);
823 static void install_info_free(InstallInfo *i) {
828 strv_free(i->aliases);
829 strv_free(i->wanted_by);
830 strv_free(i->required_by);
834 static void install_info_hashmap_free(Hashmap *m) {
840 while ((i = hashmap_steal_first(m)))
841 install_info_free(i);
846 static void install_context_done(InstallContext *c) {
849 install_info_hashmap_free(c->will_install);
850 install_info_hashmap_free(c->have_installed);
852 c->will_install = c->have_installed = NULL;
855 static int install_info_add(
859 InstallInfo *i = NULL;
863 assert(name || path);
866 name = path_get_file_name(path);
868 if (!unit_name_is_valid(name, true))
871 if (hashmap_get(c->have_installed, name) ||
872 hashmap_get(c->will_install, name))
875 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
879 i = new0(InstallInfo, 1);
883 i->name = strdup(name);
890 i->path = strdup(path);
897 r = hashmap_put(c->will_install, i->name, i);
905 install_info_free(i);
910 static int install_info_add_auto(
912 const char *name_or_path) {
915 assert(name_or_path);
917 if (path_is_absolute(name_or_path))
918 return install_info_add(c, NULL, name_or_path);
920 return install_info_add(c, name_or_path, NULL);
923 static int config_parse_also(const char *unit,
924 const char *filename,
936 InstallContext *c = data;
942 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
943 _cleanup_free_ char *n;
950 r = install_info_add(c, n, NULL);
958 static int config_parse_user(const char *unit,
959 const char *filename,
968 InstallInfo *i = data;
975 printed = install_full_printf(i, rvalue);
985 static int unit_file_load(
989 bool allow_symlink) {
991 const ConfigTableItem items[] = {
992 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
993 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
994 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
995 { "Install", "Also", config_parse_also, 0, c },
996 { "Exec", "User", config_parse_user, 0, info },
997 { NULL, NULL, NULL, 0, NULL }
1001 _cleanup_fclose_ FILE *f = NULL;
1008 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1012 f = fdopen(fd, "re");
1014 close_nointr_nofail(fd);
1018 r = config_parse(NULL, path, f, NULL,
1019 config_item_table_lookup, (void*) items, true, true, info);
1024 strv_length(info->aliases) +
1025 strv_length(info->wanted_by) +
1026 strv_length(info->required_by);
1029 static int unit_file_search(
1033 const char *root_dir,
1034 bool allow_symlink) {
1044 return unit_file_load(c, info, info->path, allow_symlink);
1048 STRV_FOREACH(p, paths->unit_path) {
1051 if (isempty(root_dir))
1052 asprintf(&path, "%s/%s", *p, info->name);
1054 asprintf(&path, "%s/%s/%s", root_dir, *p, info->name);
1059 r = unit_file_load(c, info, path, allow_symlink);
1064 if (r == -ENOENT && unit_name_is_instance(info->name)) {
1065 /* Unit file doesn't exist, however instance enablement was requested.
1066 * We will check if it is possible to load template unit file. */
1067 char *template = NULL,
1068 *template_path = NULL,
1069 *template_dir = NULL;
1071 template = unit_name_template(info->name);
1077 /* We will reuse path variable since we don't need it anymore. */
1078 template_dir = path;
1079 *(strrchr(path, '/') + 1) = '\0';
1081 template_path = strjoin(template_dir, template, NULL);
1082 if (!template_path) {
1088 /* Let's try to load template unit. */
1089 r = unit_file_load(c, info, template_path, allow_symlink);
1091 info->path = strdup(template_path);
1095 free(template_path);
1101 free(template_path);
1106 if (r != -ENOENT && r != -ELOOP)
1113 static int unit_file_can_install(
1115 const char *root_dir,
1117 bool allow_symlink) {
1119 _cleanup_install_context_done_ InstallContext c = {};
1126 r = install_info_add_auto(&c, name);
1130 assert_se(i = hashmap_first(c.will_install));
1132 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1136 strv_length(i->aliases) +
1137 strv_length(i->wanted_by) +
1138 strv_length(i->required_by);
1143 static int create_symlink(
1144 const char *old_path,
1145 const char *new_path,
1147 UnitFileChange **changes,
1148 unsigned *n_changes) {
1150 _cleanup_free_ char *dest = NULL;
1156 mkdir_parents_label(new_path, 0755);
1158 if (symlink(old_path, new_path) >= 0) {
1159 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1163 if (errno != EEXIST)
1166 r = readlink_and_make_absolute(new_path, &dest);
1170 if (path_equal(dest, old_path))
1178 if (symlink(old_path, new_path) >= 0) {
1179 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1180 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1187 static int install_info_symlink_alias(
1189 const char *config_path,
1191 UnitFileChange **changes,
1192 unsigned *n_changes) {
1198 assert(config_path);
1200 STRV_FOREACH(s, i->aliases) {
1201 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1203 dst = install_full_printf(i, *s);
1207 alias_path = path_make_absolute(dst, config_path);
1211 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1219 static int install_info_symlink_wants(
1221 const char *config_path,
1223 UnitFileChange **changes,
1224 unsigned *n_changes) {
1230 assert(config_path);
1232 STRV_FOREACH(s, i->wanted_by) {
1233 _cleanup_free_ char *path = NULL, *dst = NULL;
1235 dst = install_full_printf(i, *s);
1239 if (!unit_name_is_valid(dst, true)) {
1244 if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
1247 q = create_symlink(i->path, path, force, changes, n_changes);
1256 static int install_info_symlink_requires(
1258 const char *config_path,
1260 UnitFileChange **changes,
1261 unsigned *n_changes) {
1267 assert(config_path);
1269 STRV_FOREACH(s, i->required_by) {
1270 _cleanup_free_ char *path = NULL, *dst = NULL;
1272 dst = install_full_printf(i, *s);
1276 if (!unit_name_is_valid(dst, true)) {
1281 if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
1284 q = create_symlink(i->path, path, force, changes, n_changes);
1293 static int install_info_symlink_link(
1296 const char *config_path,
1298 UnitFileChange **changes,
1299 unsigned *n_changes) {
1302 _cleanup_free_ char *path = NULL;
1306 assert(config_path);
1309 r = in_search_path(i->path, paths->unit_path);
1313 if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1316 r = create_symlink(i->path, path, force, changes, n_changes);
1320 static int install_info_apply(
1323 const char *config_path,
1325 UnitFileChange **changes,
1326 unsigned *n_changes) {
1332 assert(config_path);
1334 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1336 q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1340 q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1344 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1351 static int install_context_apply(
1354 const char *config_path,
1355 const char *root_dir,
1357 UnitFileChange **changes,
1358 unsigned *n_changes) {
1365 assert(config_path);
1367 while ((i = hashmap_first(c->will_install))) {
1369 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1373 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1375 q = unit_file_search(c, i, paths, root_dir, false);
1384 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1385 if (r >= 0 && q < 0)
1392 static int install_context_mark_for_removal(
1395 Set **remove_symlinks_to,
1396 const char *config_path,
1397 const char *root_dir) {
1404 assert(config_path);
1406 /* Marks all items for removal */
1408 while ((i = hashmap_first(c->will_install))) {
1410 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1414 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1416 q = unit_file_search(c, i, paths, root_dir, false);
1427 if (unit_name_is_instance(i->name)) {
1431 unit_file = path_get_file_name(i->path);
1433 if (unit_name_is_instance(unit_file))
1434 /* unit file named as instance exists, thus all symlinks
1435 * pointing to it will be removed */
1436 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1438 /* does not exist, thus we will mark for removal symlinks
1439 * to template unit file */
1440 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1442 /* If i->path is not set, it means that we didn't actually find
1443 * the unit file. But we can still remove symlinks to the
1444 * nonexistent template. */
1445 unit_file = unit_name_template(i->name);
1449 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1453 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1455 if (r >= 0 && q < 0)
1462 int unit_file_enable(
1463 UnitFileScope scope,
1465 const char *root_dir,
1468 UnitFileChange **changes,
1469 unsigned *n_changes) {
1471 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1472 _cleanup_install_context_done_ InstallContext c = {};
1474 _cleanup_free_ char *config_path = NULL;
1478 assert(scope < _UNIT_FILE_SCOPE_MAX);
1480 r = lookup_paths_init_from_scope(&paths, scope);
1484 r = get_config_path(scope, runtime, root_dir, &config_path);
1488 STRV_FOREACH(i, files) {
1489 r = install_info_add_auto(&c, *i);
1494 /* This will return the number of symlink rules that were
1495 supposed to be created, not the ones actually created. This is
1496 useful to determine whether the passed files had any
1497 installation data at all. */
1498 r = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1502 int unit_file_disable(
1503 UnitFileScope scope,
1505 const char *root_dir,
1507 UnitFileChange **changes,
1508 unsigned *n_changes) {
1510 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1511 _cleanup_install_context_done_ InstallContext c = {};
1513 _cleanup_free_ char *config_path = NULL;
1514 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1518 assert(scope < _UNIT_FILE_SCOPE_MAX);
1520 r = lookup_paths_init_from_scope(&paths, scope);
1524 r = get_config_path(scope, runtime, root_dir, &config_path);
1528 STRV_FOREACH(i, files) {
1529 r = install_info_add_auto(&c, *i);
1534 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1536 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1543 int unit_file_reenable(
1544 UnitFileScope scope,
1546 const char *root_dir,
1549 UnitFileChange **changes,
1550 unsigned *n_changes) {
1553 r = unit_file_disable(scope, runtime, root_dir, files,
1554 changes, n_changes);
1558 return unit_file_enable(scope, runtime, root_dir, files, force,
1559 changes, n_changes);
1562 int unit_file_set_default(
1563 UnitFileScope scope,
1564 const char *root_dir,
1566 UnitFileChange **changes,
1567 unsigned *n_changes) {
1569 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1570 _cleanup_install_context_done_ InstallContext c = {};
1571 _cleanup_free_ char *config_path = NULL;
1574 InstallInfo *i = NULL;
1577 assert(scope < _UNIT_FILE_SCOPE_MAX);
1579 if (unit_name_to_type(file) != UNIT_TARGET)
1582 r = lookup_paths_init_from_scope(&paths, scope);
1586 r = get_config_path(scope, false, root_dir, &config_path);
1590 r = install_info_add_auto(&c, file);
1594 i = (InstallInfo*)hashmap_first(c.will_install);
1596 r = unit_file_search(&c, i, &paths, root_dir, false);
1600 path = strappenda(config_path, "/default.target");
1601 r = create_symlink(i->path, path, true, changes, n_changes);
1608 int unit_file_get_default(
1609 UnitFileScope scope,
1610 const char *root_dir,
1613 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1617 r = lookup_paths_init_from_scope(&paths, scope);
1621 STRV_FOREACH(p, paths.unit_path) {
1622 _cleanup_free_ char *path = NULL, *tmp = NULL;
1624 if (isempty(root_dir))
1625 path = strappend(*p, "/default.target");
1627 path = strjoin(root_dir, "/", *p, "/default.target", NULL);
1632 r = readlink_malloc(path, &tmp);
1638 *name = strdup(path_get_file_name(tmp));
1648 UnitFileState unit_file_get_state(
1649 UnitFileScope scope,
1650 const char *root_dir,
1653 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1654 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1656 _cleanup_free_ char *path = NULL;
1660 assert(scope < _UNIT_FILE_SCOPE_MAX);
1663 if (root_dir && scope != UNIT_FILE_SYSTEM)
1666 if (!unit_name_is_valid(name, true))
1669 r = lookup_paths_init_from_scope(&paths, scope);
1673 STRV_FOREACH(i, paths.unit_path) {
1680 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1682 asprintf(&path, "%s/%s", *i, name);
1688 * Search for a unit file in our default paths, to
1689 * be sure, that there are no broken symlinks.
1691 if (lstat(path, &st) < 0) {
1693 if (errno != ENOENT)
1696 if (!unit_name_is_instance(name))
1699 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1702 r = null_or_empty_path(path);
1703 if (r < 0 && r != -ENOENT)
1706 state = path_startswith(*i, "/run") ?
1707 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1712 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1718 r = unit_file_can_install(&paths, root_dir, path, true);
1719 if (r < 0 && errno != ENOENT)
1722 return UNIT_FILE_DISABLED;
1724 return UNIT_FILE_STATIC;
1727 return r < 0 ? r : state;
1730 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1731 _cleanup_strv_free_ char **files = NULL;
1736 assert(scope < _UNIT_FILE_SCOPE_MAX);
1739 if (scope == UNIT_FILE_SYSTEM)
1740 r = conf_files_list(&files, ".preset", NULL,
1741 "/etc/systemd/system-preset",
1742 "/usr/local/lib/systemd/system-preset",
1743 "/usr/lib/systemd/system-preset",
1744 #ifdef HAVE_SPLIT_USR
1745 "/lib/systemd/system-preset",
1748 else if (scope == UNIT_FILE_GLOBAL)
1749 r = conf_files_list(&files, ".preset", NULL,
1750 "/etc/systemd/user-preset",
1751 "/usr/local/lib/systemd/user-preset",
1752 "/usr/lib/systemd/user-preset",
1760 STRV_FOREACH(i, files) {
1761 _cleanup_fclose_ FILE *f;
1763 f = fopen(*i, "re");
1765 if (errno == ENOENT)
1772 char line[LINE_MAX], *l;
1774 if (!fgets(line, sizeof(line), f))
1781 if (strchr(COMMENTS "\n", *l))
1784 if (first_word(l, "enable")) {
1786 l += strspn(l, WHITESPACE);
1788 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1791 } else if (first_word(l, "disable")) {
1793 l += strspn(l, WHITESPACE);
1795 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1799 log_debug("Couldn't parse line '%s'", l);
1803 /* Default is "enable" */
1807 int unit_file_preset(
1808 UnitFileScope scope,
1810 const char *root_dir,
1813 UnitFileChange **changes,
1814 unsigned *n_changes) {
1816 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1817 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1819 _cleanup_free_ char *config_path = NULL;
1820 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1824 assert(scope < _UNIT_FILE_SCOPE_MAX);
1826 r = lookup_paths_init_from_scope(&paths, scope);
1830 r = get_config_path(scope, runtime, root_dir, &config_path);
1834 STRV_FOREACH(i, files) {
1836 if (!unit_name_is_valid(*i, true))
1839 r = unit_file_query_preset(scope, *i);
1844 r = install_info_add_auto(&plus, *i);
1846 r = install_info_add_auto(&minus, *i);
1852 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to,
1853 config_path, root_dir);
1855 q = remove_marked_symlinks(remove_symlinks_to, config_path,
1856 changes, n_changes, files);
1860 /* Returns number of symlinks that where supposed to be installed. */
1861 q = install_context_apply(&plus, &paths, config_path, root_dir, force,
1862 changes, n_changes);
1869 static void unitfilelist_free(UnitFileList **f) {
1877 int unit_file_get_list(
1878 UnitFileScope scope,
1879 const char *root_dir,
1882 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1884 _cleanup_free_ char *buf = NULL;
1885 _cleanup_closedir_ DIR *d = NULL;
1889 assert(scope < _UNIT_FILE_SCOPE_MAX);
1892 if (root_dir && scope != UNIT_FILE_SYSTEM)
1895 r = lookup_paths_init_from_scope(&paths, scope);
1899 STRV_FOREACH(i, paths.unit_path) {
1900 const char *units_dir;
1906 if (asprintf(&buf, "%s/%s", root_dir, *i) < 0)
1916 d = opendir(units_dir);
1918 if (errno == ENOENT)
1926 union dirent_storage buffer;
1927 UnitFileList __attribute__((cleanup(unitfilelist_free)))
1930 r = readdir_r(d, &buffer.de, &de);
1937 if (ignore_file(de->d_name))
1940 if (!unit_name_is_valid(de->d_name, true))
1943 if (hashmap_get(h, de->d_name))
1946 r = dirent_ensure_type(d, de);
1954 if (de->d_type != DT_LNK && de->d_type != DT_REG)
1957 f = new0(UnitFileList, 1);
1961 f->path = path_make_absolute(de->d_name, units_dir);
1965 r = null_or_empty_path(f->path);
1966 if (r < 0 && r != -ENOENT)
1970 path_startswith(*i, "/run") ?
1971 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1975 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
1979 f->state = UNIT_FILE_ENABLED;
1983 r = unit_file_can_install(&paths, root_dir, f->path, true);
1984 if (r == -EINVAL || /* Invalid setting? */
1985 r == -EBADMSG || /* Invalid format? */
1986 r == -ENOENT /* Included file not found? */)
1987 f->state = UNIT_FILE_INVALID;
1991 f->state = UNIT_FILE_DISABLED;
1993 f->state = UNIT_FILE_STATIC;
1996 r = hashmap_put(h, path_get_file_name(f->path), f);
1999 f = NULL; /* prevent cleanup */
2006 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2007 [UNIT_FILE_ENABLED] = "enabled",
2008 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2009 [UNIT_FILE_LINKED] = "linked",
2010 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2011 [UNIT_FILE_MASKED] = "masked",
2012 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2013 [UNIT_FILE_STATIC] = "static",
2014 [UNIT_FILE_DISABLED] = "disabled",
2015 [UNIT_FILE_INVALID] = "invalid",
2018 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2020 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2021 [UNIT_FILE_SYMLINK] = "symlink",
2022 [UNIT_FILE_UNLINK] = "unlink",
2025 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);