]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/install.c
tree-wide: remove Emacs lines from all files
[thirdparty/systemd.git] / src / shared / install.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2011 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty <of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <dirent.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <fnmatch.h>
24 #include <limits.h>
25 #include <stddef.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31
32 #include "alloc-util.h"
33 #include "conf-files.h"
34 #include "conf-parser.h"
35 #include "dirent-util.h"
36 #include "extract-word.h"
37 #include "fd-util.h"
38 #include "fileio.h"
39 #include "fs-util.h"
40 #include "hashmap.h"
41 #include "install-printf.h"
42 #include "install.h"
43 #include "log.h"
44 #include "macro.h"
45 #include "mkdir.h"
46 #include "path-lookup.h"
47 #include "path-util.h"
48 #include "set.h"
49 #include "special.h"
50 #include "stat-util.h"
51 #include "string-table.h"
52 #include "string-util.h"
53 #include "strv.h"
54 #include "unit-name.h"
55
56 #define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
57
58 typedef enum SearchFlags {
59 SEARCH_LOAD = 1,
60 SEARCH_FOLLOW_CONFIG_SYMLINKS = 2,
61 } SearchFlags;
62
63 typedef struct {
64 OrderedHashmap *will_process;
65 OrderedHashmap *have_processed;
66 } InstallContext;
67
68 static int in_search_path(const char *path, char **search) {
69 _cleanup_free_ char *parent = NULL;
70 char **i;
71
72 assert(path);
73
74 parent = dirname_malloc(path);
75 if (!parent)
76 return -ENOMEM;
77
78 STRV_FOREACH(i, search)
79 if (path_equal(parent, *i))
80 return true;
81
82 return false;
83 }
84
85 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
86 char *p = NULL;
87 int r;
88
89 assert(scope >= 0);
90 assert(scope < _UNIT_FILE_SCOPE_MAX);
91 assert(ret);
92
93 /* This determines where we shall create or remove our
94 * installation ("configuration") symlinks */
95
96 switch (scope) {
97
98 case UNIT_FILE_SYSTEM:
99
100 if (runtime)
101 p = path_join(root_dir, "/run/systemd/system", NULL);
102 else
103 p = path_join(root_dir, SYSTEM_CONFIG_UNIT_PATH, NULL);
104 break;
105
106 case UNIT_FILE_GLOBAL:
107
108 if (root_dir)
109 return -EINVAL;
110
111 if (runtime)
112 p = strdup("/run/systemd/user");
113 else
114 p = strdup(USER_CONFIG_UNIT_PATH);
115 break;
116
117 case UNIT_FILE_USER:
118
119 if (root_dir)
120 return -EINVAL;
121
122 if (runtime)
123 r = user_runtime_dir(&p);
124 else
125 r = user_config_home(&p);
126 if (r < 0)
127 return r;
128 if (r == 0)
129 return -ENOENT;
130
131 break;
132
133 default:
134 assert_not_reached("Bad scope");
135 }
136
137 if (!p)
138 return -ENOMEM;
139
140 *ret = p;
141 return 0;
142 }
143
144 static bool is_config_path(UnitFileScope scope, const char *path) {
145 int r;
146
147 assert(scope >= 0);
148 assert(scope < _UNIT_FILE_SCOPE_MAX);
149 assert(path);
150
151 /* Checks whether the specified path is intended for
152 * configuration or is outside of it */
153
154 switch (scope) {
155
156 case UNIT_FILE_SYSTEM:
157 case UNIT_FILE_GLOBAL:
158 return path_startswith(path, "/etc") ||
159 path_startswith(path, SYSTEM_CONFIG_UNIT_PATH) ||
160 path_startswith(path, "/run");
161
162
163 case UNIT_FILE_USER: {
164 _cleanup_free_ char *p = NULL;
165
166 r = user_config_home(&p);
167 if (r < 0)
168 return r;
169 if (r > 0 && path_startswith(path, p))
170 return true;
171
172 p = mfree(p);
173
174 r = user_runtime_dir(&p);
175 if (r < 0)
176 return r;
177 if (r > 0 && path_startswith(path, p))
178 return true;
179
180 return false;
181 }
182
183 default:
184 assert_not_reached("Bad scope");
185 }
186 }
187
188
189 static int verify_root_dir(UnitFileScope scope, const char **root_dir) {
190 int r;
191
192 assert(root_dir);
193
194 /* Verifies that the specified root directory to operate on
195 * makes sense. Reset it to NULL if it is the root directory
196 * or set to empty */
197
198 if (isempty(*root_dir) || path_equal(*root_dir, "/")) {
199 *root_dir = NULL;
200 return 0;
201 }
202
203 if (scope != UNIT_FILE_SYSTEM)
204 return -EINVAL;
205
206 r = is_dir(*root_dir, true);
207 if (r < 0)
208 return r;
209 if (r == 0)
210 return -ENOTDIR;
211
212 return 0;
213 }
214
215 int unit_file_changes_add(
216 UnitFileChange **changes,
217 unsigned *n_changes,
218 UnitFileChangeType type,
219 const char *path,
220 const char *source) {
221
222 UnitFileChange *c;
223 unsigned i;
224
225 assert(path);
226 assert(!changes == !n_changes);
227
228 if (!changes)
229 return 0;
230
231 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
232 if (!c)
233 return -ENOMEM;
234
235 *changes = c;
236 i = *n_changes;
237
238 c[i].type = type;
239 c[i].path = strdup(path);
240 if (!c[i].path)
241 return -ENOMEM;
242
243 path_kill_slashes(c[i].path);
244
245 if (source) {
246 c[i].source = strdup(source);
247 if (!c[i].source) {
248 free(c[i].path);
249 return -ENOMEM;
250 }
251
252 path_kill_slashes(c[i].path);
253 } else
254 c[i].source = NULL;
255
256 *n_changes = i+1;
257 return 0;
258 }
259
260 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
261 unsigned i;
262
263 assert(changes || n_changes == 0);
264
265 if (!changes)
266 return;
267
268 for (i = 0; i < n_changes; i++) {
269 free(changes[i].path);
270 free(changes[i].source);
271 }
272
273 free(changes);
274 }
275
276 static int create_symlink(
277 const char *old_path,
278 const char *new_path,
279 bool force,
280 UnitFileChange **changes,
281 unsigned *n_changes) {
282
283 _cleanup_free_ char *dest = NULL;
284 int r;
285
286 assert(old_path);
287 assert(new_path);
288
289 /* Actually create a symlink, and remember that we did. Is
290 * smart enough to check if there's already a valid symlink in
291 * place. */
292
293 mkdir_parents_label(new_path, 0755);
294
295 if (symlink(old_path, new_path) >= 0) {
296 unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
297 return 0;
298 }
299
300 if (errno != EEXIST)
301 return -errno;
302
303 r = readlink_malloc(new_path, &dest);
304 if (r < 0)
305 return r;
306
307 if (path_equal(dest, old_path))
308 return 0;
309
310 if (!force)
311 return -EEXIST;
312
313 r = symlink_atomic(old_path, new_path);
314 if (r < 0)
315 return r;
316
317 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
318 unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
319
320 return 0;
321 }
322
323 static int mark_symlink_for_removal(
324 Set **remove_symlinks_to,
325 const char *p) {
326
327 char *n;
328 int r;
329
330 assert(p);
331
332 r = set_ensure_allocated(remove_symlinks_to, &string_hash_ops);
333 if (r < 0)
334 return r;
335
336 n = strdup(p);
337 if (!n)
338 return -ENOMEM;
339
340 path_kill_slashes(n);
341
342 r = set_consume(*remove_symlinks_to, n);
343 if (r == -EEXIST)
344 return 0;
345 if (r < 0)
346 return r;
347
348 return 1;
349 }
350
351 static int remove_marked_symlinks_fd(
352 Set *remove_symlinks_to,
353 int fd,
354 const char *path,
355 const char *config_path,
356 bool *restart,
357 UnitFileChange **changes,
358 unsigned *n_changes) {
359
360 _cleanup_closedir_ DIR *d = NULL;
361 struct dirent *de;
362 int r = 0;
363
364 assert(remove_symlinks_to);
365 assert(fd >= 0);
366 assert(path);
367 assert(config_path);
368 assert(restart);
369
370 d = fdopendir(fd);
371 if (!d) {
372 safe_close(fd);
373 return -errno;
374 }
375
376 rewinddir(d);
377
378 FOREACH_DIRENT(de, d, return -errno) {
379
380 dirent_ensure_type(d, de);
381
382 if (de->d_type == DT_DIR) {
383 _cleanup_free_ char *p = NULL;
384 int nfd, q;
385
386 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
387 if (nfd < 0) {
388 if (errno == ENOENT)
389 continue;
390
391 if (r == 0)
392 r = -errno;
393 continue;
394 }
395
396 p = path_make_absolute(de->d_name, path);
397 if (!p) {
398 safe_close(nfd);
399 return -ENOMEM;
400 }
401
402 /* This will close nfd, regardless whether it succeeds or not */
403 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, restart, changes, n_changes);
404 if (q < 0 && r == 0)
405 r = q;
406
407 } else if (de->d_type == DT_LNK) {
408 _cleanup_free_ char *p = NULL, *dest = NULL;
409 bool found;
410 int q;
411
412 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
413 continue;
414
415 p = path_make_absolute(de->d_name, path);
416 if (!p)
417 return -ENOMEM;
418
419 q = readlink_malloc(p, &dest);
420 if (q < 0) {
421 if (q == -ENOENT)
422 continue;
423
424 if (r == 0)
425 r = q;
426 continue;
427 }
428
429 /* We remove all links pointing to a file or
430 * path that is marked, as well as all files
431 * sharing the same name as a file that is
432 * marked. */
433
434 found =
435 set_contains(remove_symlinks_to, dest) ||
436 set_contains(remove_symlinks_to, basename(dest)) ||
437 set_contains(remove_symlinks_to, de->d_name);
438
439 if (!found)
440 continue;
441
442 if (unlink(p) < 0 && errno != ENOENT) {
443 if (r == 0)
444 r = -errno;
445 continue;
446 }
447
448 path_kill_slashes(p);
449 (void) rmdir_parents(p, config_path);
450
451 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
452
453 q = mark_symlink_for_removal(&remove_symlinks_to, p);
454 if (q < 0)
455 return q;
456 if (q > 0)
457 *restart = true;
458 }
459 }
460
461 return r;
462 }
463
464 static int remove_marked_symlinks(
465 Set *remove_symlinks_to,
466 const char *config_path,
467 UnitFileChange **changes,
468 unsigned *n_changes) {
469
470 _cleanup_close_ int fd = -1;
471 bool restart;
472 int r = 0;
473
474 assert(config_path);
475
476 if (set_size(remove_symlinks_to) <= 0)
477 return 0;
478
479 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
480 if (fd < 0)
481 return -errno;
482
483 do {
484 int q, cfd;
485 restart = false;
486
487 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
488 if (cfd < 0)
489 return -errno;
490
491 /* This takes possession of cfd and closes it */
492 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &restart, changes, n_changes);
493 if (r == 0)
494 r = q;
495 } while (restart);
496
497 return r;
498 }
499
500 static int find_symlinks_fd(
501 const char *root_dir,
502 const char *name,
503 int fd,
504 const char *path,
505 const char *config_path,
506 bool *same_name_link) {
507
508 _cleanup_closedir_ DIR *d = NULL;
509 struct dirent *de;
510 int r = 0;
511
512 assert(name);
513 assert(fd >= 0);
514 assert(path);
515 assert(config_path);
516 assert(same_name_link);
517
518 d = fdopendir(fd);
519 if (!d) {
520 safe_close(fd);
521 return -errno;
522 }
523
524 FOREACH_DIRENT(de, d, return -errno) {
525
526 dirent_ensure_type(d, de);
527
528 if (de->d_type == DT_DIR) {
529 _cleanup_free_ char *p = NULL;
530 int nfd, q;
531
532 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
533 if (nfd < 0) {
534 if (errno == ENOENT)
535 continue;
536
537 if (r == 0)
538 r = -errno;
539 continue;
540 }
541
542 p = path_make_absolute(de->d_name, path);
543 if (!p) {
544 safe_close(nfd);
545 return -ENOMEM;
546 }
547
548 /* This will close nfd, regardless whether it succeeds or not */
549 q = find_symlinks_fd(root_dir, name, nfd, p, config_path, same_name_link);
550 if (q > 0)
551 return 1;
552 if (r == 0)
553 r = q;
554
555 } else if (de->d_type == DT_LNK) {
556 _cleanup_free_ char *p = NULL, *dest = NULL;
557 bool found_path, found_dest, b = false;
558 int q;
559
560 /* Acquire symlink name */
561 p = path_make_absolute(de->d_name, path);
562 if (!p)
563 return -ENOMEM;
564
565 /* Acquire symlink destination */
566 q = readlink_malloc(p, &dest);
567 if (q == -ENOENT)
568 continue;
569 if (q < 0) {
570 if (r == 0)
571 r = q;
572 continue;
573 }
574
575 /* Make absolute */
576 if (!path_is_absolute(dest)) {
577 char *x;
578
579 x = prefix_root(root_dir, dest);
580 if (!x)
581 return -ENOMEM;
582
583 free(dest);
584 dest = x;
585 }
586
587 /* Check if the symlink itself matches what we
588 * are looking for */
589 if (path_is_absolute(name))
590 found_path = path_equal(p, name);
591 else
592 found_path = streq(de->d_name, name);
593
594 /* Check if what the symlink points to
595 * matches what we are looking for */
596 if (path_is_absolute(name))
597 found_dest = path_equal(dest, name);
598 else
599 found_dest = streq(basename(dest), name);
600
601 if (found_path && found_dest) {
602 _cleanup_free_ char *t = NULL;
603
604 /* Filter out same name links in the main
605 * config path */
606 t = path_make_absolute(name, config_path);
607 if (!t)
608 return -ENOMEM;
609
610 b = path_equal(t, p);
611 }
612
613 if (b)
614 *same_name_link = true;
615 else if (found_path || found_dest)
616 return 1;
617 }
618 }
619
620 return r;
621 }
622
623 static int find_symlinks(
624 const char *root_dir,
625 const char *name,
626 const char *config_path,
627 bool *same_name_link) {
628
629 int fd;
630
631 assert(name);
632 assert(config_path);
633 assert(same_name_link);
634
635 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
636 if (fd < 0) {
637 if (errno == ENOENT)
638 return 0;
639 return -errno;
640 }
641
642 /* This takes possession of fd and closes it */
643 return find_symlinks_fd(root_dir, name, fd, config_path, config_path, same_name_link);
644 }
645
646 static int find_symlinks_in_scope(
647 UnitFileScope scope,
648 const char *root_dir,
649 const char *name,
650 UnitFileState *state) {
651
652 _cleanup_free_ char *normal_path = NULL, *runtime_path = NULL;
653 bool same_name_link_runtime = false, same_name_link = false;
654 int r;
655
656 assert(scope >= 0);
657 assert(scope < _UNIT_FILE_SCOPE_MAX);
658 assert(name);
659
660 /* First look in the normal config path */
661 r = get_config_path(scope, false, root_dir, &normal_path);
662 if (r < 0)
663 return r;
664
665 r = find_symlinks(root_dir, name, normal_path, &same_name_link);
666 if (r < 0)
667 return r;
668 if (r > 0) {
669 *state = UNIT_FILE_ENABLED;
670 return r;
671 }
672
673 /* Then look in runtime config path */
674 r = get_config_path(scope, true, root_dir, &runtime_path);
675 if (r < 0)
676 return r;
677
678 r = find_symlinks(root_dir, name, runtime_path, &same_name_link_runtime);
679 if (r < 0)
680 return r;
681 if (r > 0) {
682 *state = UNIT_FILE_ENABLED_RUNTIME;
683 return r;
684 }
685
686 /* Hmm, we didn't find it, but maybe we found the same name
687 * link? */
688 if (same_name_link) {
689 *state = UNIT_FILE_LINKED;
690 return 1;
691 }
692 if (same_name_link_runtime) {
693 *state = UNIT_FILE_LINKED_RUNTIME;
694 return 1;
695 }
696
697 return 0;
698 }
699
700 static void install_info_free(UnitFileInstallInfo *i) {
701
702 if (!i)
703 return;
704
705 free(i->name);
706 free(i->path);
707 strv_free(i->aliases);
708 strv_free(i->wanted_by);
709 strv_free(i->required_by);
710 strv_free(i->also);
711 free(i->default_instance);
712 free(i->symlink_target);
713 free(i);
714 }
715
716 static OrderedHashmap* install_info_hashmap_free(OrderedHashmap *m) {
717 UnitFileInstallInfo *i;
718
719 if (!m)
720 return NULL;
721
722 while ((i = ordered_hashmap_steal_first(m)))
723 install_info_free(i);
724
725 return ordered_hashmap_free(m);
726 }
727
728 static void install_context_done(InstallContext *c) {
729 assert(c);
730
731 c->will_process = install_info_hashmap_free(c->will_process);
732 c->have_processed = install_info_hashmap_free(c->have_processed);
733 }
734
735 static UnitFileInstallInfo *install_info_find(InstallContext *c, const char *name) {
736 UnitFileInstallInfo *i;
737
738 i = ordered_hashmap_get(c->have_processed, name);
739 if (i)
740 return i;
741
742 return ordered_hashmap_get(c->will_process, name);
743 }
744
745 static int install_info_add(
746 InstallContext *c,
747 const char *name,
748 const char *path,
749 UnitFileInstallInfo **ret) {
750
751 UnitFileInstallInfo *i = NULL;
752 int r;
753
754 assert(c);
755 assert(name || path);
756
757 if (!name)
758 name = basename(path);
759
760 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
761 return -EINVAL;
762
763 i = install_info_find(c, name);
764 if (i) {
765 if (ret)
766 *ret = i;
767 return 0;
768 }
769
770 r = ordered_hashmap_ensure_allocated(&c->will_process, &string_hash_ops);
771 if (r < 0)
772 return r;
773
774 i = new0(UnitFileInstallInfo, 1);
775 if (!i)
776 return -ENOMEM;
777 i->type = _UNIT_FILE_TYPE_INVALID;
778
779 i->name = strdup(name);
780 if (!i->name) {
781 r = -ENOMEM;
782 goto fail;
783 }
784
785 if (path) {
786 i->path = strdup(path);
787 if (!i->path) {
788 r = -ENOMEM;
789 goto fail;
790 }
791 }
792
793 r = ordered_hashmap_put(c->will_process, i->name, i);
794 if (r < 0)
795 goto fail;
796
797 if (ret)
798 *ret = i;
799
800 return 0;
801
802 fail:
803 install_info_free(i);
804 return r;
805 }
806
807 static int install_info_add_auto(
808 InstallContext *c,
809 const char *name_or_path,
810 UnitFileInstallInfo **ret) {
811
812 assert(c);
813 assert(name_or_path);
814
815 if (path_is_absolute(name_or_path))
816 return install_info_add(c, NULL, name_or_path, ret);
817 else
818 return install_info_add(c, name_or_path, NULL, ret);
819 }
820
821 static int config_parse_also(
822 const char *unit,
823 const char *filename,
824 unsigned line,
825 const char *section,
826 unsigned section_line,
827 const char *lvalue,
828 int ltype,
829 const char *rvalue,
830 void *data,
831 void *userdata) {
832
833 UnitFileInstallInfo *i = userdata;
834 InstallContext *c = data;
835 int r;
836
837 assert(filename);
838 assert(lvalue);
839 assert(rvalue);
840
841 for (;;) {
842 _cleanup_free_ char *word = NULL;
843
844 r = extract_first_word(&rvalue, &word, NULL, 0);
845 if (r < 0)
846 return r;
847 if (r == 0)
848 break;
849
850 r = install_info_add(c, word, NULL, NULL);
851 if (r < 0)
852 return r;
853
854 r = strv_push(&i->also, word);
855 if (r < 0)
856 return r;
857
858 word = NULL;
859 }
860
861 return 0;
862 }
863
864 static int config_parse_default_instance(
865 const char *unit,
866 const char *filename,
867 unsigned line,
868 const char *section,
869 unsigned section_line,
870 const char *lvalue,
871 int ltype,
872 const char *rvalue,
873 void *data,
874 void *userdata) {
875
876 UnitFileInstallInfo *i = data;
877 char *printed;
878 int r;
879
880 assert(filename);
881 assert(lvalue);
882 assert(rvalue);
883
884 r = install_full_printf(i, rvalue, &printed);
885 if (r < 0)
886 return r;
887
888 if (!unit_instance_is_valid(printed)) {
889 free(printed);
890 return -EINVAL;
891 }
892
893 free(i->default_instance);
894 i->default_instance = printed;
895
896 return 0;
897 }
898
899 static int unit_file_load(
900 InstallContext *c,
901 UnitFileInstallInfo *info,
902 const char *path,
903 const char *root_dir,
904 SearchFlags flags) {
905
906 const ConfigTableItem items[] = {
907 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
908 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
909 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
910 { "Install", "DefaultInstance", config_parse_default_instance, 0, info },
911 { "Install", "Also", config_parse_also, 0, c },
912 {}
913 };
914
915 _cleanup_fclose_ FILE *f = NULL;
916 _cleanup_close_ int fd = -1;
917 struct stat st;
918 int r;
919
920 assert(c);
921 assert(info);
922 assert(path);
923
924 path = prefix_roota(root_dir, path);
925
926 if (!(flags & SEARCH_LOAD)) {
927 r = lstat(path, &st);
928 if (r < 0)
929 return -errno;
930
931 if (null_or_empty(&st))
932 info->type = UNIT_FILE_TYPE_MASKED;
933 else if (S_ISREG(st.st_mode))
934 info->type = UNIT_FILE_TYPE_REGULAR;
935 else if (S_ISLNK(st.st_mode))
936 return -ELOOP;
937 else if (S_ISDIR(st.st_mode))
938 return -EISDIR;
939 else
940 return -ENOTTY;
941
942 return 0;
943 }
944
945 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
946 if (fd < 0)
947 return -errno;
948 if (fstat(fd, &st) < 0)
949 return -errno;
950 if (null_or_empty(&st)) {
951 info->type = UNIT_FILE_TYPE_MASKED;
952 return 0;
953 }
954 if (S_ISDIR(st.st_mode))
955 return -EISDIR;
956 if (!S_ISREG(st.st_mode))
957 return -ENOTTY;
958
959 f = fdopen(fd, "re");
960 if (!f)
961 return -errno;
962 fd = -1;
963
964 r = config_parse(NULL, path, f,
965 NULL,
966 config_item_table_lookup, items,
967 true, true, false, info);
968 if (r < 0)
969 return r;
970
971 info->type = UNIT_FILE_TYPE_REGULAR;
972
973 return
974 (int) strv_length(info->aliases) +
975 (int) strv_length(info->wanted_by) +
976 (int) strv_length(info->required_by);
977 }
978
979 static int unit_file_load_or_readlink(
980 InstallContext *c,
981 UnitFileInstallInfo *info,
982 const char *path,
983 const char *root_dir,
984 SearchFlags flags) {
985
986 _cleanup_free_ char *np = NULL;
987 int r;
988
989 r = unit_file_load(c, info, path, root_dir, flags);
990 if (r != -ELOOP)
991 return r;
992
993 /* This is a symlink, let's read it. */
994
995 r = readlink_and_make_absolute_root(root_dir, path, &np);
996 if (r < 0)
997 return r;
998
999 if (path_equal(np, "/dev/null"))
1000 info->type = UNIT_FILE_TYPE_MASKED;
1001 else {
1002 const char *bn;
1003 UnitType a, b;
1004
1005 bn = basename(np);
1006
1007 if (unit_name_is_valid(info->name, UNIT_NAME_PLAIN)) {
1008
1009 if (!unit_name_is_valid(bn, UNIT_NAME_PLAIN))
1010 return -EINVAL;
1011
1012 } else if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
1013
1014 if (!unit_name_is_valid(bn, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE))
1015 return -EINVAL;
1016
1017 } else if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE)) {
1018
1019 if (!unit_name_is_valid(bn, UNIT_NAME_TEMPLATE))
1020 return -EINVAL;
1021 } else
1022 return -EINVAL;
1023
1024 /* Enforce that the symlink destination does not
1025 * change the unit file type. */
1026
1027 a = unit_name_to_type(info->name);
1028 b = unit_name_to_type(bn);
1029 if (a < 0 || b < 0 || a != b)
1030 return -EINVAL;
1031
1032 info->type = UNIT_FILE_TYPE_SYMLINK;
1033 info->symlink_target = np;
1034 np = NULL;
1035 }
1036
1037 return 0;
1038 }
1039
1040 static int unit_file_search(
1041 InstallContext *c,
1042 UnitFileInstallInfo *info,
1043 const LookupPaths *paths,
1044 const char *root_dir,
1045 SearchFlags flags) {
1046
1047 char **p;
1048 int r;
1049
1050 assert(c);
1051 assert(info);
1052 assert(paths);
1053
1054 /* Was this unit already loaded? */
1055 if (info->type != _UNIT_FILE_TYPE_INVALID)
1056 return 0;
1057
1058 if (info->path)
1059 return unit_file_load_or_readlink(c, info, info->path, root_dir, flags);
1060
1061 assert(info->name);
1062
1063 STRV_FOREACH(p, paths->unit_path) {
1064 _cleanup_free_ char *path = NULL;
1065
1066 path = strjoin(*p, "/", info->name, NULL);
1067 if (!path)
1068 return -ENOMEM;
1069
1070 r = unit_file_load_or_readlink(c, info, path, root_dir, flags);
1071 if (r < 0) {
1072 if (r != -ENOENT)
1073 return r;
1074 } else {
1075 info->path = path;
1076 path = NULL;
1077 return r;
1078 }
1079 }
1080
1081 if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
1082
1083 /* Unit file doesn't exist, however instance
1084 * enablement was requested. We will check if it is
1085 * possible to load template unit file. */
1086
1087 _cleanup_free_ char *template = NULL;
1088
1089 r = unit_name_template(info->name, &template);
1090 if (r < 0)
1091 return r;
1092
1093 STRV_FOREACH(p, paths->unit_path) {
1094 _cleanup_free_ char *path = NULL;
1095
1096 path = strjoin(*p, "/", template, NULL);
1097 if (!path)
1098 return -ENOMEM;
1099
1100 r = unit_file_load_or_readlink(c, info, path, root_dir, flags);
1101 if (r < 0) {
1102 if (r != -ENOENT)
1103 return r;
1104 } else {
1105 info->path = path;
1106 path = NULL;
1107 return r;
1108 }
1109 }
1110 }
1111
1112 return -ENOENT;
1113 }
1114
1115 static int install_info_follow(
1116 InstallContext *c,
1117 UnitFileInstallInfo *i,
1118 const char *root_dir,
1119 SearchFlags flags) {
1120
1121 assert(c);
1122 assert(i);
1123
1124 if (i->type != UNIT_FILE_TYPE_SYMLINK)
1125 return -EINVAL;
1126 if (!i->symlink_target)
1127 return -EINVAL;
1128
1129 /* If the basename doesn't match, the caller should add a
1130 * complete new entry for this. */
1131
1132 if (!streq(basename(i->symlink_target), i->name))
1133 return -EXDEV;
1134
1135 free(i->path);
1136 i->path = i->symlink_target;
1137 i->symlink_target = NULL;
1138 i->type = _UNIT_FILE_TYPE_INVALID;
1139
1140 return unit_file_load_or_readlink(c, i, i->path, root_dir, flags);
1141 }
1142
1143 static int install_info_traverse(
1144 UnitFileScope scope,
1145 InstallContext *c,
1146 const char *root_dir,
1147 const LookupPaths *paths,
1148 UnitFileInstallInfo *start,
1149 SearchFlags flags,
1150 UnitFileInstallInfo **ret) {
1151
1152 UnitFileInstallInfo *i;
1153 unsigned k = 0;
1154 int r;
1155
1156 assert(paths);
1157 assert(start);
1158 assert(c);
1159
1160 r = unit_file_search(c, start, paths, root_dir, flags);
1161 if (r < 0)
1162 return r;
1163
1164 i = start;
1165 while (i->type == UNIT_FILE_TYPE_SYMLINK) {
1166 /* Follow the symlink */
1167
1168 if (++k > UNIT_FILE_FOLLOW_SYMLINK_MAX)
1169 return -ELOOP;
1170
1171 if (!(flags & SEARCH_FOLLOW_CONFIG_SYMLINKS) && is_config_path(scope, i->path))
1172 return -ELOOP;
1173
1174 r = install_info_follow(c, i, root_dir, flags);
1175 if (r < 0) {
1176 _cleanup_free_ char *buffer = NULL;
1177 const char *bn;
1178
1179 if (r != -EXDEV)
1180 return r;
1181
1182 /* Target has a different name, create a new
1183 * install info object for that, and continue
1184 * with that. */
1185
1186 bn = basename(i->symlink_target);
1187
1188 if (unit_name_is_valid(i->name, UNIT_NAME_INSTANCE) &&
1189 unit_name_is_valid(bn, UNIT_NAME_TEMPLATE)) {
1190
1191 _cleanup_free_ char *instance = NULL;
1192
1193 r = unit_name_to_instance(i->name, &instance);
1194 if (r < 0)
1195 return r;
1196
1197 r = unit_name_replace_instance(bn, instance, &buffer);
1198 if (r < 0)
1199 return r;
1200
1201 bn = buffer;
1202 }
1203
1204 r = install_info_add(c, bn, NULL, &i);
1205 if (r < 0)
1206 return r;
1207
1208 r = unit_file_search(c, i, paths, root_dir, flags);
1209 if (r < 0)
1210 return r;
1211 }
1212
1213 /* Try again, with the new target we found. */
1214 }
1215
1216 if (ret)
1217 *ret = i;
1218
1219 return 0;
1220 }
1221
1222 static int install_info_discover(
1223 UnitFileScope scope,
1224 InstallContext *c,
1225 const char *root_dir,
1226 const LookupPaths *paths,
1227 const char *name,
1228 SearchFlags flags,
1229 UnitFileInstallInfo **ret) {
1230
1231 UnitFileInstallInfo *i;
1232 int r;
1233
1234 assert(c);
1235 assert(paths);
1236 assert(name);
1237
1238 r = install_info_add_auto(c, name, &i);
1239 if (r < 0)
1240 return r;
1241
1242 return install_info_traverse(scope, c, root_dir, paths, i, flags, ret);
1243 }
1244
1245 static int install_info_symlink_alias(
1246 UnitFileInstallInfo *i,
1247 const char *config_path,
1248 bool force,
1249 UnitFileChange **changes,
1250 unsigned *n_changes) {
1251
1252 char **s;
1253 int r = 0, q;
1254
1255 assert(i);
1256 assert(config_path);
1257
1258 STRV_FOREACH(s, i->aliases) {
1259 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1260
1261 q = install_full_printf(i, *s, &dst);
1262 if (q < 0)
1263 return q;
1264
1265 alias_path = path_make_absolute(dst, config_path);
1266 if (!alias_path)
1267 return -ENOMEM;
1268
1269 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1270 if (r == 0)
1271 r = q;
1272 }
1273
1274 return r;
1275 }
1276
1277 static int install_info_symlink_wants(
1278 UnitFileInstallInfo *i,
1279 const char *config_path,
1280 char **list,
1281 const char *suffix,
1282 bool force,
1283 UnitFileChange **changes,
1284 unsigned *n_changes) {
1285
1286 _cleanup_free_ char *buf = NULL;
1287 const char *n;
1288 char **s;
1289 int r = 0, q;
1290
1291 assert(i);
1292 assert(config_path);
1293
1294 if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE)) {
1295
1296 /* Don't install any symlink if there's no default
1297 * instance configured */
1298
1299 if (!i->default_instance)
1300 return 0;
1301
1302 r = unit_name_replace_instance(i->name, i->default_instance, &buf);
1303 if (r < 0)
1304 return r;
1305
1306 n = buf;
1307 } else
1308 n = i->name;
1309
1310 STRV_FOREACH(s, list) {
1311 _cleanup_free_ char *path = NULL, *dst = NULL;
1312
1313 q = install_full_printf(i, *s, &dst);
1314 if (q < 0)
1315 return q;
1316
1317 if (!unit_name_is_valid(dst, UNIT_NAME_ANY)) {
1318 r = -EINVAL;
1319 continue;
1320 }
1321
1322 path = strjoin(config_path, "/", dst, suffix, n, NULL);
1323 if (!path)
1324 return -ENOMEM;
1325
1326 q = create_symlink(i->path, path, force, changes, n_changes);
1327 if (r == 0)
1328 r = q;
1329 }
1330
1331 return r;
1332 }
1333
1334 static int install_info_symlink_link(
1335 UnitFileInstallInfo *i,
1336 const LookupPaths *paths,
1337 const char *config_path,
1338 const char *root_dir,
1339 bool force,
1340 UnitFileChange **changes,
1341 unsigned *n_changes) {
1342
1343 _cleanup_free_ char *path = NULL;
1344 int r;
1345
1346 assert(i);
1347 assert(paths);
1348 assert(config_path);
1349 assert(i->path);
1350
1351 r = in_search_path(i->path, paths->unit_path);
1352 if (r != 0)
1353 return r;
1354
1355 path = strjoin(config_path, "/", i->name, NULL);
1356 if (!path)
1357 return -ENOMEM;
1358
1359 return create_symlink(i->path, path, force, changes, n_changes);
1360 }
1361
1362 static int install_info_apply(
1363 UnitFileInstallInfo *i,
1364 const LookupPaths *paths,
1365 const char *config_path,
1366 const char *root_dir,
1367 bool force,
1368 UnitFileChange **changes,
1369 unsigned *n_changes) {
1370
1371 int r, q;
1372
1373 assert(i);
1374 assert(paths);
1375 assert(config_path);
1376
1377 if (i->type != UNIT_FILE_TYPE_REGULAR)
1378 return 0;
1379
1380 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1381
1382 q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes);
1383 if (r == 0)
1384 r = q;
1385
1386 q = install_info_symlink_wants(i, config_path, i->required_by, ".requires/", force, changes, n_changes);
1387 if (r == 0)
1388 r = q;
1389
1390 q = install_info_symlink_link(i, paths, config_path, root_dir, force, changes, n_changes);
1391 if (r == 0)
1392 r = q;
1393
1394 return r;
1395 }
1396
1397 static int install_context_apply(
1398 UnitFileScope scope,
1399 InstallContext *c,
1400 const LookupPaths *paths,
1401 const char *config_path,
1402 const char *root_dir,
1403 bool force,
1404 SearchFlags flags,
1405 UnitFileChange **changes,
1406 unsigned *n_changes) {
1407
1408 UnitFileInstallInfo *i;
1409 int r;
1410
1411 assert(c);
1412 assert(paths);
1413 assert(config_path);
1414
1415 if (ordered_hashmap_isempty(c->will_process))
1416 return 0;
1417
1418 r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops);
1419 if (r < 0)
1420 return r;
1421
1422 r = 0;
1423 while ((i = ordered_hashmap_first(c->will_process))) {
1424 int q;
1425
1426 q = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name);
1427 if (q < 0)
1428 return q;
1429
1430 r = install_info_traverse(scope, c, root_dir, paths, i, flags, NULL);
1431 if (r < 0)
1432 return r;
1433
1434 if (i->type != UNIT_FILE_TYPE_REGULAR)
1435 continue;
1436
1437 q = install_info_apply(i, paths, config_path, root_dir, force, changes, n_changes);
1438 if (r >= 0) {
1439 if (q < 0)
1440 r = q;
1441 else
1442 r+= q;
1443 }
1444 }
1445
1446 return r;
1447 }
1448
1449 static int install_context_mark_for_removal(
1450 UnitFileScope scope,
1451 InstallContext *c,
1452 const LookupPaths *paths,
1453 Set **remove_symlinks_to,
1454 const char *config_path,
1455 const char *root_dir) {
1456
1457 UnitFileInstallInfo *i;
1458 int r;
1459
1460 assert(c);
1461 assert(paths);
1462 assert(config_path);
1463
1464 /* Marks all items for removal */
1465
1466 if (ordered_hashmap_isempty(c->will_process))
1467 return 0;
1468
1469 r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops);
1470 if (r < 0)
1471 return r;
1472
1473 while ((i = ordered_hashmap_first(c->will_process))) {
1474
1475 r = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name);
1476 if (r < 0)
1477 return r;
1478
1479 r = install_info_traverse(scope, c, root_dir, paths, i, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, NULL);
1480 if (r < 0)
1481 return r;
1482
1483 if (i->type != UNIT_FILE_TYPE_REGULAR)
1484 continue;
1485
1486 r = mark_symlink_for_removal(remove_symlinks_to, i->name);
1487 if (r < 0)
1488 return r;
1489 }
1490
1491 return 0;
1492 }
1493
1494 int unit_file_mask(
1495 UnitFileScope scope,
1496 bool runtime,
1497 const char *root_dir,
1498 char **files,
1499 bool force,
1500 UnitFileChange **changes,
1501 unsigned *n_changes) {
1502
1503 _cleanup_free_ char *prefix = NULL;
1504 char **i;
1505 int r;
1506
1507 assert(scope >= 0);
1508 assert(scope < _UNIT_FILE_SCOPE_MAX);
1509
1510 r = verify_root_dir(scope, &root_dir);
1511 if (r < 0)
1512 return r;
1513
1514 r = get_config_path(scope, runtime, root_dir, &prefix);
1515 if (r < 0)
1516 return r;
1517
1518 STRV_FOREACH(i, files) {
1519 _cleanup_free_ char *path = NULL;
1520 int q;
1521
1522 if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) {
1523 if (r == 0)
1524 r = -EINVAL;
1525 continue;
1526 }
1527
1528 path = path_make_absolute(*i, prefix);
1529 if (!path)
1530 return -ENOMEM;
1531
1532 q = create_symlink("/dev/null", path, force, changes, n_changes);
1533 if (q < 0 && r >= 0)
1534 r = q;
1535 }
1536
1537 return r;
1538 }
1539
1540 int unit_file_unmask(
1541 UnitFileScope scope,
1542 bool runtime,
1543 const char *root_dir,
1544 char **files,
1545 UnitFileChange **changes,
1546 unsigned *n_changes) {
1547
1548 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1549 _cleanup_free_ char *config_path = NULL;
1550 _cleanup_free_ char **todo = NULL;
1551 size_t n_todo = 0, n_allocated = 0;
1552 char **i;
1553 int r, q;
1554
1555 assert(scope >= 0);
1556 assert(scope < _UNIT_FILE_SCOPE_MAX);
1557
1558 r = verify_root_dir(scope, &root_dir);
1559 if (r < 0)
1560 return r;
1561
1562 r = get_config_path(scope, runtime, root_dir, &config_path);
1563 if (r < 0)
1564 return r;
1565
1566 STRV_FOREACH(i, files) {
1567 _cleanup_free_ char *path = NULL;
1568
1569 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
1570 return -EINVAL;
1571
1572 path = path_make_absolute(*i, config_path);
1573 if (!path)
1574 return -ENOMEM;
1575
1576 r = null_or_empty_path(path);
1577 if (r == -ENOENT)
1578 continue;
1579 if (r < 0)
1580 return r;
1581 if (r == 0)
1582 continue;
1583
1584 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
1585 return -ENOMEM;
1586
1587 todo[n_todo++] = *i;
1588 }
1589
1590 strv_uniq(todo);
1591
1592 r = 0;
1593 STRV_FOREACH(i, todo) {
1594 _cleanup_free_ char *path = NULL;
1595
1596 path = path_make_absolute(*i, config_path);
1597 if (!path)
1598 return -ENOMEM;
1599
1600 if (unlink(path) < 0) {
1601 if (errno != -ENOENT && r >= 0)
1602 r = -errno;
1603 } else {
1604 q = mark_symlink_for_removal(&remove_symlinks_to, path);
1605 if (q < 0)
1606 return q;
1607
1608 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
1609 }
1610 }
1611
1612 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);
1613 if (r >= 0)
1614 r = q;
1615
1616 return r;
1617 }
1618
1619 int unit_file_link(
1620 UnitFileScope scope,
1621 bool runtime,
1622 const char *root_dir,
1623 char **files,
1624 bool force,
1625 UnitFileChange **changes,
1626 unsigned *n_changes) {
1627
1628 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1629 _cleanup_free_ char *config_path = NULL;
1630 _cleanup_free_ char **todo = NULL;
1631 size_t n_todo = 0, n_allocated = 0;
1632 char **i;
1633 int r, q;
1634
1635 assert(scope >= 0);
1636 assert(scope < _UNIT_FILE_SCOPE_MAX);
1637
1638 r = verify_root_dir(scope, &root_dir);
1639 if (r < 0)
1640 return r;
1641
1642 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1643 if (r < 0)
1644 return r;
1645
1646 r = get_config_path(scope, runtime, root_dir, &config_path);
1647 if (r < 0)
1648 return r;
1649
1650 STRV_FOREACH(i, files) {
1651 _cleanup_free_ char *full = NULL;
1652 struct stat st;
1653 char *fn;
1654
1655 if (!path_is_absolute(*i))
1656 return -EINVAL;
1657
1658 fn = basename(*i);
1659 if (!unit_name_is_valid(fn, UNIT_NAME_ANY))
1660 return -EINVAL;
1661
1662 full = prefix_root(root_dir, *i);
1663 if (!full)
1664 return -ENOMEM;
1665
1666 if (lstat(full, &st) < 0)
1667 return -errno;
1668 if (S_ISLNK(st.st_mode))
1669 return -ELOOP;
1670 if (S_ISDIR(st.st_mode))
1671 return -EISDIR;
1672 if (!S_ISREG(st.st_mode))
1673 return -ENOTTY;
1674
1675 q = in_search_path(*i, paths.unit_path);
1676 if (q < 0)
1677 return q;
1678 if (q > 0)
1679 continue;
1680
1681 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
1682 return -ENOMEM;
1683
1684 todo[n_todo++] = *i;
1685 }
1686
1687 strv_uniq(todo);
1688
1689 r = 0;
1690 STRV_FOREACH(i, todo) {
1691 _cleanup_free_ char *path = NULL;
1692
1693 path = path_make_absolute(basename(*i), config_path);
1694 if (!path)
1695 return -ENOMEM;
1696
1697 q = create_symlink(*i, path, force, changes, n_changes);
1698 if (q < 0 && r >= 0)
1699 r = q;
1700 }
1701
1702 return r;
1703 }
1704
1705 int unit_file_add_dependency(
1706 UnitFileScope scope,
1707 bool runtime,
1708 const char *root_dir,
1709 char **files,
1710 const char *target,
1711 UnitDependency dep,
1712 bool force,
1713 UnitFileChange **changes,
1714 unsigned *n_changes) {
1715
1716 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1717 _cleanup_(install_context_done) InstallContext c = {};
1718 _cleanup_free_ char *config_path = NULL;
1719 UnitFileInstallInfo *i, *target_info;
1720 char **f;
1721 int r;
1722
1723 assert(scope >= 0);
1724 assert(scope < _UNIT_FILE_SCOPE_MAX);
1725 assert(target);
1726
1727 if (!IN_SET(dep, UNIT_WANTS, UNIT_REQUIRES))
1728 return -EINVAL;
1729
1730 if (!unit_name_is_valid(target, UNIT_NAME_ANY))
1731 return -EINVAL;
1732
1733 r = verify_root_dir(scope, &root_dir);
1734 if (r < 0)
1735 return r;
1736
1737 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1738 if (r < 0)
1739 return r;
1740
1741 r = get_config_path(scope, runtime, root_dir, &config_path);
1742 if (r < 0)
1743 return r;
1744
1745 r = install_info_discover(scope, &c, root_dir, &paths, target, SEARCH_FOLLOW_CONFIG_SYMLINKS, &target_info);
1746 if (r < 0)
1747 return r;
1748 if (target_info->type == UNIT_FILE_TYPE_MASKED)
1749 return -ESHUTDOWN;
1750
1751 assert(target_info->type == UNIT_FILE_TYPE_REGULAR);
1752
1753 STRV_FOREACH(f, files) {
1754 char ***l;
1755
1756 r = install_info_discover(scope, &c, root_dir, &paths, *f, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
1757 if (r < 0)
1758 return r;
1759 if (i->type == UNIT_FILE_TYPE_MASKED)
1760 return -ESHUTDOWN;
1761
1762 assert(i->type == UNIT_FILE_TYPE_REGULAR);
1763
1764 /* We didn't actually load anything from the unit
1765 * file, but instead just add in our new symlink to
1766 * create. */
1767
1768 if (dep == UNIT_WANTS)
1769 l = &i->wanted_by;
1770 else
1771 l = &i->required_by;
1772
1773 strv_free(*l);
1774 *l = strv_new(target_info->name, NULL);
1775 if (!*l)
1776 return -ENOMEM;
1777 }
1778
1779 return install_context_apply(scope, &c, &paths, config_path, root_dir, force, SEARCH_FOLLOW_CONFIG_SYMLINKS, changes, n_changes);
1780 }
1781
1782 int unit_file_enable(
1783 UnitFileScope scope,
1784 bool runtime,
1785 const char *root_dir,
1786 char **files,
1787 bool force,
1788 UnitFileChange **changes,
1789 unsigned *n_changes) {
1790
1791 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1792 _cleanup_(install_context_done) InstallContext c = {};
1793 _cleanup_free_ char *config_path = NULL;
1794 UnitFileInstallInfo *i;
1795 char **f;
1796 int r;
1797
1798 assert(scope >= 0);
1799 assert(scope < _UNIT_FILE_SCOPE_MAX);
1800
1801 r = verify_root_dir(scope, &root_dir);
1802 if (r < 0)
1803 return r;
1804
1805 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1806 if (r < 0)
1807 return r;
1808
1809 r = get_config_path(scope, runtime, root_dir, &config_path);
1810 if (r < 0)
1811 return r;
1812
1813 STRV_FOREACH(f, files) {
1814 r = install_info_discover(scope, &c, root_dir, &paths, *f, SEARCH_LOAD, &i);
1815 if (r < 0)
1816 return r;
1817 if (i->type == UNIT_FILE_TYPE_MASKED)
1818 return -ESHUTDOWN;
1819
1820 assert(i->type == UNIT_FILE_TYPE_REGULAR);
1821 }
1822
1823 /* This will return the number of symlink rules that were
1824 supposed to be created, not the ones actually created. This
1825 is useful to determine whether the passed files had any
1826 installation data at all. */
1827
1828 return install_context_apply(scope, &c, &paths, config_path, root_dir, force, SEARCH_LOAD, changes, n_changes);
1829 }
1830
1831 int unit_file_disable(
1832 UnitFileScope scope,
1833 bool runtime,
1834 const char *root_dir,
1835 char **files,
1836 UnitFileChange **changes,
1837 unsigned *n_changes) {
1838
1839 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1840 _cleanup_(install_context_done) InstallContext c = {};
1841 _cleanup_free_ char *config_path = NULL;
1842 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1843 char **i;
1844 int r;
1845
1846 assert(scope >= 0);
1847 assert(scope < _UNIT_FILE_SCOPE_MAX);
1848
1849 r = verify_root_dir(scope, &root_dir);
1850 if (r < 0)
1851 return r;
1852
1853 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1854 if (r < 0)
1855 return r;
1856
1857 r = get_config_path(scope, runtime, root_dir, &config_path);
1858 if (r < 0)
1859 return r;
1860
1861 STRV_FOREACH(i, files) {
1862 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
1863 return -EINVAL;
1864
1865 r = install_info_add(&c, *i, NULL, NULL);
1866 if (r < 0)
1867 return r;
1868 }
1869
1870 r = install_context_mark_for_removal(scope, &c, &paths, &remove_symlinks_to, config_path, root_dir);
1871 if (r < 0)
1872 return r;
1873
1874 return remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);
1875 }
1876
1877 int unit_file_reenable(
1878 UnitFileScope scope,
1879 bool runtime,
1880 const char *root_dir,
1881 char **files,
1882 bool force,
1883 UnitFileChange **changes,
1884 unsigned *n_changes) {
1885
1886 char **n;
1887 int r;
1888 size_t l, i;
1889
1890 /* First, we invoke the disable command with only the basename... */
1891 l = strv_length(files);
1892 n = newa(char*, l+1);
1893 for (i = 0; i < l; i++)
1894 n[i] = basename(files[i]);
1895 n[i] = NULL;
1896
1897 r = unit_file_disable(scope, runtime, root_dir, n, changes, n_changes);
1898 if (r < 0)
1899 return r;
1900
1901 /* But the enable command with the full name */
1902 return unit_file_enable(scope, runtime, root_dir, files, force, changes, n_changes);
1903 }
1904
1905 int unit_file_set_default(
1906 UnitFileScope scope,
1907 const char *root_dir,
1908 const char *name,
1909 bool force,
1910 UnitFileChange **changes,
1911 unsigned *n_changes) {
1912
1913 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1914 _cleanup_(install_context_done) InstallContext c = {};
1915 _cleanup_free_ char *config_path = NULL;
1916 UnitFileInstallInfo *i;
1917 const char *path;
1918 int r;
1919
1920 assert(scope >= 0);
1921 assert(scope < _UNIT_FILE_SCOPE_MAX);
1922 assert(name);
1923
1924 if (unit_name_to_type(name) != UNIT_TARGET)
1925 return -EINVAL;
1926 if (streq(name, SPECIAL_DEFAULT_TARGET))
1927 return -EINVAL;
1928
1929 r = verify_root_dir(scope, &root_dir);
1930 if (r < 0)
1931 return r;
1932
1933 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1934 if (r < 0)
1935 return r;
1936
1937 r = get_config_path(scope, false, root_dir, &config_path);
1938 if (r < 0)
1939 return r;
1940
1941 r = install_info_discover(scope, &c, root_dir, &paths, name, 0, &i);
1942 if (r < 0)
1943 return r;
1944 if (i->type == UNIT_FILE_TYPE_MASKED)
1945 return -ESHUTDOWN;
1946
1947 path = strjoina(config_path, "/" SPECIAL_DEFAULT_TARGET);
1948
1949 return create_symlink(i->path, path, force, changes, n_changes);
1950 }
1951
1952 int unit_file_get_default(
1953 UnitFileScope scope,
1954 const char *root_dir,
1955 char **name) {
1956
1957 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1958 _cleanup_(install_context_done) InstallContext c = {};
1959 UnitFileInstallInfo *i;
1960 char *n;
1961 int r;
1962
1963 assert(scope >= 0);
1964 assert(scope < _UNIT_FILE_SCOPE_MAX);
1965 assert(name);
1966
1967 r = verify_root_dir(scope, &root_dir);
1968 if (r < 0)
1969 return r;
1970
1971 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1972 if (r < 0)
1973 return r;
1974
1975 r = install_info_discover(scope, &c, root_dir, &paths, SPECIAL_DEFAULT_TARGET, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
1976 if (r < 0)
1977 return r;
1978 if (i->type == UNIT_FILE_TYPE_MASKED)
1979 return -ESHUTDOWN;
1980
1981 n = strdup(i->name);
1982 if (!n)
1983 return -ENOMEM;
1984
1985 *name = n;
1986 return 0;
1987 }
1988
1989 int unit_file_lookup_state(
1990 UnitFileScope scope,
1991 const char *root_dir,
1992 const LookupPaths *paths,
1993 const char *name,
1994 UnitFileState *ret) {
1995
1996 _cleanup_(install_context_done) InstallContext c = {};
1997 UnitFileInstallInfo *i;
1998 UnitFileState state;
1999 int r;
2000
2001 assert(paths);
2002 assert(name);
2003
2004 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
2005 return -EINVAL;
2006
2007 r = verify_root_dir(scope, &root_dir);
2008 if (r < 0)
2009 return r;
2010
2011 r = install_info_discover(scope, &c, root_dir, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
2012 if (r < 0)
2013 return r;
2014
2015 /* Shortcut things, if the caller just wants to know if this unit exists. */
2016 if (!ret)
2017 return 0;
2018
2019 switch (i->type) {
2020
2021 case UNIT_FILE_TYPE_MASKED:
2022 state = path_startswith(i->path, "/run") ? UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2023 break;
2024
2025 case UNIT_FILE_TYPE_REGULAR:
2026 r = find_symlinks_in_scope(scope, root_dir, i->name, &state);
2027 if (r < 0)
2028 return r;
2029 if (r == 0) {
2030 if (UNIT_FILE_INSTALL_INFO_HAS_RULES(i))
2031 state = UNIT_FILE_DISABLED;
2032 else if (UNIT_FILE_INSTALL_INFO_HAS_ALSO(i))
2033 state = UNIT_FILE_INDIRECT;
2034 else
2035 state = UNIT_FILE_STATIC;
2036 }
2037
2038 break;
2039
2040 default:
2041 assert_not_reached("Unexpect unit file type.");
2042 }
2043
2044 *ret = state;
2045 return 0;
2046 }
2047
2048 int unit_file_get_state(
2049 UnitFileScope scope,
2050 const char *root_dir,
2051 const char *name,
2052 UnitFileState *ret) {
2053
2054 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2055 int r;
2056
2057 assert(scope >= 0);
2058 assert(scope < _UNIT_FILE_SCOPE_MAX);
2059 assert(name);
2060
2061 r = verify_root_dir(scope, &root_dir);
2062 if (r < 0)
2063 return r;
2064
2065 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2066 if (r < 0)
2067 return r;
2068
2069 return unit_file_lookup_state(scope, root_dir, &paths, name, ret);
2070 }
2071
2072 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
2073 _cleanup_strv_free_ char **files = NULL;
2074 char **p;
2075 int r;
2076
2077 assert(scope >= 0);
2078 assert(scope < _UNIT_FILE_SCOPE_MAX);
2079 assert(name);
2080
2081 r = verify_root_dir(scope, &root_dir);
2082 if (r < 0)
2083 return r;
2084
2085 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
2086 return -EINVAL;
2087
2088 if (scope == UNIT_FILE_SYSTEM)
2089 r = conf_files_list(&files, ".preset", root_dir,
2090 "/etc/systemd/system-preset",
2091 "/usr/local/lib/systemd/system-preset",
2092 "/usr/lib/systemd/system-preset",
2093 #ifdef HAVE_SPLIT_USR
2094 "/lib/systemd/system-preset",
2095 #endif
2096 NULL);
2097 else if (scope == UNIT_FILE_GLOBAL)
2098 r = conf_files_list(&files, ".preset", root_dir,
2099 "/etc/systemd/user-preset",
2100 "/usr/local/lib/systemd/user-preset",
2101 "/usr/lib/systemd/user-preset",
2102 NULL);
2103 else
2104 return 1; /* Default is "enable" */
2105
2106 if (r < 0)
2107 return r;
2108
2109 STRV_FOREACH(p, files) {
2110 _cleanup_fclose_ FILE *f;
2111 char line[LINE_MAX];
2112
2113 f = fopen(*p, "re");
2114 if (!f) {
2115 if (errno == ENOENT)
2116 continue;
2117
2118 return -errno;
2119 }
2120
2121 FOREACH_LINE(line, f, return -errno) {
2122 const char *parameter;
2123 char *l;
2124
2125 l = strstrip(line);
2126
2127 if (isempty(l))
2128 continue;
2129 if (strchr(COMMENTS, *l))
2130 continue;
2131
2132 parameter = first_word(l, "enable");
2133 if (parameter) {
2134 if (fnmatch(parameter, name, FNM_NOESCAPE) == 0) {
2135 log_debug("Preset file says enable %s.", name);
2136 return 1;
2137 }
2138
2139 continue;
2140 }
2141
2142 parameter = first_word(l, "disable");
2143 if (parameter) {
2144 if (fnmatch(parameter, name, FNM_NOESCAPE) == 0) {
2145 log_debug("Preset file says disable %s.", name);
2146 return 0;
2147 }
2148
2149 continue;
2150 }
2151
2152 log_debug("Couldn't parse line '%s'", l);
2153 }
2154 }
2155
2156 /* Default is "enable" */
2157 log_debug("Preset file doesn't say anything about %s, enabling.", name);
2158 return 1;
2159 }
2160
2161 static int execute_preset(
2162 UnitFileScope scope,
2163 InstallContext *plus,
2164 InstallContext *minus,
2165 const LookupPaths *paths,
2166 const char *config_path,
2167 const char *root_dir,
2168 char **files,
2169 UnitFilePresetMode mode,
2170 bool force,
2171 UnitFileChange **changes,
2172 unsigned *n_changes) {
2173
2174 int r;
2175
2176 assert(plus);
2177 assert(minus);
2178 assert(paths);
2179 assert(config_path);
2180
2181 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2182 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2183
2184 r = install_context_mark_for_removal(scope, minus, paths, &remove_symlinks_to, config_path, root_dir);
2185 if (r < 0)
2186 return r;
2187
2188 r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);
2189 } else
2190 r = 0;
2191
2192 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2193 int q;
2194
2195 /* Returns number of symlinks that where supposed to be installed. */
2196 q = install_context_apply(scope, plus, paths, config_path, root_dir, force, SEARCH_LOAD, changes, n_changes);
2197 if (r >= 0) {
2198 if (q < 0)
2199 r = q;
2200 else
2201 r+= q;
2202 }
2203 }
2204
2205 return r;
2206 }
2207
2208 static int preset_prepare_one(
2209 UnitFileScope scope,
2210 InstallContext *plus,
2211 InstallContext *minus,
2212 LookupPaths *paths,
2213 const char *root_dir,
2214 UnitFilePresetMode mode,
2215 const char *name) {
2216
2217 UnitFileInstallInfo *i;
2218 int r;
2219
2220 if (install_info_find(plus, name) ||
2221 install_info_find(minus, name))
2222 return 0;
2223
2224 r = unit_file_query_preset(scope, root_dir, name);
2225 if (r < 0)
2226 return r;
2227
2228 if (r > 0) {
2229 r = install_info_discover(scope, plus, root_dir, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
2230 if (r < 0)
2231 return r;
2232
2233 if (i->type == UNIT_FILE_TYPE_MASKED)
2234 return -ESHUTDOWN;
2235 } else
2236 r = install_info_discover(scope, minus, root_dir, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
2237
2238 return r;
2239 }
2240
2241 int unit_file_preset(
2242 UnitFileScope scope,
2243 bool runtime,
2244 const char *root_dir,
2245 char **files,
2246 UnitFilePresetMode mode,
2247 bool force,
2248 UnitFileChange **changes,
2249 unsigned *n_changes) {
2250
2251 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
2252 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2253 _cleanup_free_ char *config_path = NULL;
2254 char **i;
2255 int r;
2256
2257 assert(scope >= 0);
2258 assert(scope < _UNIT_FILE_SCOPE_MAX);
2259 assert(mode < _UNIT_FILE_PRESET_MAX);
2260
2261 r = verify_root_dir(scope, &root_dir);
2262 if (r < 0)
2263 return r;
2264
2265 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2266 if (r < 0)
2267 return r;
2268
2269 r = get_config_path(scope, runtime, root_dir, &config_path);
2270 if (r < 0)
2271 return r;
2272
2273 STRV_FOREACH(i, files) {
2274 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
2275 return -EINVAL;
2276
2277 r = preset_prepare_one(scope, &plus, &minus, &paths, root_dir, mode, *i);
2278 if (r < 0)
2279 return r;
2280 }
2281
2282 return execute_preset(scope, &plus, &minus, &paths, config_path, root_dir, files, mode, force, changes, n_changes);
2283 }
2284
2285 int unit_file_preset_all(
2286 UnitFileScope scope,
2287 bool runtime,
2288 const char *root_dir,
2289 UnitFilePresetMode mode,
2290 bool force,
2291 UnitFileChange **changes,
2292 unsigned *n_changes) {
2293
2294 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
2295 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2296 _cleanup_free_ char *config_path = NULL;
2297 char **i;
2298 int r;
2299
2300 assert(scope >= 0);
2301 assert(scope < _UNIT_FILE_SCOPE_MAX);
2302 assert(mode < _UNIT_FILE_PRESET_MAX);
2303
2304 r = verify_root_dir(scope, &root_dir);
2305 if (r < 0)
2306 return r;
2307
2308 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2309 if (r < 0)
2310 return r;
2311
2312 r = get_config_path(scope, runtime, root_dir, &config_path);
2313 if (r < 0)
2314 return r;
2315
2316 STRV_FOREACH(i, paths.unit_path) {
2317 _cleanup_closedir_ DIR *d = NULL;
2318 _cleanup_free_ char *units_dir;
2319 struct dirent *de;
2320
2321 units_dir = path_join(root_dir, *i, NULL);
2322 if (!units_dir)
2323 return -ENOMEM;
2324
2325 d = opendir(units_dir);
2326 if (!d) {
2327 if (errno == ENOENT)
2328 continue;
2329
2330 return -errno;
2331 }
2332
2333 FOREACH_DIRENT(de, d, return -errno) {
2334
2335 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
2336 continue;
2337
2338 dirent_ensure_type(d, de);
2339
2340 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2341 continue;
2342
2343 r = preset_prepare_one(scope, &plus, &minus, &paths, root_dir, mode, de->d_name);
2344 if (r < 0)
2345 return r;
2346 }
2347 }
2348
2349 return execute_preset(scope, &plus, &minus, &paths, config_path, root_dir, NULL, mode, force, changes, n_changes);
2350 }
2351
2352 static void unit_file_list_free_one(UnitFileList *f) {
2353 if (!f)
2354 return;
2355
2356 free(f->path);
2357 free(f);
2358 }
2359
2360 Hashmap* unit_file_list_free(Hashmap *h) {
2361 UnitFileList *i;
2362
2363 while ((i = hashmap_steal_first(h)))
2364 unit_file_list_free_one(i);
2365
2366 return hashmap_free(h);
2367 }
2368
2369 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one);
2370
2371 int unit_file_get_list(
2372 UnitFileScope scope,
2373 const char *root_dir,
2374 Hashmap *h) {
2375
2376 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2377 char **i;
2378 int r;
2379
2380 assert(scope >= 0);
2381 assert(scope < _UNIT_FILE_SCOPE_MAX);
2382 assert(h);
2383
2384 r = verify_root_dir(scope, &root_dir);
2385 if (r < 0)
2386 return r;
2387
2388 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2389 if (r < 0)
2390 return r;
2391
2392 STRV_FOREACH(i, paths.unit_path) {
2393 _cleanup_closedir_ DIR *d = NULL;
2394 _cleanup_free_ char *units_dir;
2395 struct dirent *de;
2396
2397 units_dir = path_join(root_dir, *i, NULL);
2398 if (!units_dir)
2399 return -ENOMEM;
2400
2401 d = opendir(units_dir);
2402 if (!d) {
2403 if (errno == ENOENT)
2404 continue;
2405
2406 return -errno;
2407 }
2408
2409 FOREACH_DIRENT(de, d, return -errno) {
2410 _cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL;
2411
2412 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
2413 continue;
2414
2415 if (hashmap_get(h, de->d_name))
2416 continue;
2417
2418 dirent_ensure_type(d, de);
2419
2420 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2421 continue;
2422
2423 f = new0(UnitFileList, 1);
2424 if (!f)
2425 return -ENOMEM;
2426
2427 f->path = path_make_absolute(de->d_name, units_dir);
2428 if (!f->path)
2429 return -ENOMEM;
2430
2431 r = unit_file_lookup_state(scope, root_dir, &paths, basename(f->path), &f->state);
2432 if (r < 0)
2433 f->state = UNIT_FILE_BAD;
2434
2435 r = hashmap_put(h, basename(f->path), f);
2436 if (r < 0)
2437 return r;
2438
2439 f = NULL; /* prevent cleanup */
2440 }
2441 }
2442
2443 return 0;
2444 }
2445
2446 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2447 [UNIT_FILE_ENABLED] = "enabled",
2448 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2449 [UNIT_FILE_LINKED] = "linked",
2450 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2451 [UNIT_FILE_MASKED] = "masked",
2452 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2453 [UNIT_FILE_STATIC] = "static",
2454 [UNIT_FILE_DISABLED] = "disabled",
2455 [UNIT_FILE_INDIRECT] = "indirect",
2456 [UNIT_FILE_BAD] = "bad",
2457 };
2458
2459 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2460
2461 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2462 [UNIT_FILE_SYMLINK] = "symlink",
2463 [UNIT_FILE_UNLINK] = "unlink",
2464 };
2465
2466 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2467
2468 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = {
2469 [UNIT_FILE_PRESET_FULL] = "full",
2470 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2471 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2472 };
2473
2474 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);