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