chiark / gitweb /
sd-icmp6-nd: Parse ICMPv6 prefix information
[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                         if (i->type == IGNORE_DIRECTORY_PATH && streq(dent->d_name, p))
469                                 log_debug("Ignoring directory \"%s\"", sub_path);
470                         else {
471                                 log_debug("Removing directory \"%s\".", sub_path);
472
473                                 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
474                                         if (errno != ENOENT && errno != ENOTEMPTY) {
475                                                 log_error_errno(errno, "rmdir(%s): %m", sub_path);
476                                                 r = -errno;
477                                         }
478                                 }
479                         }
480
481                 } else {
482                         /* Skip files for which the sticky bit is
483                          * set. These are semantics we define, and are
484                          * unknown elsewhere. See XDG_RUNTIME_DIR
485                          * specification for details. */
486                         if (s.st_mode & S_ISVTX) {
487                                 log_debug("Skipping \"%s\": sticky bit set.", sub_path);
488                                 continue;
489                         }
490
491                         if (mountpoint && S_ISREG(s.st_mode))
492                                 if ((streq(dent->d_name, ".journal") && s.st_uid == 0) ||
493                                     streq(dent->d_name, "aquota.user") ||
494                                     streq(dent->d_name, "aquota.group")) {
495                                         log_debug("Skipping \"%s\".", sub_path);
496                                         continue;
497                                 }
498
499                         /* Ignore sockets that are listed in /proc/net/unix */
500                         if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path)) {
501                                 log_debug("Skipping \"%s\": live socket.", sub_path);
502                                 continue;
503                         }
504
505                         /* Ignore device nodes */
506                         if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode)) {
507                                 log_debug("Skipping \"%s\": a device.", sub_path);
508                                 continue;
509                         }
510
511                         /* Keep files on this level around if this is
512                          * requested */
513                         if (keep_this_level) {
514                                 log_debug("Keeping \"%s\".", sub_path);
515                                 continue;
516                         }
517
518                         age = timespec_load(&s.st_mtim);
519                         if (age >= cutoff) {
520                                 char a[FORMAT_TIMESTAMP_MAX];
521                                 /* Follows spelling in stat(1). */
522                                 log_debug("File \"%s\": modify time %s is too new.",
523                                           sub_path,
524                                           format_timestamp_us(a, sizeof(a), age));
525                                 continue;
526                         }
527
528                         age = timespec_load(&s.st_atim);
529                         if (age >= cutoff) {
530                                 char a[FORMAT_TIMESTAMP_MAX];
531                                 log_debug("File \"%s\": access time %s is too new.",
532                                           sub_path,
533                                           format_timestamp_us(a, sizeof(a), age));
534                                 continue;
535                         }
536
537                         age = timespec_load(&s.st_ctim);
538                         if (age >= cutoff) {
539                                 char a[FORMAT_TIMESTAMP_MAX];
540                                 log_debug("File \"%s\": change time %s is too new.",
541                                           sub_path,
542                                           format_timestamp_us(a, sizeof(a), age));
543                                 continue;
544                         }
545
546                         log_debug("unlink \"%s\"", sub_path);
547
548                         if (unlinkat(dirfd(d), dent->d_name, 0) < 0)
549                                 if (errno != ENOENT)
550                                         r = log_error_errno(errno, "unlink(%s): %m", sub_path);
551
552                         deleted = true;
553                 }
554         }
555
556 finish:
557         if (deleted) {
558                 usec_t age1, age2;
559                 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
560
561                 /* Restore original directory timestamps */
562                 times[0] = ds->st_atim;
563                 times[1] = ds->st_mtim;
564
565                 age1 = timespec_load(&ds->st_atim);
566                 age2 = timespec_load(&ds->st_mtim);
567                 log_debug("Restoring access and modification time on \"%s\": %s, %s",
568                           p,
569                           format_timestamp_us(a, sizeof(a), age1),
570                           format_timestamp_us(b, sizeof(b), age2));
571                 if (futimens(dirfd(d), times) < 0)
572                         log_error_errno(errno, "utimensat(%s): %m", p);
573         }
574
575         return r;
576 }
577
578 static int path_set_perms(Item *i, const char *path) {
579         struct stat st;
580         bool st_valid;
581
582         assert(i);
583         assert(path);
584
585         st_valid = stat(path, &st) == 0;
586
587         /* not using i->path directly because it may be a glob */
588         if (i->mode_set) {
589                 mode_t m = i->mode;
590
591                 if (i->mask_perms && st_valid) {
592                         if (!(st.st_mode & 0111))
593                                 m &= ~0111;
594                         if (!(st.st_mode & 0222))
595                                 m &= ~0222;
596                         if (!(st.st_mode & 0444))
597                                 m &= ~0444;
598                         if (!S_ISDIR(st.st_mode))
599                                 m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
600                 }
601
602                 if (st_valid && m == (st.st_mode & 07777))
603                         log_debug("\"%s\" has right mode %o", path, st.st_mode);
604                 else {
605                         log_debug("chmod \"%s\" to mode %o", path, m);
606                         if (chmod(path, m) < 0)
607                                 return log_error_errno(errno, "chmod(%s) failed: %m", path);
608                 }
609         }
610
611         if ((!st_valid || i->uid != st.st_uid || i->gid != st.st_gid) &&
612             (i->uid_set || i->gid_set)) {
613                 log_debug("chown \"%s\" to "UID_FMT"."GID_FMT,
614                           path,
615                           i->uid_set ? i->uid : UID_INVALID,
616                           i->gid_set ? i->gid : GID_INVALID);
617                 if (chown(path,
618                           i->uid_set ? i->uid : UID_INVALID,
619                           i->gid_set ? i->gid : GID_INVALID) < 0)
620
621                         return log_error_errno(errno, "chown(%s) failed: %m", path);
622         }
623
624         return label_fix(path, false, false);
625 }
626
627 static int get_xattrs_from_arg(Item *i) {
628         char *xattr;
629         const char *p;
630         int r;
631
632         assert(i);
633         assert(i->argument);
634
635         p = i->argument;
636
637         while ((r = unquote_first_word(&p, &xattr, false)) > 0) {
638                 _cleanup_free_ char *tmp = NULL, *name = NULL,
639                         *value = NULL, *value2 = NULL, *_xattr = xattr;
640
641                 r = split_pair(xattr, "=", &name, &value);
642                 if (r < 0) {
643                         log_warning("Illegal xattr found: \"%s\" - ignoring.", xattr);
644                         continue;
645                 }
646
647                 if (strempty(name) || strempty(value)) {
648                         log_warning("Malformed xattr found: \"%s\" - ignoring.", xattr);
649                         continue;
650                 }
651
652                 tmp = unquote(value, "\"");
653                 if (!tmp)
654                         return log_oom();
655
656                 value2 = cunescape(tmp);
657                 if (!value2)
658                         return log_oom();
659
660                 if (strv_push_pair(&i->xattrs, name, value2) < 0)
661                         return log_oom();
662                 name = value2 = NULL;
663         }
664
665         return r;
666 }
667
668 static int path_set_xattrs(Item *i, const char *path) {
669         char **name, **value;
670
671         assert(i);
672         assert(path);
673
674         STRV_FOREACH_PAIR(name, value, i->xattrs) {
675                 int n;
676
677                 n = strlen(*value);
678                 log_debug("\"%s\": setting xattr \"%s=%s\"", path, *name, *value);
679                 if (lsetxattr(path, *name, *value, n, 0) < 0) {
680                         log_error("Setting extended attribute %s=%s on %s failed: %m",
681                                   *name, *value, path);
682                         return -errno;
683                 }
684         }
685         return 0;
686 }
687
688 static int get_acls_from_arg(Item *item) {
689 #ifdef HAVE_ACL
690         int r;
691         _cleanup_(acl_freep) acl_t a = NULL, d = NULL;
692
693         assert(item);
694
695         /* If force (= modify) is set, we will not modify the acl
696          * afterwards, so the mask can be added now if necessary. */
697         r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
698         if (r < 0)
699                 log_warning_errno(errno, "Failed to parse ACL \"%s\": %m. Ignoring",
700                                   item->argument);
701 #else
702         log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
703 #endif
704
705         return 0;
706 }
707
708 static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
709         _cleanup_(acl_freep) acl_t dup = NULL;
710         int r;
711         _cleanup_(acl_free_charpp) char *t = NULL;
712
713         if (modify) {
714                 r = acls_for_file(path, type, acl, &dup);
715                 if (r < 0)
716                         return r;
717
718                 r = calc_acl_mask_if_needed(&dup);
719                 if (r < 0)
720                         return r;
721         } else {
722                 dup = acl_dup(acl);
723                 if (!dup)
724                         return -errno;
725
726                 /* the mask was already added earlier if needed */
727         }
728
729         r = add_base_acls_if_needed(&dup, path);
730         if (r < 0)
731                 return r;
732
733         t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
734         log_debug("\"%s\": setting %s ACL \"%s\"", path,
735                   type == ACL_TYPE_ACCESS ? "access" : "default",
736                   strna(t));
737
738         r = acl_set_file(path, type, dup);
739         if (r < 0)
740                 return log_error_errno(-errno,
741                                        "Setting %s ACL \"%s\" on %s failed: %m",
742                                        type == ACL_TYPE_ACCESS ? "access" : "default",
743                                        strna(t), path);
744         return 0;
745 }
746
747 static int path_set_acls(Item *item, const char *path) {
748 #ifdef HAVE_ACL
749         int r;
750
751         assert(item);
752         assert(path);
753
754         if (item->acl_access) {
755                 r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
756                 if (r < 0)
757                         return r;
758         }
759
760         if (item->acl_default) {
761                 r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
762                 if (r < 0)
763                         return r;
764         }
765 #endif
766
767         return 0;
768 }
769
770 static int write_one_file(Item *i, const char *path) {
771         _cleanup_close_ int fd = -1;
772         int flags, r = 0;
773         struct stat st;
774
775         assert(i);
776         assert(path);
777
778         flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
779                 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
780
781         RUN_WITH_UMASK(0000) {
782                 mac_selinux_create_file_prepare(path, S_IFREG);
783                 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
784                 mac_selinux_create_file_clear();
785         }
786
787         if (fd < 0) {
788                 if (i->type == WRITE_FILE && errno == ENOENT) {
789                         log_debug_errno(errno, "Not writing \"%s\": %m", path);
790                         return 0;
791                 }
792
793                 log_error_errno(errno, "Failed to create file %s: %m", path);
794                 return -errno;
795         }
796
797         if (i->argument) {
798                 _cleanup_free_ char *unescaped;
799
800                 log_debug("%s to \"%s\".",
801                           i->type == CREATE_FILE ? "Appending" : "Writing", path);
802
803                 unescaped = cunescape(i->argument);
804                 if (!unescaped)
805                         return log_oom();
806
807                 r = loop_write(fd, unescaped, strlen(unescaped), false);
808                 if (r < 0)
809                         return log_error_errno(r, "Failed to write file \"%s\": %m", path);
810         } else
811                 log_debug("\"%s\" has been created.", path);
812
813         fd = safe_close(fd);
814
815         if (stat(path, &st) < 0)
816                 return log_error_errno(errno, "stat(%s) failed: %m", path);
817
818         if (!S_ISREG(st.st_mode)) {
819                 log_error("%s is not a file.", path);
820                 return -EEXIST;
821         }
822
823         r = path_set_perms(i, path);
824         if (r < 0)
825                 return r;
826
827         return 0;
828 }
829
830 typedef int (*action_t)(Item *, const char *);
831
832 static int item_do_children(Item *i, const char *path, action_t action) {
833         _cleanup_closedir_ DIR *d;
834         int r = 0;
835
836         assert(i);
837         assert(path);
838
839         /* This returns the first error we run into, but nevertheless
840          * tries to go on */
841
842         d = opendir_nomod(path);
843         if (!d)
844                 return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
845
846         for (;;) {
847                 _cleanup_free_ char *p = NULL;
848                 struct dirent *de;
849                 int q;
850
851                 errno = 0;
852                 de = readdir(d);
853                 if (!de) {
854                         if (errno != 0 && r == 0)
855                                 r = -errno;
856
857                         break;
858                 }
859
860                 if (STR_IN_SET(de->d_name, ".", ".."))
861                         continue;
862
863                 p = strjoin(path, "/", de->d_name, NULL);
864                 if (!p)
865                         return -ENOMEM;
866
867                 q = action(i, p);
868                 if (q < 0 && q != -ENOENT && r == 0)
869                         r = q;
870
871                 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
872                         q = item_do_children(i, p, action);
873                         if (q < 0 && r == 0)
874                                 r = q;
875                 }
876         }
877
878         return r;
879 }
880
881 static int glob_item(Item *i, action_t action, bool recursive) {
882         _cleanup_globfree_ glob_t g = {
883                 .gl_closedir = (void (*)(void *)) closedir,
884                 .gl_readdir = (struct dirent *(*)(void *)) readdir,
885                 .gl_opendir = (void *(*)(const char *)) opendir_nomod,
886                 .gl_lstat = lstat,
887                 .gl_stat = stat,
888         };
889         int r = 0, k;
890         char **fn;
891
892         errno = 0;
893         k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
894         if (k != 0 && k != GLOB_NOMATCH)
895                 return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
896
897         STRV_FOREACH(fn, g.gl_pathv) {
898                 k = action(i, *fn);
899                 if (k < 0 && r == 0)
900                         r = k;
901
902                 if (recursive) {
903                         k = item_do_children(i, *fn, action);
904                         if (k < 0 && r == 0)
905                                 r = k;
906                 }
907         }
908
909         return r;
910 }
911
912 static int create_item(Item *i) {
913         struct stat st;
914         int r = 0;
915
916         assert(i);
917
918         log_debug("Running create action for entry %c %s", (char) i->type, i->path);
919
920         switch (i->type) {
921
922         case IGNORE_PATH:
923         case IGNORE_DIRECTORY_PATH:
924         case REMOVE_PATH:
925         case RECURSIVE_REMOVE_PATH:
926                 return 0;
927
928         case CREATE_FILE:
929         case TRUNCATE_FILE:
930                 r = write_one_file(i, i->path);
931                 if (r < 0)
932                         return r;
933                 break;
934
935         case COPY_FILES:
936                 log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
937                 r = copy_tree(i->argument, i->path, false);
938                 if (r < 0) {
939                         struct stat a, b;
940
941                         if (r != -EEXIST)
942                                 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
943
944                         if (stat(i->argument, &a) < 0)
945                                 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
946
947                         if (stat(i->path, &b) < 0)
948                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
949
950                         if ((a.st_mode ^ b.st_mode) & S_IFMT) {
951                                 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
952                                 return 0;
953                         }
954                 }
955
956                 r = path_set_perms(i, i->path);
957                 if (r < 0)
958                         return r;
959
960                 break;
961
962         case WRITE_FILE:
963                 r = glob_item(i, write_one_file, false);
964                 if (r < 0)
965                         return r;
966
967                 break;
968
969         case CREATE_DIRECTORY:
970         case TRUNCATE_DIRECTORY:
971         case CREATE_SUBVOLUME:
972
973                 RUN_WITH_UMASK(0000)
974                         mkdir_parents_label(i->path, 0755);
975
976                 if (i->type == CREATE_SUBVOLUME)
977                         RUN_WITH_UMASK((~i->mode) & 0777) {
978                                 r = btrfs_subvol_make(i->path);
979                                 log_debug_errno(r, "Creating subvolume \"%s\": %m", i->path);
980                         }
981                 else
982                         r = 0;
983
984                 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
985                         RUN_WITH_UMASK(0000)
986                                 r = mkdir_label(i->path, i->mode);
987
988                 if (r < 0) {
989                         if (r != -EEXIST)
990                                 return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);
991
992                         if (stat(i->path, &st) < 0)
993                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
994
995                         if (!S_ISDIR(st.st_mode)) {
996                                 log_debug("\"%s\" already exists and is not a directory.", i->path);
997                                 return 0;
998                         }
999                 }
1000                 log_debug("Created directory \"%s\".", i->path);
1001
1002                 r = path_set_perms(i, i->path);
1003                 if (r < 0)
1004                         return r;
1005
1006                 break;
1007
1008         case CREATE_FIFO:
1009
1010                 RUN_WITH_UMASK(0000) {
1011                         mac_selinux_create_file_prepare(i->path, S_IFIFO);
1012                         r = mkfifo(i->path, i->mode);
1013                         mac_selinux_create_file_clear();
1014                 }
1015
1016                 if (r < 0) {
1017                         if (errno != EEXIST)
1018                                 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
1019
1020                         if (stat(i->path, &st) < 0)
1021                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1022
1023                         if (!S_ISFIFO(st.st_mode)) {
1024
1025                                 if (i->force) {
1026
1027                                         RUN_WITH_UMASK(0000) {
1028                                                 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1029                                                 r = mkfifo_atomic(i->path, i->mode);
1030                                                 mac_selinux_create_file_clear();
1031                                         }
1032
1033                                         if (r < 0)
1034                                                 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
1035                                 } else {
1036                                         log_debug("%s is not a fifo.", i->path);
1037                                         return 0;
1038                                 }
1039                         }
1040                 }
1041                 log_debug("Created fifo \"%s\".", i->path);
1042
1043                 r = path_set_perms(i, i->path);
1044                 if (r < 0)
1045                         return r;
1046
1047                 break;
1048
1049         case CREATE_SYMLINK:
1050
1051                 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1052                 r = symlink(i->argument, i->path);
1053                 mac_selinux_create_file_clear();
1054
1055                 if (r < 0) {
1056                         _cleanup_free_ char *x = NULL;
1057
1058                         if (errno != EEXIST)
1059                                 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
1060
1061                         r = readlink_malloc(i->path, &x);
1062                         if (r < 0 || !streq(i->argument, x)) {
1063
1064                                 if (i->force) {
1065                                         mac_selinux_create_file_prepare(i->path, S_IFLNK);
1066                                         r = symlink_atomic(i->argument, i->path);
1067                                         mac_selinux_create_file_clear();
1068
1069                                         if (r < 0)
1070                                                 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
1071                                 } else {
1072                                         log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
1073                                         return 0;
1074                                 }
1075                         }
1076                 }
1077                 log_debug("Created symlink \"%s\".", i->path);
1078
1079                 break;
1080
1081         case CREATE_BLOCK_DEVICE:
1082         case CREATE_CHAR_DEVICE: {
1083                 mode_t file_type;
1084
1085                 if (have_effective_cap(CAP_MKNOD) == 0) {
1086                         /* In a container we lack CAP_MKNOD. We
1087                         shouldn't attempt to create the device node in
1088                         that case to avoid noise, and we don't support
1089                         virtualized devices in containers anyway. */
1090
1091                         log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
1092                         return 0;
1093                 }
1094
1095                 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
1096
1097                 RUN_WITH_UMASK(0000) {
1098                         mac_selinux_create_file_prepare(i->path, file_type);
1099                         r = mknod(i->path, i->mode | file_type, i->major_minor);
1100                         mac_selinux_create_file_clear();
1101                 }
1102
1103                 if (r < 0) {
1104                         if (errno == EPERM) {
1105                                 log_debug("We lack permissions, possibly because of cgroup configuration; "
1106                                           "skipping creation of device node %s.", i->path);
1107                                 return 0;
1108                         }
1109
1110                         if (errno != EEXIST)
1111                                 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1112
1113                         if (stat(i->path, &st) < 0)
1114                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1115
1116                         if ((st.st_mode & S_IFMT) != file_type) {
1117
1118                                 if (i->force) {
1119
1120                                         RUN_WITH_UMASK(0000) {
1121                                                 mac_selinux_create_file_prepare(i->path, file_type);
1122                                                 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1123                                                 mac_selinux_create_file_clear();
1124                                         }
1125
1126                                         if (r < 0)
1127                                                 return log_error_errno(r, "Failed to create device node %s: %m", i->path);
1128                                 } else {
1129                                         log_debug("%s is not a device node.", i->path);
1130                                         return 0;
1131                                 }
1132                         }
1133                 }
1134                 log_debug("Created %s device node \"%s\" %u:%u.",
1135                           i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
1136                           i->path, major(i->mode), minor(i->mode));
1137
1138                 r = path_set_perms(i, i->path);
1139                 if (r < 0)
1140                         return r;
1141
1142                 break;
1143         }
1144
1145         case ADJUST_MODE:
1146         case RELABEL_PATH:
1147                 r = glob_item(i, path_set_perms, false);
1148                 if (r < 0)
1149                         return r;
1150                 break;
1151
1152         case RECURSIVE_RELABEL_PATH:
1153                 r = glob_item(i, path_set_perms, true);
1154                 if (r < 0)
1155                         return r;
1156                 break;
1157
1158         case SET_XATTR:
1159                 r = glob_item(i, path_set_xattrs, false);
1160                 if (r < 0)
1161                         return r;
1162                 break;
1163
1164         case RECURSIVE_SET_XATTR:
1165                 r = glob_item(i, path_set_xattrs, true);
1166                 if (r < 0)
1167                         return r;
1168                 break;
1169
1170         case SET_ACL:
1171                 r = glob_item(i, path_set_acls, false);
1172                 if (r < 0)
1173                         return r;
1174                 break;
1175
1176         case RECURSIVE_SET_ACL:
1177                 r = glob_item(i, path_set_acls, true);
1178                 if (r < 0)
1179                         return r;
1180                 break;
1181         }
1182
1183         log_debug("%s created successfully.", i->path);
1184
1185         return 0;
1186 }
1187
1188 static int remove_item_instance(Item *i, const char *instance) {
1189         int r;
1190
1191         assert(i);
1192
1193         switch (i->type) {
1194
1195         case REMOVE_PATH:
1196                 if (remove(instance) < 0 && errno != ENOENT)
1197                         return log_error_errno(errno, "rm(%s): %m", instance);
1198
1199                 break;
1200
1201         case TRUNCATE_DIRECTORY:
1202         case RECURSIVE_REMOVE_PATH:
1203                 /* FIXME: we probably should use dir_cleanup() here
1204                  * instead of rm_rf() so that 'x' is honoured. */
1205                 log_debug("rm -rf \"%s\"", instance);
1206                 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1207                 if (r < 0 && r != -ENOENT)
1208                         return log_error_errno(r, "rm_rf(%s): %m", instance);
1209
1210                 break;
1211
1212         default:
1213                 assert_not_reached("wut?");
1214         }
1215
1216         return 0;
1217 }
1218
1219 static int remove_item(Item *i) {
1220         int r = 0;
1221
1222         assert(i);
1223
1224         log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
1225
1226         switch (i->type) {
1227
1228         case CREATE_FILE:
1229         case TRUNCATE_FILE:
1230         case CREATE_DIRECTORY:
1231         case CREATE_SUBVOLUME:
1232         case CREATE_FIFO:
1233         case CREATE_SYMLINK:
1234         case CREATE_CHAR_DEVICE:
1235         case CREATE_BLOCK_DEVICE:
1236         case IGNORE_PATH:
1237         case IGNORE_DIRECTORY_PATH:
1238         case ADJUST_MODE:
1239         case RELABEL_PATH:
1240         case RECURSIVE_RELABEL_PATH:
1241         case WRITE_FILE:
1242         case COPY_FILES:
1243         case SET_XATTR:
1244         case RECURSIVE_SET_XATTR:
1245         case SET_ACL:
1246         case RECURSIVE_SET_ACL:
1247                 break;
1248
1249         case REMOVE_PATH:
1250         case TRUNCATE_DIRECTORY:
1251         case RECURSIVE_REMOVE_PATH:
1252                 r = glob_item(i, remove_item_instance, false);
1253                 break;
1254         }
1255
1256         return r;
1257 }
1258
1259 static int clean_item_instance(Item *i, const char* instance) {
1260         _cleanup_closedir_ DIR *d = NULL;
1261         struct stat s, ps;
1262         bool mountpoint;
1263         usec_t cutoff, n;
1264         char timestamp[FORMAT_TIMESTAMP_MAX];
1265
1266         assert(i);
1267
1268         if (!i->age_set)
1269                 return 0;
1270
1271         n = now(CLOCK_REALTIME);
1272         if (n < i->age)
1273                 return 0;
1274
1275         cutoff = n - i->age;
1276
1277         d = opendir_nomod(instance);
1278         if (!d) {
1279                 if (errno == ENOENT || errno == ENOTDIR) {
1280                         log_debug_errno(errno, "Directory \"%s\": %m", instance);
1281                         return 0;
1282                 }
1283
1284                 log_error_errno(errno, "Failed to open directory %s: %m", instance);
1285                 return -errno;
1286         }
1287
1288         if (fstat(dirfd(d), &s) < 0)
1289                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1290
1291         if (!S_ISDIR(s.st_mode)) {
1292                 log_error("%s is not a directory.", i->path);
1293                 return -ENOTDIR;
1294         }
1295
1296         if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1297                 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1298
1299         mountpoint = s.st_dev != ps.st_dev ||
1300                      (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1301
1302         log_debug("Cleanup threshold for %s \"%s\" is %s",
1303                   mountpoint ? "mount point" : "directory",
1304                   instance,
1305                   format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
1306
1307         return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1308                            MAX_DEPTH, i->keep_first_level);
1309 }
1310
1311 static int clean_item(Item *i) {
1312         int r = 0;
1313
1314         assert(i);
1315
1316         log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
1317
1318         switch (i->type) {
1319         case CREATE_DIRECTORY:
1320         case CREATE_SUBVOLUME:
1321         case TRUNCATE_DIRECTORY:
1322         case IGNORE_PATH:
1323         case COPY_FILES:
1324                 clean_item_instance(i, i->path);
1325                 break;
1326         case IGNORE_DIRECTORY_PATH:
1327                 r = glob_item(i, clean_item_instance, false);
1328                 break;
1329         default:
1330                 break;
1331         }
1332
1333         return r;
1334 }
1335
1336 static int process_item_array(ItemArray *array);
1337
1338 static int process_item(Item *i) {
1339         int r, q, p, t = 0;
1340         _cleanup_free_ char *prefix = NULL;
1341
1342         assert(i);
1343
1344         if (i->done)
1345                 return 0;
1346
1347         i->done = true;
1348
1349         prefix = malloc(strlen(i->path) + 1);
1350         if (!prefix)
1351                 return log_oom();
1352
1353         PATH_FOREACH_PREFIX(prefix, i->path) {
1354                 ItemArray *j;
1355
1356                 j = hashmap_get(items, prefix);
1357                 if (j) {
1358                         int s;
1359
1360                         s = process_item_array(j);
1361                         if (s < 0 && t == 0)
1362                                 t = s;
1363                 }
1364         }
1365
1366         r = arg_create ? create_item(i) : 0;
1367         q = arg_remove ? remove_item(i) : 0;
1368         p = arg_clean ? clean_item(i) : 0;
1369
1370         return t < 0 ? t :
1371                 r < 0 ? r :
1372                 q < 0 ? q :
1373                 p;
1374 }
1375
1376 static int process_item_array(ItemArray *array) {
1377         unsigned n;
1378         int r = 0, k;
1379
1380         assert(array);
1381
1382         for (n = 0; n < array->count; n++) {
1383                 k = process_item(array->items + n);
1384                 if (k < 0 && r == 0)
1385                         r = k;
1386         }
1387
1388         return r;
1389 }
1390
1391 static void item_free_contents(Item *i) {
1392         assert(i);
1393         free(i->path);
1394         free(i->argument);
1395         strv_free(i->xattrs);
1396
1397 #ifdef HAVE_ACL
1398         acl_free(i->acl_access);
1399         acl_free(i->acl_default);
1400 #endif
1401 }
1402
1403 static void item_array_free(ItemArray *a) {
1404         unsigned n;
1405
1406         if (!a)
1407                 return;
1408
1409         for (n = 0; n < a->count; n++)
1410                 item_free_contents(a->items + n);
1411         free(a->items);
1412         free(a);
1413 }
1414
1415 static bool item_compatible(Item *a, Item *b) {
1416         assert(a);
1417         assert(b);
1418         assert(streq(a->path, b->path));
1419
1420         if (takes_ownership(a->type) && takes_ownership(b->type))
1421                 /* check if the items are the same */
1422                 return  streq_ptr(a->argument, b->argument) &&
1423
1424                         a->uid_set == b->uid_set &&
1425                         a->uid == b->uid &&
1426
1427                         a->gid_set == b->gid_set &&
1428                         a->gid == b->gid &&
1429
1430                         a->mode_set == b->mode_set &&
1431                         a->mode == b->mode &&
1432
1433                         a->age_set == b->age_set &&
1434                         a->age == b->age &&
1435
1436                         a->mask_perms == b->mask_perms &&
1437
1438                         a->keep_first_level == b->keep_first_level &&
1439
1440                         a->major_minor == b->major_minor;
1441
1442         return true;
1443 }
1444
1445 static bool should_include_path(const char *path) {
1446         char **prefix;
1447
1448         STRV_FOREACH(prefix, arg_exclude_prefixes)
1449                 if (path_startswith(path, *prefix)) {
1450                         log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
1451                                   path, *prefix);
1452                         return false;
1453                 }
1454
1455         STRV_FOREACH(prefix, arg_include_prefixes)
1456                 if (path_startswith(path, *prefix)) {
1457                         log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
1458                         return true;
1459                 }
1460
1461         /* no matches, so we should include this path only if we
1462          * have no whitelist at all */
1463         if (strv_length(arg_include_prefixes) == 0)
1464                 return true;
1465
1466         log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
1467         return false;
1468 }
1469
1470 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1471
1472         static const Specifier specifier_table[] = {
1473                 { 'm', specifier_machine_id, NULL },
1474                 { 'b', specifier_boot_id, NULL },
1475                 { 'H', specifier_host_name, NULL },
1476                 { 'v', specifier_kernel_release, NULL },
1477                 {}
1478         };
1479
1480         _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1481         _cleanup_(item_free_contents) Item i = {};
1482         ItemArray *existing;
1483         Hashmap *h;
1484         int r, c = -1, pos;
1485         bool force = false, boot = false;
1486
1487         assert(fname);
1488         assert(line >= 1);
1489         assert(buffer);
1490
1491         r = sscanf(buffer,
1492                    "%ms %ms %ms %ms %ms %ms %n",
1493                    &action,
1494                    &path,
1495                    &mode,
1496                    &user,
1497                    &group,
1498                    &age,
1499                    &c);
1500         if (r < 2) {
1501                 log_error("[%s:%u] Syntax error.", fname, line);
1502                 return -EIO;
1503         }
1504
1505         if (isempty(action)) {
1506                 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1507                 return -EINVAL;
1508         }
1509
1510         for (pos = 1; action[pos]; pos++) {
1511                 if (action[pos] == '!' && !boot)
1512                         boot = true;
1513                 else if (action[pos] == '+' && !force)
1514                         force = true;
1515                 else {
1516                         log_error("[%s:%u] Unknown modifiers in command '%s'",
1517                                   fname, line, action);
1518                         return -EINVAL;
1519                 }
1520         }
1521
1522         if (boot && !arg_boot) {
1523                 log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
1524                           action, path);
1525                 return 0;
1526         }
1527
1528         i.type = action[0];
1529         i.force = force;
1530
1531         r = specifier_printf(path, specifier_table, NULL, &i.path);
1532         if (r < 0) {
1533                 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1534                 return r;
1535         }
1536
1537         if (c >= 0)  {
1538                 c += strspn(buffer+c, WHITESPACE);
1539                 if (buffer[c] != 0 && (buffer[c] != '-' || buffer[c+1] != 0)) {
1540                         i.argument = unquote(buffer+c, "\"");
1541                         if (!i.argument)
1542                                 return log_oom();
1543                 }
1544         }
1545
1546         switch (i.type) {
1547
1548         case CREATE_FILE:
1549         case TRUNCATE_FILE:
1550         case CREATE_DIRECTORY:
1551         case CREATE_SUBVOLUME:
1552         case TRUNCATE_DIRECTORY:
1553         case CREATE_FIFO:
1554         case IGNORE_PATH:
1555         case IGNORE_DIRECTORY_PATH:
1556         case REMOVE_PATH:
1557         case RECURSIVE_REMOVE_PATH:
1558         case ADJUST_MODE:
1559         case RELABEL_PATH:
1560         case RECURSIVE_RELABEL_PATH:
1561                 break;
1562
1563         case CREATE_SYMLINK:
1564                 if (!i.argument) {
1565                         i.argument = strappend("/usr/share/factory/", i.path);
1566                         if (!i.argument)
1567                                 return log_oom();
1568                 }
1569                 break;
1570
1571         case WRITE_FILE:
1572                 if (!i.argument) {
1573                         log_error("[%s:%u] Write file requires argument.", fname, line);
1574                         return -EBADMSG;
1575                 }
1576                 break;
1577
1578         case COPY_FILES:
1579                 if (!i.argument) {
1580                         i.argument = strappend("/usr/share/factory/", i.path);
1581                         if (!i.argument)
1582                                 return log_oom();
1583                 } else if (!path_is_absolute(i.argument)) {
1584                         log_error("[%s:%u] Source path is not absolute.", fname, line);
1585                         return -EBADMSG;
1586                 }
1587
1588                 path_kill_slashes(i.argument);
1589                 break;
1590
1591         case CREATE_CHAR_DEVICE:
1592         case CREATE_BLOCK_DEVICE: {
1593                 unsigned major, minor;
1594
1595                 if (!i.argument) {
1596                         log_error("[%s:%u] Device file requires argument.", fname, line);
1597                         return -EBADMSG;
1598                 }
1599
1600                 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1601                         log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1602                         return -EBADMSG;
1603                 }
1604
1605                 i.major_minor = makedev(major, minor);
1606                 break;
1607         }
1608
1609         case SET_XATTR:
1610         case RECURSIVE_SET_XATTR:
1611                 if (!i.argument) {
1612                         log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1613                         return -EBADMSG;
1614                 }
1615                 r = get_xattrs_from_arg(&i);
1616                 if (r < 0)
1617                         return r;
1618                 break;
1619
1620         case SET_ACL:
1621         case RECURSIVE_SET_ACL:
1622                 if (!i.argument) {
1623                         log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1624                         return -EBADMSG;
1625                 }
1626                 r = get_acls_from_arg(&i);
1627                 if (r < 0)
1628                         return r;
1629                 break;
1630
1631         default:
1632                 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
1633                 return -EBADMSG;
1634         }
1635
1636         if (!path_is_absolute(i.path)) {
1637                 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1638                 return -EBADMSG;
1639         }
1640
1641         path_kill_slashes(i.path);
1642
1643         if (!should_include_path(i.path))
1644                 return 0;
1645
1646         if (arg_root) {
1647                 char *p;
1648
1649                 p = strappend(arg_root, i.path);
1650                 if (!p)
1651                         return log_oom();
1652
1653                 free(i.path);
1654                 i.path = p;
1655         }
1656
1657         if (user && !streq(user, "-")) {
1658                 const char *u = user;
1659
1660                 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1661                 if (r < 0) {
1662                         log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1663                         return r;
1664                 }
1665
1666                 i.uid_set = true;
1667         }
1668
1669         if (group && !streq(group, "-")) {
1670                 const char *g = group;
1671
1672                 r = get_group_creds(&g, &i.gid);
1673                 if (r < 0) {
1674                         log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1675                         return r;
1676                 }
1677
1678                 i.gid_set = true;
1679         }
1680
1681         if (mode && !streq(mode, "-")) {
1682                 const char *mm = mode;
1683                 unsigned m;
1684
1685                 if (*mm == '~') {
1686                         i.mask_perms = true;
1687                         mm++;
1688                 }
1689
1690                 if (sscanf(mm, "%o", &m) != 1) {
1691                         log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1692                         return -ENOENT;
1693                 }
1694
1695                 i.mode = m;
1696                 i.mode_set = true;
1697         } else
1698                 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1699                         ? 0755 : 0644;
1700
1701         if (age && !streq(age, "-")) {
1702                 const char *a = age;
1703
1704                 if (*a == '~') {
1705                         i.keep_first_level = true;
1706                         a++;
1707                 }
1708
1709                 if (parse_sec(a, &i.age) < 0) {
1710                         log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1711                         return -EBADMSG;
1712                 }
1713
1714                 i.age_set = true;
1715         }
1716
1717         h = needs_glob(i.type) ? globs : items;
1718
1719         existing = hashmap_get(h, i.path);
1720         if (existing) {
1721                 unsigned n;
1722
1723                 for (n = 0; n < existing->count; n++) {
1724                         if (!item_compatible(existing->items + n, &i))
1725                                 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1726                                             fname, line, i.path);
1727                 }
1728         } else {
1729                 existing = new0(ItemArray, 1);
1730                 r = hashmap_put(h, i.path, existing);
1731                 if (r < 0)
1732                         return log_oom();
1733         }
1734
1735         if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1736                 return log_oom();
1737
1738         memcpy(existing->items + existing->count++, &i, sizeof(i));
1739         zero(i);
1740         return 0;
1741 }
1742
1743 static void help(void) {
1744         printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1745                "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1746                "  -h --help                 Show this help\n"
1747                "     --version              Show package version\n"
1748                "     --create               Create marked files/directories\n"
1749                "     --clean                Clean up marked directories\n"
1750                "     --remove               Remove marked files/directories\n"
1751                "     --boot                 Execute actions only safe at boot\n"
1752                "     --prefix=PATH          Only apply rules that apply to paths with the specified prefix\n"
1753                "     --exclude-prefix=PATH  Ignore rules that apply to paths with the specified prefix\n"
1754                "     --root=PATH            Operate on an alternate filesystem root\n",
1755                program_invocation_short_name);
1756 }
1757
1758 static int parse_argv(int argc, char *argv[]) {
1759
1760         enum {
1761                 ARG_VERSION = 0x100,
1762                 ARG_CREATE,
1763                 ARG_CLEAN,
1764                 ARG_REMOVE,
1765                 ARG_BOOT,
1766                 ARG_PREFIX,
1767                 ARG_EXCLUDE_PREFIX,
1768                 ARG_ROOT,
1769         };
1770
1771         static const struct option options[] = {
1772                 { "help",           no_argument,         NULL, 'h'                },
1773                 { "version",        no_argument,         NULL, ARG_VERSION        },
1774                 { "create",         no_argument,         NULL, ARG_CREATE         },
1775                 { "clean",          no_argument,         NULL, ARG_CLEAN          },
1776                 { "remove",         no_argument,         NULL, ARG_REMOVE         },
1777                 { "boot",           no_argument,         NULL, ARG_BOOT           },
1778                 { "prefix",         required_argument,   NULL, ARG_PREFIX         },
1779                 { "exclude-prefix", required_argument,   NULL, ARG_EXCLUDE_PREFIX },
1780                 { "root",           required_argument,   NULL, ARG_ROOT           },
1781                 {}
1782         };
1783
1784         int c;
1785
1786         assert(argc >= 0);
1787         assert(argv);
1788
1789         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1790
1791                 switch (c) {
1792
1793                 case 'h':
1794                         help();
1795                         return 0;
1796
1797                 case ARG_VERSION:
1798                         puts(PACKAGE_STRING);
1799                         puts(SYSTEMD_FEATURES);
1800                         return 0;
1801
1802                 case ARG_CREATE:
1803                         arg_create = true;
1804                         break;
1805
1806                 case ARG_CLEAN:
1807                         arg_clean = true;
1808                         break;
1809
1810                 case ARG_REMOVE:
1811                         arg_remove = true;
1812                         break;
1813
1814                 case ARG_BOOT:
1815                         arg_boot = true;
1816                         break;
1817
1818                 case ARG_PREFIX:
1819                         if (strv_push(&arg_include_prefixes, optarg) < 0)
1820                                 return log_oom();
1821                         break;
1822
1823                 case ARG_EXCLUDE_PREFIX:
1824                         if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1825                                 return log_oom();
1826                         break;
1827
1828                 case ARG_ROOT:
1829                         free(arg_root);
1830                         arg_root = path_make_absolute_cwd(optarg);
1831                         if (!arg_root)
1832                                 return log_oom();
1833
1834                         path_kill_slashes(arg_root);
1835                         break;
1836
1837                 case '?':
1838                         return -EINVAL;
1839
1840                 default:
1841                         assert_not_reached("Unhandled option");
1842                 }
1843
1844         if (!arg_clean && !arg_create && !arg_remove) {
1845                 log_error("You need to specify at least one of --clean, --create or --remove.");
1846                 return -EINVAL;
1847         }
1848
1849         return 1;
1850 }
1851
1852 static int read_config_file(const char *fn, bool ignore_enoent) {
1853         _cleanup_fclose_ FILE *f = NULL;
1854         char line[LINE_MAX];
1855         Iterator iterator;
1856         unsigned v = 0;
1857         Item *i;
1858         int r;
1859
1860         assert(fn);
1861
1862         r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
1863         if (r < 0) {
1864                 if (ignore_enoent && r == -ENOENT) {
1865                         log_debug_errno(r, "Failed to open \"%s\": %m", fn);
1866                         return 0;
1867                 }
1868
1869                 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
1870         }
1871         log_debug("Reading config file \"%s\".", fn);
1872
1873         FOREACH_LINE(line, f, break) {
1874                 char *l;
1875                 int k;
1876
1877                 v++;
1878
1879                 l = strstrip(line);
1880                 if (*l == '#' || *l == 0)
1881                         continue;
1882
1883                 k = parse_line(fn, v, l);
1884                 if (k < 0 && r == 0)
1885                         r = k;
1886         }
1887
1888         /* we have to determine age parameter for each entry of type X */
1889         HASHMAP_FOREACH(i, globs, iterator) {
1890                 Iterator iter;
1891                 Item *j, *candidate_item = NULL;
1892
1893                 if (i->type != IGNORE_DIRECTORY_PATH)
1894                         continue;
1895
1896                 HASHMAP_FOREACH(j, items, iter) {
1897                         if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
1898                                 continue;
1899
1900                         if (path_equal(j->path, i->path)) {
1901                                 candidate_item = j;
1902                                 break;
1903                         }
1904
1905                         if ((!candidate_item && path_startswith(i->path, j->path)) ||
1906                             (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1907                                 candidate_item = j;
1908                 }
1909
1910                 if (candidate_item && candidate_item->age_set) {
1911                         i->age = candidate_item->age;
1912                         i->age_set = true;
1913                 }
1914         }
1915
1916         if (ferror(f)) {
1917                 log_error_errno(errno, "Failed to read from file %s: %m", fn);
1918                 if (r == 0)
1919                         r = -EIO;
1920         }
1921
1922         return r;
1923 }
1924
1925 int main(int argc, char *argv[]) {
1926         int r, k;
1927         ItemArray *a;
1928         Iterator iterator;
1929
1930         r = parse_argv(argc, argv);
1931         if (r <= 0)
1932                 goto finish;
1933
1934         log_set_target(LOG_TARGET_AUTO);
1935         log_parse_environment();
1936         log_open();
1937
1938         umask(0022);
1939
1940         mac_selinux_init(NULL);
1941
1942         items = hashmap_new(&string_hash_ops);
1943         globs = hashmap_new(&string_hash_ops);
1944
1945         if (!items || !globs) {
1946                 r = log_oom();
1947                 goto finish;
1948         }
1949
1950         r = 0;
1951
1952         if (optind < argc) {
1953                 int j;
1954
1955                 for (j = optind; j < argc; j++) {
1956                         k = read_config_file(argv[j], false);
1957                         if (k < 0 && r == 0)
1958                                 r = k;
1959                 }
1960
1961         } else {
1962                 _cleanup_strv_free_ char **files = NULL;
1963                 char **f;
1964
1965                 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
1966                 if (r < 0) {
1967                         log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
1968                         goto finish;
1969                 }
1970
1971                 STRV_FOREACH(f, files) {
1972                         k = read_config_file(*f, true);
1973                         if (k < 0 && r == 0)
1974                                 r = k;
1975                 }
1976         }
1977
1978         HASHMAP_FOREACH(a, globs, iterator) {
1979                 k = process_item_array(a);
1980                 if (k < 0 && r == 0)
1981                         r = k;
1982         }
1983
1984         HASHMAP_FOREACH(a, items, iterator) {
1985                 k = process_item_array(a);
1986                 if (k < 0 && r == 0)
1987                         r = k;
1988         }
1989
1990 finish:
1991         while ((a = hashmap_steal_first(items)))
1992                 item_array_free(a);
1993
1994         while ((a = hashmap_steal_first(globs)))
1995                 item_array_free(a);
1996
1997         hashmap_free(items);
1998         hashmap_free(globs);
1999
2000         free(arg_include_prefixes);
2001         free(arg_exclude_prefixes);
2002         free(arg_root);
2003
2004         set_free_free(unix_sockets);
2005
2006         mac_selinux_finish();
2007
2008         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
2009 }