chiark / gitweb /
0e1bd86748396228bf4412ae98ea9ca9f74ad431
[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 typedef enum {
907         CREATION_NORMAL,
908         CREATION_EXISTING,
909         CREATION_FORCE,
910 } CreationMode;
911
912 static const char* creation_verb(CreationMode mode) {
913         switch(mode) {
914         case CREATION_NORMAL:
915                 return "Created";
916         case CREATION_EXISTING:
917                 return "Found existing";
918         case CREATION_FORCE:
919                 return "Created replacement";
920         }
921         assert_not_reached("Bad creation");
922 }
923
924 static int create_item(Item *i) {
925         struct stat st;
926         int r = 0;
927         CreationMode creation;
928
929         assert(i);
930
931         log_debug("Running create action for entry %c %s", (char) i->type, i->path);
932
933         switch (i->type) {
934
935         case IGNORE_PATH:
936         case IGNORE_DIRECTORY_PATH:
937         case REMOVE_PATH:
938         case RECURSIVE_REMOVE_PATH:
939                 return 0;
940
941         case CREATE_FILE:
942         case TRUNCATE_FILE:
943                 r = write_one_file(i, i->path);
944                 if (r < 0)
945                         return r;
946                 break;
947
948         case COPY_FILES:
949                 log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
950                 r = copy_tree(i->argument, i->path, false);
951                 if (r < 0) {
952                         struct stat a, b;
953
954                         if (r != -EEXIST)
955                                 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
956
957                         if (stat(i->argument, &a) < 0)
958                                 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
959
960                         if (stat(i->path, &b) < 0)
961                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
962
963                         if ((a.st_mode ^ b.st_mode) & S_IFMT) {
964                                 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
965                                 return 0;
966                         }
967                 }
968
969                 r = path_set_perms(i, i->path);
970                 if (r < 0)
971                         return r;
972
973                 break;
974
975         case WRITE_FILE:
976                 r = glob_item(i, write_one_file, false);
977                 if (r < 0)
978                         return r;
979
980                 break;
981
982         case CREATE_DIRECTORY:
983         case TRUNCATE_DIRECTORY:
984         case CREATE_SUBVOLUME:
985
986                 RUN_WITH_UMASK(0000)
987                         mkdir_parents_label(i->path, 0755);
988
989                 if (i->type == CREATE_SUBVOLUME)
990                         RUN_WITH_UMASK((~i->mode) & 0777) {
991                                 r = btrfs_subvol_make(i->path);
992                                 log_debug_errno(r, "Creating subvolume \"%s\": %m", i->path);
993                         }
994                 else
995                         r = 0;
996
997                 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
998                         RUN_WITH_UMASK(0000)
999                                 r = mkdir_label(i->path, i->mode);
1000
1001                 if (r < 0) {
1002                         if (r != -EEXIST)
1003                                 return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);
1004
1005                         if (stat(i->path, &st) < 0)
1006                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1007
1008                         if (!S_ISDIR(st.st_mode)) {
1009                                 log_debug("\"%s\" already exists and is not a directory.", i->path);
1010                                 return 0;
1011                         }
1012
1013                         creation = CREATION_EXISTING;
1014                 } else
1015                         creation = CREATION_NORMAL;
1016                 log_debug("%s directory \"%s\".", creation_verb(creation), i->path);
1017
1018                 r = path_set_perms(i, i->path);
1019                 if (r < 0)
1020                         return r;
1021
1022                 break;
1023
1024         case CREATE_FIFO:
1025
1026                 RUN_WITH_UMASK(0000) {
1027                         mac_selinux_create_file_prepare(i->path, S_IFIFO);
1028                         r = mkfifo(i->path, i->mode);
1029                         mac_selinux_create_file_clear();
1030                 }
1031
1032                 if (r < 0) {
1033                         if (errno != EEXIST)
1034                                 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
1035
1036                         if (stat(i->path, &st) < 0)
1037                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1038
1039                         if (!S_ISFIFO(st.st_mode)) {
1040
1041                                 if (i->force) {
1042
1043                                         RUN_WITH_UMASK(0000) {
1044                                                 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1045                                                 r = mkfifo_atomic(i->path, i->mode);
1046                                                 mac_selinux_create_file_clear();
1047                                         }
1048
1049                                         if (r < 0)
1050                                                 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
1051                                         creation = CREATION_FORCE;
1052                                 } else {
1053                                         log_debug("%s is not a fifo.", i->path);
1054                                         return 0;
1055                                 }
1056                         } else
1057                                 creation = CREATION_EXISTING;
1058                 } else
1059                         creation = CREATION_NORMAL;
1060                 log_debug("%s fifo \"%s\".", creation_verb(creation), i->path);
1061
1062                 r = path_set_perms(i, i->path);
1063                 if (r < 0)
1064                         return r;
1065
1066                 break;
1067
1068         case CREATE_SYMLINK:
1069
1070                 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1071                 r = symlink(i->argument, i->path);
1072                 mac_selinux_create_file_clear();
1073
1074                 if (r < 0) {
1075                         _cleanup_free_ char *x = NULL;
1076
1077                         if (errno != EEXIST)
1078                                 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
1079
1080                         r = readlink_malloc(i->path, &x);
1081                         if (r < 0 || !streq(i->argument, x)) {
1082
1083                                 if (i->force) {
1084                                         mac_selinux_create_file_prepare(i->path, S_IFLNK);
1085                                         r = symlink_atomic(i->argument, i->path);
1086                                         mac_selinux_create_file_clear();
1087
1088                                         if (r < 0)
1089                                                 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
1090                                         creation = CREATION_FORCE;
1091                                 } else {
1092                                         log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
1093                                         return 0;
1094                                 }
1095                         } else
1096                                 creation = CREATION_EXISTING;
1097                 } else
1098                         creation = CREATION_NORMAL;
1099                 log_debug("%s symlink \"%s\".", creation_verb(creation), i->path);
1100
1101                 break;
1102
1103         case CREATE_BLOCK_DEVICE:
1104         case CREATE_CHAR_DEVICE: {
1105                 mode_t file_type;
1106
1107                 if (have_effective_cap(CAP_MKNOD) == 0) {
1108                         /* In a container we lack CAP_MKNOD. We
1109                         shouldn't attempt to create the device node in
1110                         that case to avoid noise, and we don't support
1111                         virtualized devices in containers anyway. */
1112
1113                         log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
1114                         return 0;
1115                 }
1116
1117                 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
1118
1119                 RUN_WITH_UMASK(0000) {
1120                         mac_selinux_create_file_prepare(i->path, file_type);
1121                         r = mknod(i->path, i->mode | file_type, i->major_minor);
1122                         mac_selinux_create_file_clear();
1123                 }
1124
1125                 if (r < 0) {
1126                         if (errno == EPERM) {
1127                                 log_debug("We lack permissions, possibly because of cgroup configuration; "
1128                                           "skipping creation of device node %s.", i->path);
1129                                 return 0;
1130                         }
1131
1132                         if (errno != EEXIST)
1133                                 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1134
1135                         if (stat(i->path, &st) < 0)
1136                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1137
1138                         if ((st.st_mode & S_IFMT) != file_type) {
1139
1140                                 if (i->force) {
1141
1142                                         RUN_WITH_UMASK(0000) {
1143                                                 mac_selinux_create_file_prepare(i->path, file_type);
1144                                                 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1145                                                 mac_selinux_create_file_clear();
1146                                         }
1147
1148                                         if (r < 0)
1149                                                 return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path);
1150                                         creation = CREATION_FORCE;
1151                                 } else {
1152                                         log_debug("%s is not a device node.", i->path);
1153                                         return 0;
1154                                 }
1155                         } else
1156                                 creation = CREATION_EXISTING;
1157                 } else
1158                         creation = CREATION_NORMAL;
1159                 log_debug("%s %s device node \"%s\" %u:%u.",
1160                           creation_verb(creation),
1161                           i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
1162                           i->path, major(i->mode), minor(i->mode));
1163
1164                 r = path_set_perms(i, i->path);
1165                 if (r < 0)
1166                         return r;
1167
1168                 break;
1169         }
1170
1171         case ADJUST_MODE:
1172         case RELABEL_PATH:
1173                 r = glob_item(i, path_set_perms, false);
1174                 if (r < 0)
1175                         return r;
1176                 break;
1177
1178         case RECURSIVE_RELABEL_PATH:
1179                 r = glob_item(i, path_set_perms, true);
1180                 if (r < 0)
1181                         return r;
1182                 break;
1183
1184         case SET_XATTR:
1185                 r = glob_item(i, path_set_xattrs, false);
1186                 if (r < 0)
1187                         return r;
1188                 break;
1189
1190         case RECURSIVE_SET_XATTR:
1191                 r = glob_item(i, path_set_xattrs, true);
1192                 if (r < 0)
1193                         return r;
1194                 break;
1195
1196         case SET_ACL:
1197                 r = glob_item(i, path_set_acls, false);
1198                 if (r < 0)
1199                         return r;
1200                 break;
1201
1202         case RECURSIVE_SET_ACL:
1203                 r = glob_item(i, path_set_acls, true);
1204                 if (r < 0)
1205                         return r;
1206                 break;
1207         }
1208
1209         log_debug("%s created successfully.", i->path);
1210
1211         return 0;
1212 }
1213
1214 static int remove_item_instance(Item *i, const char *instance) {
1215         int r;
1216
1217         assert(i);
1218
1219         switch (i->type) {
1220
1221         case REMOVE_PATH:
1222                 if (remove(instance) < 0 && errno != ENOENT)
1223                         return log_error_errno(errno, "rm(%s): %m", instance);
1224
1225                 break;
1226
1227         case TRUNCATE_DIRECTORY:
1228         case RECURSIVE_REMOVE_PATH:
1229                 /* FIXME: we probably should use dir_cleanup() here
1230                  * instead of rm_rf() so that 'x' is honoured. */
1231                 log_debug("rm -rf \"%s\"", instance);
1232                 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1233                 if (r < 0 && r != -ENOENT)
1234                         return log_error_errno(r, "rm_rf(%s): %m", instance);
1235
1236                 break;
1237
1238         default:
1239                 assert_not_reached("wut?");
1240         }
1241
1242         return 0;
1243 }
1244
1245 static int remove_item(Item *i) {
1246         int r = 0;
1247
1248         assert(i);
1249
1250         log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
1251
1252         switch (i->type) {
1253
1254         case CREATE_FILE:
1255         case TRUNCATE_FILE:
1256         case CREATE_DIRECTORY:
1257         case CREATE_SUBVOLUME:
1258         case CREATE_FIFO:
1259         case CREATE_SYMLINK:
1260         case CREATE_CHAR_DEVICE:
1261         case CREATE_BLOCK_DEVICE:
1262         case IGNORE_PATH:
1263         case IGNORE_DIRECTORY_PATH:
1264         case ADJUST_MODE:
1265         case RELABEL_PATH:
1266         case RECURSIVE_RELABEL_PATH:
1267         case WRITE_FILE:
1268         case COPY_FILES:
1269         case SET_XATTR:
1270         case RECURSIVE_SET_XATTR:
1271         case SET_ACL:
1272         case RECURSIVE_SET_ACL:
1273                 break;
1274
1275         case REMOVE_PATH:
1276         case TRUNCATE_DIRECTORY:
1277         case RECURSIVE_REMOVE_PATH:
1278                 r = glob_item(i, remove_item_instance, false);
1279                 break;
1280         }
1281
1282         return r;
1283 }
1284
1285 static int clean_item_instance(Item *i, const char* instance) {
1286         _cleanup_closedir_ DIR *d = NULL;
1287         struct stat s, ps;
1288         bool mountpoint;
1289         usec_t cutoff, n;
1290         char timestamp[FORMAT_TIMESTAMP_MAX];
1291
1292         assert(i);
1293
1294         if (!i->age_set)
1295                 return 0;
1296
1297         n = now(CLOCK_REALTIME);
1298         if (n < i->age)
1299                 return 0;
1300
1301         cutoff = n - i->age;
1302
1303         d = opendir_nomod(instance);
1304         if (!d) {
1305                 if (errno == ENOENT || errno == ENOTDIR) {
1306                         log_debug_errno(errno, "Directory \"%s\": %m", instance);
1307                         return 0;
1308                 }
1309
1310                 log_error_errno(errno, "Failed to open directory %s: %m", instance);
1311                 return -errno;
1312         }
1313
1314         if (fstat(dirfd(d), &s) < 0)
1315                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1316
1317         if (!S_ISDIR(s.st_mode)) {
1318                 log_error("%s is not a directory.", i->path);
1319                 return -ENOTDIR;
1320         }
1321
1322         if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1323                 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1324
1325         mountpoint = s.st_dev != ps.st_dev ||
1326                      (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1327
1328         log_debug("Cleanup threshold for %s \"%s\" is %s",
1329                   mountpoint ? "mount point" : "directory",
1330                   instance,
1331                   format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
1332
1333         return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1334                            MAX_DEPTH, i->keep_first_level);
1335 }
1336
1337 static int clean_item(Item *i) {
1338         int r = 0;
1339
1340         assert(i);
1341
1342         log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
1343
1344         switch (i->type) {
1345         case CREATE_DIRECTORY:
1346         case CREATE_SUBVOLUME:
1347         case TRUNCATE_DIRECTORY:
1348         case IGNORE_PATH:
1349         case COPY_FILES:
1350                 clean_item_instance(i, i->path);
1351                 break;
1352         case IGNORE_DIRECTORY_PATH:
1353                 r = glob_item(i, clean_item_instance, false);
1354                 break;
1355         default:
1356                 break;
1357         }
1358
1359         return r;
1360 }
1361
1362 static int process_item_array(ItemArray *array);
1363
1364 static int process_item(Item *i) {
1365         int r, q, p, t = 0;
1366         _cleanup_free_ char *prefix = NULL;
1367
1368         assert(i);
1369
1370         if (i->done)
1371                 return 0;
1372
1373         i->done = true;
1374
1375         prefix = malloc(strlen(i->path) + 1);
1376         if (!prefix)
1377                 return log_oom();
1378
1379         PATH_FOREACH_PREFIX(prefix, i->path) {
1380                 ItemArray *j;
1381
1382                 j = hashmap_get(items, prefix);
1383                 if (j) {
1384                         int s;
1385
1386                         s = process_item_array(j);
1387                         if (s < 0 && t == 0)
1388                                 t = s;
1389                 }
1390         }
1391
1392         r = arg_create ? create_item(i) : 0;
1393         q = arg_remove ? remove_item(i) : 0;
1394         p = arg_clean ? clean_item(i) : 0;
1395
1396         return t < 0 ? t :
1397                 r < 0 ? r :
1398                 q < 0 ? q :
1399                 p;
1400 }
1401
1402 static int process_item_array(ItemArray *array) {
1403         unsigned n;
1404         int r = 0, k;
1405
1406         assert(array);
1407
1408         for (n = 0; n < array->count; n++) {
1409                 k = process_item(array->items + n);
1410                 if (k < 0 && r == 0)
1411                         r = k;
1412         }
1413
1414         return r;
1415 }
1416
1417 static void item_free_contents(Item *i) {
1418         assert(i);
1419         free(i->path);
1420         free(i->argument);
1421         strv_free(i->xattrs);
1422
1423 #ifdef HAVE_ACL
1424         acl_free(i->acl_access);
1425         acl_free(i->acl_default);
1426 #endif
1427 }
1428
1429 static void item_array_free(ItemArray *a) {
1430         unsigned n;
1431
1432         if (!a)
1433                 return;
1434
1435         for (n = 0; n < a->count; n++)
1436                 item_free_contents(a->items + n);
1437         free(a->items);
1438         free(a);
1439 }
1440
1441 static bool item_compatible(Item *a, Item *b) {
1442         assert(a);
1443         assert(b);
1444         assert(streq(a->path, b->path));
1445
1446         if (takes_ownership(a->type) && takes_ownership(b->type))
1447                 /* check if the items are the same */
1448                 return  streq_ptr(a->argument, b->argument) &&
1449
1450                         a->uid_set == b->uid_set &&
1451                         a->uid == b->uid &&
1452
1453                         a->gid_set == b->gid_set &&
1454                         a->gid == b->gid &&
1455
1456                         a->mode_set == b->mode_set &&
1457                         a->mode == b->mode &&
1458
1459                         a->age_set == b->age_set &&
1460                         a->age == b->age &&
1461
1462                         a->mask_perms == b->mask_perms &&
1463
1464                         a->keep_first_level == b->keep_first_level &&
1465
1466                         a->major_minor == b->major_minor;
1467
1468         return true;
1469 }
1470
1471 static bool should_include_path(const char *path) {
1472         char **prefix;
1473
1474         STRV_FOREACH(prefix, arg_exclude_prefixes)
1475                 if (path_startswith(path, *prefix)) {
1476                         log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
1477                                   path, *prefix);
1478                         return false;
1479                 }
1480
1481         STRV_FOREACH(prefix, arg_include_prefixes)
1482                 if (path_startswith(path, *prefix)) {
1483                         log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
1484                         return true;
1485                 }
1486
1487         /* no matches, so we should include this path only if we
1488          * have no whitelist at all */
1489         if (strv_length(arg_include_prefixes) == 0)
1490                 return true;
1491
1492         log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
1493         return false;
1494 }
1495
1496 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1497
1498         static const Specifier specifier_table[] = {
1499                 { 'm', specifier_machine_id, NULL },
1500                 { 'b', specifier_boot_id, NULL },
1501                 { 'H', specifier_host_name, NULL },
1502                 { 'v', specifier_kernel_release, NULL },
1503                 {}
1504         };
1505
1506         _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1507         _cleanup_(item_free_contents) Item i = {};
1508         ItemArray *existing;
1509         Hashmap *h;
1510         int r, c = -1, pos;
1511         bool force = false, boot = false;
1512
1513         assert(fname);
1514         assert(line >= 1);
1515         assert(buffer);
1516
1517         r = sscanf(buffer,
1518                    "%ms %ms %ms %ms %ms %ms %n",
1519                    &action,
1520                    &path,
1521                    &mode,
1522                    &user,
1523                    &group,
1524                    &age,
1525                    &c);
1526         if (r < 2) {
1527                 log_error("[%s:%u] Syntax error.", fname, line);
1528                 return -EIO;
1529         }
1530
1531         if (isempty(action)) {
1532                 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1533                 return -EINVAL;
1534         }
1535
1536         for (pos = 1; action[pos]; pos++) {
1537                 if (action[pos] == '!' && !boot)
1538                         boot = true;
1539                 else if (action[pos] == '+' && !force)
1540                         force = true;
1541                 else {
1542                         log_error("[%s:%u] Unknown modifiers in command '%s'",
1543                                   fname, line, action);
1544                         return -EINVAL;
1545                 }
1546         }
1547
1548         if (boot && !arg_boot) {
1549                 log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
1550                           action, path);
1551                 return 0;
1552         }
1553
1554         i.type = action[0];
1555         i.force = force;
1556
1557         r = specifier_printf(path, specifier_table, NULL, &i.path);
1558         if (r < 0) {
1559                 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1560                 return r;
1561         }
1562
1563         if (c >= 0)  {
1564                 c += strspn(buffer+c, WHITESPACE);
1565                 if (buffer[c] != 0 && (buffer[c] != '-' || buffer[c+1] != 0)) {
1566                         i.argument = unquote(buffer+c, "\"");
1567                         if (!i.argument)
1568                                 return log_oom();
1569                 }
1570         }
1571
1572         switch (i.type) {
1573
1574         case CREATE_FILE:
1575         case TRUNCATE_FILE:
1576         case CREATE_DIRECTORY:
1577         case CREATE_SUBVOLUME:
1578         case TRUNCATE_DIRECTORY:
1579         case CREATE_FIFO:
1580         case IGNORE_PATH:
1581         case IGNORE_DIRECTORY_PATH:
1582         case REMOVE_PATH:
1583         case RECURSIVE_REMOVE_PATH:
1584         case ADJUST_MODE:
1585         case RELABEL_PATH:
1586         case RECURSIVE_RELABEL_PATH:
1587                 break;
1588
1589         case CREATE_SYMLINK:
1590                 if (!i.argument) {
1591                         i.argument = strappend("/usr/share/factory/", i.path);
1592                         if (!i.argument)
1593                                 return log_oom();
1594                 }
1595                 break;
1596
1597         case WRITE_FILE:
1598                 if (!i.argument) {
1599                         log_error("[%s:%u] Write file requires argument.", fname, line);
1600                         return -EBADMSG;
1601                 }
1602                 break;
1603
1604         case COPY_FILES:
1605                 if (!i.argument) {
1606                         i.argument = strappend("/usr/share/factory/", i.path);
1607                         if (!i.argument)
1608                                 return log_oom();
1609                 } else if (!path_is_absolute(i.argument)) {
1610                         log_error("[%s:%u] Source path is not absolute.", fname, line);
1611                         return -EBADMSG;
1612                 }
1613
1614                 path_kill_slashes(i.argument);
1615                 break;
1616
1617         case CREATE_CHAR_DEVICE:
1618         case CREATE_BLOCK_DEVICE: {
1619                 unsigned major, minor;
1620
1621                 if (!i.argument) {
1622                         log_error("[%s:%u] Device file requires argument.", fname, line);
1623                         return -EBADMSG;
1624                 }
1625
1626                 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1627                         log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1628                         return -EBADMSG;
1629                 }
1630
1631                 i.major_minor = makedev(major, minor);
1632                 break;
1633         }
1634
1635         case SET_XATTR:
1636         case RECURSIVE_SET_XATTR:
1637                 if (!i.argument) {
1638                         log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1639                         return -EBADMSG;
1640                 }
1641                 r = get_xattrs_from_arg(&i);
1642                 if (r < 0)
1643                         return r;
1644                 break;
1645
1646         case SET_ACL:
1647         case RECURSIVE_SET_ACL:
1648                 if (!i.argument) {
1649                         log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1650                         return -EBADMSG;
1651                 }
1652                 r = get_acls_from_arg(&i);
1653                 if (r < 0)
1654                         return r;
1655                 break;
1656
1657         default:
1658                 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
1659                 return -EBADMSG;
1660         }
1661
1662         if (!path_is_absolute(i.path)) {
1663                 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1664                 return -EBADMSG;
1665         }
1666
1667         path_kill_slashes(i.path);
1668
1669         if (!should_include_path(i.path))
1670                 return 0;
1671
1672         if (arg_root) {
1673                 char *p;
1674
1675                 p = strappend(arg_root, i.path);
1676                 if (!p)
1677                         return log_oom();
1678
1679                 free(i.path);
1680                 i.path = p;
1681         }
1682
1683         if (user && !streq(user, "-")) {
1684                 const char *u = user;
1685
1686                 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1687                 if (r < 0) {
1688                         log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1689                         return r;
1690                 }
1691
1692                 i.uid_set = true;
1693         }
1694
1695         if (group && !streq(group, "-")) {
1696                 const char *g = group;
1697
1698                 r = get_group_creds(&g, &i.gid);
1699                 if (r < 0) {
1700                         log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1701                         return r;
1702                 }
1703
1704                 i.gid_set = true;
1705         }
1706
1707         if (mode && !streq(mode, "-")) {
1708                 const char *mm = mode;
1709                 unsigned m;
1710
1711                 if (*mm == '~') {
1712                         i.mask_perms = true;
1713                         mm++;
1714                 }
1715
1716                 if (sscanf(mm, "%o", &m) != 1) {
1717                         log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1718                         return -ENOENT;
1719                 }
1720
1721                 i.mode = m;
1722                 i.mode_set = true;
1723         } else
1724                 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1725                         ? 0755 : 0644;
1726
1727         if (age && !streq(age, "-")) {
1728                 const char *a = age;
1729
1730                 if (*a == '~') {
1731                         i.keep_first_level = true;
1732                         a++;
1733                 }
1734
1735                 if (parse_sec(a, &i.age) < 0) {
1736                         log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1737                         return -EBADMSG;
1738                 }
1739
1740                 i.age_set = true;
1741         }
1742
1743         h = needs_glob(i.type) ? globs : items;
1744
1745         existing = hashmap_get(h, i.path);
1746         if (existing) {
1747                 unsigned n;
1748
1749                 for (n = 0; n < existing->count; n++) {
1750                         if (!item_compatible(existing->items + n, &i))
1751                                 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1752                                             fname, line, i.path);
1753                 }
1754         } else {
1755                 existing = new0(ItemArray, 1);
1756                 r = hashmap_put(h, i.path, existing);
1757                 if (r < 0)
1758                         return log_oom();
1759         }
1760
1761         if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1762                 return log_oom();
1763
1764         memcpy(existing->items + existing->count++, &i, sizeof(i));
1765         zero(i);
1766         return 0;
1767 }
1768
1769 static void help(void) {
1770         printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1771                "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1772                "  -h --help                 Show this help\n"
1773                "     --version              Show package version\n"
1774                "     --create               Create marked files/directories\n"
1775                "     --clean                Clean up marked directories\n"
1776                "     --remove               Remove marked files/directories\n"
1777                "     --boot                 Execute actions only safe at boot\n"
1778                "     --prefix=PATH          Only apply rules with the specified prefix\n"
1779                "     --exclude-prefix=PATH  Ignore rules with the specified prefix\n"
1780                "     --root=PATH            Operate on an alternate filesystem root\n",
1781                program_invocation_short_name);
1782 }
1783
1784 static int parse_argv(int argc, char *argv[]) {
1785
1786         enum {
1787                 ARG_VERSION = 0x100,
1788                 ARG_CREATE,
1789                 ARG_CLEAN,
1790                 ARG_REMOVE,
1791                 ARG_BOOT,
1792                 ARG_PREFIX,
1793                 ARG_EXCLUDE_PREFIX,
1794                 ARG_ROOT,
1795         };
1796
1797         static const struct option options[] = {
1798                 { "help",           no_argument,         NULL, 'h'                },
1799                 { "version",        no_argument,         NULL, ARG_VERSION        },
1800                 { "create",         no_argument,         NULL, ARG_CREATE         },
1801                 { "clean",          no_argument,         NULL, ARG_CLEAN          },
1802                 { "remove",         no_argument,         NULL, ARG_REMOVE         },
1803                 { "boot",           no_argument,         NULL, ARG_BOOT           },
1804                 { "prefix",         required_argument,   NULL, ARG_PREFIX         },
1805                 { "exclude-prefix", required_argument,   NULL, ARG_EXCLUDE_PREFIX },
1806                 { "root",           required_argument,   NULL, ARG_ROOT           },
1807                 {}
1808         };
1809
1810         int c;
1811
1812         assert(argc >= 0);
1813         assert(argv);
1814
1815         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1816
1817                 switch (c) {
1818
1819                 case 'h':
1820                         help();
1821                         return 0;
1822
1823                 case ARG_VERSION:
1824                         puts(PACKAGE_STRING);
1825                         puts(SYSTEMD_FEATURES);
1826                         return 0;
1827
1828                 case ARG_CREATE:
1829                         arg_create = true;
1830                         break;
1831
1832                 case ARG_CLEAN:
1833                         arg_clean = true;
1834                         break;
1835
1836                 case ARG_REMOVE:
1837                         arg_remove = true;
1838                         break;
1839
1840                 case ARG_BOOT:
1841                         arg_boot = true;
1842                         break;
1843
1844                 case ARG_PREFIX:
1845                         if (strv_push(&arg_include_prefixes, optarg) < 0)
1846                                 return log_oom();
1847                         break;
1848
1849                 case ARG_EXCLUDE_PREFIX:
1850                         if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1851                                 return log_oom();
1852                         break;
1853
1854                 case ARG_ROOT:
1855                         free(arg_root);
1856                         arg_root = path_make_absolute_cwd(optarg);
1857                         if (!arg_root)
1858                                 return log_oom();
1859
1860                         path_kill_slashes(arg_root);
1861                         break;
1862
1863                 case '?':
1864                         return -EINVAL;
1865
1866                 default:
1867                         assert_not_reached("Unhandled option");
1868                 }
1869
1870         if (!arg_clean && !arg_create && !arg_remove) {
1871                 log_error("You need to specify at least one of --clean, --create or --remove.");
1872                 return -EINVAL;
1873         }
1874
1875         return 1;
1876 }
1877
1878 static int read_config_file(const char *fn, bool ignore_enoent) {
1879         _cleanup_fclose_ FILE *f = NULL;
1880         char line[LINE_MAX];
1881         Iterator iterator;
1882         unsigned v = 0;
1883         Item *i;
1884         int r;
1885
1886         assert(fn);
1887
1888         r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
1889         if (r < 0) {
1890                 if (ignore_enoent && r == -ENOENT) {
1891                         log_debug_errno(r, "Failed to open \"%s\": %m", fn);
1892                         return 0;
1893                 }
1894
1895                 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
1896         }
1897         log_debug("Reading config file \"%s\".", fn);
1898
1899         FOREACH_LINE(line, f, break) {
1900                 char *l;
1901                 int k;
1902
1903                 v++;
1904
1905                 l = strstrip(line);
1906                 if (*l == '#' || *l == 0)
1907                         continue;
1908
1909                 k = parse_line(fn, v, l);
1910                 if (k < 0 && r == 0)
1911                         r = k;
1912         }
1913
1914         /* we have to determine age parameter for each entry of type X */
1915         HASHMAP_FOREACH(i, globs, iterator) {
1916                 Iterator iter;
1917                 Item *j, *candidate_item = NULL;
1918
1919                 if (i->type != IGNORE_DIRECTORY_PATH)
1920                         continue;
1921
1922                 HASHMAP_FOREACH(j, items, iter) {
1923                         if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
1924                                 continue;
1925
1926                         if (path_equal(j->path, i->path)) {
1927                                 candidate_item = j;
1928                                 break;
1929                         }
1930
1931                         if ((!candidate_item && path_startswith(i->path, j->path)) ||
1932                             (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1933                                 candidate_item = j;
1934                 }
1935
1936                 if (candidate_item && candidate_item->age_set) {
1937                         i->age = candidate_item->age;
1938                         i->age_set = true;
1939                 }
1940         }
1941
1942         if (ferror(f)) {
1943                 log_error_errno(errno, "Failed to read from file %s: %m", fn);
1944                 if (r == 0)
1945                         r = -EIO;
1946         }
1947
1948         return r;
1949 }
1950
1951 int main(int argc, char *argv[]) {
1952         int r, k;
1953         ItemArray *a;
1954         Iterator iterator;
1955
1956         r = parse_argv(argc, argv);
1957         if (r <= 0)
1958                 goto finish;
1959
1960         log_set_target(LOG_TARGET_AUTO);
1961         log_parse_environment();
1962         log_open();
1963
1964         umask(0022);
1965
1966         mac_selinux_init(NULL);
1967
1968         items = hashmap_new(&string_hash_ops);
1969         globs = hashmap_new(&string_hash_ops);
1970
1971         if (!items || !globs) {
1972                 r = log_oom();
1973                 goto finish;
1974         }
1975
1976         r = 0;
1977
1978         if (optind < argc) {
1979                 int j;
1980
1981                 for (j = optind; j < argc; j++) {
1982                         k = read_config_file(argv[j], false);
1983                         if (k < 0 && r == 0)
1984                                 r = k;
1985                 }
1986
1987         } else {
1988                 _cleanup_strv_free_ char **files = NULL;
1989                 char **f;
1990
1991                 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
1992                 if (r < 0) {
1993                         log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
1994                         goto finish;
1995                 }
1996
1997                 STRV_FOREACH(f, files) {
1998                         k = read_config_file(*f, true);
1999                         if (k < 0 && r == 0)
2000                                 r = k;
2001                 }
2002         }
2003
2004         HASHMAP_FOREACH(a, globs, iterator) {
2005                 k = process_item_array(a);
2006                 if (k < 0 && r == 0)
2007                         r = k;
2008         }
2009
2010         HASHMAP_FOREACH(a, items, iterator) {
2011                 k = process_item_array(a);
2012                 if (k < 0 && r == 0)
2013                         r = k;
2014         }
2015
2016 finish:
2017         while ((a = hashmap_steal_first(items)))
2018                 item_array_free(a);
2019
2020         while ((a = hashmap_steal_first(globs)))
2021                 item_array_free(a);
2022
2023         hashmap_free(items);
2024         hashmap_free(globs);
2025
2026         free(arg_include_prefixes);
2027         free(arg_exclude_prefixes);
2028         free(arg_root);
2029
2030         set_free_free(unix_sockets);
2031
2032         mac_selinux_finish();
2033
2034         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
2035 }