chiark / gitweb /
e816bed2016114518a1ca49fa7498b5282d7fe14
[elogind.git] / src / tmpfiles / tmpfiles.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering, Kay Sievers
7   Copyright 2015 Zbigniew JÄ™drzejewski-Szmek
8
9   systemd is free software; you can redistribute it and/or modify it
10   under the terms of the GNU Lesser General Public License as published by
11   the Free Software Foundation; either version 2.1 of the License, or
12   (at your option) any later version.
13
14   systemd is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <limits.h>
28 #include <dirent.h>
29 #include <grp.h>
30 #include <pwd.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stddef.h>
34 #include <getopt.h>
35 #include <stdbool.h>
36 #include <time.h>
37 #include <glob.h>
38 #include <fnmatch.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <sys/param.h>
42 #include <sys/xattr.h>
43
44 #include "log.h"
45 #include "util.h"
46 #include "macro.h"
47 #include "missing.h"
48 #include "mkdir.h"
49 #include "path-util.h"
50 #include "strv.h"
51 #include "label.h"
52 #include "set.h"
53 #include "conf-files.h"
54 #include "capability.h"
55 #include "specifier.h"
56 #include "build.h"
57 #include "copy.h"
58 #include "selinux-util.h"
59 #include "btrfs-util.h"
60 #include "acl-util.h"
61
62 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
63  * them in the file system. This is intended to be used to create
64  * properly owned directories beneath /tmp, /var/tmp, /run, which are
65  * volatile and hence need to be recreated on bootup. */
66
67 typedef enum ItemType {
68         /* These ones take file names */
69         CREATE_FILE = 'f',
70         TRUNCATE_FILE = 'F',
71         CREATE_DIRECTORY = 'd',
72         TRUNCATE_DIRECTORY = 'D',
73         CREATE_SUBVOLUME = 'v',
74         CREATE_FIFO = 'p',
75         CREATE_SYMLINK = 'L',
76         CREATE_CHAR_DEVICE = 'c',
77         CREATE_BLOCK_DEVICE = 'b',
78         COPY_FILES = 'C',
79
80         /* These ones take globs */
81         SET_XATTR = 't',
82         RECURSIVE_SET_XATTR = 'T',
83         SET_ACL = 'a',
84         RECURSIVE_SET_ACL = 'A',
85         WRITE_FILE = 'w',
86         IGNORE_PATH = 'x',
87         IGNORE_DIRECTORY_PATH = 'X',
88         REMOVE_PATH = 'r',
89         RECURSIVE_REMOVE_PATH = 'R',
90         ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */
91         RELABEL_PATH = 'z',
92         RECURSIVE_RELABEL_PATH = 'Z',
93 } ItemType;
94
95 typedef struct Item {
96         ItemType type;
97
98         char *path;
99         char *argument;
100         char **xattrs;
101 #ifdef HAVE_ACL
102         acl_t acl_access;
103         acl_t acl_default;
104 #endif
105         uid_t uid;
106         gid_t gid;
107         mode_t mode;
108         usec_t age;
109
110         dev_t major_minor;
111
112         bool uid_set:1;
113         bool gid_set:1;
114         bool mode_set:1;
115         bool age_set:1;
116         bool mask_perms:1;
117
118         bool keep_first_level:1;
119
120         bool force:1;
121
122         bool done:1;
123 } Item;
124
125 typedef struct ItemArray {
126         Item *items;
127         size_t count;
128         size_t size;
129 } ItemArray;
130
131 static bool arg_create = false;
132 static bool arg_clean = false;
133 static bool arg_remove = false;
134 static bool arg_boot = false;
135
136 static char **arg_include_prefixes = NULL;
137 static char **arg_exclude_prefixes = NULL;
138 static char *arg_root = NULL;
139
140 static const char conf_file_dirs[] = CONF_DIRS_NULSTR("tmpfiles");
141
142 #define MAX_DEPTH 256
143
144 static Hashmap *items = NULL, *globs = NULL;
145 static Set *unix_sockets = NULL;
146
147 static bool needs_glob(ItemType t) {
148         return IN_SET(t,
149                       WRITE_FILE,
150                       IGNORE_PATH,
151                       IGNORE_DIRECTORY_PATH,
152                       REMOVE_PATH,
153                       RECURSIVE_REMOVE_PATH,
154                       ADJUST_MODE,
155                       RELABEL_PATH,
156                       RECURSIVE_RELABEL_PATH,
157                       SET_XATTR,
158                       RECURSIVE_SET_XATTR,
159                       SET_ACL,
160                       RECURSIVE_SET_ACL);
161 }
162
163 static bool takes_ownership(ItemType t) {
164         return IN_SET(t,
165                       CREATE_FILE,
166                       TRUNCATE_FILE,
167                       CREATE_DIRECTORY,
168                       TRUNCATE_DIRECTORY,
169                       CREATE_SUBVOLUME,
170                       CREATE_FIFO,
171                       CREATE_SYMLINK,
172                       CREATE_CHAR_DEVICE,
173                       CREATE_BLOCK_DEVICE,
174                       COPY_FILES,
175
176                       WRITE_FILE,
177                       IGNORE_PATH,
178                       IGNORE_DIRECTORY_PATH,
179                       REMOVE_PATH,
180                       RECURSIVE_REMOVE_PATH);
181 }
182
183 static struct Item* find_glob(Hashmap *h, const char *match) {
184         ItemArray *j;
185         Iterator i;
186
187         HASHMAP_FOREACH(j, h, i) {
188                 unsigned n;
189
190                 for (n = 0; n < j->count; n++) {
191                         Item *item = j->items + n;
192
193                         if (fnmatch(item->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
194                                 return item;
195                 }
196         }
197
198         return NULL;
199 }
200
201 static void load_unix_sockets(void) {
202         _cleanup_fclose_ FILE *f = NULL;
203         char line[LINE_MAX];
204
205         if (unix_sockets)
206                 return;
207
208         /* We maintain a cache of the sockets we found in
209          * /proc/net/unix to speed things up a little. */
210
211         unix_sockets = set_new(&string_hash_ops);
212         if (!unix_sockets)
213                 return;
214
215         f = fopen("/proc/net/unix", "re");
216         if (!f)
217                 return;
218
219         /* Skip header */
220         if (!fgets(line, sizeof(line), f))
221                 goto fail;
222
223         for (;;) {
224                 char *p, *s;
225                 int k;
226
227                 if (!fgets(line, sizeof(line), f))
228                         break;
229
230                 truncate_nl(line);
231
232                 p = strchr(line, ':');
233                 if (!p)
234                         continue;
235
236                 if (strlen(p) < 37)
237                         continue;
238
239                 p += 37;
240                 p += strspn(p, WHITESPACE);
241                 p += strcspn(p, WHITESPACE); /* skip one more word */
242                 p += strspn(p, WHITESPACE);
243
244                 if (*p != '/')
245                         continue;
246
247                 s = strdup(p);
248                 if (!s)
249                         goto fail;
250
251                 path_kill_slashes(s);
252
253                 k = set_consume(unix_sockets, s);
254                 if (k < 0 && k != -EEXIST)
255                         goto fail;
256         }
257
258         return;
259
260 fail:
261         set_free_free(unix_sockets);
262         unix_sockets = NULL;
263 }
264
265 static bool unix_socket_alive(const char *fn) {
266         assert(fn);
267
268         load_unix_sockets();
269
270         if (unix_sockets)
271                 return !!set_get(unix_sockets, (char*) fn);
272
273         /* We don't know, so assume yes */
274         return true;
275 }
276
277 static int dir_is_mount_point(DIR *d, const char *subdir) {
278
279         union file_handle_union h = FILE_HANDLE_INIT;
280         int mount_id_parent, mount_id;
281         int r_p, r;
282
283         r_p = name_to_handle_at(dirfd(d), ".", &h.handle, &mount_id_parent, 0);
284         if (r_p < 0)
285                 r_p = -errno;
286
287         h.handle.handle_bytes = MAX_HANDLE_SZ;
288         r = name_to_handle_at(dirfd(d), subdir, &h.handle, &mount_id, 0);
289         if (r < 0)
290                 r = -errno;
291
292         /* got no handle; make no assumptions, return error */
293         if (r_p < 0 && r < 0)
294                 return r_p;
295
296         /* got both handles; if they differ, it is a mount point */
297         if (r_p >= 0 && r >= 0)
298                 return mount_id_parent != mount_id;
299
300         /* got only one handle; assume different mount points if one
301          * of both queries was not supported by the filesystem */
302         if (r_p == -ENOSYS || r_p == -EOPNOTSUPP || r == -ENOSYS || r == -EOPNOTSUPP)
303                 return true;
304
305         /* return error */
306         if (r_p < 0)
307                 return r_p;
308         return r;
309 }
310
311 static DIR* xopendirat_nomod(int dirfd, const char *path) {
312         DIR *dir;
313
314         dir = xopendirat(dirfd, path, O_NOFOLLOW|O_NOATIME);
315         if (!dir) {
316                 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m",
317                                 dirfd == AT_FDCWD ? "" : "sub", path);
318                 if (errno == EPERM) {
319                         dir = xopendirat(dirfd, path, O_NOFOLLOW);
320                         if (!dir)
321                                 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m",
322                                                 dirfd == AT_FDCWD ? "" : "sub", path);
323                 }
324         }
325
326         return dir;
327 }
328
329 static DIR* opendir_nomod(const char *path) {
330         return xopendirat_nomod(AT_FDCWD, path);
331 }
332
333 static int dir_cleanup(
334                 Item *i,
335                 const char *p,
336                 DIR *d,
337                 const struct stat *ds,
338                 usec_t cutoff,
339                 dev_t rootdev,
340                 bool mountpoint,
341                 int maxdepth,
342                 bool keep_this_level) {
343
344         struct dirent *dent;
345         struct timespec times[2];
346         bool deleted = false;
347         int r = 0;
348
349         while ((dent = readdir(d))) {
350                 struct stat s;
351                 usec_t age;
352                 _cleanup_free_ char *sub_path = NULL;
353
354                 if (STR_IN_SET(dent->d_name, ".", ".."))
355                         continue;
356
357                 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
358                         if (errno == ENOENT)
359                                 continue;
360
361                         /* FUSE, NFS mounts, SELinux might return EACCES */
362                         if (errno == EACCES)
363                                 log_debug_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
364                         else
365                                 log_error_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
366                         r = -errno;
367                         continue;
368                 }
369
370                 /* Stay on the same filesystem */
371                 if (s.st_dev != rootdev) {
372                         log_debug("Ignoring \"%s/%s\": different filesystem.", p, dent->d_name);
373                         continue;
374                 }
375
376                 /* Try to detect bind mounts of the same filesystem instance; they
377                  * do not differ in device major/minors. This type of query is not
378                  * supported on all kernels or filesystem types though. */
379                 if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0) {
380                         log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.",
381                                   p, dent->d_name);
382                         continue;
383                 }
384
385                 /* Do not delete read-only files owned by root */
386                 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR)) {
387                         log_debug("Ignoring \"%s/%s\": read-only and owner by root.", p, dent->d_name);
388                         continue;
389                 }
390
391                 sub_path = strjoin(p, "/", dent->d_name, NULL);
392                 if (!sub_path) {
393                         r = log_oom();
394                         goto finish;
395                 }
396
397                 /* Is there an item configured for this path? */
398                 if (hashmap_get(items, sub_path)) {
399                         log_debug("Ignoring \"%s\": a separate entry exists.", sub_path);
400                         continue;
401                 }
402
403                 if (find_glob(globs, sub_path)) {
404                         log_debug("Ignoring \"%s\": a separate glob exists.", sub_path);
405                         continue;
406                 }
407
408                 if (S_ISDIR(s.st_mode)) {
409
410                         if (mountpoint &&
411                             streq(dent->d_name, "lost+found") &&
412                             s.st_uid == 0) {
413                                 log_debug("Ignoring \"%s\".", sub_path);
414                                 continue;
415                         }
416
417                         if (maxdepth <= 0)
418                                 log_warning("Reached max depth on \"%s\".", sub_path);
419                         else {
420                                 _cleanup_closedir_ DIR *sub_dir;
421                                 int q;
422
423                                 sub_dir = xopendirat_nomod(dirfd(d), dent->d_name);
424                                 if (!sub_dir) {
425                                         if (errno != ENOENT)
426                                                 r = log_error_errno(errno, "opendir(%s) failed: %m", sub_path);
427
428                                         continue;
429                                 }
430
431                                 q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
432                                 if (q < 0)
433                                         r = q;
434                         }
435
436                         /* Note: if you are wondering why we don't
437                          * support the sticky bit for excluding
438                          * directories from cleaning like we do it for
439                          * other file system objects: well, the sticky
440                          * bit already has a meaning for directories,
441                          * so we don't want to overload that. */
442
443                         if (keep_this_level) {
444                                 log_debug("Keeping \"%s\".", sub_path);
445                                 continue;
446                         }
447
448                         /* Ignore ctime, we change it when deleting */
449                         age = timespec_load(&s.st_mtim);
450                         if (age >= cutoff) {
451                                 char a[FORMAT_TIMESTAMP_MAX];
452                                 /* Follows spelling in stat(1). */
453                                 log_debug("Directory \"%s\": modify time %s is too new.",
454                                           sub_path,
455                                           format_timestamp_us(a, sizeof(a), age));
456                                 continue;
457                         }
458
459                         age = timespec_load(&s.st_atim);
460                         if (age >= cutoff) {
461                                 char a[FORMAT_TIMESTAMP_MAX];
462                                 log_debug("Directory \"%s\": access time %s is too new.",
463                                           sub_path,
464                                           format_timestamp_us(a, sizeof(a), age));
465                                 continue;
466                         }
467
468                         log_debug("Removing directory \"%s\".", sub_path);
469                         if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0)
470                                 if (errno != ENOENT && errno != ENOTEMPTY) {
471                                         log_error_errno(errno, "rmdir(%s): %m", sub_path);
472                                         r = -errno;
473                                 }
474
475                 } else {
476                         /* Skip files for which the sticky bit is
477                          * set. These are semantics we define, and are
478                          * unknown elsewhere. See XDG_RUNTIME_DIR
479                          * specification for details. */
480                         if (s.st_mode & S_ISVTX) {
481                                 log_debug("Skipping \"%s\": sticky bit set.", sub_path);
482                                 continue;
483                         }
484
485                         if (mountpoint && S_ISREG(s.st_mode))
486                                 if ((streq(dent->d_name, ".journal") && s.st_uid == 0) ||
487                                     streq(dent->d_name, "aquota.user") ||
488                                     streq(dent->d_name, "aquota.group")) {
489                                         log_debug("Skipping \"%s\".", sub_path);
490                                         continue;
491                                 }
492
493                         /* Ignore sockets that are listed in /proc/net/unix */
494                         if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path)) {
495                                 log_debug("Skipping \"%s\": live socket.", sub_path);
496                                 continue;
497                         }
498
499                         /* Ignore device nodes */
500                         if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode)) {
501                                 log_debug("Skipping \"%s\": a device.", sub_path);
502                                 continue;
503                         }
504
505                         /* Keep files on this level around if this is
506                          * requested */
507                         if (keep_this_level) {
508                                 log_debug("Keeping \"%s\".", sub_path);
509                                 continue;
510                         }
511
512                         age = timespec_load(&s.st_mtim);
513                         if (age >= cutoff) {
514                                 char a[FORMAT_TIMESTAMP_MAX];
515                                 /* Follows spelling in stat(1). */
516                                 log_debug("File \"%s\": modify time %s is too new.",
517                                           sub_path,
518                                           format_timestamp_us(a, sizeof(a), age));
519                                 continue;
520                         }
521
522                         age = timespec_load(&s.st_atim);
523                         if (age >= cutoff) {
524                                 char a[FORMAT_TIMESTAMP_MAX];
525                                 log_debug("File \"%s\": access time %s is too new.",
526                                           sub_path,
527                                           format_timestamp_us(a, sizeof(a), age));
528                                 continue;
529                         }
530
531                         age = timespec_load(&s.st_ctim);
532                         if (age >= cutoff) {
533                                 char a[FORMAT_TIMESTAMP_MAX];
534                                 log_debug("File \"%s\": change time %s is too new.",
535                                           sub_path,
536                                           format_timestamp_us(a, sizeof(a), age));
537                                 continue;
538                         }
539
540                         log_debug("unlink \"%s\"", sub_path);
541
542                         if (unlinkat(dirfd(d), dent->d_name, 0) < 0)
543                                 if (errno != ENOENT)
544                                         r = log_error_errno(errno, "unlink(%s): %m", sub_path);
545
546                         deleted = true;
547                 }
548         }
549
550 finish:
551         if (deleted) {
552                 usec_t age1, age2;
553                 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
554
555                 /* Restore original directory timestamps */
556                 times[0] = ds->st_atim;
557                 times[1] = ds->st_mtim;
558
559                 age1 = timespec_load(&ds->st_atim);
560                 age2 = timespec_load(&ds->st_mtim);
561                 log_debug("Restoring access and modification time on \"%s\": %s, %s",
562                           p,
563                           format_timestamp_us(a, sizeof(a), age1),
564                           format_timestamp_us(b, sizeof(b), age2));
565                 if (futimens(dirfd(d), times) < 0)
566                         log_error_errno(errno, "utimensat(%s): %m", p);
567         }
568
569         return r;
570 }
571
572 static int path_set_perms(Item *i, const char *path) {
573         struct stat st;
574         bool st_valid;
575
576         assert(i);
577         assert(path);
578
579         st_valid = stat(path, &st) == 0;
580
581         /* not using i->path directly because it may be a glob */
582         if (i->mode_set) {
583                 mode_t m = i->mode;
584
585                 if (i->mask_perms && st_valid) {
586                         if (!(st.st_mode & 0111))
587                                 m &= ~0111;
588                         if (!(st.st_mode & 0222))
589                                 m &= ~0222;
590                         if (!(st.st_mode & 0444))
591                                 m &= ~0444;
592                         if (!S_ISDIR(st.st_mode))
593                                 m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
594                 }
595
596                 if (st_valid && m == (st.st_mode & 07777))
597                         log_debug("\"%s\" has right mode %o", path, st.st_mode);
598                 else {
599                         log_debug("chmod \"%s\" to mode %o", path, m);
600                         if (chmod(path, m) < 0)
601                                 return log_error_errno(errno, "chmod(%s) failed: %m", path);
602                 }
603         }
604
605         if ((!st_valid || i->uid != st.st_uid || i->gid != st.st_gid) &&
606             (i->uid_set || i->gid_set)) {
607                 log_debug("chown \"%s\" to "UID_FMT"."GID_FMT,
608                           path,
609                           i->uid_set ? i->uid : UID_INVALID,
610                           i->gid_set ? i->gid : GID_INVALID);
611                 if (chown(path,
612                           i->uid_set ? i->uid : UID_INVALID,
613                           i->gid_set ? i->gid : GID_INVALID) < 0)
614
615                         return log_error_errno(errno, "chown(%s) failed: %m", path);
616         }
617
618         return label_fix(path, false, false);
619 }
620
621 static int get_xattrs_from_arg(Item *i) {
622         char *xattr;
623         const char *p;
624         int r;
625
626         assert(i);
627         assert(i->argument);
628
629         p = i->argument;
630
631         while ((r = unquote_first_word(&p, &xattr, false)) > 0) {
632                 _cleanup_free_ char *tmp = NULL, *name = NULL,
633                         *value = NULL, *value2 = NULL, *_xattr = xattr;
634
635                 r = split_pair(xattr, "=", &name, &value);
636                 if (r < 0) {
637                         log_warning("Illegal xattr found: \"%s\" - ignoring.", xattr);
638                         continue;
639                 }
640
641                 if (strempty(name) || strempty(value)) {
642                         log_warning("Malformed xattr found: \"%s\" - ignoring.", xattr);
643                         continue;
644                 }
645
646                 tmp = unquote(value, "\"");
647                 if (!tmp)
648                         return log_oom();
649
650                 value2 = cunescape(tmp);
651                 if (!value2)
652                         return log_oom();
653
654                 if (strv_push_pair(&i->xattrs, name, value2) < 0)
655                         return log_oom();
656                 name = value2 = NULL;
657         }
658
659         return r;
660 }
661
662 static int path_set_xattrs(Item *i, const char *path) {
663         char **name, **value;
664
665         assert(i);
666         assert(path);
667
668         STRV_FOREACH_PAIR(name, value, i->xattrs) {
669                 int n;
670
671                 n = strlen(*value);
672                 log_debug("\"%s\": setting xattr \"%s=%s\"", path, *name, *value);
673                 if (lsetxattr(path, *name, *value, n, 0) < 0) {
674                         log_error("Setting extended attribute %s=%s on %s failed: %m",
675                                   *name, *value, path);
676                         return -errno;
677                 }
678         }
679         return 0;
680 }
681
682 static int get_acls_from_arg(Item *item) {
683 #ifdef HAVE_ACL
684         int r;
685         _cleanup_(acl_freep) acl_t a = NULL, d = NULL;
686
687         assert(item);
688
689         /* If force (= modify) is set, we will not modify the acl
690          * afterwards, so the mask can be added now if necessary. */
691         r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
692         if (r < 0)
693                 log_warning_errno(errno, "Failed to parse ACL \"%s\": %m. Ignoring",
694                                   item->argument);
695 #else
696         log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
697 #endif
698
699         return 0;
700 }
701
702 static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
703         _cleanup_(acl_freep) acl_t dup = NULL;
704         int r;
705         _cleanup_(acl_free_charpp) char *t = NULL;
706
707         if (modify) {
708                 r = acls_for_file(path, type, acl, &dup);
709                 if (r < 0)
710                         return r;
711
712                 r = calc_acl_mask_if_needed(&dup);
713                 if (r < 0)
714                         return r;
715         } else {
716                 dup = acl_dup(acl);
717                 if (!dup)
718                         return -errno;
719
720                 /* the mask was already added earlier if needed */
721         }
722
723         r = add_base_acls_if_needed(&dup, path);
724         if (r < 0)
725                 return r;
726
727         t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
728         log_debug("\"%s\": setting %s ACL \"%s\"", path,
729                   type == ACL_TYPE_ACCESS ? "access" : "default",
730                   strna(t));
731
732         r = acl_set_file(path, type, dup);
733         if (r < 0)
734                 return log_error_errno(-errno,
735                                        "Setting %s ACL \"%s\" on %s failed: %m",
736                                        type == ACL_TYPE_ACCESS ? "access" : "default",
737                                        strna(t), path);
738         return 0;
739 }
740
741 static int path_set_acls(Item *item, const char *path) {
742 #ifdef HAVE_ACL
743         int r;
744
745         assert(item);
746         assert(path);
747
748         if (item->acl_access) {
749                 r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
750                 if (r < 0)
751                         return r;
752         }
753
754         if (item->acl_default) {
755                 r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
756                 if (r < 0)
757                         return r;
758         }
759 #endif
760
761         return 0;
762 }
763
764 static int write_one_file(Item *i, const char *path) {
765         _cleanup_close_ int fd = -1;
766         int flags, r = 0;
767         struct stat st;
768
769         assert(i);
770         assert(path);
771
772         flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
773                 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
774
775         RUN_WITH_UMASK(0000) {
776                 mac_selinux_create_file_prepare(path, S_IFREG);
777                 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
778                 mac_selinux_create_file_clear();
779         }
780
781         if (fd < 0) {
782                 if (i->type == WRITE_FILE && errno == ENOENT) {
783                         log_debug_errno(errno, "Not writing \"%s\": %m", path);
784                         return 0;
785                 }
786
787                 log_error_errno(errno, "Failed to create file %s: %m", path);
788                 return -errno;
789         }
790
791         if (i->argument) {
792                 _cleanup_free_ char *unescaped;
793
794                 log_debug("%s to \"%s\".",
795                           i->type == CREATE_FILE ? "Appending" : "Writing", path);
796
797                 unescaped = cunescape(i->argument);
798                 if (!unescaped)
799                         return log_oom();
800
801                 r = loop_write(fd, unescaped, strlen(unescaped), false);
802                 if (r < 0)
803                         return log_error_errno(r, "Failed to write file \"%s\": %m", path);
804         } else
805                 log_debug("\"%s\" has been created.", path);
806
807         fd = safe_close(fd);
808
809         if (stat(path, &st) < 0)
810                 return log_error_errno(errno, "stat(%s) failed: %m", path);
811
812         if (!S_ISREG(st.st_mode)) {
813                 log_error("%s is not a file.", path);
814                 return -EEXIST;
815         }
816
817         r = path_set_perms(i, path);
818         if (r < 0)
819                 return r;
820
821         return 0;
822 }
823
824 typedef int (*action_t)(Item *, const char *);
825
826 static int item_do_children(Item *i, const char *path, action_t action) {
827         _cleanup_closedir_ DIR *d;
828         int r = 0;
829
830         assert(i);
831         assert(path);
832
833         /* This returns the first error we run into, but nevertheless
834          * tries to go on */
835
836         d = opendir_nomod(path);
837         if (!d)
838                 return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
839
840         for (;;) {
841                 _cleanup_free_ char *p = NULL;
842                 struct dirent *de;
843                 int q;
844
845                 errno = 0;
846                 de = readdir(d);
847                 if (!de) {
848                         if (errno != 0 && r == 0)
849                                 r = -errno;
850
851                         break;
852                 }
853
854                 if (STR_IN_SET(de->d_name, ".", ".."))
855                         continue;
856
857                 p = strjoin(path, "/", de->d_name, NULL);
858                 if (!p)
859                         return -ENOMEM;
860
861                 q = action(i, p);
862                 if (q < 0 && q != -ENOENT && r == 0)
863                         r = q;
864
865                 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
866                         q = item_do_children(i, p, action);
867                         if (q < 0 && r == 0)
868                                 r = q;
869                 }
870         }
871
872         return r;
873 }
874
875 static int glob_item(Item *i, action_t action, bool recursive) {
876         _cleanup_globfree_ glob_t g = {
877                 .gl_closedir = (void (*)(void *)) closedir,
878                 .gl_readdir = (struct dirent *(*)(void *)) readdir,
879                 .gl_opendir = (void *(*)(const char *)) opendir_nomod,
880                 .gl_lstat = lstat,
881                 .gl_stat = stat,
882         };
883         int r = 0, k;
884         char **fn;
885
886         errno = 0;
887         k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
888         if (k != 0 && k != GLOB_NOMATCH)
889                 return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
890
891         STRV_FOREACH(fn, g.gl_pathv) {
892                 k = action(i, *fn);
893                 if (k < 0 && r == 0)
894                         r = k;
895
896                 if (recursive) {
897                         k = item_do_children(i, *fn, action);
898                         if (k < 0 && r == 0)
899                                 r = k;
900                 }
901         }
902
903         return r;
904 }
905
906 static int create_item(Item *i) {
907         struct stat st;
908         int r = 0;
909
910         assert(i);
911
912         log_debug("Running create action for entry %c %s", (char) i->type, i->path);
913
914         switch (i->type) {
915
916         case IGNORE_PATH:
917         case IGNORE_DIRECTORY_PATH:
918         case REMOVE_PATH:
919         case RECURSIVE_REMOVE_PATH:
920                 return 0;
921
922         case CREATE_FILE:
923         case TRUNCATE_FILE:
924                 r = write_one_file(i, i->path);
925                 if (r < 0)
926                         return r;
927                 break;
928
929         case COPY_FILES:
930                 log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
931                 r = copy_tree(i->argument, i->path, false);
932                 if (r < 0) {
933                         struct stat a, b;
934
935                         if (r != -EEXIST)
936                                 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
937
938                         if (stat(i->argument, &a) < 0)
939                                 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
940
941                         if (stat(i->path, &b) < 0)
942                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
943
944                         if ((a.st_mode ^ b.st_mode) & S_IFMT) {
945                                 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
946                                 return 0;
947                         }
948                 }
949
950                 r = path_set_perms(i, i->path);
951                 if (r < 0)
952                         return r;
953
954                 break;
955
956         case WRITE_FILE:
957                 r = glob_item(i, write_one_file, false);
958                 if (r < 0)
959                         return r;
960
961                 break;
962
963         case CREATE_DIRECTORY:
964         case TRUNCATE_DIRECTORY:
965         case CREATE_SUBVOLUME:
966
967                 RUN_WITH_UMASK(0000)
968                         mkdir_parents_label(i->path, 0755);
969
970                 if (i->type == CREATE_SUBVOLUME)
971                         RUN_WITH_UMASK((~i->mode) & 0777) {
972                                 r = btrfs_subvol_make(i->path);
973                                 log_debug_errno(r, "Creating subvolume \"%s\": %m", i->path);
974                         }
975                 else
976                         r = 0;
977
978                 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
979                         RUN_WITH_UMASK(0000)
980                                 r = mkdir_label(i->path, i->mode);
981
982                 if (r < 0) {
983                         if (r != -EEXIST)
984                                 return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);
985
986                         if (stat(i->path, &st) < 0)
987                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
988
989                         if (!S_ISDIR(st.st_mode)) {
990                                 log_debug("\"%s\" already exists and is not a directory.", i->path);
991                                 return 0;
992                         }
993                 }
994                 log_debug("Created directory \"%s\".", i->path);
995
996                 r = path_set_perms(i, i->path);
997                 if (r < 0)
998                         return r;
999
1000                 break;
1001
1002         case CREATE_FIFO:
1003
1004                 RUN_WITH_UMASK(0000) {
1005                         mac_selinux_create_file_prepare(i->path, S_IFIFO);
1006                         r = mkfifo(i->path, i->mode);
1007                         mac_selinux_create_file_clear();
1008                 }
1009
1010                 if (r < 0) {
1011                         if (errno != EEXIST)
1012                                 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
1013
1014                         if (stat(i->path, &st) < 0)
1015                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1016
1017                         if (!S_ISFIFO(st.st_mode)) {
1018
1019                                 if (i->force) {
1020
1021                                         RUN_WITH_UMASK(0000) {
1022                                                 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1023                                                 r = mkfifo_atomic(i->path, i->mode);
1024                                                 mac_selinux_create_file_clear();
1025                                         }
1026
1027                                         if (r < 0)
1028                                                 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
1029                                 } else {
1030                                         log_debug("%s is not a fifo.", i->path);
1031                                         return 0;
1032                                 }
1033                         }
1034                 }
1035                 log_debug("Created fifo \"%s\".", i->path);
1036
1037                 r = path_set_perms(i, i->path);
1038                 if (r < 0)
1039                         return r;
1040
1041                 break;
1042
1043         case CREATE_SYMLINK:
1044
1045                 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1046                 r = symlink(i->argument, i->path);
1047                 mac_selinux_create_file_clear();
1048
1049                 if (r < 0) {
1050                         _cleanup_free_ char *x = NULL;
1051
1052                         if (errno != EEXIST)
1053                                 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
1054
1055                         r = readlink_malloc(i->path, &x);
1056                         if (r < 0 || !streq(i->argument, x)) {
1057
1058                                 if (i->force) {
1059                                         mac_selinux_create_file_prepare(i->path, S_IFLNK);
1060                                         r = symlink_atomic(i->argument, i->path);
1061                                         mac_selinux_create_file_clear();
1062
1063                                         if (r < 0)
1064                                                 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
1065                                 } else {
1066                                         log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
1067                                         return 0;
1068                                 }
1069                         }
1070                 }
1071                 log_debug("Created symlink \"%s\".", i->path);
1072
1073                 break;
1074
1075         case CREATE_BLOCK_DEVICE:
1076         case CREATE_CHAR_DEVICE: {
1077                 mode_t file_type;
1078
1079                 if (have_effective_cap(CAP_MKNOD) == 0) {
1080                         /* In a container we lack CAP_MKNOD. We
1081                         shouldn't attempt to create the device node in
1082                         that case to avoid noise, and we don't support
1083                         virtualized devices in containers anyway. */
1084
1085                         log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
1086                         return 0;
1087                 }
1088
1089                 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
1090
1091                 RUN_WITH_UMASK(0000) {
1092                         mac_selinux_create_file_prepare(i->path, file_type);
1093                         r = mknod(i->path, i->mode | file_type, i->major_minor);
1094                         mac_selinux_create_file_clear();
1095                 }
1096
1097                 if (r < 0) {
1098                         if (errno == EPERM) {
1099                                 log_debug("We lack permissions, possibly because of cgroup configuration; "
1100                                           "skipping creation of device node %s.", i->path);
1101                                 return 0;
1102                         }
1103
1104                         if (errno != EEXIST)
1105                                 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1106
1107                         if (stat(i->path, &st) < 0)
1108                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1109
1110                         if ((st.st_mode & S_IFMT) != file_type) {
1111
1112                                 if (i->force) {
1113
1114                                         RUN_WITH_UMASK(0000) {
1115                                                 mac_selinux_create_file_prepare(i->path, file_type);
1116                                                 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1117                                                 mac_selinux_create_file_clear();
1118                                         }
1119
1120                                         if (r < 0)
1121                                                 return log_error_errno(r, "Failed to create device node %s: %m", i->path);
1122                                 } else {
1123                                         log_debug("%s is not a device node.", i->path);
1124                                         return 0;
1125                                 }
1126                         }
1127                 }
1128                 log_debug("Created %s device node \"%s\" %u:%u.",
1129                           i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
1130                           i->path, major(i->mode), minor(i->mode));
1131
1132                 r = path_set_perms(i, i->path);
1133                 if (r < 0)
1134                         return r;
1135
1136                 break;
1137         }
1138
1139         case ADJUST_MODE:
1140         case RELABEL_PATH:
1141                 r = glob_item(i, path_set_perms, false);
1142                 if (r < 0)
1143                         return r;
1144                 break;
1145
1146         case RECURSIVE_RELABEL_PATH:
1147                 r = glob_item(i, path_set_perms, true);
1148                 if (r < 0)
1149                         return r;
1150                 break;
1151
1152         case SET_XATTR:
1153                 r = glob_item(i, path_set_xattrs, false);
1154                 if (r < 0)
1155                         return r;
1156                 break;
1157
1158         case RECURSIVE_SET_XATTR:
1159                 r = glob_item(i, path_set_xattrs, true);
1160                 if (r < 0)
1161                         return r;
1162                 break;
1163
1164         case SET_ACL:
1165                 r = glob_item(i, path_set_acls, false);
1166                 if (r < 0)
1167                         return r;
1168                 break;
1169
1170         case RECURSIVE_SET_ACL:
1171                 r = glob_item(i, path_set_acls, true);
1172                 if (r < 0)
1173                         return r;
1174                 break;
1175         }
1176
1177         log_debug("%s created successfully.", i->path);
1178
1179         return 0;
1180 }
1181
1182 static int remove_item_instance(Item *i, const char *instance) {
1183         int r;
1184
1185         assert(i);
1186
1187         switch (i->type) {
1188
1189         case REMOVE_PATH:
1190                 if (remove(instance) < 0 && errno != ENOENT)
1191                         return log_error_errno(errno, "rm(%s): %m", instance);
1192
1193                 break;
1194
1195         case TRUNCATE_DIRECTORY:
1196         case RECURSIVE_REMOVE_PATH:
1197                 /* FIXME: we probably should use dir_cleanup() here
1198                  * instead of rm_rf() so that 'x' is honoured. */
1199                 log_debug("rm -rf \"%s\"", instance);
1200                 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1201                 if (r < 0 && r != -ENOENT)
1202                         return log_error_errno(r, "rm_rf(%s): %m", instance);
1203
1204                 break;
1205
1206         default:
1207                 assert_not_reached("wut?");
1208         }
1209
1210         return 0;
1211 }
1212
1213 static int remove_item(Item *i) {
1214         int r = 0;
1215
1216         assert(i);
1217
1218         log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
1219
1220         switch (i->type) {
1221
1222         case CREATE_FILE:
1223         case TRUNCATE_FILE:
1224         case CREATE_DIRECTORY:
1225         case CREATE_SUBVOLUME:
1226         case CREATE_FIFO:
1227         case CREATE_SYMLINK:
1228         case CREATE_CHAR_DEVICE:
1229         case CREATE_BLOCK_DEVICE:
1230         case IGNORE_PATH:
1231         case IGNORE_DIRECTORY_PATH:
1232         case ADJUST_MODE:
1233         case RELABEL_PATH:
1234         case RECURSIVE_RELABEL_PATH:
1235         case WRITE_FILE:
1236         case COPY_FILES:
1237         case SET_XATTR:
1238         case RECURSIVE_SET_XATTR:
1239         case SET_ACL:
1240         case RECURSIVE_SET_ACL:
1241                 break;
1242
1243         case REMOVE_PATH:
1244         case TRUNCATE_DIRECTORY:
1245         case RECURSIVE_REMOVE_PATH:
1246                 r = glob_item(i, remove_item_instance, false);
1247                 break;
1248         }
1249
1250         return r;
1251 }
1252
1253 static int clean_item_instance(Item *i, const char* instance) {
1254         _cleanup_closedir_ DIR *d = NULL;
1255         struct stat s, ps;
1256         bool mountpoint;
1257         usec_t cutoff, n;
1258         char timestamp[FORMAT_TIMESTAMP_MAX];
1259
1260         assert(i);
1261
1262         if (!i->age_set)
1263                 return 0;
1264
1265         n = now(CLOCK_REALTIME);
1266         if (n < i->age)
1267                 return 0;
1268
1269         cutoff = n - i->age;
1270
1271         d = opendir_nomod(instance);
1272         if (!d) {
1273                 if (errno == ENOENT || errno == ENOTDIR) {
1274                         log_debug_errno(errno, "Directory \"%s\": %m", instance);
1275                         return 0;
1276                 }
1277
1278                 log_error_errno(errno, "Failed to open directory %s: %m", instance);
1279                 return -errno;
1280         }
1281
1282         if (fstat(dirfd(d), &s) < 0)
1283                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1284
1285         if (!S_ISDIR(s.st_mode)) {
1286                 log_error("%s is not a directory.", i->path);
1287                 return -ENOTDIR;
1288         }
1289
1290         if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1291                 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1292
1293         mountpoint = s.st_dev != ps.st_dev ||
1294                      (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1295
1296         log_debug("Cleanup threshold for %s \"%s\" is %s",
1297                   mountpoint ? "mount point" : "directory",
1298                   instance,
1299                   format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
1300
1301         return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1302                            MAX_DEPTH, i->keep_first_level);
1303 }
1304
1305 static int clean_item(Item *i) {
1306         int r = 0;
1307
1308         assert(i);
1309
1310         log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
1311
1312         switch (i->type) {
1313         case CREATE_DIRECTORY:
1314         case CREATE_SUBVOLUME:
1315         case TRUNCATE_DIRECTORY:
1316         case IGNORE_PATH:
1317         case COPY_FILES:
1318                 clean_item_instance(i, i->path);
1319                 break;
1320         case IGNORE_DIRECTORY_PATH:
1321                 r = glob_item(i, clean_item_instance, false);
1322                 break;
1323         default:
1324                 break;
1325         }
1326
1327         return r;
1328 }
1329
1330 static int process_item_array(ItemArray *array);
1331
1332 static int process_item(Item *i) {
1333         int r, q, p, t = 0;
1334         _cleanup_free_ char *prefix = NULL;
1335
1336         assert(i);
1337
1338         if (i->done)
1339                 return 0;
1340
1341         i->done = true;
1342
1343         prefix = malloc(strlen(i->path) + 1);
1344         if (!prefix)
1345                 return log_oom();
1346
1347         PATH_FOREACH_PREFIX(prefix, i->path) {
1348                 ItemArray *j;
1349
1350                 j = hashmap_get(items, prefix);
1351                 if (j) {
1352                         int s;
1353
1354                         s = process_item_array(j);
1355                         if (s < 0 && t == 0)
1356                                 t = s;
1357                 }
1358         }
1359
1360         r = arg_create ? create_item(i) : 0;
1361         q = arg_remove ? remove_item(i) : 0;
1362         p = arg_clean ? clean_item(i) : 0;
1363
1364         return t < 0 ? t :
1365                 r < 0 ? r :
1366                 q < 0 ? q :
1367                 p;
1368 }
1369
1370 static int process_item_array(ItemArray *array) {
1371         unsigned n;
1372         int r = 0, k;
1373
1374         assert(array);
1375
1376         for (n = 0; n < array->count; n++) {
1377                 k = process_item(array->items + n);
1378                 if (k < 0 && r == 0)
1379                         r = k;
1380         }
1381
1382         return r;
1383 }
1384
1385 static void item_free_contents(Item *i) {
1386         assert(i);
1387         free(i->path);
1388         free(i->argument);
1389         strv_free(i->xattrs);
1390
1391 #ifdef HAVE_ACL
1392         acl_free(i->acl_access);
1393         acl_free(i->acl_default);
1394 #endif
1395 }
1396
1397 static void item_array_free(ItemArray *a) {
1398         unsigned n;
1399
1400         if (!a)
1401                 return;
1402
1403         for (n = 0; n < a->count; n++)
1404                 item_free_contents(a->items + n);
1405         free(a->items);
1406         free(a);
1407 }
1408
1409 static bool item_compatible(Item *a, Item *b) {
1410         assert(a);
1411         assert(b);
1412         assert(streq(a->path, b->path));
1413
1414         if (takes_ownership(a->type) && takes_ownership(b->type))
1415                 /* check if the items are the same */
1416                 return  streq_ptr(a->argument, b->argument) &&
1417
1418                         a->uid_set == b->uid_set &&
1419                         a->uid == b->uid &&
1420
1421                         a->gid_set == b->gid_set &&
1422                         a->gid == b->gid &&
1423
1424                         a->mode_set == b->mode_set &&
1425                         a->mode == b->mode &&
1426
1427                         a->age_set == b->age_set &&
1428                         a->age == b->age &&
1429
1430                         a->mask_perms == b->mask_perms &&
1431
1432                         a->keep_first_level == b->keep_first_level &&
1433
1434                         a->major_minor == b->major_minor;
1435
1436         return true;
1437 }
1438
1439 static bool should_include_path(const char *path) {
1440         char **prefix;
1441
1442         STRV_FOREACH(prefix, arg_exclude_prefixes)
1443                 if (path_startswith(path, *prefix)) {
1444                         log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
1445                                   path, *prefix);
1446                         return false;
1447                 }
1448
1449         STRV_FOREACH(prefix, arg_include_prefixes)
1450                 if (path_startswith(path, *prefix)) {
1451                         log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
1452                         return true;
1453                 }
1454
1455         /* no matches, so we should include this path only if we
1456          * have no whitelist at all */
1457         if (strv_length(arg_include_prefixes) == 0)
1458                 return true;
1459
1460         log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
1461         return false;
1462 }
1463
1464 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1465
1466         static const Specifier specifier_table[] = {
1467                 { 'm', specifier_machine_id, NULL },
1468                 { 'b', specifier_boot_id, NULL },
1469                 { 'H', specifier_host_name, NULL },
1470                 { 'v', specifier_kernel_release, NULL },
1471                 {}
1472         };
1473
1474         _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1475         _cleanup_(item_free_contents) Item i = {};
1476         ItemArray *existing;
1477         Hashmap *h;
1478         int r, c = -1, pos;
1479         bool force = false, boot = false;
1480
1481         assert(fname);
1482         assert(line >= 1);
1483         assert(buffer);
1484
1485         r = sscanf(buffer,
1486                    "%ms %ms %ms %ms %ms %ms %n",
1487                    &action,
1488                    &path,
1489                    &mode,
1490                    &user,
1491                    &group,
1492                    &age,
1493                    &c);
1494         if (r < 2) {
1495                 log_error("[%s:%u] Syntax error.", fname, line);
1496                 return -EIO;
1497         }
1498
1499         if (isempty(action)) {
1500                 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1501                 return -EINVAL;
1502         }
1503
1504         for (pos = 1; action[pos]; pos++) {
1505                 if (action[pos] == '!' && !boot)
1506                         boot = true;
1507                 else if (action[pos] == '+' && !force)
1508                         force = true;
1509                 else {
1510                         log_error("[%s:%u] Unknown modifiers in command '%s'",
1511                                   fname, line, action);
1512                         return -EINVAL;
1513                 }
1514         }
1515
1516         if (boot && !arg_boot) {
1517                 log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
1518                           action, path);
1519                 return 0;
1520         }
1521
1522         i.type = action[0];
1523         i.force = force;
1524
1525         r = specifier_printf(path, specifier_table, NULL, &i.path);
1526         if (r < 0) {
1527                 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1528                 return r;
1529         }
1530
1531         if (c >= 0)  {
1532                 c += strspn(buffer+c, WHITESPACE);
1533                 if (buffer[c] != 0 && (buffer[c] != '-' || buffer[c+1] != 0)) {
1534                         i.argument = unquote(buffer+c, "\"");
1535                         if (!i.argument)
1536                                 return log_oom();
1537                 }
1538         }
1539
1540         switch (i.type) {
1541
1542         case CREATE_FILE:
1543         case TRUNCATE_FILE:
1544         case CREATE_DIRECTORY:
1545         case CREATE_SUBVOLUME:
1546         case TRUNCATE_DIRECTORY:
1547         case CREATE_FIFO:
1548         case IGNORE_PATH:
1549         case IGNORE_DIRECTORY_PATH:
1550         case REMOVE_PATH:
1551         case RECURSIVE_REMOVE_PATH:
1552         case ADJUST_MODE:
1553         case RELABEL_PATH:
1554         case RECURSIVE_RELABEL_PATH:
1555                 break;
1556
1557         case CREATE_SYMLINK:
1558                 if (!i.argument) {
1559                         i.argument = strappend("/usr/share/factory/", i.path);
1560                         if (!i.argument)
1561                                 return log_oom();
1562                 }
1563                 break;
1564
1565         case WRITE_FILE:
1566                 if (!i.argument) {
1567                         log_error("[%s:%u] Write file requires argument.", fname, line);
1568                         return -EBADMSG;
1569                 }
1570                 break;
1571
1572         case COPY_FILES:
1573                 if (!i.argument) {
1574                         i.argument = strappend("/usr/share/factory/", i.path);
1575                         if (!i.argument)
1576                                 return log_oom();
1577                 } else if (!path_is_absolute(i.argument)) {
1578                         log_error("[%s:%u] Source path is not absolute.", fname, line);
1579                         return -EBADMSG;
1580                 }
1581
1582                 path_kill_slashes(i.argument);
1583                 break;
1584
1585         case CREATE_CHAR_DEVICE:
1586         case CREATE_BLOCK_DEVICE: {
1587                 unsigned major, minor;
1588
1589                 if (!i.argument) {
1590                         log_error("[%s:%u] Device file requires argument.", fname, line);
1591                         return -EBADMSG;
1592                 }
1593
1594                 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1595                         log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1596                         return -EBADMSG;
1597                 }
1598
1599                 i.major_minor = makedev(major, minor);
1600                 break;
1601         }
1602
1603         case SET_XATTR:
1604         case RECURSIVE_SET_XATTR:
1605                 if (!i.argument) {
1606                         log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1607                         return -EBADMSG;
1608                 }
1609                 r = get_xattrs_from_arg(&i);
1610                 if (r < 0)
1611                         return r;
1612                 break;
1613
1614         case SET_ACL:
1615         case RECURSIVE_SET_ACL:
1616                 if (!i.argument) {
1617                         log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1618                         return -EBADMSG;
1619                 }
1620                 r = get_acls_from_arg(&i);
1621                 if (r < 0)
1622                         return r;
1623                 break;
1624
1625         default:
1626                 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
1627                 return -EBADMSG;
1628         }
1629
1630         if (!path_is_absolute(i.path)) {
1631                 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1632                 return -EBADMSG;
1633         }
1634
1635         path_kill_slashes(i.path);
1636
1637         if (!should_include_path(i.path))
1638                 return 0;
1639
1640         if (arg_root) {
1641                 char *p;
1642
1643                 p = strappend(arg_root, i.path);
1644                 if (!p)
1645                         return log_oom();
1646
1647                 free(i.path);
1648                 i.path = p;
1649         }
1650
1651         if (user && !streq(user, "-")) {
1652                 const char *u = user;
1653
1654                 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1655                 if (r < 0) {
1656                         log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1657                         return r;
1658                 }
1659
1660                 i.uid_set = true;
1661         }
1662
1663         if (group && !streq(group, "-")) {
1664                 const char *g = group;
1665
1666                 r = get_group_creds(&g, &i.gid);
1667                 if (r < 0) {
1668                         log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1669                         return r;
1670                 }
1671
1672                 i.gid_set = true;
1673         }
1674
1675         if (mode && !streq(mode, "-")) {
1676                 const char *mm = mode;
1677                 unsigned m;
1678
1679                 if (*mm == '~') {
1680                         i.mask_perms = true;
1681                         mm++;
1682                 }
1683
1684                 if (sscanf(mm, "%o", &m) != 1) {
1685                         log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1686                         return -ENOENT;
1687                 }
1688
1689                 i.mode = m;
1690                 i.mode_set = true;
1691         } else
1692                 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1693                         ? 0755 : 0644;
1694
1695         if (age && !streq(age, "-")) {
1696                 const char *a = age;
1697
1698                 if (*a == '~') {
1699                         i.keep_first_level = true;
1700                         a++;
1701                 }
1702
1703                 if (parse_sec(a, &i.age) < 0) {
1704                         log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1705                         return -EBADMSG;
1706                 }
1707
1708                 i.age_set = true;
1709         }
1710
1711         h = needs_glob(i.type) ? globs : items;
1712
1713         existing = hashmap_get(h, i.path);
1714         if (existing) {
1715                 unsigned n;
1716
1717                 for (n = 0; n < existing->count; n++) {
1718                         if (!item_compatible(existing->items + n, &i))
1719                                 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1720                                             fname, line, i.path);
1721                 }
1722         } else {
1723                 existing = new0(ItemArray, 1);
1724                 r = hashmap_put(h, i.path, existing);
1725                 if (r < 0)
1726                         return log_oom();
1727         }
1728
1729         if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1730                 return log_oom();
1731
1732         memcpy(existing->items + existing->count++, &i, sizeof(i));
1733         zero(i);
1734         return 0;
1735 }
1736
1737 static void help(void) {
1738         printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1739                "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1740                "  -h --help                 Show this help\n"
1741                "     --version              Show package version\n"
1742                "     --create               Create marked files/directories\n"
1743                "     --clean                Clean up marked directories\n"
1744                "     --remove               Remove marked files/directories\n"
1745                "     --boot                 Execute actions only safe at boot\n"
1746                "     --prefix=PATH          Only apply rules with the specified prefix\n"
1747                "     --exclude-prefix=PATH  Ignore rules with the specified prefix\n"
1748                "     --root=PATH            Operate on an alternate filesystem root\n",
1749                program_invocation_short_name);
1750 }
1751
1752 static int parse_argv(int argc, char *argv[]) {
1753
1754         enum {
1755                 ARG_VERSION = 0x100,
1756                 ARG_CREATE,
1757                 ARG_CLEAN,
1758                 ARG_REMOVE,
1759                 ARG_BOOT,
1760                 ARG_PREFIX,
1761                 ARG_EXCLUDE_PREFIX,
1762                 ARG_ROOT,
1763         };
1764
1765         static const struct option options[] = {
1766                 { "help",           no_argument,         NULL, 'h'                },
1767                 { "version",        no_argument,         NULL, ARG_VERSION        },
1768                 { "create",         no_argument,         NULL, ARG_CREATE         },
1769                 { "clean",          no_argument,         NULL, ARG_CLEAN          },
1770                 { "remove",         no_argument,         NULL, ARG_REMOVE         },
1771                 { "boot",           no_argument,         NULL, ARG_BOOT           },
1772                 { "prefix",         required_argument,   NULL, ARG_PREFIX         },
1773                 { "exclude-prefix", required_argument,   NULL, ARG_EXCLUDE_PREFIX },
1774                 { "root",           required_argument,   NULL, ARG_ROOT           },
1775                 {}
1776         };
1777
1778         int c;
1779
1780         assert(argc >= 0);
1781         assert(argv);
1782
1783         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1784
1785                 switch (c) {
1786
1787                 case 'h':
1788                         help();
1789                         return 0;
1790
1791                 case ARG_VERSION:
1792                         puts(PACKAGE_STRING);
1793                         puts(SYSTEMD_FEATURES);
1794                         return 0;
1795
1796                 case ARG_CREATE:
1797                         arg_create = true;
1798                         break;
1799
1800                 case ARG_CLEAN:
1801                         arg_clean = true;
1802                         break;
1803
1804                 case ARG_REMOVE:
1805                         arg_remove = true;
1806                         break;
1807
1808                 case ARG_BOOT:
1809                         arg_boot = true;
1810                         break;
1811
1812                 case ARG_PREFIX:
1813                         if (strv_push(&arg_include_prefixes, optarg) < 0)
1814                                 return log_oom();
1815                         break;
1816
1817                 case ARG_EXCLUDE_PREFIX:
1818                         if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1819                                 return log_oom();
1820                         break;
1821
1822                 case ARG_ROOT:
1823                         free(arg_root);
1824                         arg_root = path_make_absolute_cwd(optarg);
1825                         if (!arg_root)
1826                                 return log_oom();
1827
1828                         path_kill_slashes(arg_root);
1829                         break;
1830
1831                 case '?':
1832                         return -EINVAL;
1833
1834                 default:
1835                         assert_not_reached("Unhandled option");
1836                 }
1837
1838         if (!arg_clean && !arg_create && !arg_remove) {
1839                 log_error("You need to specify at least one of --clean, --create or --remove.");
1840                 return -EINVAL;
1841         }
1842
1843         return 1;
1844 }
1845
1846 static int read_config_file(const char *fn, bool ignore_enoent) {
1847         _cleanup_fclose_ FILE *f = NULL;
1848         char line[LINE_MAX];
1849         Iterator iterator;
1850         unsigned v = 0;
1851         Item *i;
1852         int r;
1853
1854         assert(fn);
1855
1856         r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
1857         if (r < 0) {
1858                 if (ignore_enoent && r == -ENOENT) {
1859                         log_debug_errno(r, "Failed to open \"%s\": %m", fn);
1860                         return 0;
1861                 }
1862
1863                 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
1864         }
1865         log_debug("Reading config file \"%s\".", fn);
1866
1867         FOREACH_LINE(line, f, break) {
1868                 char *l;
1869                 int k;
1870
1871                 v++;
1872
1873                 l = strstrip(line);
1874                 if (*l == '#' || *l == 0)
1875                         continue;
1876
1877                 k = parse_line(fn, v, l);
1878                 if (k < 0 && r == 0)
1879                         r = k;
1880         }
1881
1882         /* we have to determine age parameter for each entry of type X */
1883         HASHMAP_FOREACH(i, globs, iterator) {
1884                 Iterator iter;
1885                 Item *j, *candidate_item = NULL;
1886
1887                 if (i->type != IGNORE_DIRECTORY_PATH)
1888                         continue;
1889
1890                 HASHMAP_FOREACH(j, items, iter) {
1891                         if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
1892                                 continue;
1893
1894                         if (path_equal(j->path, i->path)) {
1895                                 candidate_item = j;
1896                                 break;
1897                         }
1898
1899                         if ((!candidate_item && path_startswith(i->path, j->path)) ||
1900                             (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1901                                 candidate_item = j;
1902                 }
1903
1904                 if (candidate_item && candidate_item->age_set) {
1905                         i->age = candidate_item->age;
1906                         i->age_set = true;
1907                 }
1908         }
1909
1910         if (ferror(f)) {
1911                 log_error_errno(errno, "Failed to read from file %s: %m", fn);
1912                 if (r == 0)
1913                         r = -EIO;
1914         }
1915
1916         return r;
1917 }
1918
1919 int main(int argc, char *argv[]) {
1920         int r, k;
1921         ItemArray *a;
1922         Iterator iterator;
1923
1924         r = parse_argv(argc, argv);
1925         if (r <= 0)
1926                 goto finish;
1927
1928         log_set_target(LOG_TARGET_AUTO);
1929         log_parse_environment();
1930         log_open();
1931
1932         umask(0022);
1933
1934         mac_selinux_init(NULL);
1935
1936         items = hashmap_new(&string_hash_ops);
1937         globs = hashmap_new(&string_hash_ops);
1938
1939         if (!items || !globs) {
1940                 r = log_oom();
1941                 goto finish;
1942         }
1943
1944         r = 0;
1945
1946         if (optind < argc) {
1947                 int j;
1948
1949                 for (j = optind; j < argc; j++) {
1950                         k = read_config_file(argv[j], false);
1951                         if (k < 0 && r == 0)
1952                                 r = k;
1953                 }
1954
1955         } else {
1956                 _cleanup_strv_free_ char **files = NULL;
1957                 char **f;
1958
1959                 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
1960                 if (r < 0) {
1961                         log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
1962                         goto finish;
1963                 }
1964
1965                 STRV_FOREACH(f, files) {
1966                         k = read_config_file(*f, true);
1967                         if (k < 0 && r == 0)
1968                                 r = k;
1969                 }
1970         }
1971
1972         HASHMAP_FOREACH(a, globs, iterator) {
1973                 k = process_item_array(a);
1974                 if (k < 0 && r == 0)
1975                         r = k;
1976         }
1977
1978         HASHMAP_FOREACH(a, items, iterator) {
1979                 k = process_item_array(a);
1980                 if (k < 0 && r == 0)
1981                         r = k;
1982         }
1983
1984 finish:
1985         while ((a = hashmap_steal_first(items)))
1986                 item_array_free(a);
1987
1988         while ((a = hashmap_steal_first(globs)))
1989                 item_array_free(a);
1990
1991         hashmap_free(items);
1992         hashmap_free(globs);
1993
1994         free(arg_include_prefixes);
1995         free(arg_exclude_prefixes);
1996         free(arg_root);
1997
1998         set_free_free(unix_sockets);
1999
2000         mac_selinux_finish();
2001
2002         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
2003 }