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, UnitFileScope scope) {
53 assert(scope < _UNIT_FILE_SCOPE_MAX);
57 return lookup_paths_init(paths,
58 scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
59 scope == UNIT_FILE_USER,
63 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
68 assert(scope < _UNIT_FILE_SCOPE_MAX);
73 case UNIT_FILE_SYSTEM:
75 if (root_dir && runtime)
76 asprintf(&p, "%s/run/systemd/system", root_dir);
78 p = strdup("/run/systemd/system");
80 asprintf(&p, "%s/%s", root_dir, SYSTEM_CONFIG_UNIT_PATH);
82 p = strdup(SYSTEM_CONFIG_UNIT_PATH);
86 case UNIT_FILE_GLOBAL:
92 p = strdup("/run/systemd/user");
94 p = strdup(USER_CONFIG_UNIT_PATH);
99 if (root_dir || runtime)
102 r = user_config_home(&p);
104 return r < 0 ? r : -ENOENT;
109 assert_not_reached("Bad scope");
119 static int add_file_change(
120 UnitFileChange **changes,
122 UnitFileChangeType type,
124 const char *source) {
130 assert(!changes == !n_changes);
135 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
143 c[i].path = strdup(path);
148 c[i].source = strdup(source);
160 static int mark_symlink_for_removal(
161 Set **remove_symlinks_to,
169 r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
177 path_kill_slashes(n);
179 r = set_consume(*remove_symlinks_to, n);
181 return r == -EEXIST ? 0 : r;
186 static int remove_marked_symlinks_fd(
187 Set *remove_symlinks_to,
190 const char *config_path,
192 UnitFileChange **changes,
197 _cleanup_closedir_ DIR *d = NULL;
199 assert(remove_symlinks_to);
218 if (!de && errno != 0) {
226 if (ignore_file(de->d_name))
229 dirent_ensure_type(d, de);
231 if (de->d_type == DT_DIR) {
233 _cleanup_free_ char *p = NULL;
235 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
245 p = path_make_absolute(de->d_name, path);
251 /* This will close nfd, regardless whether it succeeds or not */
252 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, files);
257 } else if (de->d_type == DT_LNK) {
258 _cleanup_free_ char *p = NULL, *dest = NULL;
262 p = path_make_absolute(de->d_name, path);
266 q = readlink_and_canonicalize(p, &dest);
277 set_get(remove_symlinks_to, dest) ||
278 set_get(remove_symlinks_to, basename(dest));
280 if (unit_name_is_instance(p))
281 found = found && strv_contains(files, basename(p));
285 if (unlink(p) < 0 && errno != ENOENT) {
290 rmdir_parents(p, config_path);
291 path_kill_slashes(p);
293 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
295 if (!set_get(remove_symlinks_to, p)) {
297 q = mark_symlink_for_removal(&remove_symlinks_to, p);
312 static int remove_marked_symlinks(
313 Set *remove_symlinks_to,
314 const char *config_path,
315 UnitFileChange **changes,
324 if (set_size(remove_symlinks_to) <= 0)
327 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
341 /* This takes possession of cfd and closes it */
342 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, files);
352 static int find_symlinks_fd(
356 const char *config_path,
357 bool *same_name_link) {
360 _cleanup_closedir_ DIR *d = NULL;
366 assert(same_name_link);
379 if (!de && errno != 0)
385 if (ignore_file(de->d_name))
388 dirent_ensure_type(d, de);
390 if (de->d_type == DT_DIR) {
392 _cleanup_free_ char *p = NULL;
394 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
404 p = path_make_absolute(de->d_name, path);
410 /* This will close nfd, regardless whether it succeeds or not */
411 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
419 } else if (de->d_type == DT_LNK) {
420 _cleanup_free_ char *p = NULL, *dest = NULL;
421 bool found_path, found_dest, b = false;
424 /* Acquire symlink name */
425 p = path_make_absolute(de->d_name, path);
429 /* Acquire symlink destination */
430 q = readlink_and_canonicalize(p, &dest);
440 /* Check if the symlink itself matches what we
442 if (path_is_absolute(name))
443 found_path = path_equal(p, name);
445 found_path = streq(de->d_name, name);
447 /* Check if what the symlink points to
448 * matches what we are looking for */
449 if (path_is_absolute(name))
450 found_dest = path_equal(dest, name);
452 found_dest = streq(basename(dest), name);
454 if (found_path && found_dest) {
455 _cleanup_free_ char *t = NULL;
457 /* Filter out same name links in the main
459 t = path_make_absolute(name, config_path);
463 b = path_equal(t, p);
467 *same_name_link = true;
468 else if (found_path || found_dest)
474 static int find_symlinks(
476 const char *config_path,
477 bool *same_name_link) {
483 assert(same_name_link);
485 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
492 /* This takes possession of fd and closes it */
493 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
496 static int find_symlinks_in_scope(
498 const char *root_dir,
500 UnitFileState *state) {
503 _cleanup_free_ char *path2 = NULL;
504 bool same_name_link_runtime = false, same_name_link = false;
507 assert(scope < _UNIT_FILE_SCOPE_MAX);
510 if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
511 _cleanup_free_ char *path = NULL;
513 /* First look in runtime config path */
514 r = get_config_path(scope, true, root_dir, &path);
518 r = find_symlinks(name, path, &same_name_link_runtime);
522 *state = UNIT_FILE_ENABLED_RUNTIME;
527 /* Then look in the normal config path */
528 r = get_config_path(scope, false, root_dir, &path2);
532 r = find_symlinks(name, path2, &same_name_link);
536 *state = UNIT_FILE_ENABLED;
540 /* Hmm, we didn't find it, but maybe we found the same name
542 if (same_name_link_runtime) {
543 *state = UNIT_FILE_LINKED_RUNTIME;
545 } else if (same_name_link) {
546 *state = UNIT_FILE_LINKED;
556 const char *root_dir,
559 UnitFileChange **changes,
560 unsigned *n_changes) {
563 _cleanup_free_ char *prefix;
567 assert(scope < _UNIT_FILE_SCOPE_MAX);
569 r = get_config_path(scope, runtime, root_dir, &prefix);
573 STRV_FOREACH(i, files) {
574 _cleanup_free_ char *path = NULL;
576 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
582 path = path_make_absolute(*i, prefix);
588 if (symlink("/dev/null", path) >= 0) {
589 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
594 if (errno == EEXIST) {
596 if (null_or_empty_path(path) > 0)
602 if (symlink("/dev/null", path) >= 0) {
604 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
605 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
622 int unit_file_unmask(
625 const char *root_dir,
627 UnitFileChange **changes,
628 unsigned *n_changes) {
630 char **i, *config_path = NULL;
632 Set *remove_symlinks_to = NULL;
635 assert(scope < _UNIT_FILE_SCOPE_MAX);
637 r = get_config_path(scope, runtime, root_dir, &config_path);
641 STRV_FOREACH(i, files) {
644 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
650 path = path_make_absolute(*i, config_path);
656 q = null_or_empty_path(path);
658 if (unlink(path) >= 0) {
659 mark_symlink_for_removal(&remove_symlinks_to, path);
660 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
669 if (q != -ENOENT && r == 0)
677 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
681 set_free_free(remove_symlinks_to);
690 const char *root_dir,
693 UnitFileChange **changes,
694 unsigned *n_changes) {
696 _cleanup_lookup_paths_free_ LookupPaths paths = {};
698 _cleanup_free_ char *config_path = NULL;
702 assert(scope < _UNIT_FILE_SCOPE_MAX);
704 r = lookup_paths_init_from_scope(&paths, scope);
708 r = get_config_path(scope, runtime, root_dir, &config_path);
712 STRV_FOREACH(i, files) {
713 _cleanup_free_ char *path = NULL;
719 if (!path_is_absolute(*i) ||
720 !unit_name_is_valid(fn, TEMPLATE_VALID)) {
726 if (lstat(*i, &st) < 0) {
732 if (!S_ISREG(st.st_mode)) {
737 q = in_search_path(*i, paths.unit_path);
744 path = path_make_absolute(fn, config_path);
748 if (symlink(*i, path) >= 0) {
749 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
753 if (errno == EEXIST) {
754 _cleanup_free_ char *dest = NULL;
756 q = readlink_and_make_absolute(path, &dest);
758 if (q < 0 && errno != ENOENT) {
764 if (q >= 0 && path_equal(dest, *i))
770 if (symlink(*i, path) >= 0) {
772 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
773 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
790 void unit_file_list_free(Hashmap *h) {
793 while ((i = hashmap_steal_first(h))) {
801 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
804 assert(changes || n_changes == 0);
809 for (i = 0; i < n_changes; i++) {
810 free(changes[i].path);
811 free(changes[i].source);
817 static void install_info_free(InstallInfo *i) {
822 strv_free(i->aliases);
823 strv_free(i->wanted_by);
824 strv_free(i->required_by);
828 static void install_info_hashmap_free(Hashmap *m) {
834 while ((i = hashmap_steal_first(m)))
835 install_info_free(i);
840 static void install_context_done(InstallContext *c) {
843 install_info_hashmap_free(c->will_install);
844 install_info_hashmap_free(c->have_installed);
846 c->will_install = c->have_installed = NULL;
849 static int install_info_add(
853 InstallInfo *i = NULL;
857 assert(name || path);
860 name = basename(path);
862 if (!unit_name_is_valid(name, TEMPLATE_VALID))
865 if (hashmap_get(c->have_installed, name) ||
866 hashmap_get(c->will_install, name))
869 r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
873 i = new0(InstallInfo, 1);
877 i->name = strdup(name);
884 i->path = strdup(path);
891 r = hashmap_put(c->will_install, i->name, i);
899 install_info_free(i);
904 static int install_info_add_auto(
906 const char *name_or_path) {
909 assert(name_or_path);
911 if (path_is_absolute(name_or_path))
912 return install_info_add(c, NULL, name_or_path);
914 return install_info_add(c, name_or_path, NULL);
917 static int config_parse_also(const char *unit,
918 const char *filename,
921 unsigned section_line,
931 InstallContext *c = data;
937 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
938 _cleanup_free_ char *n;
945 r = install_info_add(c, n, NULL);
953 static int config_parse_user(const char *unit,
954 const char *filename,
957 unsigned section_line,
964 InstallInfo *i = data;
972 r = install_full_printf(i, rvalue, &printed);
982 static int unit_file_load(
986 bool allow_symlink) {
988 const ConfigTableItem items[] = {
989 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
990 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
991 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
992 { "Install", "Also", config_parse_also, 0, c },
993 { "Exec", "User", config_parse_user, 0, info },
994 { NULL, NULL, NULL, 0, NULL }
998 _cleanup_fclose_ FILE *f = NULL;
1005 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1009 f = fdopen(fd, "re");
1015 r = config_parse(NULL, path, f, NULL,
1016 config_item_table_lookup, (void*) items, true, true, info);
1021 (int) strv_length(info->aliases) +
1022 (int) strv_length(info->wanted_by) +
1023 (int) strv_length(info->required_by);
1026 static int unit_file_search(
1030 const char *root_dir,
1031 bool allow_symlink) {
1041 return unit_file_load(c, info, info->path, allow_symlink);
1045 STRV_FOREACH(p, paths->unit_path) {
1048 if (isempty(root_dir))
1049 asprintf(&path, "%s/%s", *p, info->name);
1051 asprintf(&path, "%s/%s/%s", root_dir, *p, info->name);
1056 r = unit_file_load(c, info, path, allow_symlink);
1061 if (r == -ENOENT && unit_name_is_instance(info->name)) {
1062 /* Unit file doesn't exist, however instance enablement was requested.
1063 * We will check if it is possible to load template unit file. */
1064 char *template = NULL,
1065 *template_path = NULL,
1066 *template_dir = NULL;
1068 template = unit_name_template(info->name);
1074 /* We will reuse path variable since we don't need it anymore. */
1075 template_dir = path;
1076 *(strrchr(path, '/') + 1) = '\0';
1078 template_path = strjoin(template_dir, template, NULL);
1079 if (!template_path) {
1085 /* Let's try to load template unit. */
1086 r = unit_file_load(c, info, template_path, allow_symlink);
1088 info->path = strdup(template_path);
1092 free(template_path);
1098 free(template_path);
1103 if (r != -ENOENT && r != -ELOOP)
1110 static int unit_file_can_install(
1112 const char *root_dir,
1114 bool allow_symlink) {
1116 _cleanup_install_context_done_ InstallContext c = {};
1123 r = install_info_add_auto(&c, name);
1127 assert_se(i = hashmap_first(c.will_install));
1129 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1133 (int) strv_length(i->aliases) +
1134 (int) strv_length(i->wanted_by) +
1135 (int) strv_length(i->required_by);
1140 static int create_symlink(
1141 const char *old_path,
1142 const char *new_path,
1144 UnitFileChange **changes,
1145 unsigned *n_changes) {
1147 _cleanup_free_ char *dest = NULL;
1153 mkdir_parents_label(new_path, 0755);
1155 if (symlink(old_path, new_path) >= 0) {
1156 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1160 if (errno != EEXIST)
1163 r = readlink_and_make_absolute(new_path, &dest);
1167 if (path_equal(dest, old_path))
1173 r = unlink(new_path);
1174 if (r < 0 && errno != ENOENT)
1177 if (symlink(old_path, new_path) >= 0) {
1178 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1179 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1186 static int install_info_symlink_alias(
1188 const char *config_path,
1190 UnitFileChange **changes,
1191 unsigned *n_changes) {
1197 assert(config_path);
1199 STRV_FOREACH(s, i->aliases) {
1200 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1202 q = install_full_printf(i, *s, &dst);
1206 alias_path = path_make_absolute(dst, config_path);
1210 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1218 static int install_info_symlink_wants(
1220 const char *config_path,
1222 UnitFileChange **changes,
1223 unsigned *n_changes) {
1229 assert(config_path);
1231 STRV_FOREACH(s, i->wanted_by) {
1232 _cleanup_free_ char *path = NULL, *dst = NULL;
1234 q = install_full_printf(i, *s, &dst);
1238 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1243 if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
1246 q = create_symlink(i->path, path, force, changes, n_changes);
1255 static int install_info_symlink_requires(
1257 const char *config_path,
1259 UnitFileChange **changes,
1260 unsigned *n_changes) {
1266 assert(config_path);
1268 STRV_FOREACH(s, i->required_by) {
1269 _cleanup_free_ char *path = NULL, *dst = NULL;
1271 q = install_full_printf(i, *s, &dst);
1275 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1280 if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
1283 q = create_symlink(i->path, path, force, changes, n_changes);
1292 static int install_info_symlink_link(
1295 const char *config_path,
1297 UnitFileChange **changes,
1298 unsigned *n_changes) {
1301 _cleanup_free_ char *path = NULL;
1305 assert(config_path);
1308 r = in_search_path(i->path, paths->unit_path);
1312 if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1315 r = create_symlink(i->path, path, force, changes, n_changes);
1319 static int install_info_apply(
1322 const char *config_path,
1324 UnitFileChange **changes,
1325 unsigned *n_changes) {
1331 assert(config_path);
1333 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1335 q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1339 q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1343 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1350 static int install_context_apply(
1353 const char *config_path,
1354 const char *root_dir,
1356 UnitFileChange **changes,
1357 unsigned *n_changes) {
1364 assert(config_path);
1366 while ((i = hashmap_first(c->will_install))) {
1368 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1372 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1374 q = unit_file_search(c, i, paths, root_dir, false);
1383 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1384 if (r >= 0 && q < 0)
1391 static int install_context_mark_for_removal(
1394 Set **remove_symlinks_to,
1395 const char *config_path,
1396 const char *root_dir) {
1403 assert(config_path);
1405 /* Marks all items for removal */
1407 while ((i = hashmap_first(c->will_install))) {
1409 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1413 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1415 q = unit_file_search(c, i, paths, root_dir, false);
1426 if (unit_name_is_instance(i->name)) {
1430 unit_file = basename(i->path);
1432 if (unit_name_is_instance(unit_file))
1433 /* unit file named as instance exists, thus all symlinks
1434 * pointing to it will be removed */
1435 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1437 /* does not exist, thus we will mark for removal symlinks
1438 * to template unit file */
1439 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1441 /* If i->path is not set, it means that we didn't actually find
1442 * the unit file. But we can still remove symlinks to the
1443 * nonexistent template. */
1444 unit_file = unit_name_template(i->name);
1448 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1452 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1454 if (r >= 0 && q < 0)
1461 int unit_file_enable(
1462 UnitFileScope scope,
1464 const char *root_dir,
1467 UnitFileChange **changes,
1468 unsigned *n_changes) {
1470 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1471 _cleanup_install_context_done_ InstallContext c = {};
1473 _cleanup_free_ char *config_path = NULL;
1477 assert(scope < _UNIT_FILE_SCOPE_MAX);
1479 r = lookup_paths_init_from_scope(&paths, scope);
1483 r = get_config_path(scope, runtime, root_dir, &config_path);
1487 STRV_FOREACH(i, files) {
1488 r = install_info_add_auto(&c, *i);
1493 /* This will return the number of symlink rules that were
1494 supposed to be created, not the ones actually created. This is
1495 useful to determine whether the passed files had any
1496 installation data at all. */
1498 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1501 int unit_file_disable(
1502 UnitFileScope scope,
1504 const char *root_dir,
1506 UnitFileChange **changes,
1507 unsigned *n_changes) {
1509 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1510 _cleanup_install_context_done_ InstallContext c = {};
1512 _cleanup_free_ char *config_path = NULL;
1513 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1517 assert(scope < _UNIT_FILE_SCOPE_MAX);
1519 r = lookup_paths_init_from_scope(&paths, scope);
1523 r = get_config_path(scope, runtime, root_dir, &config_path);
1527 STRV_FOREACH(i, files) {
1528 r = install_info_add_auto(&c, *i);
1533 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1535 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1542 int unit_file_reenable(
1543 UnitFileScope scope,
1545 const char *root_dir,
1548 UnitFileChange **changes,
1549 unsigned *n_changes) {
1552 r = unit_file_disable(scope, runtime, root_dir, files,
1553 changes, n_changes);
1557 return unit_file_enable(scope, runtime, root_dir, files, force,
1558 changes, n_changes);
1561 int unit_file_set_default(
1562 UnitFileScope scope,
1563 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);
1580 if (unit_name_to_type(file) != UNIT_TARGET)
1583 r = lookup_paths_init_from_scope(&paths, scope);
1587 r = get_config_path(scope, false, root_dir, &config_path);
1591 r = install_info_add_auto(&c, file);
1595 assert_se(i = hashmap_first(c.will_install));
1597 r = unit_file_search(&c, i, &paths, root_dir, false);
1601 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1603 r = create_symlink(i->path, path, force, changes, n_changes);
1610 int unit_file_get_default(
1611 UnitFileScope scope,
1612 const char *root_dir,
1615 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1620 assert(scope < _UNIT_FILE_SCOPE_MAX);
1623 r = lookup_paths_init_from_scope(&paths, scope);
1627 STRV_FOREACH(p, paths.unit_path) {
1628 _cleanup_free_ char *path = NULL, *tmp = NULL;
1631 if (isempty(root_dir))
1632 path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
1634 path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
1639 r = readlink_malloc(path, &tmp);
1642 else if (r == -EINVAL)
1644 n = strdup(SPECIAL_DEFAULT_TARGET);
1648 n = strdup(basename(tmp));
1660 UnitFileState unit_file_get_state(
1661 UnitFileScope scope,
1662 const char *root_dir,
1665 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1666 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1668 _cleanup_free_ char *path = NULL;
1672 assert(scope < _UNIT_FILE_SCOPE_MAX);
1675 if (root_dir && scope != UNIT_FILE_SYSTEM)
1678 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1681 r = lookup_paths_init_from_scope(&paths, scope);
1685 STRV_FOREACH(i, paths.unit_path) {
1692 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1694 asprintf(&path, "%s/%s", *i, name);
1700 * Search for a unit file in our default paths, to
1701 * be sure, that there are no broken symlinks.
1703 if (lstat(path, &st) < 0) {
1705 if (errno != ENOENT)
1708 if (!unit_name_is_instance(name))
1711 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1714 r = null_or_empty_path(path);
1715 if (r < 0 && r != -ENOENT)
1718 state = path_startswith(*i, "/run") ?
1719 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1724 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1730 r = unit_file_can_install(&paths, root_dir, path, true);
1731 if (r < 0 && errno != ENOENT)
1734 return UNIT_FILE_DISABLED;
1736 return UNIT_FILE_STATIC;
1739 return r < 0 ? r : state;
1742 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1743 _cleanup_strv_free_ char **files = NULL;
1748 assert(scope < _UNIT_FILE_SCOPE_MAX);
1751 if (scope == UNIT_FILE_SYSTEM)
1752 r = conf_files_list(&files, ".preset", NULL,
1753 "/etc/systemd/system-preset",
1754 "/usr/local/lib/systemd/system-preset",
1755 "/usr/lib/systemd/system-preset",
1756 #ifdef HAVE_SPLIT_USR
1757 "/lib/systemd/system-preset",
1760 else if (scope == UNIT_FILE_GLOBAL)
1761 r = conf_files_list(&files, ".preset", NULL,
1762 "/etc/systemd/user-preset",
1763 "/usr/local/lib/systemd/user-preset",
1764 "/usr/lib/systemd/user-preset",
1772 STRV_FOREACH(i, files) {
1773 _cleanup_fclose_ FILE *f;
1775 f = fopen(*i, "re");
1777 if (errno == ENOENT)
1784 char line[LINE_MAX], *l;
1786 if (!fgets(line, sizeof(line), f))
1793 if (strchr(COMMENTS "\n", *l))
1796 if (first_word(l, "enable")) {
1798 l += strspn(l, WHITESPACE);
1800 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1803 } else if (first_word(l, "disable")) {
1805 l += strspn(l, WHITESPACE);
1807 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1811 log_debug("Couldn't parse line '%s'", l);
1815 /* Default is "enable" */
1819 int unit_file_preset(
1820 UnitFileScope scope,
1822 const char *root_dir,
1825 UnitFileChange **changes,
1826 unsigned *n_changes) {
1828 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1829 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1831 _cleanup_free_ char *config_path = NULL;
1832 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1836 assert(scope < _UNIT_FILE_SCOPE_MAX);
1838 r = lookup_paths_init_from_scope(&paths, scope);
1842 r = get_config_path(scope, runtime, root_dir, &config_path);
1846 STRV_FOREACH(i, files) {
1848 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1851 r = unit_file_query_preset(scope, *i);
1856 r = install_info_add_auto(&plus, *i);
1858 r = install_info_add_auto(&minus, *i);
1864 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to,
1865 config_path, root_dir);
1867 q = remove_marked_symlinks(remove_symlinks_to, config_path,
1868 changes, n_changes, files);
1872 /* Returns number of symlinks that where supposed to be installed. */
1873 q = install_context_apply(&plus, &paths, config_path, root_dir, force,
1874 changes, n_changes);
1881 static void unitfilelist_free(UnitFileList **f) {
1888 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
1890 int unit_file_get_list(
1891 UnitFileScope scope,
1892 const char *root_dir,
1895 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1897 _cleanup_free_ char *buf = NULL;
1898 _cleanup_closedir_ DIR *d = NULL;
1902 assert(scope < _UNIT_FILE_SCOPE_MAX);
1905 if (root_dir && scope != UNIT_FILE_SYSTEM)
1908 r = lookup_paths_init_from_scope(&paths, scope);
1912 STRV_FOREACH(i, paths.unit_path) {
1913 const char *units_dir;
1919 if (asprintf(&buf, "%s/%s", root_dir, *i) < 0)
1929 d = opendir(units_dir);
1931 if (errno == ENOENT)
1939 _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
1943 if (!de && errno != 0)
1949 if (ignore_file(de->d_name))
1952 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1955 if (hashmap_get(h, de->d_name))
1958 r = dirent_ensure_type(d, de);
1966 if (de->d_type != DT_LNK && de->d_type != DT_REG)
1969 f = new0(UnitFileList, 1);
1973 f->path = path_make_absolute(de->d_name, units_dir);
1977 r = null_or_empty_path(f->path);
1978 if (r < 0 && r != -ENOENT)
1982 path_startswith(*i, "/run") ?
1983 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1987 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
1991 f->state = UNIT_FILE_ENABLED;
1995 r = unit_file_can_install(&paths, root_dir, f->path, true);
1996 if (r == -EINVAL || /* Invalid setting? */
1997 r == -EBADMSG || /* Invalid format? */
1998 r == -ENOENT /* Included file not found? */)
1999 f->state = UNIT_FILE_INVALID;
2003 f->state = UNIT_FILE_DISABLED;
2005 f->state = UNIT_FILE_STATIC;
2008 r = hashmap_put(h, basename(f->path), f);
2011 f = NULL; /* prevent cleanup */
2018 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2019 [UNIT_FILE_ENABLED] = "enabled",
2020 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2021 [UNIT_FILE_LINKED] = "linked",
2022 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2023 [UNIT_FILE_MASKED] = "masked",
2024 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2025 [UNIT_FILE_STATIC] = "static",
2026 [UNIT_FILE_DISABLED] = "disabled",
2027 [UNIT_FILE_INVALID] = "invalid",
2030 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2032 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2033 [UNIT_FILE_SYMLINK] = "symlink",
2034 [UNIT_FILE_UNLINK] = "unlink",
2037 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);