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