chiark / gitweb /
install: various modernizations
[elogind.git] / src / shared / install.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2011 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <fnmatch.h>
27
28 #include "util.h"
29 #include "mkdir.h"
30 #include "hashmap.h"
31 #include "set.h"
32 #include "path-util.h"
33 #include "path-lookup.h"
34 #include "strv.h"
35 #include "unit-name.h"
36 #include "install.h"
37 #include "conf-parser.h"
38 #include "conf-files.h"
39 #include "specifier.h"
40 #include "install-printf.h"
41 #include "special.h"
42
43 typedef struct {
44         Hashmap *will_install;
45         Hashmap *have_installed;
46 } InstallContext;
47
48 #define _cleanup_install_context_done_ _cleanup_(install_context_done)
49
50 static int lookup_paths_init_from_scope(LookupPaths *paths,
51                                         UnitFileScope scope,
52                                         const char *root_dir) {
53         assert(paths);
54         assert(scope >= 0);
55         assert(scope < _UNIT_FILE_SCOPE_MAX);
56
57         zero(*paths);
58
59         return lookup_paths_init(paths,
60                                  scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
61                                  scope == UNIT_FILE_USER,
62                                  root_dir,
63                                  NULL, NULL, NULL);
64 }
65
66 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
67         char *p = NULL;
68         int r;
69
70         assert(scope >= 0);
71         assert(scope < _UNIT_FILE_SCOPE_MAX);
72         assert(ret);
73
74         switch (scope) {
75
76         case UNIT_FILE_SYSTEM:
77
78                 if (root_dir && runtime)
79                         asprintf(&p, "%s/run/systemd/system", root_dir);
80                 else if (runtime)
81                         p = strdup("/run/systemd/system");
82                 else if (root_dir)
83                         asprintf(&p, "%s/%s", root_dir, SYSTEM_CONFIG_UNIT_PATH);
84                 else
85                         p = strdup(SYSTEM_CONFIG_UNIT_PATH);
86
87                 break;
88
89         case UNIT_FILE_GLOBAL:
90
91                 if (root_dir)
92                         return -EINVAL;
93
94                 if (runtime)
95                         p = strdup("/run/systemd/user");
96                 else
97                         p = strdup(USER_CONFIG_UNIT_PATH);
98                 break;
99
100         case UNIT_FILE_USER:
101
102                 if (root_dir || runtime)
103                         return -EINVAL;
104
105                 r = user_config_home(&p);
106                 if (r <= 0)
107                         return r < 0 ? r : -ENOENT;
108
109                 break;
110
111         default:
112                 assert_not_reached("Bad scope");
113         }
114
115         if (!p)
116                 return -ENOMEM;
117
118         *ret = p;
119         return 0;
120 }
121
122 static int add_file_change(
123                 UnitFileChange **changes,
124                 unsigned *n_changes,
125                 UnitFileChangeType type,
126                 const char *path,
127                 const char *source) {
128
129         UnitFileChange *c;
130         unsigned i;
131
132         assert(path);
133         assert(!changes == !n_changes);
134
135         if (!changes)
136                 return 0;
137
138         c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
139         if (!c)
140                 return -ENOMEM;
141
142         *changes = c;
143         i = *n_changes;
144
145         c[i].type = type;
146         c[i].path = strdup(path);
147         if (!c[i].path)
148                 return -ENOMEM;
149
150         if (source) {
151                 c[i].source = strdup(source);
152                 if (!c[i].source) {
153                         free(c[i].path);
154                         return -ENOMEM;
155                 }
156         } else
157                 c[i].source = NULL;
158
159         *n_changes = i+1;
160         return 0;
161 }
162
163 static int mark_symlink_for_removal(
164                 Set **remove_symlinks_to,
165                 const char *p) {
166
167         char *n;
168         int r;
169
170         assert(p);
171
172         r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
173         if (r < 0)
174                 return r;
175
176         n = strdup(p);
177         if (!n)
178                 return -ENOMEM;
179
180         path_kill_slashes(n);
181
182         r = set_consume(*remove_symlinks_to, n);
183         if (r < 0)
184                 return r == -EEXIST ? 0 : r;
185
186         return 0;
187 }
188
189 static int remove_marked_symlinks_fd(
190                 Set *remove_symlinks_to,
191                 int fd,
192                 const char *path,
193                 const char *config_path,
194                 bool *deleted,
195                 UnitFileChange **changes,
196                 unsigned *n_changes,
197                 char** instance_whitelist) {
198
199         _cleanup_closedir_ DIR *d = NULL;
200         int r = 0;
201
202         assert(remove_symlinks_to);
203         assert(fd >= 0);
204         assert(path);
205         assert(config_path);
206         assert(deleted);
207
208         d = fdopendir(fd);
209         if (!d) {
210                 safe_close(fd);
211                 return -errno;
212         }
213
214         rewinddir(d);
215
216         for (;;) {
217                 struct dirent *de;
218
219                 errno = 0;
220                 de = readdir(d);
221                 if (!de && errno != 0) {
222                         r = -errno;
223                         break;
224                 }
225
226                 if (!de)
227                         break;
228
229                 if (ignore_file(de->d_name))
230                         continue;
231
232                 dirent_ensure_type(d, de);
233
234                 if (de->d_type == DT_DIR) {
235                         int nfd, q;
236                         _cleanup_free_ char *p = NULL;
237
238                         nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
239                         if (nfd < 0) {
240                                 if (errno == ENOENT)
241                                         continue;
242
243                                 if (r == 0)
244                                         r = -errno;
245                                 continue;
246                         }
247
248                         p = path_make_absolute(de->d_name, path);
249                         if (!p) {
250                                 safe_close(nfd);
251                                 return -ENOMEM;
252                         }
253
254                         /* This will close nfd, regardless whether it succeeds or not */
255                         q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, instance_whitelist);
256                         if (q < 0 && r == 0)
257                                 r = q;
258
259                 } else if (de->d_type == DT_LNK) {
260                         _cleanup_free_ char *p = NULL, *dest = NULL;
261                         int q;
262                         bool found;
263
264                         if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
265                                 continue;
266
267                         if (unit_name_is_instance(de->d_name) &&
268                             instance_whitelist &&
269                             !strv_contains(instance_whitelist, de->d_name))
270                                 continue;
271
272                         p = path_make_absolute(de->d_name, path);
273                         if (!p)
274                                 return -ENOMEM;
275
276                         q = readlink_and_canonicalize(p, &dest);
277                         if (q < 0) {
278                                 if (q == -ENOENT)
279                                         continue;
280
281                                 if (r == 0)
282                                         r = q;
283                                 continue;
284                         }
285
286                         found =
287                                 set_get(remove_symlinks_to, dest) ||
288                                 set_get(remove_symlinks_to, basename(dest));
289
290                         if (!found)
291                                 continue;
292
293
294                         if (unlink(p) < 0 && errno != ENOENT) {
295
296                                 if (r == 0)
297                                         r = -errno;
298                                 continue;
299                         }
300
301                         rmdir_parents(p, config_path);
302
303                         path_kill_slashes(p);
304
305                         add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
306
307                         if (!set_get(remove_symlinks_to, p)) {
308
309                                 q = mark_symlink_for_removal(&remove_symlinks_to, p);
310                                 if (q < 0) {
311                                         if (r == 0)
312                                                 r = q;
313                                 } else
314                                         *deleted = true;
315                         }
316                 }
317         }
318
319         return r;
320 }
321
322 static int remove_marked_symlinks(
323                 Set *remove_symlinks_to,
324                 const char *config_path,
325                 UnitFileChange **changes,
326                 unsigned *n_changes,
327                 char** instance_whitelist) {
328
329         _cleanup_close_ int fd = -1;
330         int r = 0;
331         bool deleted;
332
333         assert(config_path);
334
335         if (set_size(remove_symlinks_to) <= 0)
336                 return 0;
337
338         fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
339         if (fd < 0)
340                 return -errno;
341
342         do {
343                 int q, cfd;
344                 deleted = false;
345
346                 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
347                 if (cfd < 0) {
348                         r = -errno;
349                         break;
350                 }
351
352                 /* This takes possession of cfd and closes it */
353                 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist);
354                 if (r == 0)
355                         r = q;
356         } while (deleted);
357
358         return r;
359 }
360
361 static int find_symlinks_fd(
362                 const char *name,
363                 int fd,
364                 const char *path,
365                 const char *config_path,
366                 bool *same_name_link) {
367
368         int r = 0;
369         _cleanup_closedir_ DIR *d = NULL;
370
371         assert(name);
372         assert(fd >= 0);
373         assert(path);
374         assert(config_path);
375         assert(same_name_link);
376
377         d = fdopendir(fd);
378         if (!d) {
379                 safe_close(fd);
380                 return -errno;
381         }
382
383         for (;;) {
384                 struct dirent *de;
385
386                 errno = 0;
387                 de = readdir(d);
388                 if (!de && errno != 0)
389                         return -errno;
390
391                 if (!de)
392                         return r;
393
394                 if (ignore_file(de->d_name))
395                         continue;
396
397                 dirent_ensure_type(d, de);
398
399                 if (de->d_type == DT_DIR) {
400                         int nfd, q;
401                         _cleanup_free_ char *p = NULL;
402
403                         nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
404                         if (nfd < 0) {
405                                 if (errno == ENOENT)
406                                         continue;
407
408                                 if (r == 0)
409                                         r = -errno;
410                                 continue;
411                         }
412
413                         p = path_make_absolute(de->d_name, path);
414                         if (!p) {
415                                 safe_close(nfd);
416                                 return -ENOMEM;
417                         }
418
419                         /* This will close nfd, regardless whether it succeeds or not */
420                         q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
421                         if (q > 0)
422                                 return 1;
423                         if (r == 0)
424                                 r = q;
425
426                 } else if (de->d_type == DT_LNK) {
427                         _cleanup_free_ char *p = NULL, *dest = NULL;
428                         bool found_path, found_dest, b = false;
429                         int q;
430
431                         /* Acquire symlink name */
432                         p = path_make_absolute(de->d_name, path);
433                         if (!p)
434                                 return -ENOMEM;
435
436                         /* Acquire symlink destination */
437                         q = readlink_and_canonicalize(p, &dest);
438                         if (q < 0) {
439                                 if (q == -ENOENT)
440                                         continue;
441
442                                 if (r == 0)
443                                         r = q;
444                                 continue;
445                         }
446
447                         /* Check if the symlink itself matches what we
448                          * are looking for */
449                         if (path_is_absolute(name))
450                                 found_path = path_equal(p, name);
451                         else
452                                 found_path = streq(de->d_name, name);
453
454                         /* Check if what the symlink points to
455                          * matches what we are looking for */
456                         if (path_is_absolute(name))
457                                 found_dest = path_equal(dest, name);
458                         else
459                                 found_dest = streq(basename(dest), name);
460
461                         if (found_path && found_dest) {
462                                 _cleanup_free_ char *t = NULL;
463
464                                 /* Filter out same name links in the main
465                                  * config path */
466                                 t = path_make_absolute(name, config_path);
467                                 if (!t)
468                                         return -ENOMEM;
469
470                                 b = path_equal(t, p);
471                         }
472
473                         if (b)
474                                 *same_name_link = true;
475                         else if (found_path || found_dest)
476                                 return 1;
477                 }
478         }
479 }
480
481 static int find_symlinks(
482                 const char *name,
483                 const char *config_path,
484                 bool *same_name_link) {
485
486         int fd;
487
488         assert(name);
489         assert(config_path);
490         assert(same_name_link);
491
492         fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
493         if (fd < 0) {
494                 if (errno == ENOENT)
495                         return 0;
496                 return -errno;
497         }
498
499         /* This takes possession of fd and closes it */
500         return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
501 }
502
503 static int find_symlinks_in_scope(
504                 UnitFileScope scope,
505                 const char *root_dir,
506                 const char *name,
507                 UnitFileState *state) {
508
509         int r;
510         _cleanup_free_ char *path2 = NULL;
511         bool same_name_link_runtime = false, same_name_link = false;
512
513         assert(scope >= 0);
514         assert(scope < _UNIT_FILE_SCOPE_MAX);
515         assert(name);
516
517         if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
518                 _cleanup_free_ char *path = NULL;
519
520                 /* First look in runtime config path */
521                 r = get_config_path(scope, true, root_dir, &path);
522                 if (r < 0)
523                         return r;
524
525                 r = find_symlinks(name, path, &same_name_link_runtime);
526                 if (r < 0)
527                         return r;
528                 else if (r > 0) {
529                         *state = UNIT_FILE_ENABLED_RUNTIME;
530                         return r;
531                 }
532         }
533
534         /* Then look in the normal config path */
535         r = get_config_path(scope, false, root_dir, &path2);
536         if (r < 0)
537                 return r;
538
539         r = find_symlinks(name, path2, &same_name_link);
540         if (r < 0)
541                 return r;
542         else if (r > 0) {
543                 *state = UNIT_FILE_ENABLED;
544                 return r;
545         }
546
547         /* Hmm, we didn't find it, but maybe we found the same name
548          * link? */
549         if (same_name_link_runtime) {
550                 *state = UNIT_FILE_LINKED_RUNTIME;
551                 return 1;
552         } else if (same_name_link) {
553                 *state = UNIT_FILE_LINKED;
554                 return 1;
555         }
556
557         return 0;
558 }
559
560 int unit_file_mask(
561                 UnitFileScope scope,
562                 bool runtime,
563                 const char *root_dir,
564                 char **files,
565                 bool force,
566                 UnitFileChange **changes,
567                 unsigned *n_changes) {
568
569         char **i;
570         _cleanup_free_ char *prefix = NULL;
571         int r;
572
573         assert(scope >= 0);
574         assert(scope < _UNIT_FILE_SCOPE_MAX);
575
576         r = get_config_path(scope, runtime, root_dir, &prefix);
577         if (r < 0)
578                 return r;
579
580         STRV_FOREACH(i, files) {
581                 _cleanup_free_ char *path = NULL;
582
583                 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
584                         if (r == 0)
585                                 r = -EINVAL;
586                         continue;
587                 }
588
589                 path = path_make_absolute(*i, prefix);
590                 if (!path) {
591                         r = -ENOMEM;
592                         break;
593                 }
594
595                 if (symlink("/dev/null", path) >= 0) {
596                         add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
597                         continue;
598                 }
599
600                 if (errno == EEXIST) {
601
602                         if (null_or_empty_path(path) > 0)
603                                 continue;
604
605                         if (force) {
606                                 unlink(path);
607
608                                 if (symlink("/dev/null", path) >= 0) {
609
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");
612
613                                         continue;
614                                 }
615                         }
616
617                         if (r == 0)
618                                 r = -EEXIST;
619                 } else {
620                         if (r == 0)
621                                 r = -errno;
622                 }
623         }
624
625         return r;
626 }
627
628 int unit_file_unmask(
629                 UnitFileScope scope,
630                 bool runtime,
631                 const char *root_dir,
632                 char **files,
633                 UnitFileChange **changes,
634                 unsigned *n_changes) {
635
636         char **i, *config_path = NULL;
637         int r, q;
638         Set *remove_symlinks_to = NULL;
639
640         assert(scope >= 0);
641         assert(scope < _UNIT_FILE_SCOPE_MAX);
642
643         r = get_config_path(scope, runtime, root_dir, &config_path);
644         if (r < 0)
645                 goto finish;
646
647         STRV_FOREACH(i, files) {
648                 char *path;
649
650                 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
651                         if (r == 0)
652                                 r = -EINVAL;
653                         continue;
654                 }
655
656                 path = path_make_absolute(*i, config_path);
657                 if (!path) {
658                         r = -ENOMEM;
659                         break;
660                 }
661
662                 q = null_or_empty_path(path);
663                 if (q > 0) {
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);
667
668                                 free(path);
669                                 continue;
670                         }
671
672                         q = -errno;
673                 }
674
675                 if (q != -ENOENT && r == 0)
676                         r = q;
677
678                 free(path);
679         }
680
681
682 finish:
683         q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
684         if (r == 0)
685                 r = q;
686
687         set_free_free(remove_symlinks_to);
688         free(config_path);
689
690         return r;
691 }
692
693 int unit_file_link(
694                 UnitFileScope scope,
695                 bool runtime,
696                 const char *root_dir,
697                 char **files,
698                 bool force,
699                 UnitFileChange **changes,
700                 unsigned *n_changes) {
701
702         _cleanup_lookup_paths_free_ LookupPaths paths = {};
703         char **i;
704         _cleanup_free_ char *config_path = NULL;
705         int r, q;
706
707         assert(scope >= 0);
708         assert(scope < _UNIT_FILE_SCOPE_MAX);
709
710         r = lookup_paths_init_from_scope(&paths, scope, root_dir);
711         if (r < 0)
712                 return r;
713
714         r = get_config_path(scope, runtime, root_dir, &config_path);
715         if (r < 0)
716                 return r;
717
718         STRV_FOREACH(i, files) {
719                 _cleanup_free_ char *path = NULL;
720                 char *fn;
721                 struct stat st;
722
723                 fn = basename(*i);
724
725                 if (!path_is_absolute(*i) ||
726                     !unit_name_is_valid(fn, TEMPLATE_VALID)) {
727                         if (r == 0)
728                                 r = -EINVAL;
729                         continue;
730                 }
731
732                 if (lstat(*i, &st) < 0) {
733                         if (r == 0)
734                                 r = -errno;
735                         continue;
736                 }
737
738                 if (!S_ISREG(st.st_mode)) {
739                         r = -ENOENT;
740                         continue;
741                 }
742
743                 q = in_search_path(*i, paths.unit_path);
744                 if (q < 0)
745                         return q;
746
747                 if (q > 0)
748                         continue;
749
750                 path = path_make_absolute(fn, config_path);
751                 if (!path)
752                         return -ENOMEM;
753
754                 if (symlink(*i, path) >= 0) {
755                         add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
756                         continue;
757                 }
758
759                 if (errno == EEXIST) {
760                         _cleanup_free_ char *dest = NULL;
761
762                         q = readlink_and_make_absolute(path, &dest);
763                         if (q < 0 && errno != ENOENT) {
764                                 if (r == 0)
765                                         r = q;
766                                 continue;
767                         }
768
769                         if (q >= 0 && path_equal(dest, *i))
770                                 continue;
771
772                         if (force) {
773                                 unlink(path);
774
775                                 if (symlink(*i, path) >= 0) {
776
777                                         add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
778                                         add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
779
780                                         continue;
781                                 }
782                         }
783
784                         if (r == 0)
785                                 r = -EEXIST;
786                 } else {
787                         if (r == 0)
788                                 r = -errno;
789                 }
790         }
791
792         return r;
793 }
794
795 void unit_file_list_free(Hashmap *h) {
796         UnitFileList *i;
797
798         while ((i = hashmap_steal_first(h))) {
799                 free(i->path);
800                 free(i);
801         }
802
803         hashmap_free(h);
804 }
805
806 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
807         unsigned i;
808
809         assert(changes || n_changes == 0);
810
811         if (!changes)
812                 return;
813
814         for (i = 0; i < n_changes; i++) {
815                 free(changes[i].path);
816                 free(changes[i].source);
817         }
818
819         free(changes);
820 }
821
822 static void install_info_free(InstallInfo *i) {
823         assert(i);
824
825         free(i->name);
826         free(i->path);
827         strv_free(i->aliases);
828         strv_free(i->wanted_by);
829         strv_free(i->required_by);
830         free(i);
831 }
832
833 static void install_info_hashmap_free(Hashmap *m) {
834         InstallInfo *i;
835
836         if (!m)
837                 return;
838
839         while ((i = hashmap_steal_first(m)))
840                 install_info_free(i);
841
842         hashmap_free(m);
843 }
844
845 static void install_context_done(InstallContext *c) {
846         assert(c);
847
848         install_info_hashmap_free(c->will_install);
849         install_info_hashmap_free(c->have_installed);
850
851         c->will_install = c->have_installed = NULL;
852 }
853
854 static int install_info_add(
855                 InstallContext *c,
856                 const char *name,
857                 const char *path) {
858         InstallInfo *i = NULL;
859         int r;
860
861         assert(c);
862         assert(name || path);
863
864         if (!name)
865                 name = basename(path);
866
867         if (!unit_name_is_valid(name, TEMPLATE_VALID))
868                 return -EINVAL;
869
870         if (hashmap_get(c->have_installed, name) ||
871             hashmap_get(c->will_install, name))
872                 return 0;
873
874         r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
875         if (r < 0)
876                 return r;
877
878         i = new0(InstallInfo, 1);
879         if (!i)
880                 return -ENOMEM;
881
882         i->name = strdup(name);
883         if (!i->name) {
884                 r = -ENOMEM;
885                 goto fail;
886         }
887
888         if (path) {
889                 i->path = strdup(path);
890                 if (!i->path) {
891                         r = -ENOMEM;
892                         goto fail;
893                 }
894         }
895
896         r = hashmap_put(c->will_install, i->name, i);
897         if (r < 0)
898                 goto fail;
899
900         return 0;
901
902 fail:
903         if (i)
904                 install_info_free(i);
905
906         return r;
907 }
908
909 static int install_info_add_auto(
910                 InstallContext *c,
911                 const char *name_or_path) {
912
913         assert(c);
914         assert(name_or_path);
915
916         if (path_is_absolute(name_or_path))
917                 return install_info_add(c, NULL, name_or_path);
918         else
919                 return install_info_add(c, name_or_path, NULL);
920 }
921
922 static int config_parse_also(const char *unit,
923                              const char *filename,
924                              unsigned line,
925                              const char *section,
926                              unsigned section_line,
927                              const char *lvalue,
928                              int ltype,
929                              const char *rvalue,
930                              void *data,
931                              void *userdata) {
932
933         char *w;
934         size_t l;
935         char *state;
936         InstallContext *c = data;
937
938         assert(filename);
939         assert(lvalue);
940         assert(rvalue);
941
942         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
943                 _cleanup_free_ char *n;
944                 int r;
945
946                 n = strndup(w, l);
947                 if (!n)
948                         return -ENOMEM;
949
950                 r = install_info_add(c, n, NULL);
951                 if (r < 0)
952                         return r;
953         }
954
955         return 0;
956 }
957
958 static int config_parse_user(const char *unit,
959                              const char *filename,
960                              unsigned line,
961                              const char *section,
962                              unsigned section_line,
963                              const char *lvalue,
964                              int ltype,
965                              const char *rvalue,
966                              void *data,
967                              void *userdata) {
968
969         InstallInfo *i = data;
970         char* printed;
971         int r;
972
973         assert(filename);
974         assert(lvalue);
975         assert(rvalue);
976
977         r = install_full_printf(i, rvalue, &printed);
978         if (r < 0)
979                 return r;
980
981         free(i->user);
982         i->user = printed;
983
984         return 0;
985 }
986
987 static int unit_file_load(
988                 InstallContext *c,
989                 InstallInfo *info,
990                 const char *path,
991                 bool allow_symlink) {
992
993         const ConfigTableItem items[] = {
994                 { "Install", "Alias",      config_parse_strv, 0, &info->aliases     },
995                 { "Install", "WantedBy",   config_parse_strv, 0, &info->wanted_by   },
996                 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
997                 { "Install", "Also",       config_parse_also, 0, c                  },
998                 { "Exec",    "User",       config_parse_user, 0, info               },
999                 { NULL, NULL, NULL, 0, NULL }
1000         };
1001
1002         int fd;
1003         _cleanup_fclose_ FILE *f = NULL;
1004         int r;
1005
1006         assert(c);
1007         assert(info);
1008         assert(path);
1009
1010         fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1011         if (fd < 0)
1012                 return -errno;
1013
1014         f = fdopen(fd, "re");
1015         if (!f) {
1016                 safe_close(fd);
1017                 return -ENOMEM;
1018         }
1019
1020         r = config_parse(NULL, path, f, NULL,
1021                          config_item_table_lookup, (void*) items, true, true, info);
1022         if (r < 0)
1023                 return r;
1024
1025         return
1026                 (int) strv_length(info->aliases) +
1027                 (int) strv_length(info->wanted_by) +
1028                 (int) strv_length(info->required_by);
1029 }
1030
1031 static int unit_file_search(
1032                 InstallContext *c,
1033                 InstallInfo *info,
1034                 LookupPaths *paths,
1035                 const char *root_dir,
1036                 bool allow_symlink) {
1037
1038         char **p;
1039         int r;
1040
1041         assert(c);
1042         assert(info);
1043         assert(paths);
1044
1045         if (info->path) {
1046                 char *full_path = NULL;
1047
1048                 if (!isempty(root_dir))
1049                         full_path = strappenda(root_dir, info->path);
1050
1051                 return unit_file_load(c, info, full_path ?: info->path, allow_symlink);
1052         }
1053
1054         assert(info->name);
1055
1056         STRV_FOREACH(p, paths->unit_path) {
1057                 _cleanup_free_ char *path = NULL, *full_path = NULL;
1058
1059                 path = strjoin(*p, "/", info->name, NULL);
1060                 if (!path)
1061                         return -ENOMEM;
1062
1063                 if (!isempty(root_dir)) {
1064                         full_path = strappend(root_dir, path);
1065                         if (!full_path)
1066                                 return -ENOMEM;
1067                 }
1068
1069                 r = unit_file_load(c, info, full_path ?: path, allow_symlink);
1070                 if (r >= 0) {
1071                         info->path = path;
1072                         path = NULL;
1073                 } else if (r == -ENOENT && unit_name_is_instance(info->name)) {
1074                         /* Unit file doesn't exist, however instance enablement was requested.
1075                          * We will check if it is possible to load template unit file. */
1076                         _cleanup_free_ char *template = NULL, *template_dir = NULL;
1077
1078                         template = unit_name_template(info->name);
1079                         if (!template)
1080                                 return -ENOMEM;
1081
1082                         /* We will reuse path variable since we don't need it anymore. */
1083                         template_dir = path;
1084                         *(strrchr(template_dir, '/') + 1) = '\0';
1085
1086                         path = strappend(template_dir, template);
1087                         if (!path)
1088                                 return -ENOMEM;
1089
1090                         if (!isempty(root_dir)) {
1091                                 free(full_path);
1092                                 full_path = strappend(root_dir, path);
1093                                 if (!full_path)
1094                                         return -ENOMEM;
1095                         }
1096
1097                         /* Let's try to load template unit. */
1098                         r = unit_file_load(c, info, full_path ?: path, allow_symlink);
1099                         if (r >= 0) {
1100                                 info->path = path;
1101                                 path = NULL;
1102                         }
1103                 }
1104
1105                 if (r != -ENOENT && r != -ELOOP)
1106                         return r;
1107         }
1108
1109         return -ENOENT;
1110 }
1111
1112 static int unit_file_can_install(
1113                 LookupPaths *paths,
1114                 const char *root_dir,
1115                 const char *name,
1116                 bool allow_symlink) {
1117
1118         _cleanup_install_context_done_ InstallContext c = {};
1119         InstallInfo *i;
1120         int r;
1121
1122         assert(paths);
1123         assert(name);
1124
1125         r = install_info_add_auto(&c, name);
1126         if (r < 0)
1127                 return r;
1128
1129         assert_se(i = hashmap_first(c.will_install));
1130
1131         r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1132
1133         if (r >= 0)
1134                 r =
1135                         (int) strv_length(i->aliases) +
1136                         (int) strv_length(i->wanted_by) +
1137                         (int) strv_length(i->required_by);
1138
1139         return r;
1140 }
1141
1142 static int create_symlink(
1143                 const char *old_path,
1144                 const char *new_path,
1145                 bool force,
1146                 UnitFileChange **changes,
1147                 unsigned *n_changes) {
1148
1149         _cleanup_free_ char *dest = NULL;
1150         int r;
1151
1152         assert(old_path);
1153         assert(new_path);
1154
1155         mkdir_parents_label(new_path, 0755);
1156
1157         if (symlink(old_path, new_path) >= 0) {
1158                 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1159                 return 0;
1160         }
1161
1162         if (errno != EEXIST)
1163                 return -errno;
1164
1165         r = readlink_and_make_absolute(new_path, &dest);
1166         if (r < 0)
1167                 return r;
1168
1169         if (path_equal(dest, old_path))
1170                 return 0;
1171
1172         if (!force)
1173                 return -EEXIST;
1174
1175         r = unlink(new_path);
1176         if (r < 0 && errno != ENOENT)
1177                 return -errno;
1178
1179         if (symlink(old_path, new_path) >= 0) {
1180                 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1181                 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1182                 return 0;
1183         }
1184
1185         return -errno;
1186 }
1187
1188 static int install_info_symlink_alias(
1189                 InstallInfo *i,
1190                 const char *config_path,
1191                 bool force,
1192                 UnitFileChange **changes,
1193                 unsigned *n_changes) {
1194
1195         char **s;
1196         int r = 0, q;
1197
1198         assert(i);
1199         assert(config_path);
1200
1201         STRV_FOREACH(s, i->aliases) {
1202                 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1203
1204                 q = install_full_printf(i, *s, &dst);
1205                 if (q < 0)
1206                         return q;
1207
1208                 alias_path = path_make_absolute(dst, config_path);
1209                 if (!alias_path)
1210                         return -ENOMEM;
1211
1212                 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1213                 if (r == 0)
1214                         r = q;
1215         }
1216
1217         return r;
1218 }
1219
1220 static int install_info_symlink_wants(
1221                 InstallInfo *i,
1222                 const char *config_path,
1223                 bool force,
1224                 UnitFileChange **changes,
1225                 unsigned *n_changes) {
1226
1227         char **s;
1228         int r = 0, q;
1229
1230         assert(i);
1231         assert(config_path);
1232
1233         STRV_FOREACH(s, i->wanted_by) {
1234                 _cleanup_free_ char *path = NULL, *dst = NULL;
1235
1236                 q = install_full_printf(i, *s, &dst);
1237                 if (q < 0)
1238                         return q;
1239
1240                 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1241                         r = -EINVAL;
1242                         continue;
1243                 }
1244
1245                 if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
1246                         return -ENOMEM;
1247
1248                 q = create_symlink(i->path, path, force, changes, n_changes);
1249
1250                 if (r == 0)
1251                         r = q;
1252         }
1253
1254         return r;
1255 }
1256
1257 static int install_info_symlink_requires(
1258                 InstallInfo *i,
1259                 const char *config_path,
1260                 bool force,
1261                 UnitFileChange **changes,
1262                 unsigned *n_changes) {
1263
1264         char **s;
1265         int r = 0, q;
1266
1267         assert(i);
1268         assert(config_path);
1269
1270         STRV_FOREACH(s, i->required_by) {
1271                 _cleanup_free_ char *path = NULL, *dst = NULL;
1272
1273                 q = install_full_printf(i, *s, &dst);
1274                 if (q < 0)
1275                         return q;
1276
1277                 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1278                         r = -EINVAL;
1279                         continue;
1280                 }
1281
1282                 if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
1283                         return -ENOMEM;
1284
1285                 q = create_symlink(i->path, path, force, changes, n_changes);
1286
1287                 if (r == 0)
1288                         r = q;
1289         }
1290
1291         return r;
1292 }
1293
1294 static int install_info_symlink_link(
1295                 InstallInfo *i,
1296                 LookupPaths *paths,
1297                 const char *config_path,
1298                 bool force,
1299                 UnitFileChange **changes,
1300                 unsigned *n_changes) {
1301
1302         _cleanup_free_ char *path = NULL;
1303         int r;
1304
1305         assert(i);
1306         assert(paths);
1307         assert(config_path);
1308         assert(i->path);
1309
1310         r = in_search_path(i->path, paths->unit_path);
1311         if (r != 0)
1312                 return r;
1313
1314         path = strjoin(config_path, "/", i->name, NULL);
1315         if (!path)
1316                 return -ENOMEM;
1317
1318         return create_symlink(i->path, path, force, changes, n_changes);
1319 }
1320
1321 static int install_info_apply(
1322                 InstallInfo *i,
1323                 LookupPaths *paths,
1324                 const char *config_path,
1325                 bool force,
1326                 UnitFileChange **changes,
1327                 unsigned *n_changes) {
1328
1329         int r, q;
1330
1331         assert(i);
1332         assert(paths);
1333         assert(config_path);
1334
1335         r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1336
1337         q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1338         if (r == 0)
1339                 r = q;
1340
1341         q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1342         if (r == 0)
1343                 r = q;
1344
1345         q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1346         if (r == 0)
1347                 r = q;
1348
1349         return r;
1350 }
1351
1352 static int install_context_apply(
1353                 InstallContext *c,
1354                 LookupPaths *paths,
1355                 const char *config_path,
1356                 const char *root_dir,
1357                 bool force,
1358                 UnitFileChange **changes,
1359                 unsigned *n_changes) {
1360
1361         InstallInfo *i;
1362         int r = 0, q;
1363
1364         assert(c);
1365         assert(paths);
1366         assert(config_path);
1367
1368         while ((i = hashmap_first(c->will_install))) {
1369
1370                 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1371                 if (q < 0)
1372                         return q;
1373
1374                 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1375
1376                 q = unit_file_search(c, i, paths, root_dir, false);
1377                 if (q < 0) {
1378                         if (r >= 0)
1379                                 r = q;
1380
1381                         return r;
1382                 } else if (r >= 0)
1383                         r += q;
1384
1385                 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1386                 if (r >= 0 && q < 0)
1387                         r = q;
1388         }
1389
1390         return r;
1391 }
1392
1393 static int install_context_mark_for_removal(
1394                 InstallContext *c,
1395                 LookupPaths *paths,
1396                 Set **remove_symlinks_to,
1397                 const char *config_path,
1398                 const char *root_dir) {
1399
1400         InstallInfo *i;
1401         int r = 0, q;
1402
1403         assert(c);
1404         assert(paths);
1405         assert(config_path);
1406
1407         /* Marks all items for removal */
1408
1409         while ((i = hashmap_first(c->will_install))) {
1410
1411                 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1412                 if (q < 0)
1413                         return q;
1414
1415                 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1416
1417                 q = unit_file_search(c, i, paths, root_dir, false);
1418                 if (q == -ENOENT) {
1419                         /* do nothing */
1420                 } else if (q < 0) {
1421                         if (r >= 0)
1422                                 r = q;
1423
1424                         return r;
1425                 } else if (r >= 0)
1426                         r += q;
1427
1428                 if (unit_name_is_instance(i->name)) {
1429                         char *unit_file;
1430
1431                         if (i->path) {
1432                                 unit_file = basename(i->path);
1433
1434                                 if (unit_name_is_instance(unit_file))
1435                                         /* unit file named as instance exists, thus all symlinks
1436                                          * pointing to it will be removed */
1437                                         q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1438                                 else
1439                                         /* does not exist, thus we will mark for removal symlinks
1440                                          * to template unit file */
1441                                         q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1442                         } else {
1443                                 /* If i->path is not set, it means that we didn't actually find
1444                                  * the unit file. But we can still remove symlinks to the
1445                                  * nonexistent template. */
1446                                 unit_file = unit_name_template(i->name);
1447                                 if (!unit_file)
1448                                         return log_oom();
1449
1450                                 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1451                                 free(unit_file);
1452                         }
1453                 } else
1454                         q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1455
1456                 if (r >= 0 && q < 0)
1457                         r = q;
1458         }
1459
1460         return r;
1461 }
1462
1463 int unit_file_enable(
1464                 UnitFileScope scope,
1465                 bool runtime,
1466                 const char *root_dir,
1467                 char **files,
1468                 bool force,
1469                 UnitFileChange **changes,
1470                 unsigned *n_changes) {
1471
1472         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1473         _cleanup_install_context_done_ InstallContext c = {};
1474         char **i;
1475         _cleanup_free_ char *config_path = NULL;
1476         int r;
1477
1478         assert(scope >= 0);
1479         assert(scope < _UNIT_FILE_SCOPE_MAX);
1480
1481         r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1482         if (r < 0)
1483                 return r;
1484
1485         r = get_config_path(scope, runtime, root_dir, &config_path);
1486         if (r < 0)
1487                 return r;
1488
1489         STRV_FOREACH(i, files) {
1490                 r = install_info_add_auto(&c, *i);
1491                 if (r < 0)
1492                         return r;
1493         }
1494
1495         /* This will return the number of symlink rules that were
1496         supposed to be created, not the ones actually created. This is
1497         useful to determine whether the passed files had any
1498         installation data at all. */
1499
1500         return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1501 }
1502
1503 int unit_file_disable(
1504                 UnitFileScope scope,
1505                 bool runtime,
1506                 const char *root_dir,
1507                 char **files,
1508                 UnitFileChange **changes,
1509                 unsigned *n_changes) {
1510
1511         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1512         _cleanup_install_context_done_ InstallContext c = {};
1513         char **i;
1514         _cleanup_free_ char *config_path = NULL;
1515         _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1516         int r, q;
1517
1518         assert(scope >= 0);
1519         assert(scope < _UNIT_FILE_SCOPE_MAX);
1520
1521         r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1522         if (r < 0)
1523                 return r;
1524
1525         r = get_config_path(scope, runtime, root_dir, &config_path);
1526         if (r < 0)
1527                 return r;
1528
1529         STRV_FOREACH(i, files) {
1530                 r = install_info_add_auto(&c, *i);
1531                 if (r < 0)
1532                         return r;
1533         }
1534
1535         r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1536
1537         q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1538         if (r == 0)
1539                 r = q;
1540
1541         return r;
1542 }
1543
1544 int unit_file_reenable(
1545                 UnitFileScope scope,
1546                 bool runtime,
1547                 const char *root_dir,
1548                 char **files,
1549                 bool force,
1550                 UnitFileChange **changes,
1551                 unsigned *n_changes) {
1552         int r;
1553
1554         r = unit_file_disable(scope, runtime, root_dir, files,
1555                               changes, n_changes);
1556         if (r < 0)
1557                 return r;
1558
1559         return unit_file_enable(scope, runtime, root_dir, files, force,
1560                                 changes, n_changes);
1561 }
1562
1563 int unit_file_set_default(
1564                 UnitFileScope scope,
1565                 const char *root_dir,
1566                 const char *file,
1567                 bool force,
1568                 UnitFileChange **changes,
1569                 unsigned *n_changes) {
1570
1571         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1572         _cleanup_install_context_done_ InstallContext c = {};
1573         _cleanup_free_ char *config_path = NULL;
1574         char *path;
1575         int r;
1576         InstallInfo *i = NULL;
1577
1578         assert(scope >= 0);
1579         assert(scope < _UNIT_FILE_SCOPE_MAX);
1580         assert(file);
1581
1582         if (unit_name_to_type(file) != UNIT_TARGET)
1583                 return -EINVAL;
1584
1585         r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1586         if (r < 0)
1587                 return r;
1588
1589         r = get_config_path(scope, false, root_dir, &config_path);
1590         if (r < 0)
1591                 return r;
1592
1593         r = install_info_add_auto(&c, file);
1594         if (r < 0)
1595                 return r;
1596
1597         assert_se(i = hashmap_first(c.will_install));
1598
1599         r = unit_file_search(&c, i, &paths, root_dir, false);
1600         if (r < 0)
1601                 return r;
1602
1603         path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1604
1605         r = create_symlink(i->path, path, force, changes, n_changes);
1606         if (r < 0)
1607                 return r;
1608
1609         return 0;
1610 }
1611
1612 int unit_file_get_default(
1613                 UnitFileScope scope,
1614                 const char *root_dir,
1615                 char **name) {
1616
1617         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1618         char **p;
1619         int r;
1620
1621         assert(scope >= 0);
1622         assert(scope < _UNIT_FILE_SCOPE_MAX);
1623         assert(name);
1624
1625         r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1626         if (r < 0)
1627                 return r;
1628
1629         STRV_FOREACH(p, paths.unit_path) {
1630                 _cleanup_free_ char *path = NULL, *tmp = NULL;
1631                 char *n;
1632
1633                 if (isempty(root_dir))
1634                         path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
1635                 else
1636                         path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
1637
1638                 if (!path)
1639                         return -ENOMEM;
1640
1641                 r = readlink_malloc(path, &tmp);
1642                 if (r == -ENOENT)
1643                         continue;
1644                 else if (r == -EINVAL)
1645                         /* not a symlink */
1646                         n = strdup(SPECIAL_DEFAULT_TARGET);
1647                 else if (r < 0)
1648                         return r;
1649                 else
1650                         n = strdup(basename(tmp));
1651
1652                 if (!n)
1653                         return -ENOMEM;
1654
1655                 *name = n;
1656                 return 0;
1657         }
1658
1659         return -ENOENT;
1660 }
1661
1662 UnitFileState unit_file_get_state(
1663                 UnitFileScope scope,
1664                 const char *root_dir,
1665                 const char *name) {
1666
1667         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1668         UnitFileState state = _UNIT_FILE_STATE_INVALID;
1669         char **i;
1670         _cleanup_free_ char *path = NULL;
1671         int r;
1672
1673         assert(scope >= 0);
1674         assert(scope < _UNIT_FILE_SCOPE_MAX);
1675         assert(name);
1676
1677         if (root_dir && scope != UNIT_FILE_SYSTEM)
1678                 return -EINVAL;
1679
1680         if (!unit_name_is_valid(name, TEMPLATE_VALID))
1681                 return -EINVAL;
1682
1683         r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1684         if (r < 0)
1685                 return r;
1686
1687         STRV_FOREACH(i, paths.unit_path) {
1688                 struct stat st;
1689                 char *partial;
1690
1691                 free(path);
1692                 path = NULL;
1693
1694                 if (root_dir)
1695                         asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1696                 else
1697                         asprintf(&path, "%s/%s", *i, name);
1698                 if (!path)
1699                         return -ENOMEM;
1700
1701                 if (root_dir)
1702                         partial = path + strlen(root_dir) + 1;
1703                 else
1704                         partial = path;
1705
1706                 /*
1707                  * Search for a unit file in our default paths, to
1708                  * be sure, that there are no broken symlinks.
1709                  */
1710                 if (lstat(path, &st) < 0) {
1711                         r = -errno;
1712                         if (errno != ENOENT)
1713                                 return r;
1714
1715                         if (!unit_name_is_instance(name))
1716                                 continue;
1717                 } else {
1718                         if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1719                                 return -ENOENT;
1720
1721                         r = null_or_empty_path(path);
1722                         if (r < 0 && r != -ENOENT)
1723                                 return r;
1724                         else if (r > 0) {
1725                                 state = path_startswith(*i, "/run") ?
1726                                         UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1727                                 return state;
1728                         }
1729                 }
1730
1731                 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1732                 if (r < 0)
1733                         return r;
1734                 else if (r > 0)
1735                         return state;
1736
1737                 r = unit_file_can_install(&paths, root_dir, partial, true);
1738                 if (r < 0 && errno != ENOENT)
1739                         return r;
1740                 else if (r > 0)
1741                         return UNIT_FILE_DISABLED;
1742                 else if (r == 0)
1743                         return UNIT_FILE_STATIC;
1744         }
1745
1746         return r < 0 ? r : state;
1747 }
1748
1749 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
1750         _cleanup_strv_free_ char **files = NULL;
1751         char **i;
1752         int r;
1753
1754         assert(scope >= 0);
1755         assert(scope < _UNIT_FILE_SCOPE_MAX);
1756         assert(name);
1757
1758         if (scope == UNIT_FILE_SYSTEM)
1759                 r = conf_files_list(&files, ".preset", root_dir,
1760                                     "/etc/systemd/system-preset",
1761                                     "/usr/local/lib/systemd/system-preset",
1762                                     "/usr/lib/systemd/system-preset",
1763 #ifdef HAVE_SPLIT_USR
1764                                     "/lib/systemd/system-preset",
1765 #endif
1766                                     NULL);
1767         else if (scope == UNIT_FILE_GLOBAL)
1768                 r = conf_files_list(&files, ".preset", root_dir,
1769                                     "/etc/systemd/user-preset",
1770                                     "/usr/local/lib/systemd/user-preset",
1771                                     "/usr/lib/systemd/user-preset",
1772                                     NULL);
1773         else
1774                 return 1;
1775
1776         if (r < 0)
1777                 return r;
1778
1779         STRV_FOREACH(i, files) {
1780                 _cleanup_free_ char *buf = NULL;
1781                 _cleanup_fclose_ FILE *f;
1782                 const char *p;
1783
1784                 if (root_dir)
1785                         p = buf = strjoin(root_dir, "/", *i, NULL);
1786                 else
1787                         p = *i;
1788
1789                 f = fopen(p, "re");
1790                 if (!f) {
1791                         if (errno == ENOENT)
1792                                 continue;
1793
1794                         return -errno;
1795                 }
1796
1797                 for (;;) {
1798                         char line[LINE_MAX], *l;
1799
1800                         if (!fgets(line, sizeof(line), f))
1801                                 break;
1802
1803                         l = strstrip(line);
1804                         if (!*l)
1805                                 continue;
1806
1807                         if (strchr(COMMENTS "\n", *l))
1808                                 continue;
1809
1810                         if (first_word(l, "enable")) {
1811                                 l += 6;
1812                                 l += strspn(l, WHITESPACE);
1813
1814                                 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1815                                         log_debug("Preset file says enable %s.", name);
1816                                         return 1;
1817                                 }
1818
1819                         } else if (first_word(l, "disable")) {
1820                                 l += 7;
1821                                 l += strspn(l, WHITESPACE);
1822
1823                                 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1824                                         log_debug("Preset file says disable %s.", name);
1825                                         return 0;
1826                                 }
1827
1828                         } else
1829                                 log_debug("Couldn't parse line '%s'", l);
1830                 }
1831         }
1832
1833         /* Default is "enable" */
1834         log_debug("Preset file doesn't say anything about %s, enabling.", name);
1835         return 1;
1836 }
1837
1838 int unit_file_preset(
1839                 UnitFileScope scope,
1840                 bool runtime,
1841                 const char *root_dir,
1842                 char **files,
1843                 UnitFilePresetMode mode,
1844                 bool force,
1845                 UnitFileChange **changes,
1846                 unsigned *n_changes) {
1847
1848         _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1849         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1850         _cleanup_free_ char *config_path = NULL;
1851         char **i;
1852         int r, q;
1853
1854         assert(scope >= 0);
1855         assert(scope < _UNIT_FILE_SCOPE_MAX);
1856         assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
1857
1858         r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1859         if (r < 0)
1860                 return r;
1861
1862         r = get_config_path(scope, runtime, root_dir, &config_path);
1863         if (r < 0)
1864                 return r;
1865
1866         STRV_FOREACH(i, files) {
1867
1868                 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1869                         return -EINVAL;
1870
1871                 r = unit_file_query_preset(scope, root_dir, *i);
1872                 if (r < 0)
1873                         return r;
1874
1875                 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1876                         r = install_info_add_auto(&plus, *i);
1877                 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1878                         r = install_info_add_auto(&minus, *i);
1879                 else
1880                         r = 0;
1881                 if (r < 0)
1882                         return r;
1883         }
1884
1885         r = 0;
1886
1887         if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1888                 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1889
1890                 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1891
1892                 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1893                 if (r == 0)
1894                         r = q;
1895         }
1896
1897         if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
1898                 /* Returns number of symlinks that where supposed to be installed. */
1899                 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
1900                 if (r == 0)
1901                         r = q;
1902         }
1903
1904         return r;
1905 }
1906
1907 int unit_file_preset_all(
1908                 UnitFileScope scope,
1909                 bool runtime,
1910                 const char *root_dir,
1911                 UnitFilePresetMode mode,
1912                 bool force,
1913                 UnitFileChange **changes,
1914                 unsigned *n_changes) {
1915
1916         _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1917         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1918         _cleanup_free_ char *config_path = NULL;
1919         char **i;
1920         int r, q;
1921
1922         assert(scope >= 0);
1923         assert(scope < _UNIT_FILE_SCOPE_MAX);
1924         assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
1925
1926         r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1927         if (r < 0)
1928                 return r;
1929
1930         r = get_config_path(scope, runtime, root_dir, &config_path);
1931         if (r < 0)
1932                 return r;
1933
1934         STRV_FOREACH(i, paths.unit_path) {
1935                 _cleanup_closedir_ DIR *d = NULL;
1936                 _cleanup_free_ char *buf = NULL;
1937                 const char *units_dir;
1938
1939                 if (!isempty(root_dir)) {
1940                         buf = strjoin(root_dir, "/", *i, NULL);
1941                         if (!buf)
1942                                 return -ENOMEM;
1943
1944                         units_dir = buf;
1945                 } else
1946                         units_dir = *i;
1947
1948                 d = opendir(units_dir);
1949                 if (!d) {
1950                         if (errno == ENOENT)
1951                                 continue;
1952
1953                         return -errno;
1954                 }
1955
1956                 for (;;) {
1957                         struct dirent *de;
1958
1959                         errno = 0;
1960                         de = readdir(d);
1961                         if (!de && errno != 0)
1962                                 return -errno;
1963
1964                         if (!de)
1965                                 break;
1966
1967                         if (ignore_file(de->d_name))
1968                                 continue;
1969
1970                         if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
1971                                 continue;
1972
1973                         dirent_ensure_type(d, de);
1974
1975                         if (de->d_type != DT_REG)
1976                                 continue;
1977
1978                         r = unit_file_query_preset(scope, root_dir, de->d_name);
1979                         if (r < 0)
1980                                 return r;
1981
1982                         if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
1983                                 r = install_info_add_auto(&plus, de->d_name);
1984                         else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
1985                                 r = install_info_add_auto(&minus, de->d_name);
1986                         else
1987                                 r = 0;
1988                         if (r < 0)
1989                                 return r;
1990                 }
1991         }
1992
1993         r = 0;
1994
1995         if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
1996                 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1997
1998                 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
1999
2000                 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
2001                 if (r == 0)
2002                         r = q;
2003         }
2004
2005         if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2006                 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2007                 if (r == 0)
2008                         r = q;
2009         }
2010
2011         return r;
2012 }
2013
2014 static void unitfilelist_free(UnitFileList **f) {
2015         if (!*f)
2016                 return;
2017
2018         free((*f)->path);
2019         free(*f);
2020 }
2021 #define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
2022
2023 int unit_file_get_list(
2024                 UnitFileScope scope,
2025                 const char *root_dir,
2026                 Hashmap *h) {
2027
2028         _cleanup_lookup_paths_free_ LookupPaths paths = {};
2029         char **i;
2030         int r;
2031
2032         assert(scope >= 0);
2033         assert(scope < _UNIT_FILE_SCOPE_MAX);
2034         assert(h);
2035
2036         if (root_dir && scope != UNIT_FILE_SYSTEM)
2037                 return -EINVAL;
2038
2039         r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2040         if (r < 0)
2041                 return r;
2042
2043         STRV_FOREACH(i, paths.unit_path) {
2044                 _cleanup_closedir_ DIR *d = NULL;
2045                 _cleanup_free_ char *buf = NULL;
2046                 const char *units_dir;
2047
2048                 if (!isempty(root_dir)) {
2049                         buf = strjoin(root_dir, "/", *i, NULL);
2050                         if (!buf)
2051                                 return -ENOMEM;
2052
2053                         units_dir = buf;
2054                 } else
2055                         units_dir = *i;
2056
2057                 d = opendir(units_dir);
2058                 if (!d) {
2059                         if (errno == ENOENT)
2060                                 continue;
2061
2062                         return -errno;
2063                 }
2064
2065                 for (;;) {
2066                         _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
2067                         struct dirent *de;
2068
2069                         errno = 0;
2070                         de = readdir(d);
2071                         if (!de && errno != 0)
2072                                 return -errno;
2073
2074                         if (!de)
2075                                 break;
2076
2077                         if (ignore_file(de->d_name))
2078                                 continue;
2079
2080                         if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2081                                 continue;
2082
2083                         if (hashmap_get(h, de->d_name))
2084                                 continue;
2085
2086                         dirent_ensure_type(d, de);
2087
2088                         if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2089                                 continue;
2090
2091                         f = new0(UnitFileList, 1);
2092                         if (!f)
2093                                 return -ENOMEM;
2094
2095                         f->path = path_make_absolute(de->d_name, units_dir);
2096                         if (!f->path)
2097                                 return -ENOMEM;
2098
2099                         r = null_or_empty_path(f->path);
2100                         if (r < 0 && r != -ENOENT)
2101                                 return r;
2102                         else if (r > 0) {
2103                                 f->state =
2104                                         path_startswith(*i, "/run") ?
2105                                         UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2106                                 goto found;
2107                         }
2108
2109                         r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2110                         if (r < 0)
2111                                 return r;
2112                         else if (r > 0) {
2113                                 f->state = UNIT_FILE_ENABLED;
2114                                 goto found;
2115                         }
2116
2117                         r = unit_file_can_install(&paths, root_dir, f->path, true);
2118                         if (r == -EINVAL ||  /* Invalid setting? */
2119                             r == -EBADMSG || /* Invalid format? */
2120                             r == -ENOENT     /* Included file not found? */)
2121                                 f->state = UNIT_FILE_INVALID;
2122                         else if (r < 0)
2123                                 return r;
2124                         else if (r > 0)
2125                                 f->state = UNIT_FILE_DISABLED;
2126                         else
2127                                 f->state = UNIT_FILE_STATIC;
2128
2129                 found:
2130                         r = hashmap_put(h, basename(f->path), f);
2131                         if (r < 0)
2132                                 return r;
2133                         f = NULL; /* prevent cleanup */
2134                 }
2135         }
2136
2137         return r;
2138 }
2139
2140 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2141         [UNIT_FILE_ENABLED] = "enabled",
2142         [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2143         [UNIT_FILE_LINKED] = "linked",
2144         [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2145         [UNIT_FILE_MASKED] = "masked",
2146         [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2147         [UNIT_FILE_STATIC] = "static",
2148         [UNIT_FILE_DISABLED] = "disabled",
2149         [UNIT_FILE_INVALID] = "invalid",
2150 };
2151
2152 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2153
2154 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2155         [UNIT_FILE_SYMLINK] = "symlink",
2156         [UNIT_FILE_UNLINK] = "unlink",
2157 };
2158
2159 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2160
2161 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MODE_MAX] = {
2162         [UNIT_FILE_PRESET_FULL] = "full",
2163         [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2164         [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2165 };
2166
2167 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);