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