chiark / gitweb /
eb9a5fc0b5d51af6a44b1beb09397b3c86f25f3c
[elogind.git] / src / shared / install.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2011 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty <of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <fnmatch.h>
27
28 #include "util.h"
29 #include "mkdir.h"
30 #include "hashmap.h"
31 #include "set.h"
32 #include "path-util.h"
33 #include "path-lookup.h"
34 #include "strv.h"
35 #include "unit-name.h"
36 #include "install.h"
37 #include "conf-parser.h"
38 #include "conf-files.h"
39 #include "specifier.h"
40 #include "install-printf.h"
41
42 typedef struct {
43         Hashmap *will_install;
44         Hashmap *have_installed;
45 } InstallContext;
46
47 #define _cleanup_lookup_paths_free_ \
48         __attribute__((cleanup(lookup_paths_free)))
49 #define _cleanup_install_context_done_ \
50         __attribute__((cleanup(install_context_done)))
51
52 static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope) {
53         assert(paths);
54         assert(scope >= 0);
55         assert(scope < _UNIT_FILE_SCOPE_MAX);
56
57         zero(*paths);
58
59         return lookup_paths_init(paths,
60                                  scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
61                                  scope == UNIT_FILE_USER,
62                                  NULL, NULL, NULL);
63 }
64
65 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
66         char *p = NULL;
67         int r;
68
69         assert(scope >= 0);
70         assert(scope < _UNIT_FILE_SCOPE_MAX);
71         assert(ret);
72
73         switch (scope) {
74
75         case UNIT_FILE_SYSTEM:
76
77                 if (root_dir && runtime)
78                         asprintf(&p, "%s/run/systemd/system", root_dir);
79                 else if (runtime)
80                         p = strdup("/run/systemd/system");
81                 else if (root_dir)
82                         asprintf(&p, "%s/%s", root_dir, SYSTEM_CONFIG_UNIT_PATH);
83                 else
84                         p = strdup(SYSTEM_CONFIG_UNIT_PATH);
85
86                 break;
87
88         case UNIT_FILE_GLOBAL:
89
90                 if (root_dir)
91                         return -EINVAL;
92
93                 if (runtime)
94                         p = strdup("/run/systemd/user");
95                 else
96                         p = strdup(USER_CONFIG_UNIT_PATH);
97                 break;
98
99         case UNIT_FILE_USER:
100
101                 if (root_dir || runtime)
102                         return -EINVAL;
103
104                 r = user_config_home(&p);
105                 if (r <= 0)
106                         return r < 0 ? r : -ENOENT;
107
108                 break;
109
110         default:
111                 assert_not_reached("Bad scope");
112         }
113
114         if (!p)
115                 return -ENOMEM;
116
117         *ret = p;
118         return 0;
119 }
120
121 static int add_file_change(
122                 UnitFileChange **changes,
123                 unsigned *n_changes,
124                 UnitFileChangeType type,
125                 const char *path,
126                 const char *source) {
127
128         UnitFileChange *c;
129         unsigned i;
130
131         assert(path);
132         assert(!changes == !n_changes);
133
134         if (!changes)
135                 return 0;
136
137         c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
138         if (!c)
139                 return -ENOMEM;
140
141         *changes = c;
142         i = *n_changes;
143
144         c[i].type = type;
145         c[i].path = strdup(path);
146         if (!c[i].path)
147                 return -ENOMEM;
148
149         if (source) {
150                 c[i].source = strdup(source);
151                 if (!c[i].source) {
152                         free(c[i].path);
153                         return -ENOMEM;
154                 }
155         } else
156                 c[i].source = NULL;
157
158         *n_changes = i+1;
159         return 0;
160 }
161
162 static int mark_symlink_for_removal(
163                 Set **remove_symlinks_to,
164                 const char *p) {
165
166         char *n;
167         int r;
168
169         assert(p);
170
171         r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
172         if (r < 0)
173                 return r;
174
175         n = strdup(p);
176         if (!n)
177                 return -ENOMEM;
178
179         path_kill_slashes(n);
180
181         r = set_consume(*remove_symlinks_to, n);
182         if (r < 0)
183                 return r == -EEXIST ? 0 : r;
184
185         return 0;
186 }
187
188 static int remove_marked_symlinks_fd(
189                 Set *remove_symlinks_to,
190                 int fd,
191                 const char *path,
192                 const char *config_path,
193                 bool *deleted,
194                 UnitFileChange **changes,
195                 unsigned *n_changes,
196                 char** files) {
197
198         int r = 0;
199         _cleanup_closedir_ DIR *d = NULL;
200
201         assert(remove_symlinks_to);
202         assert(fd >= 0);
203         assert(path);
204         assert(config_path);
205         assert(deleted);
206
207         d = fdopendir(fd);
208         if (!d) {
209                 close_nointr_nofail(fd);
210                 return -errno;
211         }
212
213         rewinddir(d);
214
215         for (;;) {
216                 struct dirent *de;
217                 union dirent_storage buf;
218                 int k;
219
220                 k = readdir_r(d, &buf.de, &de);
221                 if (k != 0) {
222                         r = -errno;
223                         break;
224                 }
225
226                 if (!de)
227                         break;
228
229                 if (ignore_file(de->d_name))
230                         continue;
231
232                 dirent_ensure_type(d, de);
233
234                 if (de->d_type == DT_DIR) {
235                         int nfd, q;
236                         _cleanup_free_ char *p = NULL;
237
238                         nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
239                         if (nfd < 0) {
240                                 if (errno == ENOENT)
241                                         continue;
242
243                                 if (r == 0)
244                                         r = -errno;
245                                 continue;
246                         }
247
248                         p = path_make_absolute(de->d_name, path);
249                         if (!p) {
250                                 close_nointr_nofail(nfd);
251                                 return -ENOMEM;
252                         }
253
254                         /* This will close nfd, regardless whether it succeeds or not */
255                         q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, files);
256
257                         if (r == 0)
258                                 r = q;
259
260                 } else if (de->d_type == DT_LNK) {
261                         _cleanup_free_ char *p = NULL, *dest = NULL;
262                         int q;
263                         bool found;
264
265                         p = path_make_absolute(de->d_name, path);
266                         if (!p)
267                                 return -ENOMEM;
268
269                         q = readlink_and_canonicalize(p, &dest);
270                         if (q < 0) {
271                                 if (q == -ENOENT)
272                                         continue;
273
274                                 if (r == 0)
275                                         r = q;
276                                 continue;
277                         }
278
279                         found =
280                                 set_get(remove_symlinks_to, dest) ||
281                                 set_get(remove_symlinks_to, path_get_file_name(dest));
282
283                         if (unit_name_is_instance(p))
284                                 found = found && strv_contains(files, path_get_file_name(p));
285
286                         if (found) {
287
288                                 if (unlink(p) < 0 && errno != ENOENT) {
289
290                                         if (r == 0)
291                                                 r = -errno;
292                                 } else {
293                                         rmdir_parents(p, config_path);
294                                         path_kill_slashes(p);
295
296                                         add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
297
298                                         if (!set_get(remove_symlinks_to, p)) {
299
300                                                 q = mark_symlink_for_removal(&remove_symlinks_to, p);
301                                                 if (q < 0) {
302                                                         if (r == 0)
303                                                                 r = q;
304                                                 } else
305                                                         *deleted = true;
306                                         }
307                                 }
308                         }
309                 }
310         }
311
312         return r;
313 }
314
315 static int remove_marked_symlinks(
316                 Set *remove_symlinks_to,
317                 const char *config_path,
318                 UnitFileChange **changes,
319                 unsigned *n_changes,
320                 char** files) {
321
322         int fd, r = 0;
323         bool deleted;
324
325         assert(config_path);
326
327         if (set_size(remove_symlinks_to) <= 0)
328                 return 0;
329
330         fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
331         if (fd < 0)
332                 return -errno;
333
334         do {
335                 int q, cfd;
336                 deleted = false;
337
338                 cfd = dup(fd);
339                 if (cfd < 0) {
340                         r = -errno;
341                         break;
342                 }
343
344                 /* This takes possession of cfd and closes it */
345                 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, files);
346                 if (r == 0)
347                         r = q;
348         } while (deleted);
349
350         close_nointr_nofail(fd);
351
352         return r;
353 }
354
355 static int find_symlinks_fd(
356                 const char *name,
357                 int fd,
358                 const char *path,
359                 const char *config_path,
360                 bool *same_name_link) {
361
362         int r = 0;
363         _cleanup_closedir_ DIR *d = NULL;
364
365         assert(name);
366         assert(fd >= 0);
367         assert(path);
368         assert(config_path);
369         assert(same_name_link);
370
371         d = fdopendir(fd);
372         if (!d) {
373                 close_nointr_nofail(fd);
374                 return -errno;
375         }
376
377         for (;;) {
378                 int k;
379                 struct dirent *de;
380                 union dirent_storage buf;
381
382                 k = readdir_r(d, &buf.de, &de);
383                 if (k != 0)
384                         return -errno;
385
386                 if (!de)
387                         return r;
388
389                 if (ignore_file(de->d_name))
390                         continue;
391
392                 dirent_ensure_type(d, de);
393
394                 if (de->d_type == DT_DIR) {
395                         int nfd, q;
396                         _cleanup_free_ char *p = NULL;
397
398                         nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
399                         if (nfd < 0) {
400                                 if (errno == ENOENT)
401                                         continue;
402
403                                 if (r == 0)
404                                         r = -errno;
405                                 continue;
406                         }
407
408                         p = path_make_absolute(de->d_name, path);
409                         if (!p) {
410                                 close_nointr_nofail(nfd);
411                                 return -ENOMEM;
412                         }
413
414                         /* This will close nfd, regardless whether it succeeds or not */
415                         q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
416
417                         if (q > 0)
418                                 return 1;
419
420                         if (r == 0)
421                                 r = q;
422
423                 } else if (de->d_type == DT_LNK) {
424                         _cleanup_free_ char *p = NULL, *dest = NULL;
425                         bool found_path, found_dest, b = false;
426                         int q;
427
428                         /* Acquire symlink name */
429                         p = path_make_absolute(de->d_name, path);
430                         if (!p)
431                                 return -ENOMEM;
432
433                         /* Acquire symlink destination */
434                         q = readlink_and_canonicalize(p, &dest);
435                         if (q < 0) {
436                                 if (q == -ENOENT)
437                                         continue;
438
439                                 if (r == 0)
440                                         r = q;
441                                 continue;
442                         }
443
444                         /* Check if the symlink itself matches what we
445                          * are looking for */
446                         if (path_is_absolute(name))
447                                 found_path = path_equal(p, name);
448                         else
449                                 found_path = streq(de->d_name, name);
450
451                         /* Check if what the symlink points to
452                          * matches what we are looking for */
453                         if (path_is_absolute(name))
454                                 found_dest = path_equal(dest, name);
455                         else
456                                 found_dest = streq(path_get_file_name(dest), name);
457
458                         if (found_path && found_dest) {
459                                 _cleanup_free_ char *t = NULL;
460
461                                 /* Filter out same name links in the main
462                                  * config path */
463                                 t = path_make_absolute(name, config_path);
464                                 if (!t)
465                                         return -ENOMEM;
466
467                                 b = path_equal(t, p);
468                         }
469
470                         if (b)
471                                 *same_name_link = true;
472                         else if (found_path || found_dest)
473                                 return 1;
474                 }
475         }
476
477         return r;
478 }
479
480 static int find_symlinks(
481                 const char *name,
482                 const char *config_path,
483                 bool *same_name_link) {
484
485         int fd;
486
487         assert(name);
488         assert(config_path);
489         assert(same_name_link);
490
491         fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
492         if (fd < 0) {
493                 if (errno == ENOENT)
494                         return 0;
495                 return -errno;
496         }
497
498         /* This takes possession of fd and closes it */
499         return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
500 }
501
502 static int find_symlinks_in_scope(
503                 UnitFileScope scope,
504                 const char *root_dir,
505                 const char *name,
506                 UnitFileState *state) {
507
508         int r;
509         _cleanup_free_ char *path2 = NULL;
510         bool same_name_link_runtime = false, same_name_link = false;
511
512         assert(scope >= 0);
513         assert(scope < _UNIT_FILE_SCOPE_MAX);
514         assert(name);
515
516         if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
517                 _cleanup_free_ char *path = NULL;
518
519                 /* First look in runtime config path */
520                 r = get_config_path(scope, true, root_dir, &path);
521                 if (r < 0)
522                         return r;
523
524                 r = find_symlinks(name, path, &same_name_link_runtime);
525                 if (r < 0)
526                         return r;
527                 else if (r > 0) {
528                         *state = UNIT_FILE_ENABLED_RUNTIME;
529                         return r;
530                 }
531         }
532
533         /* Then look in the normal config path */
534         r = get_config_path(scope, false, root_dir, &path2);
535         if (r < 0)
536                 return r;
537
538         r = find_symlinks(name, path2, &same_name_link);
539         if (r < 0)
540                 return r;
541         else if (r > 0) {
542                 *state = UNIT_FILE_ENABLED;
543                 return r;
544         }
545
546         /* Hmm, we didn't find it, but maybe we found the same name
547          * link? */
548         if (same_name_link_runtime) {
549                 *state = UNIT_FILE_LINKED_RUNTIME;
550                 return 1;
551         } else if (same_name_link) {
552                 *state = UNIT_FILE_LINKED;
553                 return 1;
554         }
555
556         return 0;
557 }
558
559 int unit_file_mask(
560                 UnitFileScope scope,
561                 bool runtime,
562                 const char *root_dir,
563                 char *files[],
564                 bool force,
565                 UnitFileChange **changes,
566                 unsigned *n_changes) {
567
568         char **i;
569         _cleanup_free_ char *prefix;
570         int r;
571
572         assert(scope >= 0);
573         assert(scope < _UNIT_FILE_SCOPE_MAX);
574
575         r = get_config_path(scope, runtime, root_dir, &prefix);
576         if (r < 0)
577                 return r;
578
579         STRV_FOREACH(i, files) {
580                 _cleanup_free_ char *path = NULL;
581
582                 if (!unit_name_is_valid(*i, true)) {
583                         if (r == 0)
584                                 r = -EINVAL;
585                         continue;
586                 }
587
588                 path = path_make_absolute(*i, prefix);
589                 if (!path) {
590                         r = -ENOMEM;
591                         break;
592                 }
593
594                 if (symlink("/dev/null", path) >= 0) {
595                         add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
596
597                         continue;
598                 }
599
600                 if (errno == EEXIST) {
601
602                         if (null_or_empty_path(path) > 0)
603                                 continue;
604
605                         if (force) {
606                                 unlink(path);
607
608                                 if (symlink("/dev/null", path) >= 0) {
609
610                                         add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
611                                         add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
612
613                                         continue;
614                                 }
615                         }
616
617                         if (r == 0)
618                                 r = -EEXIST;
619                 } else {
620                         if (r == 0)
621                                 r = -errno;
622                 }
623         }
624
625         return r;
626 }
627
628 int unit_file_unmask(
629                 UnitFileScope scope,
630                 bool runtime,
631                 const char *root_dir,
632                 char *files[],
633                 UnitFileChange **changes,
634                 unsigned *n_changes) {
635
636         char **i, *config_path = NULL;
637         int r, q;
638         Set *remove_symlinks_to = NULL;
639
640         assert(scope >= 0);
641         assert(scope < _UNIT_FILE_SCOPE_MAX);
642
643         r = get_config_path(scope, runtime, root_dir, &config_path);
644         if (r < 0)
645                 goto finish;
646
647         STRV_FOREACH(i, files) {
648                 char *path;
649
650                 if (!unit_name_is_valid(*i, true)) {
651                         if (r == 0)
652                                 r = -EINVAL;
653                         continue;
654                 }
655
656                 path = path_make_absolute(*i, config_path);
657                 if (!path) {
658                         r = -ENOMEM;
659                         break;
660                 }
661
662                 q = null_or_empty_path(path);
663                 if (q > 0) {
664                         if (unlink(path) >= 0) {
665                                 mark_symlink_for_removal(&remove_symlinks_to, path);
666                                 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
667
668                                 free(path);
669                                 continue;
670                         }
671
672                         q = -errno;
673                 }
674
675                 if (q != -ENOENT && r == 0)
676                         r = q;
677
678                 free(path);
679         }
680
681
682 finish:
683         q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
684         if (r == 0)
685                 r = q;
686
687         set_free_free(remove_symlinks_to);
688         free(config_path);
689
690         return r;
691 }
692
693 int unit_file_link(
694                 UnitFileScope scope,
695                 bool runtime,
696                 const char *root_dir,
697                 char *files[],
698                 bool force,
699                 UnitFileChange **changes,
700                 unsigned *n_changes) {
701
702         _cleanup_lookup_paths_free_ LookupPaths paths = {};
703         char **i;
704         _cleanup_free_ char *config_path = NULL;
705         int r, q;
706
707         assert(scope >= 0);
708         assert(scope < _UNIT_FILE_SCOPE_MAX);
709
710         r = lookup_paths_init_from_scope(&paths, scope);
711         if (r < 0)
712                 return r;
713
714         r = get_config_path(scope, runtime, root_dir, &config_path);
715         if (r < 0)
716                 return r;
717
718         STRV_FOREACH(i, files) {
719                 _cleanup_free_ char *path = NULL;
720                 char *fn;
721                 struct stat st;
722
723                 fn = path_get_file_name(*i);
724
725                 if (!path_is_absolute(*i) ||
726                     !unit_name_is_valid(fn, true)) {
727                         if (r == 0)
728                                 r = -EINVAL;
729                         continue;
730                 }
731
732                 if (lstat(*i, &st) < 0) {
733                         if (r == 0)
734                                 r = -errno;
735                         continue;
736                 }
737
738                 if (!S_ISREG(st.st_mode)) {
739                         r = -ENOENT;
740                         continue;
741                 }
742
743                 q = in_search_path(*i, paths.unit_path);
744                 if (q < 0)
745                         return q;
746
747                 if (q > 0)
748                         continue;
749
750                 path = path_make_absolute(fn, config_path);
751                 if (!path)
752                         return -ENOMEM;
753
754                 if (symlink(*i, path) >= 0) {
755                         add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
756                         continue;
757                 }
758
759                 if (errno == EEXIST) {
760                         _cleanup_free_ char *dest = NULL;
761
762                         q = readlink_and_make_absolute(path, &dest);
763
764                         if (q < 0 && errno != ENOENT) {
765                                 if (r == 0)
766                                         r = q;
767                                 continue;
768                         }
769
770                         if (q >= 0 && path_equal(dest, *i))
771                                 continue;
772
773                         if (force) {
774                                 unlink(path);
775
776                                 if (symlink(*i, path) >= 0) {
777
778                                         add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
779                                         add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
780
781                                         continue;
782                                 }
783                         }
784
785                         if (r == 0)
786                                 r = -EEXIST;
787                 } else {
788                         if (r == 0)
789                                 r = -errno;
790                 }
791         }
792
793         return r;
794 }
795
796 void unit_file_list_free(Hashmap *h) {
797         UnitFileList *i;
798
799         while ((i = hashmap_steal_first(h))) {
800                 free(i->path);
801                 free(i);
802         }
803
804         hashmap_free(h);
805 }
806
807 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
808         unsigned i;
809
810         assert(changes || n_changes == 0);
811
812         if (!changes)
813                 return;
814
815         for (i = 0; i < n_changes; i++) {
816                 free(changes[i].path);
817                 free(changes[i].source);
818         }
819
820         free(changes);
821 }
822
823 static void install_info_free(InstallInfo *i) {
824         assert(i);
825
826         free(i->name);
827         free(i->path);
828         strv_free(i->aliases);
829         strv_free(i->wanted_by);
830         strv_free(i->required_by);
831         free(i);
832 }
833
834 static void install_info_hashmap_free(Hashmap *m) {
835         InstallInfo *i;
836
837         if (!m)
838                 return;
839
840         while ((i = hashmap_steal_first(m)))
841                 install_info_free(i);
842
843         hashmap_free(m);
844 }
845
846 static void install_context_done(InstallContext *c) {
847         assert(c);
848
849         install_info_hashmap_free(c->will_install);
850         install_info_hashmap_free(c->have_installed);
851
852         c->will_install = c->have_installed = NULL;
853 }
854
855 static int install_info_add(
856                 InstallContext *c,
857                 const char *name,
858                 const char *path) {
859         InstallInfo *i = NULL;
860         int r;
861
862         assert(c);
863         assert(name || path);
864
865         if (!name)
866                 name = path_get_file_name(path);
867
868         if (!unit_name_is_valid(name, true))
869                 return -EINVAL;
870
871         if (hashmap_get(c->have_installed, name) ||
872             hashmap_get(c->will_install, name))
873                 return 0;
874
875         r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
876         if (r < 0)
877                 return r;
878
879         i = new0(InstallInfo, 1);
880         if (!i)
881                 return -ENOMEM;
882
883         i->name = strdup(name);
884         if (!i->name) {
885                 r = -ENOMEM;
886                 goto fail;
887         }
888
889         if (path) {
890                 i->path = strdup(path);
891                 if (!i->path) {
892                         r = -ENOMEM;
893                         goto fail;
894                 }
895         }
896
897         r = hashmap_put(c->will_install, i->name, i);
898         if (r < 0)
899                 goto fail;
900
901         return 0;
902
903 fail:
904         if (i)
905                 install_info_free(i);
906
907         return r;
908 }
909
910 static int install_info_add_auto(
911                 InstallContext *c,
912                 const char *name_or_path) {
913
914         assert(c);
915         assert(name_or_path);
916
917         if (path_is_absolute(name_or_path))
918                 return install_info_add(c, NULL, name_or_path);
919         else
920                 return install_info_add(c, name_or_path, NULL);
921 }
922
923 static int config_parse_also(const char *unit,
924                              const char *filename,
925                              unsigned line,
926                              const char *section,
927                              const char *lvalue,
928                              int ltype,
929                              const char *rvalue,
930                              void *data,
931                              void *userdata) {
932
933         char *w;
934         size_t l;
935         char *state;
936         InstallContext *c = data;
937
938         assert(filename);
939         assert(lvalue);
940         assert(rvalue);
941
942         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
943                 _cleanup_free_ char *n;
944                 int r;
945
946                 n = strndup(w, l);
947                 if (!n)
948                         return -ENOMEM;
949
950                 r = install_info_add(c, n, NULL);
951                 if (r < 0)
952                         return r;
953         }
954
955         return 0;
956 }
957
958 static int config_parse_user(const char *unit,
959                              const char *filename,
960                              unsigned line,
961                              const char *section,
962                              const char *lvalue,
963                              int ltype,
964                              const char *rvalue,
965                              void *data,
966                              void *userdata) {
967
968         InstallInfo *i = data;
969         char* printed;
970
971         assert(filename);
972         assert(lvalue);
973         assert(rvalue);
974
975         printed = install_full_printf(i, rvalue);
976         if (!printed)
977                 return -ENOMEM;
978
979         free(i->user);
980         i->user = printed;
981
982         return 0;
983 }
984
985 static int unit_file_load(
986                 InstallContext *c,
987                 InstallInfo *info,
988                 const char *path,
989                 bool allow_symlink) {
990
991         const ConfigTableItem items[] = {
992                 { "Install", "Alias",      config_parse_strv, 0, &info->aliases     },
993                 { "Install", "WantedBy",   config_parse_strv, 0, &info->wanted_by   },
994                 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
995                 { "Install", "Also",       config_parse_also, 0, c                  },
996                 { "Exec",    "User",       config_parse_user, 0, info               },
997                 { NULL, NULL, NULL, 0, NULL }
998         };
999
1000         int fd;
1001         _cleanup_fclose_ FILE *f = NULL;
1002         int r;
1003
1004         assert(c);
1005         assert(info);
1006         assert(path);
1007
1008         fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1009         if (fd < 0)
1010                 return -errno;
1011
1012         f = fdopen(fd, "re");
1013         if (!f) {
1014                 close_nointr_nofail(fd);
1015                 return -ENOMEM;
1016         }
1017
1018         r = config_parse(NULL, path, f, NULL,
1019                          config_item_table_lookup, (void*) items, true, true, info);
1020         if (r < 0)
1021                 return r;
1022
1023         return
1024                 strv_length(info->aliases) +
1025                 strv_length(info->wanted_by) +
1026                 strv_length(info->required_by);
1027 }
1028
1029 static int unit_file_search(
1030                 InstallContext *c,
1031                 InstallInfo *info,
1032                 LookupPaths *paths,
1033                 const char *root_dir,
1034                 bool allow_symlink) {
1035
1036         char **p;
1037         int r;
1038
1039         assert(c);
1040         assert(info);
1041         assert(paths);
1042
1043         if (info->path)
1044                 return unit_file_load(c, info, info->path, allow_symlink);
1045
1046         assert(info->name);
1047
1048         STRV_FOREACH(p, paths->unit_path) {
1049                 char *path = NULL;
1050
1051                 if (isempty(root_dir))
1052                         asprintf(&path, "%s/%s", *p, info->name);
1053                 else
1054                         asprintf(&path, "%s/%s/%s", root_dir, *p, info->name);
1055
1056                 if (!path)
1057                         return -ENOMEM;
1058
1059                 r = unit_file_load(c, info, path, allow_symlink);
1060
1061                 if (r >= 0)
1062                         info->path = path;
1063                 else {
1064                         if (r == -ENOENT && unit_name_is_instance(info->name)) {
1065                                 /* unit file doesn't exist, however instance enablement was request */
1066                                 /* we will check if it is possible to load template unit file */
1067                                 char *template = NULL,
1068                                      *template_path = NULL,
1069                                      *template_dir = NULL;
1070
1071                                 template = unit_name_template(info->name);
1072                                 if (!template) {
1073                                         free(path);
1074                                         return -ENOMEM;
1075                                 }
1076
1077                                 /* we will reuse path variable since we don't need it anymore */
1078                                 template_dir = path;
1079                                 *(strrchr(path, '/') + 1) = '\0';
1080
1081                                 template_path = strjoin(template_dir, template, NULL);
1082                                 if (!template_path) {
1083                                         free(path);
1084                                         free(template);
1085                                         return -ENOMEM;
1086                                 }
1087
1088                                 /* let's try to load template unit */
1089                                 r = unit_file_load(c, info, template_path, allow_symlink);
1090                                 if (r >= 0) {
1091                                         info->path = strdup(template_path);
1092                                         if (!info->path) {
1093                                                 free(path);
1094                                                 free(template);
1095                                                 free(template_path);
1096                                                 return -ENOMEM;
1097                                         }
1098                                 }
1099
1100                                 free(template);
1101                                 free(template_path);
1102                         }
1103                         free(path);
1104                 }
1105
1106                 if (r != -ENOENT && r != -ELOOP)
1107                         return r;
1108         }
1109
1110         return -ENOENT;
1111 }
1112
1113 static int unit_file_can_install(
1114                 LookupPaths *paths,
1115                 const char *root_dir,
1116                 const char *name,
1117                 bool allow_symlink) {
1118
1119         _cleanup_install_context_done_ InstallContext c = {};
1120         InstallInfo *i;
1121         int r;
1122
1123         assert(paths);
1124         assert(name);
1125
1126         r = install_info_add_auto(&c, name);
1127         if (r < 0)
1128                 return r;
1129
1130         assert_se(i = hashmap_first(c.will_install));
1131
1132         r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1133
1134         if (r >= 0)
1135                 r =
1136                         strv_length(i->aliases) +
1137                         strv_length(i->wanted_by) +
1138                         strv_length(i->required_by);
1139
1140         return r;
1141 }
1142
1143 static int create_symlink(
1144                 const char *old_path,
1145                 const char *new_path,
1146                 bool force,
1147                 UnitFileChange **changes,
1148                 unsigned *n_changes) {
1149
1150         _cleanup_free_ char *dest = NULL;
1151         int r;
1152
1153         assert(old_path);
1154         assert(new_path);
1155
1156         mkdir_parents_label(new_path, 0755);
1157
1158         if (symlink(old_path, new_path) >= 0) {
1159                 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1160                 return 0;
1161         }
1162
1163         if (errno != EEXIST)
1164                 return -errno;
1165
1166         r = readlink_and_make_absolute(new_path, &dest);
1167         if (r < 0)
1168                 return r;
1169
1170         if (path_equal(dest, old_path))
1171                 return 0;
1172
1173         if (!force)
1174                 return -EEXIST;
1175
1176         unlink(new_path);
1177
1178         if (symlink(old_path, new_path) >= 0) {
1179                 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1180                 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1181                 return 0;
1182         }
1183
1184         return -errno;
1185 }
1186
1187 static int install_info_symlink_alias(
1188                 InstallInfo *i,
1189                 const char *config_path,
1190                 bool force,
1191                 UnitFileChange **changes,
1192                 unsigned *n_changes) {
1193
1194         char **s;
1195         int r = 0, q;
1196
1197         assert(i);
1198         assert(config_path);
1199
1200         STRV_FOREACH(s, i->aliases) {
1201                 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1202
1203                 dst = install_full_printf(i, *s);
1204                 if (!dst)
1205                         return -ENOMEM;
1206
1207                 alias_path = path_make_absolute(dst, config_path);
1208                 if (!alias_path)
1209                         return -ENOMEM;
1210
1211                 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1212                 if (r == 0)
1213                         r = q;
1214         }
1215
1216         return r;
1217 }
1218
1219 static int install_info_symlink_wants(
1220                 InstallInfo *i,
1221                 const char *config_path,
1222                 bool force,
1223                 UnitFileChange **changes,
1224                 unsigned *n_changes) {
1225
1226         char **s;
1227         int r = 0, q;
1228
1229         assert(i);
1230         assert(config_path);
1231
1232         STRV_FOREACH(s, i->wanted_by) {
1233                 _cleanup_free_ char *path = NULL, *dst = NULL;
1234
1235                 dst = install_full_printf(i, *s);
1236                 if (!dst)
1237                         return -ENOMEM;
1238
1239                 if (!unit_name_is_valid(dst, true)) {
1240                         r = -EINVAL;
1241                         continue;
1242                 }
1243
1244                 if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
1245                         return -ENOMEM;
1246
1247                 q = create_symlink(i->path, path, force, changes, n_changes);
1248
1249                 if (r == 0)
1250                         r = q;
1251         }
1252
1253         return r;
1254 }
1255
1256 static int install_info_symlink_requires(
1257                 InstallInfo *i,
1258                 const char *config_path,
1259                 bool force,
1260                 UnitFileChange **changes,
1261                 unsigned *n_changes) {
1262
1263         char **s;
1264         int r = 0, q;
1265
1266         assert(i);
1267         assert(config_path);
1268
1269         STRV_FOREACH(s, i->required_by) {
1270                 _cleanup_free_ char *path = NULL, *dst = NULL;
1271
1272                 dst = install_full_printf(i, *s);
1273                 if (!dst)
1274                         return -ENOMEM;
1275
1276                 if (!unit_name_is_valid(dst, true)) {
1277                         r = -EINVAL;
1278                         continue;
1279                 }
1280
1281                 if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
1282                         return -ENOMEM;
1283
1284                 q = create_symlink(i->path, path, force, changes, n_changes);
1285
1286                 if (r == 0)
1287                         r = q;
1288         }
1289
1290         return r;
1291 }
1292
1293 static int install_info_symlink_link(
1294                 InstallInfo *i,
1295                 LookupPaths *paths,
1296                 const char *config_path,
1297                 bool force,
1298                 UnitFileChange **changes,
1299                 unsigned *n_changes) {
1300
1301         int r;
1302         _cleanup_free_ char *path = NULL;
1303
1304         assert(i);
1305         assert(paths);
1306         assert(config_path);
1307         assert(i->path);
1308
1309         r = in_search_path(i->path, paths->unit_path);
1310         if (r != 0)
1311                 return r;
1312
1313         if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1314                 return -ENOMEM;
1315
1316         r = create_symlink(i->path, path, force, changes, n_changes);
1317         return r;
1318 }
1319
1320 static int install_info_apply(
1321                 InstallInfo *i,
1322                 LookupPaths *paths,
1323                 const char *config_path,
1324                 bool force,
1325                 UnitFileChange **changes,
1326                 unsigned *n_changes) {
1327
1328         int r, q;
1329
1330         assert(i);
1331         assert(paths);
1332         assert(config_path);
1333
1334         r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1335
1336         q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1337         if (r == 0)
1338                 r = q;
1339
1340         q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1341         if (r == 0)
1342                 r = q;
1343
1344         q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1345         if (r == 0)
1346                 r = q;
1347
1348         return r;
1349 }
1350
1351 static int install_context_apply(
1352                 InstallContext *c,
1353                 LookupPaths *paths,
1354                 const char *config_path,
1355                 const char *root_dir,
1356                 bool force,
1357                 UnitFileChange **changes,
1358                 unsigned *n_changes) {
1359
1360         InstallInfo *i;
1361         int r = 0, q;
1362
1363         assert(c);
1364         assert(paths);
1365         assert(config_path);
1366
1367         while ((i = hashmap_first(c->will_install))) {
1368
1369                 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1370                 if (q < 0)
1371                         return q;
1372
1373                 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1374
1375                 q = unit_file_search(c, i, paths, root_dir, false);
1376                 if (q < 0) {
1377                         if (r >= 0)
1378                                 r = q;
1379
1380                         return r;
1381                 } else if (r >= 0)
1382                         r += q;
1383
1384                 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1385                 if (r >= 0 && q < 0)
1386                         r = q;
1387         }
1388
1389         return r;
1390 }
1391
1392 static int install_context_mark_for_removal(
1393                 InstallContext *c,
1394                 LookupPaths *paths,
1395                 Set **remove_symlinks_to,
1396                 const char *config_path,
1397                 const char *root_dir) {
1398
1399         InstallInfo *i;
1400         int r = 0, q;
1401
1402         assert(c);
1403         assert(paths);
1404         assert(config_path);
1405
1406         /* Marks all items for removal */
1407
1408         while ((i = hashmap_first(c->will_install))) {
1409
1410                 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1411                 if (q < 0)
1412                         return q;
1413
1414                 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1415
1416                 q = unit_file_search(c, i, paths, root_dir, false);
1417                 if (q == -ENOENT) {
1418                         /* do nothing */
1419                 } else if (q < 0) {
1420                         if (r >= 0)
1421                                 r = q;
1422
1423                         return r;
1424                 } else if (r >= 0)
1425                         r += q;
1426
1427                 if (unit_name_is_instance(i->name)) {
1428                         char *unit_file = NULL;
1429
1430                         unit_file = path_get_file_name(i->path);
1431
1432                         if (unit_name_is_instance(unit_file))
1433                                 /* unit file named as instance exists, thus all symlinks pointing to it, will be removed */
1434                                 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1435                         else
1436                                 /* does not exist, thus we will mark for removal symlinks to template unit file */
1437                                 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1438                 } else
1439                         q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1440
1441                 if (r >= 0 && q < 0)
1442                         r = q;
1443         }
1444
1445         return r;
1446 }
1447
1448 int unit_file_enable(
1449                 UnitFileScope scope,
1450                 bool runtime,
1451                 const char *root_dir,
1452                 char *files[],
1453                 bool force,
1454                 UnitFileChange **changes,
1455                 unsigned *n_changes) {
1456
1457         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1458         _cleanup_install_context_done_ InstallContext c = {};
1459         char **i;
1460         _cleanup_free_ char *config_path = NULL;
1461         int r;
1462
1463         assert(scope >= 0);
1464         assert(scope < _UNIT_FILE_SCOPE_MAX);
1465
1466         r = lookup_paths_init_from_scope(&paths, scope);
1467         if (r < 0)
1468                 return r;
1469
1470         r = get_config_path(scope, runtime, root_dir, &config_path);
1471         if (r < 0)
1472                 return r;
1473
1474         STRV_FOREACH(i, files) {
1475                 r = install_info_add_auto(&c, *i);
1476                 if (r < 0)
1477                         return r;
1478         }
1479
1480         /* This will return the number of symlink rules that were
1481         supposed to be created, not the ones actually created. This is
1482         useful to determine whether the passed files had any
1483         installation data at all. */
1484         r = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1485         return r;
1486 }
1487
1488 int unit_file_disable(
1489                 UnitFileScope scope,
1490                 bool runtime,
1491                 const char *root_dir,
1492                 char *files[],
1493                 UnitFileChange **changes,
1494                 unsigned *n_changes) {
1495
1496         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1497         _cleanup_install_context_done_ InstallContext c = {};
1498         char **i;
1499         _cleanup_free_ char *config_path = NULL;
1500         _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1501         int r, q;
1502
1503         assert(scope >= 0);
1504         assert(scope < _UNIT_FILE_SCOPE_MAX);
1505
1506         r = lookup_paths_init_from_scope(&paths, scope);
1507         if (r < 0)
1508                 return r;
1509
1510         r = get_config_path(scope, runtime, root_dir, &config_path);
1511         if (r < 0)
1512                 return r;
1513
1514         STRV_FOREACH(i, files) {
1515                 r = install_info_add_auto(&c, *i);
1516                 if (r < 0)
1517                         return r;
1518         }
1519
1520         r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1521
1522         q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1523         if (r == 0)
1524                 r = q;
1525
1526         return r;
1527 }
1528
1529 int unit_file_reenable(
1530                 UnitFileScope scope,
1531                 bool runtime,
1532                 const char *root_dir,
1533                 char *files[],
1534                 bool force,
1535                 UnitFileChange **changes,
1536                 unsigned *n_changes) {
1537
1538         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1539         _cleanup_install_context_done_ InstallContext c = {};
1540         char **i;
1541         _cleanup_free_ char *config_path = NULL;
1542         _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1543         int r, q;
1544
1545         assert(scope >= 0);
1546         assert(scope < _UNIT_FILE_SCOPE_MAX);
1547
1548         r = lookup_paths_init_from_scope(&paths, scope);
1549         if (r < 0)
1550                 return r;
1551
1552         r = get_config_path(scope, runtime, root_dir, &config_path);
1553         if (r < 0)
1554                 return r;
1555
1556         STRV_FOREACH(i, files) {
1557                 r = mark_symlink_for_removal(&remove_symlinks_to, *i);
1558                 if (r < 0)
1559                         return r;
1560
1561                 r = install_info_add_auto(&c, *i);
1562                 if (r < 0)
1563                         return r;
1564         }
1565
1566         r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1567
1568         /* Returns number of symlinks that where supposed to be installed. */
1569         q = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1570         if (r == 0)
1571                 r = q;
1572
1573         return r;
1574 }
1575
1576 int unit_file_set_default(
1577                 UnitFileScope scope,
1578                 const char *root_dir,
1579                 char *file,
1580                 UnitFileChange **changes,
1581                 unsigned *n_changes) {
1582
1583         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1584         _cleanup_install_context_done_ InstallContext c = {};
1585         _cleanup_free_ char *config_path = NULL;
1586         char *path;
1587         int r;
1588         InstallInfo *i = NULL;
1589
1590         assert(scope >= 0);
1591         assert(scope < _UNIT_FILE_SCOPE_MAX);
1592
1593         if (unit_name_to_type(file) != UNIT_TARGET)
1594                 return -EINVAL;
1595
1596         r = lookup_paths_init_from_scope(&paths, scope);
1597         if (r < 0)
1598                 return r;
1599
1600         r = get_config_path(scope, false, root_dir, &config_path);
1601         if (r < 0)
1602                 return r;
1603
1604         r = install_info_add_auto(&c, file);
1605         if (r < 0)
1606                 return r;
1607
1608         i = (InstallInfo*)hashmap_first(c.will_install);
1609
1610         r = unit_file_search(&c, i, &paths, root_dir, false);
1611         if (r < 0)
1612                 return r;
1613
1614         path = strappenda(config_path, "/default.target");
1615         r = create_symlink(i->path, path, true, changes, n_changes);
1616         if (r < 0)
1617                 return r;
1618
1619         return 0;
1620 }
1621
1622 int unit_file_get_default(
1623                 UnitFileScope scope,
1624                 const char *root_dir,
1625                 char **name) {
1626
1627         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1628         char **p;
1629         int r;
1630
1631         r = lookup_paths_init_from_scope(&paths, scope);
1632         if (r < 0)
1633                 return r;
1634
1635         STRV_FOREACH(p, paths.unit_path) {
1636                 _cleanup_free_ char *path = NULL, *tmp = NULL;
1637
1638                 if (isempty(root_dir))
1639                         path = strappend(*p, "/default.target");
1640                 else
1641                         path = strjoin(root_dir, "/", *p, "/default.target", NULL);
1642
1643                 if (!path)
1644                         return -ENOMEM;
1645
1646                 r = readlink_malloc(path, &tmp);
1647                 if (r == -ENOENT)
1648                         continue;
1649                 else if (r < 0)
1650                         return r;
1651
1652                 *name = strdup(path_get_file_name(tmp));
1653                 if (!*name)
1654                         return -ENOMEM;
1655
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
1891 int unit_file_get_list(
1892                 UnitFileScope scope,
1893                 const char *root_dir,
1894                 Hashmap *h) {
1895
1896         _cleanup_lookup_paths_free_ LookupPaths paths = {};
1897         char **i;
1898         _cleanup_free_ char *buf = NULL;
1899         _cleanup_closedir_ DIR *d = NULL;
1900         int r;
1901
1902         assert(scope >= 0);
1903         assert(scope < _UNIT_FILE_SCOPE_MAX);
1904         assert(h);
1905
1906         if (root_dir && scope != UNIT_FILE_SYSTEM)
1907                 return -EINVAL;
1908
1909         r = lookup_paths_init_from_scope(&paths, scope);
1910         if (r < 0)
1911                 return r;
1912
1913         STRV_FOREACH(i, paths.unit_path) {
1914                 const char *units_dir;
1915
1916                 free(buf);
1917                 buf = NULL;
1918
1919                 if (root_dir) {
1920                         if (asprintf(&buf, "%s/%s", root_dir, *i) < 0)
1921                                 return -ENOMEM;
1922
1923                         units_dir = buf;
1924                 } else
1925                         units_dir = *i;
1926
1927                 if (d)
1928                         closedir(d);
1929
1930                 d = opendir(units_dir);
1931                 if (!d) {
1932                         if (errno == ENOENT)
1933                                 continue;
1934
1935                         return -errno;
1936                 }
1937
1938                 for (;;) {
1939                         struct dirent *de;
1940                         union dirent_storage buffer;
1941                         UnitFileList __attribute__((cleanup(unitfilelist_free)))
1942                                 *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, path_get_file_name(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);