chiark / gitweb /
8f27c6d47962b33eaa4fe6f7324fb9c1af861412
[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
42 typedef struct {
43         Hashmap *will_install;
44         Hashmap *have_installed;
45 } InstallContext;
46
47 #define _cleanup_lookup_paths_free_ \
48         __attribute__((cleanup(lookup_paths_free)))
49 #define _cleanup_install_context_done_ \
50         __attribute__((cleanup(install_context_done)))
51
52 static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope) {
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                                  NULL, NULL, NULL);
63 }
64
65 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
66         char *p = NULL;
67         int r;
68
69         assert(scope >= 0);
70         assert(scope < _UNIT_FILE_SCOPE_MAX);
71         assert(ret);
72
73         switch (scope) {
74
75         case UNIT_FILE_SYSTEM:
76
77                 if (root_dir && runtime)
78                         asprintf(&p, "%s/run/systemd/system", root_dir);
79                 else if (runtime)
80                         p = strdup("/run/systemd/system");
81                 else if (root_dir)
82                         asprintf(&p, "%s/%s", root_dir, SYSTEM_CONFIG_UNIT_PATH);
83                 else
84                         p = strdup(SYSTEM_CONFIG_UNIT_PATH);
85
86                 break;
87
88         case UNIT_FILE_GLOBAL:
89
90                 if (root_dir)
91                         return -EINVAL;
92
93                 if (runtime)
94                         p = strdup("/run/systemd/user");
95                 else
96                         p = strdup(USER_CONFIG_UNIT_PATH);
97                 break;
98
99         case UNIT_FILE_USER:
100
101                 if (root_dir || runtime)
102                         return -EINVAL;
103
104                 r = user_config_home(&p);
105                 if (r <= 0)
106                         return r < 0 ? r : -ENOENT;
107
108                 break;
109
110         default:
111                 assert_not_reached("Bad scope");
112         }
113
114         if (!p)
115                 return -ENOMEM;
116
117         *ret = p;
118         return 0;
119 }
120
121 static int add_file_change(
122                 UnitFileChange **changes,
123                 unsigned *n_changes,
124                 UnitFileChangeType type,
125                 const char *path,
126                 const char *source) {
127
128         UnitFileChange *c;
129         unsigned i;
130
131         assert(path);
132         assert(!changes == !n_changes);
133
134         if (!changes)
135                 return 0;
136
137         c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
138         if (!c)
139                 return -ENOMEM;
140
141         *changes = c;
142         i = *n_changes;
143
144         c[i].type = type;
145         c[i].path = strdup(path);
146         if (!c[i].path)
147                 return -ENOMEM;
148
149         if (source) {
150                 c[i].source = strdup(source);
151                 if (!c[i].source) {
152                         free(c[i].path);
153                         return -ENOMEM;
154                 }
155         } else
156                 c[i].source = NULL;
157
158         *n_changes = i+1;
159         return 0;
160 }
161
162 static int mark_symlink_for_removal(
163                 Set **remove_symlinks_to,
164                 const char *p) {
165
166         char *n;
167         int r;
168
169         assert(p);
170
171         r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
172         if (r < 0)
173                 return r;
174
175         n = strdup(p);
176         if (!n)
177                 return -ENOMEM;
178
179         path_kill_slashes(n);
180
181         r = set_consume(*remove_symlinks_to, n);
182         if (r < 0)
183                 return r == -EEXIST ? 0 : r;
184
185         return 0;
186 }
187
188 static int remove_marked_symlinks_fd(
189                 Set *remove_symlinks_to,
190                 int fd,
191                 const char *path,
192                 const char *config_path,
193                 bool *deleted,
194                 UnitFileChange **changes,
195                 unsigned *n_changes,
196                 char** files) {
197
198         int r = 0;
199         _cleanup_closedir_ DIR *d = NULL;
200
201         assert(remove_symlinks_to);
202         assert(fd >= 0);
203         assert(path);
204         assert(config_path);
205         assert(deleted);
206
207         d = fdopendir(fd);
208         if (!d) {
209                 close_nointr_nofail(fd);
210                 return -errno;
211         }
212
213         rewinddir(d);
214
215         for (;;) {
216                 struct dirent *de;
217                 union dirent_storage buf;
218                 int k;
219
220                 k = readdir_r(d, &buf.de, &de);
221                 if (k != 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                                 close_nointr_nofail(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, files);
256
257                         if (r == 0)
258                                 r = q;
259
260                 } else if (de->d_type == DT_LNK) {
261                         _cleanup_free_ char *p = NULL, *dest = NULL;
262                         int q;
263                         bool found;
264
265                         p = path_make_absolute(de->d_name, path);
266                         if (!p)
267                                 return -ENOMEM;
268
269                         q = readlink_and_canonicalize(p, &dest);
270                         if (q < 0) {
271                                 if (q == -ENOENT)
272                                         continue;
273
274                                 if (r == 0)
275                                         r = q;
276                                 continue;
277                         }
278
279                         found =
280                                 set_get(remove_symlinks_to, dest) ||
281                                 set_get(remove_symlinks_to, path_get_file_name(dest));
282
283                         if (unit_name_is_instance(p))
284                                 found = found && strv_contains(files, path_get_file_name(p));
285
286                         if (found) {
287
288                                 if (unlink(p) < 0 && errno != ENOENT) {
289
290                                         if (r == 0)
291                                                 r = -errno;
292                                 } else {
293                                         rmdir_parents(p, config_path);
294                                         path_kill_slashes(p);
295
296                                         add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
297
298                                         if (!set_get(remove_symlinks_to, p)) {
299
300                                                 q = mark_symlink_for_removal(&remove_symlinks_to, p);
301                                                 if (q < 0) {
302                                                         if (r == 0)
303                                                                 r = q;
304                                                 } else
305                                                         *deleted = true;
306                                         }
307                                 }
308                         }
309                 }
310         }
311
312         return r;
313 }
314
315 static int remove_marked_symlinks(
316                 Set *remove_symlinks_to,
317                 const char *config_path,
318                 UnitFileChange **changes,
319                 unsigned *n_changes,
320                 char** files) {
321
322         int fd, r = 0;
323         bool deleted;
324
325         assert(config_path);
326
327         if (set_size(remove_symlinks_to) <= 0)
328                 return 0;
329
330         fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
331         if (fd < 0)
332                 return -errno;
333
334         do {
335                 int q, cfd;
336                 deleted = false;
337
338                 cfd = dup(fd);
339                 if (cfd < 0) {
340                         r = -errno;
341                         break;
342                 }
343
344                 /* This takes possession of cfd and closes it */
345                 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, files);
346                 if (r == 0)
347                         r = q;
348         } while (deleted);
349
350         close_nointr_nofail(fd);
351
352         return r;
353 }
354
355 static int find_symlinks_fd(
356                 const char *name,
357                 int fd,
358                 const char *path,
359                 const char *config_path,
360                 bool *same_name_link) {
361
362         int r = 0;
363         _cleanup_closedir_ DIR *d = NULL;
364
365         assert(name);
366         assert(fd >= 0);
367         assert(path);
368         assert(config_path);
369         assert(same_name_link);
370
371         d = fdopendir(fd);
372         if (!d) {
373                 close_nointr_nofail(fd);
374                 return -errno;
375         }
376
377         for (;;) {
378                 int k;
379                 struct dirent *de;
380                 union dirent_storage buf;
381
382                 k = readdir_r(d, &buf.de, &de);
383                 if (k != 0)
384                         return -errno;
385
386                 if (!de)
387                         return r;
388
389                 if (ignore_file(de->d_name))
390                         continue;
391
392                 dirent_ensure_type(d, de);
393
394                 if (de->d_type == DT_DIR) {
395                         int nfd, q;
396                         _cleanup_free_ char *p = NULL;
397
398                         nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
399                         if (nfd < 0) {
400                                 if (errno == ENOENT)
401                                         continue;
402
403                                 if (r == 0)
404                                         r = -errno;
405                                 continue;
406                         }
407
408                         p = path_make_absolute(de->d_name, path);
409                         if (!p) {
410                                 close_nointr_nofail(nfd);
411                                 return -ENOMEM;
412                         }
413
414                         /* This will close nfd, regardless whether it succeeds or not */
415                         q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
416
417                         if (q > 0)
418                                 return 1;
419
420                         if (r == 0)
421                                 r = q;
422
423                 } else if (de->d_type == DT_LNK) {
424                         _cleanup_free_ char *p = NULL, *dest = NULL;
425                         bool found_path, found_dest, b = false;
426                         int q;
427
428                         /* Acquire symlink name */
429                         p = path_make_absolute(de->d_name, path);
430                         if (!p)
431                                 return -ENOMEM;
432
433                         /* Acquire symlink destination */
434                         q = readlink_and_canonicalize(p, &dest);
435                         if (q < 0) {
436                                 if (q == -ENOENT)
437                                         continue;
438
439                                 if (r == 0)
440                                         r = q;
441                                 continue;
442                         }
443
444                         /* Check if the symlink itself matches what we
445                          * are looking for */
446                         if (path_is_absolute(name))
447                                 found_path = path_equal(p, name);
448                         else
449                                 found_path = streq(de->d_name, name);
450
451                         /* Check if what the symlink points to
452                          * matches what we are looking for */
453                         if (path_is_absolute(name))
454                                 found_dest = path_equal(dest, name);
455                         else
456                                 found_dest = streq(path_get_file_name(dest), name);
457
458                         if (found_path && found_dest) {
459                                 _cleanup_free_ char *t = NULL;
460
461                                 /* Filter out same name links in the main
462                                  * config path */
463                                 t = path_make_absolute(name, config_path);
464                                 if (!t)
465                                         return -ENOMEM;
466
467                                 b = path_equal(t, p);
468                         }
469
470                         if (b)
471                                 *same_name_link = true;
472                         else if (found_path || found_dest)
473                                 return 1;
474                 }
475         }
476
477         return r;
478 }
479
480 static int find_symlinks(
481                 const char *name,
482                 const char *config_path,
483                 bool *same_name_link) {
484
485         int fd;
486
487         assert(name);
488         assert(config_path);
489         assert(same_name_link);
490
491         fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
492         if (fd < 0) {
493                 if (errno == ENOENT)
494                         return 0;
495                 return -errno;
496         }
497
498         /* This takes possession of fd and closes it */
499         return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
500 }
501
502 static int find_symlinks_in_scope(
503                 UnitFileScope scope,
504                 const char *root_dir,
505                 const char *name,
506                 UnitFileState *state) {
507
508         int r;
509         _cleanup_free_ char *path = NULL;
510         bool same_name_link_runtime = false, same_name_link = false;
511
512         assert(scope >= 0);
513         assert(scope < _UNIT_FILE_SCOPE_MAX);
514         assert(name);
515
516         if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
517
518                 /* First look in runtime config path */
519                 r = get_config_path(scope, true, root_dir, &path);
520                 if (r < 0)
521                         return r;
522
523                 r = find_symlinks(name, path, &same_name_link_runtime);
524                 if (r < 0)
525                         return r;
526                 else if (r > 0) {
527                         *state = UNIT_FILE_ENABLED_RUNTIME;
528                         return r;
529                 }
530         }
531
532         /* Then look in the normal config path */
533         r = get_config_path(scope, false, root_dir, &path);
534         if (r < 0)
535                 return r;
536
537         r = find_symlinks(name, path, &same_name_link);
538         if (r < 0)
539                 return r;
540         else if (r > 0) {
541                 *state = UNIT_FILE_ENABLED;
542                 return r;
543         }
544
545         /* Hmm, we didn't find it, but maybe we found the same name
546          * link? */
547         if (same_name_link_runtime) {
548                 *state = UNIT_FILE_LINKED_RUNTIME;
549                 return 1;
550         } else if (same_name_link) {
551                 *state = UNIT_FILE_LINKED;
552                 return 1;
553         }
554
555         return 0;
556 }
557
558 int unit_file_mask(
559                 UnitFileScope scope,
560                 bool runtime,
561                 const char *root_dir,
562                 char *files[],
563                 bool force,
564                 UnitFileChange **changes,
565                 unsigned *n_changes) {
566
567         char **i;
568         _cleanup_free_ char *prefix;
569         int r;
570
571         assert(scope >= 0);
572         assert(scope < _UNIT_FILE_SCOPE_MAX);
573
574         r = get_config_path(scope, runtime, root_dir, &prefix);
575         if (r < 0)
576                 return r;
577
578         STRV_FOREACH(i, files) {
579                 _cleanup_free_ char *path = NULL;
580
581                 if (!unit_name_is_valid(*i, true)) {
582                         if (r == 0)
583                                 r = -EINVAL;
584                         continue;
585                 }
586
587                 path = path_make_absolute(*i, prefix);
588                 if (!path) {
589                         r = -ENOMEM;
590                         break;
591                 }
592
593                 if (symlink("/dev/null", path) >= 0) {
594                         add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
595
596                         continue;
597                 }
598
599                 if (errno == EEXIST) {
600
601                         if (null_or_empty_path(path) > 0)
602                                 continue;
603
604                         if (force) {
605                                 unlink(path);
606
607                                 if (symlink("/dev/null", path) >= 0) {
608
609                                         add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
610                                         add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
611
612                                         continue;
613                                 }
614                         }
615
616                         if (r == 0)
617                                 r = -EEXIST;
618                 } else {
619                         if (r == 0)
620                                 r = -errno;
621                 }
622         }
623
624         return r;
625 }
626
627 int unit_file_unmask(
628                 UnitFileScope scope,
629                 bool runtime,
630                 const char *root_dir,
631                 char *files[],
632                 UnitFileChange **changes,
633                 unsigned *n_changes) {
634
635         char **i, *config_path = NULL;
636         int r, q;
637         Set *remove_symlinks_to = NULL;
638
639         assert(scope >= 0);
640         assert(scope < _UNIT_FILE_SCOPE_MAX);
641
642         r = get_config_path(scope, runtime, root_dir, &config_path);
643         if (r < 0)
644                 goto finish;
645
646         STRV_FOREACH(i, files) {
647                 char *path;
648
649                 if (!unit_name_is_valid(*i, true)) {
650                         if (r == 0)
651                                 r = -EINVAL;
652                         continue;
653                 }
654
655                 path = path_make_absolute(*i, config_path);
656                 if (!path) {
657                         r = -ENOMEM;
658                         break;
659                 }
660
661                 q = null_or_empty_path(path);
662                 if (q > 0) {
663                         if (unlink(path) >= 0) {
664                                 mark_symlink_for_removal(&remove_symlinks_to, path);
665                                 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
666
667                                 free(path);
668                                 continue;
669                         }
670
671                         q = -errno;
672                 }
673
674                 if (q != -ENOENT && r == 0)
675                         r = q;
676
677                 free(path);
678         }
679
680
681 finish:
682         q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
683         if (r == 0)
684                 r = q;
685
686         set_free_free(remove_symlinks_to);
687         free(config_path);
688
689         return r;
690 }
691
692 int unit_file_link(
693                 UnitFileScope scope,
694                 bool runtime,
695                 const char *root_dir,
696                 char *files[],
697                 bool force,
698                 UnitFileChange **changes,
699                 unsigned *n_changes) {
700
701         _cleanup_lookup_paths_free_ LookupPaths paths = {};
702         char **i;
703         _cleanup_free_ char *config_path = NULL;
704         int r, q;
705
706         assert(scope >= 0);
707         assert(scope < _UNIT_FILE_SCOPE_MAX);
708
709         r = lookup_paths_init_from_scope(&paths, scope);
710         if (r < 0)
711                 return r;
712
713         r = get_config_path(scope, runtime, root_dir, &config_path);
714         if (r < 0)
715                 return r;
716
717         STRV_FOREACH(i, files) {
718                 _cleanup_free_ char *path = NULL;
719                 char *fn;
720                 struct stat st;
721
722                 fn = path_get_file_name(*i);
723
724                 if (!path_is_absolute(*i) ||
725                     !unit_name_is_valid(fn, true)) {
726                         if (r == 0)
727                                 r = -EINVAL;
728                         continue;
729                 }
730
731                 if (lstat(*i, &st) < 0) {
732                         if (r == 0)
733                                 r = -errno;
734                         continue;
735                 }
736
737                 if (!S_ISREG(st.st_mode)) {
738                         r = -ENOENT;
739                         continue;
740                 }
741
742                 q = in_search_path(*i, paths.unit_path);
743                 if (q < 0)
744                         return q;
745
746                 if (q > 0)
747                         continue;
748
749                 path = path_make_absolute(fn, config_path);
750                 if (!path)
751                         return -ENOMEM;
752
753                 if (symlink(*i, path) >= 0) {
754                         add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
755                         continue;
756                 }
757
758                 if (errno == EEXIST) {
759                         _cleanup_free_ char *dest = NULL;
760
761                         q = readlink_and_make_absolute(path, &dest);
762
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 = path_get_file_name(path);
866
867         if (!unit_name_is_valid(name, true))
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                              const char *lvalue,
927                              int ltype,
928                              const char *rvalue,
929                              void *data,
930                              void *userdata) {
931
932         char *w;
933         size_t l;
934         char *state;
935         InstallContext *c = data;
936
937         assert(filename);
938         assert(lvalue);
939         assert(rvalue);
940
941         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
942                 _cleanup_free_ char *n;
943                 int r;
944
945                 n = strndup(w, l);
946                 if (!n)
947                         return -ENOMEM;
948
949                 r = install_info_add(c, n, NULL);
950                 if (r < 0)
951                         return r;
952         }
953
954         return 0;
955 }
956
957 static int config_parse_user(const char *unit,
958                              const char *filename,
959                              unsigned line,
960                              const char *section,
961                              const char *lvalue,
962                              int ltype,
963                              const char *rvalue,
964                              void *data,
965                              void *userdata) {
966
967         InstallInfo *i = data;
968         char* printed;
969
970         assert(filename);
971         assert(lvalue);
972         assert(rvalue);
973
974         printed = install_full_printf(i, rvalue);
975         if (!printed)
976                 return -ENOMEM;
977
978         free(i->user);
979         i->user = printed;
980
981         return 0;
982 }
983
984 static int unit_file_load(
985                 InstallContext *c,
986                 InstallInfo *info,
987                 const char *path,
988                 bool allow_symlink) {
989
990         const ConfigTableItem items[] = {
991                 { "Install", "Alias",      config_parse_strv, 0, &info->aliases     },
992                 { "Install", "WantedBy",   config_parse_strv, 0, &info->wanted_by   },
993                 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
994                 { "Install", "Also",       config_parse_also, 0, c                  },
995                 { "Exec",    "User",       config_parse_user, 0, info               },
996                 { NULL, NULL, NULL, 0, NULL }
997         };
998
999         int fd;
1000         _cleanup_fclose_ FILE *f = NULL;
1001         int r;
1002
1003         assert(c);
1004         assert(info);
1005         assert(path);
1006
1007         fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1008         if (fd < 0)
1009                 return -errno;
1010
1011         f = fdopen(fd, "re");
1012         if (!f) {
1013                 close_nointr_nofail(fd);
1014                 return -ENOMEM;
1015         }
1016
1017         r = config_parse(NULL, path, f, NULL,
1018                          config_item_table_lookup, (void*) items, true, true, info);
1019         if (r < 0)
1020                 return r;
1021
1022         return
1023                 strv_length(info->aliases) +
1024                 strv_length(info->wanted_by) +
1025                 strv_length(info->required_by);
1026 }
1027
1028 static int unit_file_search(
1029                 InstallContext *c,
1030                 InstallInfo *info,
1031                 LookupPaths *paths,
1032                 const char *root_dir,
1033                 bool allow_symlink) {
1034
1035         char **p;
1036         int r;
1037
1038         assert(c);
1039         assert(info);
1040         assert(paths);
1041
1042         if (info->path)
1043                 return unit_file_load(c, info, info->path, allow_symlink);
1044
1045         assert(info->name);
1046
1047         STRV_FOREACH(p, paths->unit_path) {
1048                 char *path = NULL;
1049
1050                 if (isempty(root_dir))
1051                         asprintf(&path, "%s/%s", *p, info->name);
1052                 else
1053                         asprintf(&path, "%s/%s/%s", root_dir, *p, info->name);
1054
1055                 if (!path)
1056                         return -ENOMEM;
1057
1058                 r = unit_file_load(c, info, path, allow_symlink);
1059
1060                 if (r >= 0)
1061                         info->path = path;
1062                 else {
1063                         if (r == -ENOENT && unit_name_is_instance(info->name)) {
1064                                 /* unit file doesn't exist, however instance enablement was request */
1065                                 /* we will check if it is possible to load template unit file */
1066                                 char *template = NULL,
1067                                      *template_path = NULL,
1068                                      *template_dir = NULL;
1069
1070                                 template = unit_name_template(info->name);
1071                                 if (!template) {
1072                                         free(path);
1073                                         return -ENOMEM;
1074                                 }
1075
1076                                 /* we will reuse path variable since we don't need it anymore */
1077                                 template_dir = path;
1078                                 *(strrchr(path, '/') + 1) = '\0';
1079
1080                                 template_path = strjoin(template_dir, template, NULL);
1081                                 if (!template_path) {
1082                                         free(path);
1083                                         free(template);
1084                                         return -ENOMEM;
1085                                 }
1086
1087                                 /* let's try to load template unit */
1088                                 r = unit_file_load(c, info, template_path, allow_symlink);
1089                                 if (r >= 0) {
1090                                         info->path = strdup(template_path);
1091                                         if (!info->path) {
1092                                                 free(path);
1093                                                 free(template);
1094                                                 free(template_path);
1095                                                 return -ENOMEM;
1096                                         }
1097                                 }
1098
1099                                 free(template);
1100                                 free(template_path);
1101                         }
1102                         free(path);
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                         strv_length(i->aliases) +
1136                         strv_length(i->wanted_by) +
1137                         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         unlink(new_path);
1176
1177         if (symlink(old_path, new_path) >= 0) {
1178                 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1179                 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1180                 return 0;
1181         }
1182
1183         return -errno;
1184 }
1185
1186 static int install_info_symlink_alias(
1187                 InstallInfo *i,
1188                 const char *config_path,
1189                 bool force,
1190                 UnitFileChange **changes,
1191                 unsigned *n_changes) {
1192
1193         char **s;
1194         int r = 0, q;
1195
1196         assert(i);
1197         assert(config_path);
1198
1199         STRV_FOREACH(s, i->aliases) {
1200                 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1201
1202                 dst = install_full_printf(i, *s);
1203                 if (!dst)
1204                         return -ENOMEM;
1205
1206                 alias_path = path_make_absolute(dst, config_path);
1207                 if (!alias_path)
1208                         return -ENOMEM;
1209
1210                 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1211                 if (r == 0)
1212                         r = q;
1213         }
1214
1215         return r;
1216 }
1217
1218 static int install_info_symlink_wants(
1219                 InstallInfo *i,
1220                 const char *config_path,
1221                 bool force,
1222                 UnitFileChange **changes,
1223                 unsigned *n_changes) {
1224
1225         char **s;
1226         int r = 0, q;
1227
1228         assert(i);
1229         assert(config_path);
1230
1231         STRV_FOREACH(s, i->wanted_by) {
1232                 _cleanup_free_ char *path = NULL, *dst = NULL;
1233
1234                 dst = install_full_printf(i, *s);
1235                 if (!dst)
1236                         return -ENOMEM;
1237
1238                 if (!unit_name_is_valid(dst, true)) {
1239                         r = -EINVAL;
1240                         continue;
1241                 }
1242
1243                 if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
1244                         return -ENOMEM;
1245
1246                 q = create_symlink(i->path, path, force, changes, n_changes);
1247
1248                 if (r == 0)
1249                         r = q;
1250         }
1251
1252         return r;
1253 }
1254
1255 static int install_info_symlink_requires(
1256                 InstallInfo *i,
1257                 const char *config_path,
1258                 bool force,
1259                 UnitFileChange **changes,
1260                 unsigned *n_changes) {
1261
1262         char **s;
1263         int r = 0, q;
1264
1265         assert(i);
1266         assert(config_path);
1267
1268         STRV_FOREACH(s, i->required_by) {
1269                 _cleanup_free_ char *path = NULL, *dst = NULL;
1270
1271                 dst = install_full_printf(i, *s);
1272                 if (!dst)
1273                         return -ENOMEM;
1274
1275                 if (!unit_name_is_valid(dst, true)) {
1276                         r = -EINVAL;
1277                         continue;
1278                 }
1279
1280                 if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
1281                         return -ENOMEM;
1282
1283                 q = create_symlink(i->path, path, force, changes, n_changes);
1284
1285                 if (r == 0)
1286                         r = q;
1287         }
1288
1289         return r;
1290 }
1291
1292 static int install_info_symlink_link(
1293                 InstallInfo *i,
1294                 LookupPaths *paths,
1295                 const char *config_path,
1296                 bool force,
1297                 UnitFileChange **changes,
1298                 unsigned *n_changes) {
1299
1300         int r;
1301         _cleanup_free_ char *path = NULL;
1302
1303         assert(i);
1304         assert(paths);
1305         assert(config_path);
1306         assert(i->path);
1307
1308         r = in_search_path(i->path, paths->unit_path);
1309         if (r != 0)
1310                 return r;
1311
1312         if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1313                 return -ENOMEM;
1314
1315         r = create_symlink(i->path, path, force, changes, n_changes);
1316         return r;
1317 }
1318
1319 static int install_info_apply(
1320                 InstallInfo *i,
1321                 LookupPaths *paths,
1322                 const char *config_path,
1323                 bool force,
1324                 UnitFileChange **changes,
1325                 unsigned *n_changes) {
1326
1327         int r, q;
1328
1329         assert(i);
1330         assert(paths);
1331         assert(config_path);
1332
1333         r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1334
1335         q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1336         if (r == 0)
1337                 r = q;
1338
1339         q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1340         if (r == 0)
1341                 r = q;
1342
1343         q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1344         if (r == 0)
1345                 r = q;
1346
1347         return r;
1348 }
1349
1350 static int install_context_apply(
1351                 InstallContext *c,
1352                 LookupPaths *paths,
1353                 const char *config_path,
1354                 const char *root_dir,
1355                 bool force,
1356                 UnitFileChange **changes,
1357                 unsigned *n_changes) {
1358
1359         InstallInfo *i;
1360         int r = 0, q;
1361
1362         assert(c);
1363         assert(paths);
1364         assert(config_path);
1365
1366         while ((i = hashmap_first(c->will_install))) {
1367
1368                 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1369                 if (q < 0)
1370                         return q;
1371
1372                 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1373
1374                 q = unit_file_search(c, i, paths, root_dir, false);
1375                 if (q < 0) {
1376                         if (r >= 0)
1377                                 r = q;
1378
1379                         return r;
1380                 } else if (r >= 0)
1381                         r += q;
1382
1383                 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1384                 if (r >= 0 && q < 0)
1385                         r = q;
1386         }
1387
1388         return r;
1389 }
1390
1391 static int install_context_mark_for_removal(
1392                 InstallContext *c,
1393                 LookupPaths *paths,
1394                 Set **remove_symlinks_to,
1395                 const char *config_path,
1396                 const char *root_dir) {
1397
1398         InstallInfo *i;
1399         int r = 0, q;
1400
1401         assert(c);
1402         assert(paths);
1403         assert(config_path);
1404
1405         /* Marks all items for removal */
1406
1407         while ((i = hashmap_first(c->will_install))) {
1408
1409                 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1410                 if (q < 0)
1411                         return q;
1412
1413                 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1414
1415                 q = unit_file_search(c, i, paths, root_dir, false);
1416                 if (q < 0) {
1417                         if (r >= 0)
1418                                 r = q;
1419
1420                         return r;
1421                 } else if (r >= 0)
1422                         r += q;
1423
1424                 if (unit_name_is_instance(i->name)) {
1425                         char *unit_file = NULL;
1426
1427                         unit_file = path_get_file_name(i->path);
1428
1429                         if (unit_name_is_instance(unit_file))
1430                                 /* unit file named as instance exists, thus all symlinks pointing to it, will be removed */
1431                                 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1432                         else
1433                                 /* does not exist, thus we will mark for removal symlinks to template unit file */
1434                                 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1435                 } else
1436                         q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1437
1438                 if (r >= 0 && q < 0)
1439                         r = q;
1440         }
1441
1442         return r;
1443 }
1444
1445 int unit_file_enable(
1446                 UnitFileScope scope,
1447                 bool runtime,
1448                 const char *root_dir,
1449                 char *files[],
1450                 bool force,
1451                 UnitFileChange **changes,
1452                 unsigned *n_changes) {
1453
1454         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1455         _cleanup_install_context_done_ InstallContext c = {};
1456         char **i;
1457         _cleanup_free_ char *config_path = NULL;
1458         int r;
1459
1460         assert(scope >= 0);
1461         assert(scope < _UNIT_FILE_SCOPE_MAX);
1462
1463         r = lookup_paths_init_from_scope(&paths, scope);
1464         if (r < 0)
1465                 return r;
1466
1467         r = get_config_path(scope, runtime, root_dir, &config_path);
1468         if (r < 0)
1469                 return r;
1470
1471         STRV_FOREACH(i, files) {
1472                 r = install_info_add_auto(&c, *i);
1473                 if (r < 0)
1474                         return r;
1475         }
1476
1477         /* This will return the number of symlink rules that were
1478         supposed to be created, not the ones actually created. This is
1479         useful to determine whether the passed files had any
1480         installation data at all. */
1481         r = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1482         return r;
1483 }
1484
1485 int unit_file_disable(
1486                 UnitFileScope scope,
1487                 bool runtime,
1488                 const char *root_dir,
1489                 char *files[],
1490                 UnitFileChange **changes,
1491                 unsigned *n_changes) {
1492
1493         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1494         _cleanup_install_context_done_ InstallContext c = {};
1495         char **i;
1496         _cleanup_free_ char *config_path = NULL;
1497         _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1498         int r, q;
1499
1500         assert(scope >= 0);
1501         assert(scope < _UNIT_FILE_SCOPE_MAX);
1502
1503         r = lookup_paths_init_from_scope(&paths, scope);
1504         if (r < 0)
1505                 return r;
1506
1507         r = get_config_path(scope, runtime, root_dir, &config_path);
1508         if (r < 0)
1509                 return r;
1510
1511         STRV_FOREACH(i, files) {
1512                 r = install_info_add_auto(&c, *i);
1513                 if (r < 0)
1514                         return r;
1515         }
1516
1517         r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1518
1519         q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1520         if (r == 0)
1521                 r = q;
1522
1523         return r;
1524 }
1525
1526 int unit_file_reenable(
1527                 UnitFileScope scope,
1528                 bool runtime,
1529                 const char *root_dir,
1530                 char *files[],
1531                 bool force,
1532                 UnitFileChange **changes,
1533                 unsigned *n_changes) {
1534
1535         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1536         _cleanup_install_context_done_ InstallContext c = {};
1537         char **i;
1538         _cleanup_free_ char *config_path = NULL;
1539         _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1540         int r, q;
1541
1542         assert(scope >= 0);
1543         assert(scope < _UNIT_FILE_SCOPE_MAX);
1544
1545         r = lookup_paths_init_from_scope(&paths, scope);
1546         if (r < 0)
1547                 return r;
1548
1549         r = get_config_path(scope, runtime, root_dir, &config_path);
1550         if (r < 0)
1551                 return r;
1552
1553         STRV_FOREACH(i, files) {
1554                 r = mark_symlink_for_removal(&remove_symlinks_to, *i);
1555                 if (r < 0)
1556                         return r;
1557
1558                 r = install_info_add_auto(&c, *i);
1559                 if (r < 0)
1560                         return r;
1561         }
1562
1563         r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1564
1565         /* Returns number of symlinks that where supposed to be installed. */
1566         q = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1567         if (r == 0)
1568                 r = q;
1569
1570         return r;
1571 }
1572
1573 UnitFileState unit_file_get_state(
1574                 UnitFileScope scope,
1575                 const char *root_dir,
1576                 const char *name) {
1577
1578         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1579         UnitFileState state = _UNIT_FILE_STATE_INVALID;
1580         char **i;
1581         _cleanup_free_ char *path = NULL;
1582         int r;
1583
1584         assert(scope >= 0);
1585         assert(scope < _UNIT_FILE_SCOPE_MAX);
1586         assert(name);
1587
1588         if (root_dir && scope != UNIT_FILE_SYSTEM)
1589                 return -EINVAL;
1590
1591         if (!unit_name_is_valid(name, true))
1592                 return -EINVAL;
1593
1594         r = lookup_paths_init_from_scope(&paths, scope);
1595         if (r < 0)
1596                 return r;
1597
1598         STRV_FOREACH(i, paths.unit_path) {
1599                 struct stat st;
1600
1601                 free(path);
1602                 path = NULL;
1603
1604                 if (root_dir)
1605                         asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1606                 else
1607                         asprintf(&path, "%s/%s", *i, name);
1608
1609                 if (!path)
1610                         return -ENOMEM;
1611
1612                 /*
1613                  * Search for a unit file in our default paths, to
1614                  * be sure, that there are no broken symlinks.
1615                  */
1616                 if (lstat(path, &st) < 0) {
1617                         r = -errno;
1618                         if (errno != ENOENT)
1619                                 return r;
1620
1621                         if (!unit_name_is_instance(name))
1622                                 continue;
1623                 } else {
1624                         if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1625                                 return -ENOENT;
1626
1627                         r = null_or_empty_path(path);
1628                         if (r < 0 && r != -ENOENT)
1629                                 return r;
1630                         else if (r > 0) {
1631                                 state = path_startswith(*i, "/run") ?
1632                                         UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1633                                 return state;
1634                         }
1635                 }
1636
1637                 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1638                 if (r < 0)
1639                         return r;
1640                 else if (r > 0)
1641                         return state;
1642
1643                 r = unit_file_can_install(&paths, root_dir, path, true);
1644                 if (r < 0 && errno != ENOENT)
1645                         return r;
1646                 else if (r > 0)
1647                         return UNIT_FILE_DISABLED;
1648                 else if (r == 0)
1649                         return UNIT_FILE_STATIC;
1650         }
1651
1652         return r < 0 ? r : state;
1653 }
1654
1655 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1656         _cleanup_strv_free_ char **files = NULL;
1657         char **i;
1658         int r;
1659
1660         assert(scope >= 0);
1661         assert(scope < _UNIT_FILE_SCOPE_MAX);
1662         assert(name);
1663
1664         if (scope == UNIT_FILE_SYSTEM)
1665                 r = conf_files_list(&files, ".preset", NULL,
1666                                     "/etc/systemd/system-preset",
1667                                     "/usr/local/lib/systemd/system-preset",
1668                                     "/usr/lib/systemd/system-preset",
1669 #ifdef HAVE_SPLIT_USR
1670                                     "/lib/systemd/system-preset",
1671 #endif
1672                                     NULL);
1673         else if (scope == UNIT_FILE_GLOBAL)
1674                 r = conf_files_list(&files, ".preset", NULL,
1675                                     "/etc/systemd/user-preset",
1676                                     "/usr/local/lib/systemd/user-preset",
1677                                     "/usr/lib/systemd/user-preset",
1678                                     NULL);
1679         else
1680                 return 1;
1681
1682         if (r < 0)
1683                 return r;
1684
1685         STRV_FOREACH(i, files) {
1686                 _cleanup_fclose_ FILE *f;
1687
1688                 f = fopen(*i, "re");
1689                 if (!f) {
1690                         if (errno == ENOENT)
1691                                 continue;
1692
1693                         return -errno;
1694                 }
1695
1696                 for (;;) {
1697                         char line[LINE_MAX], *l;
1698
1699                         if (!fgets(line, sizeof(line), f))
1700                                 break;
1701
1702                         l = strstrip(line);
1703                         if (!*l)
1704                                 continue;
1705
1706                         if (strchr(COMMENTS "\n", *l))
1707                                 continue;
1708
1709                         if (first_word(l, "enable")) {
1710                                 l += 6;
1711                                 l += strspn(l, WHITESPACE);
1712
1713                                 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1714                                         return 1;
1715
1716                         } else if (first_word(l, "disable")) {
1717                                 l += 7;
1718                                 l += strspn(l, WHITESPACE);
1719
1720                                 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1721                                         return 0;
1722
1723                         } else
1724                                 log_debug("Couldn't parse line '%s'", l);
1725                 }
1726         }
1727
1728         /* Default is "enable" */
1729         return 1;
1730 }
1731
1732 int unit_file_preset(
1733                 UnitFileScope scope,
1734                 bool runtime,
1735                 const char *root_dir,
1736                 char *files[],
1737                 bool force,
1738                 UnitFileChange **changes,
1739                 unsigned *n_changes) {
1740
1741         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1742         _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1743         char **i;
1744         _cleanup_free_ char *config_path = NULL;
1745         _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1746         int r, q;
1747
1748         assert(scope >= 0);
1749         assert(scope < _UNIT_FILE_SCOPE_MAX);
1750
1751         r = lookup_paths_init_from_scope(&paths, scope);
1752         if (r < 0)
1753                 return r;
1754
1755         r = get_config_path(scope, runtime, root_dir, &config_path);
1756         if (r < 0)
1757                 return r;
1758
1759         STRV_FOREACH(i, files) {
1760
1761                 if (!unit_name_is_valid(*i, true))
1762                         return -EINVAL;
1763
1764                 r = unit_file_query_preset(scope, *i);
1765                 if (r < 0)
1766                         return r;
1767
1768                 if (r)
1769                         r = install_info_add_auto(&plus, *i);
1770                 else
1771                         r = install_info_add_auto(&minus, *i);
1772
1773                 if (r < 0)
1774                         return r;
1775         }
1776
1777         r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to,
1778                                              config_path, root_dir);
1779
1780         q = remove_marked_symlinks(remove_symlinks_to, config_path,
1781                                    changes, n_changes, files);
1782         if (r == 0)
1783                 r = q;
1784
1785         /* Returns number of symlinks that where supposed to be installed. */
1786         q = install_context_apply(&plus, &paths, config_path, root_dir, force,
1787                                   changes, n_changes);
1788         if (r == 0)
1789                 r = q;
1790
1791         return r;
1792 }
1793
1794 static void unitfilelist_free(UnitFileList **f) {
1795         if (!*f)
1796                 return;
1797
1798         free((*f)->path);
1799         free(*f);
1800 }
1801
1802 int unit_file_get_list(
1803                 UnitFileScope scope,
1804                 const char *root_dir,
1805                 Hashmap *h) {
1806
1807         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1808         char **i;
1809         _cleanup_free_ char *buf = NULL;
1810         _cleanup_closedir_ DIR *d = NULL;
1811         int r;
1812
1813         assert(scope >= 0);
1814         assert(scope < _UNIT_FILE_SCOPE_MAX);
1815         assert(h);
1816
1817         if (root_dir && scope != UNIT_FILE_SYSTEM)
1818                 return -EINVAL;
1819
1820         r = lookup_paths_init_from_scope(&paths, scope);
1821         if (r < 0)
1822                 return r;
1823
1824         STRV_FOREACH(i, paths.unit_path) {
1825                 const char *units_dir;
1826
1827                 free(buf);
1828                 buf = NULL;
1829
1830                 if (root_dir) {
1831                         if (asprintf(&buf, "%s/%s", root_dir, *i) < 0)
1832                                 return -ENOMEM;
1833
1834                         units_dir = buf;
1835                 } else
1836                         units_dir = *i;
1837
1838                 if (d)
1839                         closedir(d);
1840
1841                 d = opendir(units_dir);
1842                 if (!d) {
1843                         if (errno == ENOENT)
1844                                 continue;
1845
1846                         return -errno;
1847                 }
1848
1849                 for (;;) {
1850                         struct dirent *de;
1851                         union dirent_storage buffer;
1852                         UnitFileList __attribute__((cleanup(unitfilelist_free)))
1853                                 *f = NULL;
1854
1855                         r = readdir_r(d, &buffer.de, &de);
1856                         if (r != 0)
1857                                 return -r;
1858
1859                         if (!de)
1860                                 break;
1861
1862                         if (ignore_file(de->d_name))
1863                                 continue;
1864
1865                         if (!unit_name_is_valid(de->d_name, true))
1866                                 continue;
1867
1868                         if (hashmap_get(h, de->d_name))
1869                                 continue;
1870
1871                         r = dirent_ensure_type(d, de);
1872                         if (r < 0) {
1873                                 if (r == -ENOENT)
1874                                         continue;
1875
1876                                 return r;
1877                         }
1878
1879                         if (de->d_type != DT_LNK && de->d_type != DT_REG)
1880                                 continue;
1881
1882                         f = new0(UnitFileList, 1);
1883                         if (!f)
1884                                 return -ENOMEM;
1885
1886                         f->path = path_make_absolute(de->d_name, units_dir);
1887                         if (!f->path)
1888                                 return -ENOMEM;
1889
1890                         r = null_or_empty_path(f->path);
1891                         if (r < 0 && r != -ENOENT)
1892                                 return r;
1893                         else if (r > 0) {
1894                                 f->state =
1895                                         path_startswith(*i, "/run") ?
1896                                         UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1897                                 goto found;
1898                         }
1899
1900                         r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
1901                         if (r < 0)
1902                                 return r;
1903                         else if (r > 0) {
1904                                 f->state = UNIT_FILE_ENABLED;
1905                                 goto found;
1906                         }
1907
1908                         r = unit_file_can_install(&paths, root_dir, f->path, true);
1909                         if (r == -EINVAL ||  /* Invalid setting? */
1910                             r == -EBADMSG || /* Invalid format? */
1911                             r == -ENOENT     /* Included file not found? */)
1912                                 f->state = UNIT_FILE_INVALID;
1913                         else if (r < 0)
1914                                 return r;
1915                         else if (r > 0)
1916                                 f->state = UNIT_FILE_DISABLED;
1917                         else
1918                                 f->state = UNIT_FILE_STATIC;
1919
1920                 found:
1921                         r = hashmap_put(h, path_get_file_name(f->path), f);
1922                         if (r < 0)
1923                                 return r;
1924                         f = NULL; /* prevent cleanup */
1925                 }
1926         }
1927
1928         return r;
1929 }
1930
1931 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
1932         [UNIT_FILE_ENABLED] = "enabled",
1933         [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
1934         [UNIT_FILE_LINKED] = "linked",
1935         [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
1936         [UNIT_FILE_MASKED] = "masked",
1937         [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
1938         [UNIT_FILE_STATIC] = "static",
1939         [UNIT_FILE_DISABLED] = "disabled",
1940         [UNIT_FILE_INVALID] = "invalid",
1941 };
1942
1943 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
1944
1945 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
1946         [UNIT_FILE_SYMLINK] = "symlink",
1947         [UNIT_FILE_UNLINK] = "unlink",
1948 };
1949
1950 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);