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