chiark / gitweb /
install: make "reenable" work with templated units
[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 *path2 = 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                 _cleanup_free_ char *path = NULL;
518
519                 /* First look in runtime config path */
520                 r = get_config_path(scope, true, root_dir, &path);
521                 if (r < 0)
522                         return r;
523
524                 r = find_symlinks(name, path, &same_name_link_runtime);
525                 if (r < 0)
526                         return r;
527                 else if (r > 0) {
528                         *state = UNIT_FILE_ENABLED_RUNTIME;
529                         return r;
530                 }
531         }
532
533         /* Then look in the normal config path */
534         r = get_config_path(scope, false, root_dir, &path2);
535         if (r < 0)
536                 return r;
537
538         r = find_symlinks(name, path2, &same_name_link);
539         if (r < 0)
540                 return r;
541         else if (r > 0) {
542                 *state = UNIT_FILE_ENABLED;
543                 return r;
544         }
545
546         /* Hmm, we didn't find it, but maybe we found the same name
547          * link? */
548         if (same_name_link_runtime) {
549                 *state = UNIT_FILE_LINKED_RUNTIME;
550                 return 1;
551         } else if (same_name_link) {
552                 *state = UNIT_FILE_LINKED;
553                 return 1;
554         }
555
556         return 0;
557 }
558
559 int unit_file_mask(
560                 UnitFileScope scope,
561                 bool runtime,
562                 const char *root_dir,
563                 char *files[],
564                 bool force,
565                 UnitFileChange **changes,
566                 unsigned *n_changes) {
567
568         char **i;
569         _cleanup_free_ char *prefix;
570         int r;
571
572         assert(scope >= 0);
573         assert(scope < _UNIT_FILE_SCOPE_MAX);
574
575         r = get_config_path(scope, runtime, root_dir, &prefix);
576         if (r < 0)
577                 return r;
578
579         STRV_FOREACH(i, files) {
580                 _cleanup_free_ char *path = NULL;
581
582                 if (!unit_name_is_valid(*i, true)) {
583                         if (r == 0)
584                                 r = -EINVAL;
585                         continue;
586                 }
587
588                 path = path_make_absolute(*i, prefix);
589                 if (!path) {
590                         r = -ENOMEM;
591                         break;
592                 }
593
594                 if (symlink("/dev/null", path) >= 0) {
595                         add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
596
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, true)) {
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);
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 = path_get_file_name(*i);
724
725                 if (!path_is_absolute(*i) ||
726                     !unit_name_is_valid(fn, true)) {
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
764                         if (q < 0 && errno != ENOENT) {
765                                 if (r == 0)
766                                         r = q;
767                                 continue;
768                         }
769
770                         if (q >= 0 && path_equal(dest, *i))
771                                 continue;
772
773                         if (force) {
774                                 unlink(path);
775
776                                 if (symlink(*i, path) >= 0) {
777
778                                         add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
779                                         add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
780
781                                         continue;
782                                 }
783                         }
784
785                         if (r == 0)
786                                 r = -EEXIST;
787                 } else {
788                         if (r == 0)
789                                 r = -errno;
790                 }
791         }
792
793         return r;
794 }
795
796 void unit_file_list_free(Hashmap *h) {
797         UnitFileList *i;
798
799         while ((i = hashmap_steal_first(h))) {
800                 free(i->path);
801                 free(i);
802         }
803
804         hashmap_free(h);
805 }
806
807 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
808         unsigned i;
809
810         assert(changes || n_changes == 0);
811
812         if (!changes)
813                 return;
814
815         for (i = 0; i < n_changes; i++) {
816                 free(changes[i].path);
817                 free(changes[i].source);
818         }
819
820         free(changes);
821 }
822
823 static void install_info_free(InstallInfo *i) {
824         assert(i);
825
826         free(i->name);
827         free(i->path);
828         strv_free(i->aliases);
829         strv_free(i->wanted_by);
830         strv_free(i->required_by);
831         free(i);
832 }
833
834 static void install_info_hashmap_free(Hashmap *m) {
835         InstallInfo *i;
836
837         if (!m)
838                 return;
839
840         while ((i = hashmap_steal_first(m)))
841                 install_info_free(i);
842
843         hashmap_free(m);
844 }
845
846 static void install_context_done(InstallContext *c) {
847         assert(c);
848
849         install_info_hashmap_free(c->will_install);
850         install_info_hashmap_free(c->have_installed);
851
852         c->will_install = c->have_installed = NULL;
853 }
854
855 static int install_info_add(
856                 InstallContext *c,
857                 const char *name,
858                 const char *path) {
859         InstallInfo *i = NULL;
860         int r;
861
862         assert(c);
863         assert(name || path);
864
865         if (!name)
866                 name = path_get_file_name(path);
867
868         if (!unit_name_is_valid(name, true))
869                 return -EINVAL;
870
871         if (hashmap_get(c->have_installed, name) ||
872             hashmap_get(c->will_install, name))
873                 return 0;
874
875         r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
876         if (r < 0)
877                 return r;
878
879         i = new0(InstallInfo, 1);
880         if (!i)
881                 return -ENOMEM;
882
883         i->name = strdup(name);
884         if (!i->name) {
885                 r = -ENOMEM;
886                 goto fail;
887         }
888
889         if (path) {
890                 i->path = strdup(path);
891                 if (!i->path) {
892                         r = -ENOMEM;
893                         goto fail;
894                 }
895         }
896
897         r = hashmap_put(c->will_install, i->name, i);
898         if (r < 0)
899                 goto fail;
900
901         return 0;
902
903 fail:
904         if (i)
905                 install_info_free(i);
906
907         return r;
908 }
909
910 static int install_info_add_auto(
911                 InstallContext *c,
912                 const char *name_or_path) {
913
914         assert(c);
915         assert(name_or_path);
916
917         if (path_is_absolute(name_or_path))
918                 return install_info_add(c, NULL, name_or_path);
919         else
920                 return install_info_add(c, name_or_path, NULL);
921 }
922
923 static int config_parse_also(const char *unit,
924                              const char *filename,
925                              unsigned line,
926                              const char *section,
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                              const char *lvalue,
963                              int ltype,
964                              const char *rvalue,
965                              void *data,
966                              void *userdata) {
967
968         InstallInfo *i = data;
969         char* printed;
970
971         assert(filename);
972         assert(lvalue);
973         assert(rvalue);
974
975         printed = install_full_printf(i, rvalue);
976         if (!printed)
977                 return -ENOMEM;
978
979         free(i->user);
980         i->user = printed;
981
982         return 0;
983 }
984
985 static int unit_file_load(
986                 InstallContext *c,
987                 InstallInfo *info,
988                 const char *path,
989                 bool allow_symlink) {
990
991         const ConfigTableItem items[] = {
992                 { "Install", "Alias",      config_parse_strv, 0, &info->aliases     },
993                 { "Install", "WantedBy",   config_parse_strv, 0, &info->wanted_by   },
994                 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
995                 { "Install", "Also",       config_parse_also, 0, c                  },
996                 { "Exec",    "User",       config_parse_user, 0, info               },
997                 { NULL, NULL, NULL, 0, NULL }
998         };
999
1000         int fd;
1001         _cleanup_fclose_ FILE *f = NULL;
1002         int r;
1003
1004         assert(c);
1005         assert(info);
1006         assert(path);
1007
1008         fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1009         if (fd < 0)
1010                 return -errno;
1011
1012         f = fdopen(fd, "re");
1013         if (!f) {
1014                 close_nointr_nofail(fd);
1015                 return -ENOMEM;
1016         }
1017
1018         r = config_parse(NULL, path, f, NULL,
1019                          config_item_table_lookup, (void*) items, true, true, info);
1020         if (r < 0)
1021                 return r;
1022
1023         return
1024                 strv_length(info->aliases) +
1025                 strv_length(info->wanted_by) +
1026                 strv_length(info->required_by);
1027 }
1028
1029 static int unit_file_search(
1030                 InstallContext *c,
1031                 InstallInfo *info,
1032                 LookupPaths *paths,
1033                 const char *root_dir,
1034                 bool allow_symlink) {
1035
1036         char **p;
1037         int r;
1038
1039         assert(c);
1040         assert(info);
1041         assert(paths);
1042
1043         if (info->path)
1044                 return unit_file_load(c, info, info->path, allow_symlink);
1045
1046         assert(info->name);
1047
1048         STRV_FOREACH(p, paths->unit_path) {
1049                 char *path = NULL;
1050
1051                 if (isempty(root_dir))
1052                         asprintf(&path, "%s/%s", *p, info->name);
1053                 else
1054                         asprintf(&path, "%s/%s/%s", root_dir, *p, info->name);
1055
1056                 if (!path)
1057                         return -ENOMEM;
1058
1059                 r = unit_file_load(c, info, path, allow_symlink);
1060
1061                 if (r >= 0)
1062                         info->path = path;
1063                 else {
1064                         if (r == -ENOENT && unit_name_is_instance(info->name)) {
1065                                 /* unit file doesn't exist, however instance enablement was request */
1066                                 /* we will check if it is possible to load template unit file */
1067                                 char *template = NULL,
1068                                      *template_path = NULL,
1069                                      *template_dir = NULL;
1070
1071                                 template = unit_name_template(info->name);
1072                                 if (!template) {
1073                                         free(path);
1074                                         return -ENOMEM;
1075                                 }
1076
1077                                 /* we will reuse path variable since we don't need it anymore */
1078                                 template_dir = path;
1079                                 *(strrchr(path, '/') + 1) = '\0';
1080
1081                                 template_path = strjoin(template_dir, template, NULL);
1082                                 if (!template_path) {
1083                                         free(path);
1084                                         free(template);
1085                                         return -ENOMEM;
1086                                 }
1087
1088                                 /* let's try to load template unit */
1089                                 r = unit_file_load(c, info, template_path, allow_symlink);
1090                                 if (r >= 0) {
1091                                         info->path = strdup(template_path);
1092                                         if (!info->path) {
1093                                                 free(path);
1094                                                 free(template);
1095                                                 free(template_path);
1096                                                 return -ENOMEM;
1097                                         }
1098                                 }
1099
1100                                 free(template);
1101                                 free(template_path);
1102                         }
1103                         free(path);
1104                 }
1105
1106                 if (r != -ENOENT && r != -ELOOP)
1107                         return r;
1108         }
1109
1110         return -ENOENT;
1111 }
1112
1113 static int unit_file_can_install(
1114                 LookupPaths *paths,
1115                 const char *root_dir,
1116                 const char *name,
1117                 bool allow_symlink) {
1118
1119         _cleanup_install_context_done_ InstallContext c = {};
1120         InstallInfo *i;
1121         int r;
1122
1123         assert(paths);
1124         assert(name);
1125
1126         r = install_info_add_auto(&c, name);
1127         if (r < 0)
1128                 return r;
1129
1130         assert_se(i = hashmap_first(c.will_install));
1131
1132         r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1133
1134         if (r >= 0)
1135                 r =
1136                         strv_length(i->aliases) +
1137                         strv_length(i->wanted_by) +
1138                         strv_length(i->required_by);
1139
1140         return r;
1141 }
1142
1143 static int create_symlink(
1144                 const char *old_path,
1145                 const char *new_path,
1146                 bool force,
1147                 UnitFileChange **changes,
1148                 unsigned *n_changes) {
1149
1150         _cleanup_free_ char *dest = NULL;
1151         int r;
1152
1153         assert(old_path);
1154         assert(new_path);
1155
1156         mkdir_parents_label(new_path, 0755);
1157
1158         if (symlink(old_path, new_path) >= 0) {
1159                 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1160                 return 0;
1161         }
1162
1163         if (errno != EEXIST)
1164                 return -errno;
1165
1166         r = readlink_and_make_absolute(new_path, &dest);
1167         if (r < 0)
1168                 return r;
1169
1170         if (path_equal(dest, old_path))
1171                 return 0;
1172
1173         if (!force)
1174                 return -EEXIST;
1175
1176         unlink(new_path);
1177
1178         if (symlink(old_path, new_path) >= 0) {
1179                 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1180                 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1181                 return 0;
1182         }
1183
1184         return -errno;
1185 }
1186
1187 static int install_info_symlink_alias(
1188                 InstallInfo *i,
1189                 const char *config_path,
1190                 bool force,
1191                 UnitFileChange **changes,
1192                 unsigned *n_changes) {
1193
1194         char **s;
1195         int r = 0, q;
1196
1197         assert(i);
1198         assert(config_path);
1199
1200         STRV_FOREACH(s, i->aliases) {
1201                 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1202
1203                 dst = install_full_printf(i, *s);
1204                 if (!dst)
1205                         return -ENOMEM;
1206
1207                 alias_path = path_make_absolute(dst, config_path);
1208                 if (!alias_path)
1209                         return -ENOMEM;
1210
1211                 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1212                 if (r == 0)
1213                         r = q;
1214         }
1215
1216         return r;
1217 }
1218
1219 static int install_info_symlink_wants(
1220                 InstallInfo *i,
1221                 const char *config_path,
1222                 bool force,
1223                 UnitFileChange **changes,
1224                 unsigned *n_changes) {
1225
1226         char **s;
1227         int r = 0, q;
1228
1229         assert(i);
1230         assert(config_path);
1231
1232         STRV_FOREACH(s, i->wanted_by) {
1233                 _cleanup_free_ char *path = NULL, *dst = NULL;
1234
1235                 dst = install_full_printf(i, *s);
1236                 if (!dst)
1237                         return -ENOMEM;
1238
1239                 if (!unit_name_is_valid(dst, true)) {
1240                         r = -EINVAL;
1241                         continue;
1242                 }
1243
1244                 if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
1245                         return -ENOMEM;
1246
1247                 q = create_symlink(i->path, path, force, changes, n_changes);
1248
1249                 if (r == 0)
1250                         r = q;
1251         }
1252
1253         return r;
1254 }
1255
1256 static int install_info_symlink_requires(
1257                 InstallInfo *i,
1258                 const char *config_path,
1259                 bool force,
1260                 UnitFileChange **changes,
1261                 unsigned *n_changes) {
1262
1263         char **s;
1264         int r = 0, q;
1265
1266         assert(i);
1267         assert(config_path);
1268
1269         STRV_FOREACH(s, i->required_by) {
1270                 _cleanup_free_ char *path = NULL, *dst = NULL;
1271
1272                 dst = install_full_printf(i, *s);
1273                 if (!dst)
1274                         return -ENOMEM;
1275
1276                 if (!unit_name_is_valid(dst, true)) {
1277                         r = -EINVAL;
1278                         continue;
1279                 }
1280
1281                 if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
1282                         return -ENOMEM;
1283
1284                 q = create_symlink(i->path, path, force, changes, n_changes);
1285
1286                 if (r == 0)
1287                         r = q;
1288         }
1289
1290         return r;
1291 }
1292
1293 static int install_info_symlink_link(
1294                 InstallInfo *i,
1295                 LookupPaths *paths,
1296                 const char *config_path,
1297                 bool force,
1298                 UnitFileChange **changes,
1299                 unsigned *n_changes) {
1300
1301         int r;
1302         _cleanup_free_ char *path = NULL;
1303
1304         assert(i);
1305         assert(paths);
1306         assert(config_path);
1307         assert(i->path);
1308
1309         r = in_search_path(i->path, paths->unit_path);
1310         if (r != 0)
1311                 return r;
1312
1313         if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1314                 return -ENOMEM;
1315
1316         r = create_symlink(i->path, path, force, changes, n_changes);
1317         return r;
1318 }
1319
1320 static int install_info_apply(
1321                 InstallInfo *i,
1322                 LookupPaths *paths,
1323                 const char *config_path,
1324                 bool force,
1325                 UnitFileChange **changes,
1326                 unsigned *n_changes) {
1327
1328         int r, q;
1329
1330         assert(i);
1331         assert(paths);
1332         assert(config_path);
1333
1334         r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1335
1336         q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1337         if (r == 0)
1338                 r = q;
1339
1340         q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1341         if (r == 0)
1342                 r = q;
1343
1344         q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1345         if (r == 0)
1346                 r = q;
1347
1348         return r;
1349 }
1350
1351 static int install_context_apply(
1352                 InstallContext *c,
1353                 LookupPaths *paths,
1354                 const char *config_path,
1355                 const char *root_dir,
1356                 bool force,
1357                 UnitFileChange **changes,
1358                 unsigned *n_changes) {
1359
1360         InstallInfo *i;
1361         int r = 0, q;
1362
1363         assert(c);
1364         assert(paths);
1365         assert(config_path);
1366
1367         while ((i = hashmap_first(c->will_install))) {
1368
1369                 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1370                 if (q < 0)
1371                         return q;
1372
1373                 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1374
1375                 q = unit_file_search(c, i, paths, root_dir, false);
1376                 if (q < 0) {
1377                         if (r >= 0)
1378                                 r = q;
1379
1380                         return r;
1381                 } else if (r >= 0)
1382                         r += q;
1383
1384                 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1385                 if (r >= 0 && q < 0)
1386                         r = q;
1387         }
1388
1389         return r;
1390 }
1391
1392 static int install_context_mark_for_removal(
1393                 InstallContext *c,
1394                 LookupPaths *paths,
1395                 Set **remove_symlinks_to,
1396                 const char *config_path,
1397                 const char *root_dir) {
1398
1399         InstallInfo *i;
1400         int r = 0, q;
1401
1402         assert(c);
1403         assert(paths);
1404         assert(config_path);
1405
1406         /* Marks all items for removal */
1407
1408         while ((i = hashmap_first(c->will_install))) {
1409
1410                 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1411                 if (q < 0)
1412                         return q;
1413
1414                 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1415
1416                 q = unit_file_search(c, i, paths, root_dir, false);
1417                 if (q == -ENOENT) {
1418                         /* do nothing */
1419                 } else if (q < 0) {
1420                         if (r >= 0)
1421                                 r = q;
1422
1423                         return r;
1424                 } else if (r >= 0)
1425                         r += q;
1426
1427                 if (unit_name_is_instance(i->name)) {
1428                         char *unit_file = NULL;
1429
1430                         unit_file = path_get_file_name(i->path);
1431
1432                         if (unit_name_is_instance(unit_file))
1433                                 /* unit file named as instance exists, thus all symlinks pointing to it, will be removed */
1434                                 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1435                         else
1436                                 /* does not exist, thus we will mark for removal symlinks to template unit file */
1437                                 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1438                 } else
1439                         q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1440
1441                 if (r >= 0 && q < 0)
1442                         r = q;
1443         }
1444
1445         return r;
1446 }
1447
1448 int unit_file_enable(
1449                 UnitFileScope scope,
1450                 bool runtime,
1451                 const char *root_dir,
1452                 char *files[],
1453                 bool force,
1454                 UnitFileChange **changes,
1455                 unsigned *n_changes) {
1456
1457         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1458         _cleanup_install_context_done_ InstallContext c = {};
1459         char **i;
1460         _cleanup_free_ char *config_path = NULL;
1461         int r;
1462
1463         assert(scope >= 0);
1464         assert(scope < _UNIT_FILE_SCOPE_MAX);
1465
1466         r = lookup_paths_init_from_scope(&paths, scope);
1467         if (r < 0)
1468                 return r;
1469
1470         r = get_config_path(scope, runtime, root_dir, &config_path);
1471         if (r < 0)
1472                 return r;
1473
1474         STRV_FOREACH(i, files) {
1475                 r = install_info_add_auto(&c, *i);
1476                 if (r < 0)
1477                         return r;
1478         }
1479
1480         /* This will return the number of symlink rules that were
1481         supposed to be created, not the ones actually created. This is
1482         useful to determine whether the passed files had any
1483         installation data at all. */
1484         r = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1485         return r;
1486 }
1487
1488 int unit_file_disable(
1489                 UnitFileScope scope,
1490                 bool runtime,
1491                 const char *root_dir,
1492                 char *files[],
1493                 UnitFileChange **changes,
1494                 unsigned *n_changes) {
1495
1496         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1497         _cleanup_install_context_done_ InstallContext c = {};
1498         char **i;
1499         _cleanup_free_ char *config_path = NULL;
1500         _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1501         int r, q;
1502
1503         assert(scope >= 0);
1504         assert(scope < _UNIT_FILE_SCOPE_MAX);
1505
1506         r = lookup_paths_init_from_scope(&paths, scope);
1507         if (r < 0)
1508                 return r;
1509
1510         r = get_config_path(scope, runtime, root_dir, &config_path);
1511         if (r < 0)
1512                 return r;
1513
1514         STRV_FOREACH(i, files) {
1515                 r = install_info_add_auto(&c, *i);
1516                 if (r < 0)
1517                         return r;
1518         }
1519
1520         r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1521
1522         q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1523         if (r == 0)
1524                 r = q;
1525
1526         return r;
1527 }
1528
1529 int unit_file_reenable(
1530                 UnitFileScope scope,
1531                 bool runtime,
1532                 const char *root_dir,
1533                 char *files[],
1534                 bool force,
1535                 UnitFileChange **changes,
1536                 unsigned *n_changes) {
1537         int r;
1538
1539         r = unit_file_disable(scope, runtime, root_dir, files,
1540                               changes, n_changes);
1541         if (r < 0)
1542                 return r;
1543
1544         return unit_file_enable(scope, runtime, root_dir, files, force,
1545                                 changes, n_changes);
1546 }
1547
1548 int unit_file_set_default(
1549                 UnitFileScope scope,
1550                 const char *root_dir,
1551                 char *file,
1552                 UnitFileChange **changes,
1553                 unsigned *n_changes) {
1554
1555         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1556         _cleanup_install_context_done_ InstallContext c = {};
1557         _cleanup_free_ char *config_path = NULL;
1558         char *path;
1559         int r;
1560         InstallInfo *i = NULL;
1561
1562         assert(scope >= 0);
1563         assert(scope < _UNIT_FILE_SCOPE_MAX);
1564
1565         if (unit_name_to_type(file) != UNIT_TARGET)
1566                 return -EINVAL;
1567
1568         r = lookup_paths_init_from_scope(&paths, scope);
1569         if (r < 0)
1570                 return r;
1571
1572         r = get_config_path(scope, false, root_dir, &config_path);
1573         if (r < 0)
1574                 return r;
1575
1576         r = install_info_add_auto(&c, file);
1577         if (r < 0)
1578                 return r;
1579
1580         i = (InstallInfo*)hashmap_first(c.will_install);
1581
1582         r = unit_file_search(&c, i, &paths, root_dir, false);
1583         if (r < 0)
1584                 return r;
1585
1586         path = strappenda(config_path, "/default.target");
1587         r = create_symlink(i->path, path, true, changes, n_changes);
1588         if (r < 0)
1589                 return r;
1590
1591         return 0;
1592 }
1593
1594 int unit_file_get_default(
1595                 UnitFileScope scope,
1596                 const char *root_dir,
1597                 char **name) {
1598
1599         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1600         char **p;
1601         int r;
1602
1603         r = lookup_paths_init_from_scope(&paths, scope);
1604         if (r < 0)
1605                 return r;
1606
1607         STRV_FOREACH(p, paths.unit_path) {
1608                 _cleanup_free_ char *path = NULL, *tmp = NULL;
1609
1610                 if (isempty(root_dir))
1611                         path = strappend(*p, "/default.target");
1612                 else
1613                         path = strjoin(root_dir, "/", *p, "/default.target", NULL);
1614
1615                 if (!path)
1616                         return -ENOMEM;
1617
1618                 r = readlink_malloc(path, &tmp);
1619                 if (r == -ENOENT)
1620                         continue;
1621                 else if (r < 0)
1622                         return r;
1623
1624                 *name = strdup(path_get_file_name(tmp));
1625                 if (!*name)
1626                         return -ENOMEM;
1627
1628                 return 0;
1629         }
1630
1631         return -ENOENT;
1632 }
1633
1634 UnitFileState unit_file_get_state(
1635                 UnitFileScope scope,
1636                 const char *root_dir,
1637                 const char *name) {
1638
1639         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1640         UnitFileState state = _UNIT_FILE_STATE_INVALID;
1641         char **i;
1642         _cleanup_free_ char *path = NULL;
1643         int r;
1644
1645         assert(scope >= 0);
1646         assert(scope < _UNIT_FILE_SCOPE_MAX);
1647         assert(name);
1648
1649         if (root_dir && scope != UNIT_FILE_SYSTEM)
1650                 return -EINVAL;
1651
1652         if (!unit_name_is_valid(name, true))
1653                 return -EINVAL;
1654
1655         r = lookup_paths_init_from_scope(&paths, scope);
1656         if (r < 0)
1657                 return r;
1658
1659         STRV_FOREACH(i, paths.unit_path) {
1660                 struct stat st;
1661
1662                 free(path);
1663                 path = NULL;
1664
1665                 if (root_dir)
1666                         asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1667                 else
1668                         asprintf(&path, "%s/%s", *i, name);
1669
1670                 if (!path)
1671                         return -ENOMEM;
1672
1673                 /*
1674                  * Search for a unit file in our default paths, to
1675                  * be sure, that there are no broken symlinks.
1676                  */
1677                 if (lstat(path, &st) < 0) {
1678                         r = -errno;
1679                         if (errno != ENOENT)
1680                                 return r;
1681
1682                         if (!unit_name_is_instance(name))
1683                                 continue;
1684                 } else {
1685                         if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1686                                 return -ENOENT;
1687
1688                         r = null_or_empty_path(path);
1689                         if (r < 0 && r != -ENOENT)
1690                                 return r;
1691                         else if (r > 0) {
1692                                 state = path_startswith(*i, "/run") ?
1693                                         UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1694                                 return state;
1695                         }
1696                 }
1697
1698                 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1699                 if (r < 0)
1700                         return r;
1701                 else if (r > 0)
1702                         return state;
1703
1704                 r = unit_file_can_install(&paths, root_dir, path, true);
1705                 if (r < 0 && errno != ENOENT)
1706                         return r;
1707                 else if (r > 0)
1708                         return UNIT_FILE_DISABLED;
1709                 else if (r == 0)
1710                         return UNIT_FILE_STATIC;
1711         }
1712
1713         return r < 0 ? r : state;
1714 }
1715
1716 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1717         _cleanup_strv_free_ char **files = NULL;
1718         char **i;
1719         int r;
1720
1721         assert(scope >= 0);
1722         assert(scope < _UNIT_FILE_SCOPE_MAX);
1723         assert(name);
1724
1725         if (scope == UNIT_FILE_SYSTEM)
1726                 r = conf_files_list(&files, ".preset", NULL,
1727                                     "/etc/systemd/system-preset",
1728                                     "/usr/local/lib/systemd/system-preset",
1729                                     "/usr/lib/systemd/system-preset",
1730 #ifdef HAVE_SPLIT_USR
1731                                     "/lib/systemd/system-preset",
1732 #endif
1733                                     NULL);
1734         else if (scope == UNIT_FILE_GLOBAL)
1735                 r = conf_files_list(&files, ".preset", NULL,
1736                                     "/etc/systemd/user-preset",
1737                                     "/usr/local/lib/systemd/user-preset",
1738                                     "/usr/lib/systemd/user-preset",
1739                                     NULL);
1740         else
1741                 return 1;
1742
1743         if (r < 0)
1744                 return r;
1745
1746         STRV_FOREACH(i, files) {
1747                 _cleanup_fclose_ FILE *f;
1748
1749                 f = fopen(*i, "re");
1750                 if (!f) {
1751                         if (errno == ENOENT)
1752                                 continue;
1753
1754                         return -errno;
1755                 }
1756
1757                 for (;;) {
1758                         char line[LINE_MAX], *l;
1759
1760                         if (!fgets(line, sizeof(line), f))
1761                                 break;
1762
1763                         l = strstrip(line);
1764                         if (!*l)
1765                                 continue;
1766
1767                         if (strchr(COMMENTS "\n", *l))
1768                                 continue;
1769
1770                         if (first_word(l, "enable")) {
1771                                 l += 6;
1772                                 l += strspn(l, WHITESPACE);
1773
1774                                 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1775                                         return 1;
1776
1777                         } else if (first_word(l, "disable")) {
1778                                 l += 7;
1779                                 l += strspn(l, WHITESPACE);
1780
1781                                 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1782                                         return 0;
1783
1784                         } else
1785                                 log_debug("Couldn't parse line '%s'", l);
1786                 }
1787         }
1788
1789         /* Default is "enable" */
1790         return 1;
1791 }
1792
1793 int unit_file_preset(
1794                 UnitFileScope scope,
1795                 bool runtime,
1796                 const char *root_dir,
1797                 char *files[],
1798                 bool force,
1799                 UnitFileChange **changes,
1800                 unsigned *n_changes) {
1801
1802         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1803         _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1804         char **i;
1805         _cleanup_free_ char *config_path = NULL;
1806         _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1807         int r, q;
1808
1809         assert(scope >= 0);
1810         assert(scope < _UNIT_FILE_SCOPE_MAX);
1811
1812         r = lookup_paths_init_from_scope(&paths, scope);
1813         if (r < 0)
1814                 return r;
1815
1816         r = get_config_path(scope, runtime, root_dir, &config_path);
1817         if (r < 0)
1818                 return r;
1819
1820         STRV_FOREACH(i, files) {
1821
1822                 if (!unit_name_is_valid(*i, true))
1823                         return -EINVAL;
1824
1825                 r = unit_file_query_preset(scope, *i);
1826                 if (r < 0)
1827                         return r;
1828
1829                 if (r)
1830                         r = install_info_add_auto(&plus, *i);
1831                 else
1832                         r = install_info_add_auto(&minus, *i);
1833
1834                 if (r < 0)
1835                         return r;
1836         }
1837
1838         r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to,
1839                                              config_path, root_dir);
1840
1841         q = remove_marked_symlinks(remove_symlinks_to, config_path,
1842                                    changes, n_changes, files);
1843         if (r == 0)
1844                 r = q;
1845
1846         /* Returns number of symlinks that where supposed to be installed. */
1847         q = install_context_apply(&plus, &paths, config_path, root_dir, force,
1848                                   changes, n_changes);
1849         if (r == 0)
1850                 r = q;
1851
1852         return r;
1853 }
1854
1855 static void unitfilelist_free(UnitFileList **f) {
1856         if (!*f)
1857                 return;
1858
1859         free((*f)->path);
1860         free(*f);
1861 }
1862
1863 int unit_file_get_list(
1864                 UnitFileScope scope,
1865                 const char *root_dir,
1866                 Hashmap *h) {
1867
1868         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1869         char **i;
1870         _cleanup_free_ char *buf = NULL;
1871         _cleanup_closedir_ DIR *d = NULL;
1872         int r;
1873
1874         assert(scope >= 0);
1875         assert(scope < _UNIT_FILE_SCOPE_MAX);
1876         assert(h);
1877
1878         if (root_dir && scope != UNIT_FILE_SYSTEM)
1879                 return -EINVAL;
1880
1881         r = lookup_paths_init_from_scope(&paths, scope);
1882         if (r < 0)
1883                 return r;
1884
1885         STRV_FOREACH(i, paths.unit_path) {
1886                 const char *units_dir;
1887
1888                 free(buf);
1889                 buf = NULL;
1890
1891                 if (root_dir) {
1892                         if (asprintf(&buf, "%s/%s", root_dir, *i) < 0)
1893                                 return -ENOMEM;
1894
1895                         units_dir = buf;
1896                 } else
1897                         units_dir = *i;
1898
1899                 if (d)
1900                         closedir(d);
1901
1902                 d = opendir(units_dir);
1903                 if (!d) {
1904                         if (errno == ENOENT)
1905                                 continue;
1906
1907                         return -errno;
1908                 }
1909
1910                 for (;;) {
1911                         struct dirent *de;
1912                         union dirent_storage buffer;
1913                         UnitFileList __attribute__((cleanup(unitfilelist_free)))
1914                                 *f = NULL;
1915
1916                         r = readdir_r(d, &buffer.de, &de);
1917                         if (r != 0)
1918                                 return -r;
1919
1920                         if (!de)
1921                                 break;
1922
1923                         if (ignore_file(de->d_name))
1924                                 continue;
1925
1926                         if (!unit_name_is_valid(de->d_name, true))
1927                                 continue;
1928
1929                         if (hashmap_get(h, de->d_name))
1930                                 continue;
1931
1932                         r = dirent_ensure_type(d, de);
1933                         if (r < 0) {
1934                                 if (r == -ENOENT)
1935                                         continue;
1936
1937                                 return r;
1938                         }
1939
1940                         if (de->d_type != DT_LNK && de->d_type != DT_REG)
1941                                 continue;
1942
1943                         f = new0(UnitFileList, 1);
1944                         if (!f)
1945                                 return -ENOMEM;
1946
1947                         f->path = path_make_absolute(de->d_name, units_dir);
1948                         if (!f->path)
1949                                 return -ENOMEM;
1950
1951                         r = null_or_empty_path(f->path);
1952                         if (r < 0 && r != -ENOENT)
1953                                 return r;
1954                         else if (r > 0) {
1955                                 f->state =
1956                                         path_startswith(*i, "/run") ?
1957                                         UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1958                                 goto found;
1959                         }
1960
1961                         r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
1962                         if (r < 0)
1963                                 return r;
1964                         else if (r > 0) {
1965                                 f->state = UNIT_FILE_ENABLED;
1966                                 goto found;
1967                         }
1968
1969                         r = unit_file_can_install(&paths, root_dir, f->path, true);
1970                         if (r == -EINVAL ||  /* Invalid setting? */
1971                             r == -EBADMSG || /* Invalid format? */
1972                             r == -ENOENT     /* Included file not found? */)
1973                                 f->state = UNIT_FILE_INVALID;
1974                         else if (r < 0)
1975                                 return r;
1976                         else if (r > 0)
1977                                 f->state = UNIT_FILE_DISABLED;
1978                         else
1979                                 f->state = UNIT_FILE_STATIC;
1980
1981                 found:
1982                         r = hashmap_put(h, path_get_file_name(f->path), f);
1983                         if (r < 0)
1984                                 return r;
1985                         f = NULL; /* prevent cleanup */
1986                 }
1987         }
1988
1989         return r;
1990 }
1991
1992 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
1993         [UNIT_FILE_ENABLED] = "enabled",
1994         [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
1995         [UNIT_FILE_LINKED] = "linked",
1996         [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
1997         [UNIT_FILE_MASKED] = "masked",
1998         [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
1999         [UNIT_FILE_STATIC] = "static",
2000         [UNIT_FILE_DISABLED] = "disabled",
2001         [UNIT_FILE_INVALID] = "invalid",
2002 };
2003
2004 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2005
2006 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2007         [UNIT_FILE_SYMLINK] = "symlink",
2008         [UNIT_FILE_UNLINK] = "unlink",
2009 };
2010
2011 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);