chiark / gitweb /
c4c6d8e6938af3318d494e6b143d9715cd404be5
[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         char *xattr;
624         const char *p;
625         int r;
626
627         assert(i);
628         assert(i->argument);
629
630         p = i->argument;
631
632         while ((r = unquote_first_word(&p, &xattr, false)) > 0) {
633                 _cleanup_free_ char *tmp = NULL, *name = NULL,
634                         *value = NULL, *value2 = NULL, *_xattr = xattr;
635
636                 r = split_pair(xattr, "=", &name, &value);
637                 if (r < 0) {
638                         log_warning("Illegal xattr found: \"%s\" - ignoring.", xattr);
639                         continue;
640                 }
641
642                 if (strempty(name) || strempty(value)) {
643                         log_warning("Malformed xattr found: \"%s\" - ignoring.", xattr);
644                         continue;
645                 }
646
647                 tmp = unquote(value, "\"");
648                 if (!tmp)
649                         return log_oom();
650
651                 value2 = cunescape(tmp);
652                 if (!value2)
653                         return log_oom();
654
655                 if (strv_push_pair(&i->xattrs, name, value2) < 0)
656                         return log_oom();
657                 name = value2 = NULL;
658         }
659
660         return r;
661 }
662
663 static int path_set_xattrs(Item *i, const char *path) {
664         char **name, **value;
665
666         assert(i);
667         assert(path);
668
669         STRV_FOREACH_PAIR(name, value, i->xattrs) {
670                 int n;
671
672                 n = strlen(*value);
673                 log_debug("\"%s\": setting xattr \"%s=%s\"", path, *name, *value);
674                 if (lsetxattr(path, *name, *value, n, 0) < 0) {
675                         log_error("Setting extended attribute %s=%s on %s failed: %m",
676                                   *name, *value, path);
677                         return -errno;
678                 }
679         }
680         return 0;
681 }
682
683 static int get_acls_from_arg(Item *item) {
684 #ifdef HAVE_ACL
685         int r;
686
687         assert(item);
688
689         /* If force (= modify) is set, we will not modify the acl
690          * afterwards, so the mask can be added now if necessary. */
691         r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
692         if (r < 0)
693                 log_warning_errno(r, "Failed to parse ACL \"%s\": %m. Ignoring",
694                                   item->argument);
695 #else
696         log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
697 #endif
698
699         return 0;
700 }
701
702 #ifdef HAVE_ACL
703 static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
704         _cleanup_(acl_freep) acl_t dup = NULL;
705         int r;
706         _cleanup_(acl_free_charpp) char *t = NULL;
707
708         /* Returns 0 for success, positive error if already warned,
709          * negative error otherwise. */
710
711         if (modify) {
712                 r = acls_for_file(path, type, acl, &dup);
713                 if (r < 0)
714                         return r;
715
716                 r = calc_acl_mask_if_needed(&dup);
717                 if (r < 0)
718                         return r;
719         } else {
720                 dup = acl_dup(acl);
721                 if (!dup)
722                         return -errno;
723
724                 /* the mask was already added earlier if needed */
725         }
726
727         r = add_base_acls_if_needed(&dup, path);
728         if (r < 0)
729                 return r;
730
731         t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
732         log_debug("\"%s\": setting %s ACL \"%s\"", path,
733                   type == ACL_TYPE_ACCESS ? "access" : "default",
734                   strna(t));
735
736         r = acl_set_file(path, type, dup);
737         if (r < 0)
738                 return -log_error_errno(errno,
739                                         "Setting %s ACL \"%s\" on %s failed: %m",
740                                         type == ACL_TYPE_ACCESS ? "access" : "default",
741                                         strna(t), path);
742
743         return 0;
744 }
745 #endif
746
747 static int path_set_acls(Item *item, const char *path) {
748         int r = 0;
749 #ifdef HAVE_ACL
750         assert(item);
751         assert(path);
752
753         if (item->acl_access)
754                 r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
755
756         if (r == 0 && item->acl_default)
757                 r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
758
759         if (r > 0)
760                 return -r; /* already warned */
761         else if (r == -EOPNOTSUPP) {
762                 log_debug_errno(r, "ACLs not supported by file system at %s", path);
763                 return 0;
764         } else if (r < 0)
765                 log_error_errno(r, "ACL operation on \"%s\" failed: %m", path);
766 #endif
767         return r;
768 }
769
770 #define ALL_ATTRIBS          \
771         FS_NOATIME_FL      | \
772         FS_SYNC_FL         | \
773         FS_DIRSYNC_FL      | \
774         FS_APPEND_FL       | \
775         FS_COMPR_FL        | \
776         FS_NODUMP_FL       | \
777         FS_EXTENT_FL       | \
778         FS_IMMUTABLE_FL    | \
779         FS_JOURNAL_DATA_FL | \
780         FS_SECRM_FL        | \
781         FS_UNRM_FL         | \
782         FS_NOTAIL_FL       | \
783         FS_TOPDIR_FL       | \
784         FS_NOCOW_FL
785
786 static int get_attrib_from_arg(Item *item) {
787         static const unsigned attributes[] = {
788                 [(uint8_t)'A'] = FS_NOATIME_FL,      /* do not update atime */
789                 [(uint8_t)'S'] = FS_SYNC_FL,         /* Synchronous updates */
790                 [(uint8_t)'D'] = FS_DIRSYNC_FL,      /* dirsync behaviour (directories only) */
791                 [(uint8_t)'a'] = FS_APPEND_FL,       /* writes to file may only append */
792                 [(uint8_t)'c'] = FS_COMPR_FL,        /* Compress file */
793                 [(uint8_t)'d'] = FS_NODUMP_FL,       /* do not dump file */
794                 [(uint8_t)'e'] = FS_EXTENT_FL,       /* Top of directory hierarchies*/
795                 [(uint8_t)'i'] = FS_IMMUTABLE_FL,    /* Immutable file */
796                 [(uint8_t)'j'] = FS_JOURNAL_DATA_FL, /* Reserved for ext3 */
797                 [(uint8_t)'s'] = FS_SECRM_FL,        /* Secure deletion */
798                 [(uint8_t)'u'] = FS_UNRM_FL,         /* Undelete */
799                 [(uint8_t)'t'] = FS_NOTAIL_FL,       /* file tail should not be merged */
800                 [(uint8_t)'T'] = FS_TOPDIR_FL,       /* Top of directory hierarchies*/
801                 [(uint8_t)'C'] = FS_NOCOW_FL,        /* Do not cow file */
802         };
803         char *p = item->argument;
804         enum {
805                 MODE_ADD,
806                 MODE_DEL,
807                 MODE_SET
808         } mode = MODE_ADD;
809         unsigned long value = 0, mask = 0;
810
811         if (!p) {
812                 log_error("\"%s\": setting ATTR need an argument", item->path);
813                 return -EINVAL;
814         }
815
816         if (*p == '+') {
817                 mode = MODE_ADD;
818                 p++;
819         } else if (*p == '-') {
820                 mode = MODE_DEL;
821                 p++;
822         } else  if (*p == '=') {
823                 mode = MODE_SET;
824                 p++;
825         }
826
827         if (!*p && mode != MODE_SET) {
828                 log_error("\"%s\": setting ATTR: argument is empty", item->path);
829                 return -EINVAL;
830         }
831         for (; *p ; p++) {
832                 if ((uint8_t)*p >= ELEMENTSOF(attributes) || attributes[(uint8_t)*p] == 0) {
833                         log_error("\"%s\": setting ATTR: unknown attr '%c'", item->path, *p);
834                         return -EINVAL;
835                 }
836                 if (mode == MODE_ADD || mode == MODE_SET)
837                         value |= attributes[(uint8_t)*p];
838                 else
839                         value &= ~attributes[(uint8_t)*p];
840                 mask |= attributes[(uint8_t)*p];
841         }
842
843         if (mode == MODE_SET)
844                 mask |= ALL_ATTRIBS;
845
846         assert(mask);
847
848         item->attrib_mask = mask;
849         item->attrib_value = value;
850         item->attrib_set = true;
851
852         return 0;
853
854 }
855
856 static int path_set_attrib(Item *item, const char *path) {
857         _cleanup_close_ int fd = -1;
858         int r;
859         unsigned f;
860         struct stat st;
861
862         /* do nothing */
863         if (item->attrib_mask == 0 || !item->attrib_set)
864                 return 0;
865         /*
866          * It is OK to ignore an lstat() error, because the error
867          * will be catch by the open() below anyway
868          */
869         if (lstat(path, &st) == 0 &&
870             !S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
871                 return 0;
872         }
873
874         fd = open(path, O_RDONLY|O_NONBLOCK|O_CLOEXEC);
875
876         if (fd < 0)
877                 return log_error_errno(errno, "Cannot open \"%s\": %m", path);
878
879         f = item->attrib_value & item->attrib_mask;
880         if (!S_ISDIR(st.st_mode))
881                 f &= ~FS_DIRSYNC_FL;
882         r = change_attr_fd(fd, f, item->attrib_mask);
883         if (r < 0)
884                 return log_error_errno(errno,
885                         "Cannot set attrib for \"%s\", value=0x%08lx, mask=0x%08lx: %m",
886                         path, item->attrib_value, item->attrib_mask);
887
888         return 0;
889 }
890
891 static int write_one_file(Item *i, const char *path) {
892         _cleanup_close_ int fd = -1;
893         int flags, r = 0;
894         struct stat st;
895
896         assert(i);
897         assert(path);
898
899         flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
900                 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
901
902         RUN_WITH_UMASK(0000) {
903                 mac_selinux_create_file_prepare(path, S_IFREG);
904                 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
905                 mac_selinux_create_file_clear();
906         }
907
908         if (fd < 0) {
909                 if (i->type == WRITE_FILE && errno == ENOENT) {
910                         log_debug_errno(errno, "Not writing \"%s\": %m", path);
911                         return 0;
912                 }
913
914                 log_error_errno(errno, "Failed to create file %s: %m", path);
915                 return -errno;
916         }
917
918         if (i->argument) {
919                 _cleanup_free_ char *unescaped;
920
921                 log_debug("%s to \"%s\".",
922                           i->type == CREATE_FILE ? "Appending" : "Writing", path);
923
924                 unescaped = cunescape(i->argument);
925                 if (!unescaped)
926                         return log_oom();
927
928                 r = loop_write(fd, unescaped, strlen(unescaped), false);
929                 if (r < 0)
930                         return log_error_errno(r, "Failed to write file \"%s\": %m", path);
931         } else
932                 log_debug("\"%s\" has been created.", path);
933
934         fd = safe_close(fd);
935
936         if (stat(path, &st) < 0)
937                 return log_error_errno(errno, "stat(%s) failed: %m", path);
938
939         if (!S_ISREG(st.st_mode)) {
940                 log_error("%s is not a file.", path);
941                 return -EEXIST;
942         }
943
944         r = path_set_perms(i, path);
945         if (r < 0)
946                 return r;
947
948         return 0;
949 }
950
951 typedef int (*action_t)(Item *, const char *);
952
953 static int item_do_children(Item *i, const char *path, action_t action) {
954         _cleanup_closedir_ DIR *d;
955         int r = 0;
956
957         assert(i);
958         assert(path);
959
960         /* This returns the first error we run into, but nevertheless
961          * tries to go on */
962
963         d = opendir_nomod(path);
964         if (!d)
965                 return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
966
967         for (;;) {
968                 _cleanup_free_ char *p = NULL;
969                 struct dirent *de;
970                 int q;
971
972                 errno = 0;
973                 de = readdir(d);
974                 if (!de) {
975                         if (errno != 0 && r == 0)
976                                 r = -errno;
977
978                         break;
979                 }
980
981                 if (STR_IN_SET(de->d_name, ".", ".."))
982                         continue;
983
984                 p = strjoin(path, "/", de->d_name, NULL);
985                 if (!p)
986                         return -ENOMEM;
987
988                 q = action(i, p);
989                 if (q < 0 && q != -ENOENT && r == 0)
990                         r = q;
991
992                 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
993                         q = item_do_children(i, p, action);
994                         if (q < 0 && r == 0)
995                                 r = q;
996                 }
997         }
998
999         return r;
1000 }
1001
1002 static int glob_item(Item *i, action_t action, bool recursive) {
1003         _cleanup_globfree_ glob_t g = {
1004                 .gl_closedir = (void (*)(void *)) closedir,
1005                 .gl_readdir = (struct dirent *(*)(void *)) readdir,
1006                 .gl_opendir = (void *(*)(const char *)) opendir_nomod,
1007                 .gl_lstat = lstat,
1008                 .gl_stat = stat,
1009         };
1010         int r = 0, k;
1011         char **fn;
1012
1013         errno = 0;
1014         k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
1015         if (k != 0 && k != GLOB_NOMATCH)
1016                 return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
1017
1018         STRV_FOREACH(fn, g.gl_pathv) {
1019                 k = action(i, *fn);
1020                 if (k < 0 && r == 0)
1021                         r = k;
1022
1023                 if (recursive) {
1024                         k = item_do_children(i, *fn, action);
1025                         if (k < 0 && r == 0)
1026                                 r = k;
1027                 }
1028         }
1029
1030         return r;
1031 }
1032
1033 typedef enum {
1034         CREATION_NORMAL,
1035         CREATION_EXISTING,
1036         CREATION_FORCE,
1037         _CREATION_MODE_MAX,
1038         _CREATION_MODE_INVALID = -1
1039 } CreationMode;
1040
1041 static const char *creation_mode_verb_table[_CREATION_MODE_MAX] = {
1042         [CREATION_NORMAL] = "Created",
1043         [CREATION_EXISTING] = "Found existing",
1044         [CREATION_FORCE] = "Created replacement",
1045 };
1046
1047 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(creation_mode_verb, CreationMode);
1048
1049 static int create_item(Item *i) {
1050         struct stat st;
1051         int r = 0;
1052         CreationMode creation;
1053
1054         assert(i);
1055
1056         log_debug("Running create action for entry %c %s", (char) i->type, i->path);
1057
1058         switch (i->type) {
1059
1060         case IGNORE_PATH:
1061         case IGNORE_DIRECTORY_PATH:
1062         case REMOVE_PATH:
1063         case RECURSIVE_REMOVE_PATH:
1064                 return 0;
1065
1066         case CREATE_FILE:
1067         case TRUNCATE_FILE:
1068                 r = write_one_file(i, i->path);
1069                 if (r < 0)
1070                         return r;
1071                 break;
1072
1073         case COPY_FILES:
1074                 log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
1075                 r = copy_tree(i->argument, i->path, false);
1076                 if (r < 0) {
1077                         struct stat a, b;
1078
1079                         if (r != -EEXIST)
1080                                 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
1081
1082                         if (stat(i->argument, &a) < 0)
1083                                 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
1084
1085                         if (stat(i->path, &b) < 0)
1086                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1087
1088                         if ((a.st_mode ^ b.st_mode) & S_IFMT) {
1089                                 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
1090                                 return 0;
1091                         }
1092                 }
1093
1094                 r = path_set_perms(i, i->path);
1095                 if (r < 0)
1096                         return r;
1097
1098                 break;
1099
1100         case WRITE_FILE:
1101                 r = glob_item(i, write_one_file, false);
1102                 if (r < 0)
1103                         return r;
1104
1105                 break;
1106
1107         case CREATE_DIRECTORY:
1108         case TRUNCATE_DIRECTORY:
1109         case CREATE_SUBVOLUME:
1110
1111                 RUN_WITH_UMASK(0000)
1112                         mkdir_parents_label(i->path, 0755);
1113
1114                 if (i->type == CREATE_SUBVOLUME)
1115                         RUN_WITH_UMASK((~i->mode) & 0777) {
1116                                 r = btrfs_subvol_make(i->path);
1117                                 log_debug_errno(r, "Creating subvolume \"%s\": %m", i->path);
1118                         }
1119                 else
1120                         r = 0;
1121
1122                 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
1123                         RUN_WITH_UMASK(0000)
1124                                 r = mkdir_label(i->path, i->mode);
1125
1126                 if (r < 0) {
1127                         if (r != -EEXIST)
1128                                 return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);
1129
1130                         if (stat(i->path, &st) < 0)
1131                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1132
1133                         if (!S_ISDIR(st.st_mode)) {
1134                                 log_debug("\"%s\" already exists and is not a directory.", i->path);
1135                                 return 0;
1136                         }
1137
1138                         creation = CREATION_EXISTING;
1139                 } else
1140                         creation = CREATION_NORMAL;
1141                 log_debug("%s directory \"%s\".", creation_mode_verb_to_string(creation), i->path);
1142
1143                 r = path_set_perms(i, i->path);
1144                 if (r < 0)
1145                         return r;
1146
1147                 break;
1148
1149         case CREATE_FIFO:
1150
1151                 RUN_WITH_UMASK(0000) {
1152                         mac_selinux_create_file_prepare(i->path, S_IFIFO);
1153                         r = mkfifo(i->path, i->mode);
1154                         mac_selinux_create_file_clear();
1155                 }
1156
1157                 if (r < 0) {
1158                         if (errno != EEXIST)
1159                                 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
1160
1161                         if (stat(i->path, &st) < 0)
1162                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1163
1164                         if (!S_ISFIFO(st.st_mode)) {
1165
1166                                 if (i->force) {
1167
1168                                         RUN_WITH_UMASK(0000) {
1169                                                 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1170                                                 r = mkfifo_atomic(i->path, i->mode);
1171                                                 mac_selinux_create_file_clear();
1172                                         }
1173
1174                                         if (r < 0)
1175                                                 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
1176                                         creation = CREATION_FORCE;
1177                                 } else {
1178                                         log_debug("%s is not a fifo.", i->path);
1179                                         return 0;
1180                                 }
1181                         } else
1182                                 creation = CREATION_EXISTING;
1183                 } else
1184                         creation = CREATION_NORMAL;
1185                 log_debug("%s fifo \"%s\".", creation_mode_verb_to_string(creation), i->path);
1186
1187                 r = path_set_perms(i, i->path);
1188                 if (r < 0)
1189                         return r;
1190
1191                 break;
1192
1193         case CREATE_SYMLINK:
1194
1195                 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1196                 r = symlink(i->argument, i->path);
1197                 mac_selinux_create_file_clear();
1198
1199                 if (r < 0) {
1200                         _cleanup_free_ char *x = NULL;
1201
1202                         if (errno != EEXIST)
1203                                 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
1204
1205                         r = readlink_malloc(i->path, &x);
1206                         if (r < 0 || !streq(i->argument, x)) {
1207
1208                                 if (i->force) {
1209                                         mac_selinux_create_file_prepare(i->path, S_IFLNK);
1210                                         r = symlink_atomic(i->argument, i->path);
1211                                         mac_selinux_create_file_clear();
1212
1213                                         if (r < 0)
1214                                                 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
1215                                         creation = CREATION_FORCE;
1216                                 } else {
1217                                         log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
1218                                         return 0;
1219                                 }
1220                         } else
1221                                 creation = CREATION_EXISTING;
1222                 } else
1223                         creation = CREATION_NORMAL;
1224                 log_debug("%s symlink \"%s\".", creation_mode_verb_to_string(creation), i->path);
1225
1226                 break;
1227
1228         case CREATE_BLOCK_DEVICE:
1229         case CREATE_CHAR_DEVICE: {
1230                 mode_t file_type;
1231
1232                 if (have_effective_cap(CAP_MKNOD) == 0) {
1233                         /* In a container we lack CAP_MKNOD. We
1234                         shouldn't attempt to create the device node in
1235                         that case to avoid noise, and we don't support
1236                         virtualized devices in containers anyway. */
1237
1238                         log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
1239                         return 0;
1240                 }
1241
1242                 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
1243
1244                 RUN_WITH_UMASK(0000) {
1245                         mac_selinux_create_file_prepare(i->path, file_type);
1246                         r = mknod(i->path, i->mode | file_type, i->major_minor);
1247                         mac_selinux_create_file_clear();
1248                 }
1249
1250                 if (r < 0) {
1251                         if (errno == EPERM) {
1252                                 log_debug("We lack permissions, possibly because of cgroup configuration; "
1253                                           "skipping creation of device node %s.", i->path);
1254                                 return 0;
1255                         }
1256
1257                         if (errno != EEXIST)
1258                                 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1259
1260                         if (stat(i->path, &st) < 0)
1261                                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1262
1263                         if ((st.st_mode & S_IFMT) != file_type) {
1264
1265                                 if (i->force) {
1266
1267                                         RUN_WITH_UMASK(0000) {
1268                                                 mac_selinux_create_file_prepare(i->path, file_type);
1269                                                 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1270                                                 mac_selinux_create_file_clear();
1271                                         }
1272
1273                                         if (r < 0)
1274                                                 return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path);
1275                                         creation = CREATION_FORCE;
1276                                 } else {
1277                                         log_debug("%s is not a device node.", i->path);
1278                                         return 0;
1279                                 }
1280                         } else
1281                                 creation = CREATION_EXISTING;
1282                 } else
1283                         creation = CREATION_NORMAL;
1284                 log_debug("%s %s device node \"%s\" %u:%u.",
1285                           creation_mode_verb_to_string(creation),
1286                           i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
1287                           i->path, major(i->mode), minor(i->mode));
1288
1289                 r = path_set_perms(i, i->path);
1290                 if (r < 0)
1291                         return r;
1292
1293                 break;
1294         }
1295
1296         case ADJUST_MODE:
1297         case RELABEL_PATH:
1298                 r = glob_item(i, path_set_perms, false);
1299                 if (r < 0)
1300                         return r;
1301                 break;
1302
1303         case RECURSIVE_RELABEL_PATH:
1304                 r = glob_item(i, path_set_perms, true);
1305                 if (r < 0)
1306                         return r;
1307                 break;
1308
1309         case SET_XATTR:
1310                 r = glob_item(i, path_set_xattrs, false);
1311                 if (r < 0)
1312                         return r;
1313                 break;
1314
1315         case RECURSIVE_SET_XATTR:
1316                 r = glob_item(i, path_set_xattrs, true);
1317                 if (r < 0)
1318                         return r;
1319                 break;
1320
1321         case SET_ACL:
1322                 r = glob_item(i, path_set_acls, false);
1323                 if (r < 0)
1324                         return r;
1325                 break;
1326
1327         case RECURSIVE_SET_ACL:
1328                 r = glob_item(i, path_set_acls, true);
1329                 if (r < 0)
1330                         return r;
1331                 break;
1332
1333         case SET_ATTRIB:
1334                 r = glob_item(i, path_set_attrib, false);
1335                 if (r < 0)
1336                         return r;
1337                 break;
1338
1339         case RECURSIVE_SET_ATTRIB:
1340                 r = glob_item(i, path_set_attrib, true);
1341                 if (r < 0)
1342                         return r;
1343                 break;
1344         }
1345
1346         return 0;
1347 }
1348
1349 static int remove_item_instance(Item *i, const char *instance) {
1350         int r;
1351
1352         assert(i);
1353
1354         switch (i->type) {
1355
1356         case REMOVE_PATH:
1357                 if (remove(instance) < 0 && errno != ENOENT)
1358                         return log_error_errno(errno, "rm(%s): %m", instance);
1359
1360                 break;
1361
1362         case TRUNCATE_DIRECTORY:
1363         case RECURSIVE_REMOVE_PATH:
1364                 /* FIXME: we probably should use dir_cleanup() here
1365                  * instead of rm_rf() so that 'x' is honoured. */
1366                 log_debug("rm -rf \"%s\"", instance);
1367                 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1368                 if (r < 0 && r != -ENOENT)
1369                         return log_error_errno(r, "rm_rf(%s): %m", instance);
1370
1371                 break;
1372
1373         default:
1374                 assert_not_reached("wut?");
1375         }
1376
1377         return 0;
1378 }
1379
1380 static int remove_item(Item *i) {
1381         int r = 0;
1382
1383         assert(i);
1384
1385         log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
1386
1387         switch (i->type) {
1388
1389         case CREATE_FILE:
1390         case TRUNCATE_FILE:
1391         case CREATE_DIRECTORY:
1392         case CREATE_SUBVOLUME:
1393         case CREATE_FIFO:
1394         case CREATE_SYMLINK:
1395         case CREATE_CHAR_DEVICE:
1396         case CREATE_BLOCK_DEVICE:
1397         case IGNORE_PATH:
1398         case IGNORE_DIRECTORY_PATH:
1399         case ADJUST_MODE:
1400         case RELABEL_PATH:
1401         case RECURSIVE_RELABEL_PATH:
1402         case WRITE_FILE:
1403         case COPY_FILES:
1404         case SET_XATTR:
1405         case RECURSIVE_SET_XATTR:
1406         case SET_ACL:
1407         case RECURSIVE_SET_ACL:
1408         case SET_ATTRIB:
1409         case RECURSIVE_SET_ATTRIB:
1410                 break;
1411
1412         case REMOVE_PATH:
1413         case TRUNCATE_DIRECTORY:
1414         case RECURSIVE_REMOVE_PATH:
1415                 r = glob_item(i, remove_item_instance, false);
1416                 break;
1417         }
1418
1419         return r;
1420 }
1421
1422 static int clean_item_instance(Item *i, const char* instance) {
1423         _cleanup_closedir_ DIR *d = NULL;
1424         struct stat s, ps;
1425         bool mountpoint;
1426         usec_t cutoff, n;
1427         char timestamp[FORMAT_TIMESTAMP_MAX];
1428
1429         assert(i);
1430
1431         if (!i->age_set)
1432                 return 0;
1433
1434         n = now(CLOCK_REALTIME);
1435         if (n < i->age)
1436                 return 0;
1437
1438         cutoff = n - i->age;
1439
1440         d = opendir_nomod(instance);
1441         if (!d) {
1442                 if (errno == ENOENT || errno == ENOTDIR) {
1443                         log_debug_errno(errno, "Directory \"%s\": %m", instance);
1444                         return 0;
1445                 }
1446
1447                 log_error_errno(errno, "Failed to open directory %s: %m", instance);
1448                 return -errno;
1449         }
1450
1451         if (fstat(dirfd(d), &s) < 0)
1452                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1453
1454         if (!S_ISDIR(s.st_mode)) {
1455                 log_error("%s is not a directory.", i->path);
1456                 return -ENOTDIR;
1457         }
1458
1459         if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1460                 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1461
1462         mountpoint = s.st_dev != ps.st_dev ||
1463                      (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1464
1465         log_debug("Cleanup threshold for %s \"%s\" is %s",
1466                   mountpoint ? "mount point" : "directory",
1467                   instance,
1468                   format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
1469
1470         return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1471                            MAX_DEPTH, i->keep_first_level);
1472 }
1473
1474 static int clean_item(Item *i) {
1475         int r = 0;
1476
1477         assert(i);
1478
1479         log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
1480
1481         switch (i->type) {
1482         case CREATE_DIRECTORY:
1483         case CREATE_SUBVOLUME:
1484         case TRUNCATE_DIRECTORY:
1485         case IGNORE_PATH:
1486         case COPY_FILES:
1487                 clean_item_instance(i, i->path);
1488                 break;
1489         case IGNORE_DIRECTORY_PATH:
1490                 r = glob_item(i, clean_item_instance, false);
1491                 break;
1492         default:
1493                 break;
1494         }
1495
1496         return r;
1497 }
1498
1499 static int process_item_array(ItemArray *array);
1500
1501 static int process_item(Item *i) {
1502         int r, q, p, t = 0;
1503         _cleanup_free_ char *prefix = NULL;
1504
1505         assert(i);
1506
1507         if (i->done)
1508                 return 0;
1509
1510         i->done = true;
1511
1512         prefix = malloc(strlen(i->path) + 1);
1513         if (!prefix)
1514                 return log_oom();
1515
1516         PATH_FOREACH_PREFIX(prefix, i->path) {
1517                 ItemArray *j;
1518
1519                 j = hashmap_get(items, prefix);
1520                 if (j) {
1521                         int s;
1522
1523                         s = process_item_array(j);
1524                         if (s < 0 && t == 0)
1525                                 t = s;
1526                 }
1527         }
1528
1529         r = arg_create ? create_item(i) : 0;
1530         q = arg_remove ? remove_item(i) : 0;
1531         p = arg_clean ? clean_item(i) : 0;
1532
1533         return t < 0 ? t :
1534                 r < 0 ? r :
1535                 q < 0 ? q :
1536                 p;
1537 }
1538
1539 static int process_item_array(ItemArray *array) {
1540         unsigned n;
1541         int r = 0, k;
1542
1543         assert(array);
1544
1545         for (n = 0; n < array->count; n++) {
1546                 k = process_item(array->items + n);
1547                 if (k < 0 && r == 0)
1548                         r = k;
1549         }
1550
1551         return r;
1552 }
1553
1554 static void item_free_contents(Item *i) {
1555         assert(i);
1556         free(i->path);
1557         free(i->argument);
1558         strv_free(i->xattrs);
1559
1560 #ifdef HAVE_ACL
1561         acl_free(i->acl_access);
1562         acl_free(i->acl_default);
1563 #endif
1564 }
1565
1566 static void item_array_free(ItemArray *a) {
1567         unsigned n;
1568
1569         if (!a)
1570                 return;
1571
1572         for (n = 0; n < a->count; n++)
1573                 item_free_contents(a->items + n);
1574         free(a->items);
1575         free(a);
1576 }
1577
1578 static bool item_compatible(Item *a, Item *b) {
1579         assert(a);
1580         assert(b);
1581         assert(streq(a->path, b->path));
1582
1583         if (takes_ownership(a->type) && takes_ownership(b->type))
1584                 /* check if the items are the same */
1585                 return  streq_ptr(a->argument, b->argument) &&
1586
1587                         a->uid_set == b->uid_set &&
1588                         a->uid == b->uid &&
1589
1590                         a->gid_set == b->gid_set &&
1591                         a->gid == b->gid &&
1592
1593                         a->mode_set == b->mode_set &&
1594                         a->mode == b->mode &&
1595
1596                         a->age_set == b->age_set &&
1597                         a->age == b->age &&
1598
1599                         a->mask_perms == b->mask_perms &&
1600
1601                         a->keep_first_level == b->keep_first_level &&
1602
1603                         a->major_minor == b->major_minor;
1604
1605         return true;
1606 }
1607
1608 static bool should_include_path(const char *path) {
1609         char **prefix;
1610
1611         STRV_FOREACH(prefix, arg_exclude_prefixes)
1612                 if (path_startswith(path, *prefix)) {
1613                         log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
1614                                   path, *prefix);
1615                         return false;
1616                 }
1617
1618         STRV_FOREACH(prefix, arg_include_prefixes)
1619                 if (path_startswith(path, *prefix)) {
1620                         log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
1621                         return true;
1622                 }
1623
1624         /* no matches, so we should include this path only if we
1625          * have no whitelist at all */
1626         if (strv_length(arg_include_prefixes) == 0)
1627                 return true;
1628
1629         log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
1630         return false;
1631 }
1632
1633 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1634
1635         static const Specifier specifier_table[] = {
1636                 { 'm', specifier_machine_id, NULL },
1637                 { 'b', specifier_boot_id, NULL },
1638                 { 'H', specifier_host_name, NULL },
1639                 { 'v', specifier_kernel_release, NULL },
1640                 {}
1641         };
1642
1643         _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1644         _cleanup_(item_free_contents) Item i = {};
1645         ItemArray *existing;
1646         Hashmap *h;
1647         int r, pos;
1648         bool force = false, boot = false;
1649
1650         assert(fname);
1651         assert(line >= 1);
1652         assert(buffer);
1653
1654         r = unquote_many_words(&buffer,
1655                    &action,
1656                    &path,
1657                    &mode,
1658                    &user,
1659                    &group,
1660                    &age,
1661                    &i.argument,
1662                    NULL);
1663         if (r < 0)
1664                 return log_error_errno(r, "[%s:%u] Failed to parse line: %m", fname, line);
1665         else if (r < 2) {
1666                 log_error("[%s:%u] Syntax error.", fname, line);
1667                 return -EIO;
1668         }
1669
1670         if (isempty(action)) {
1671                 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1672                 return -EINVAL;
1673         }
1674
1675         for (pos = 1; action[pos]; pos++) {
1676                 if (action[pos] == '!' && !boot)
1677                         boot = true;
1678                 else if (action[pos] == '+' && !force)
1679                         force = true;
1680                 else {
1681                         log_error("[%s:%u] Unknown modifiers in command '%s'",
1682                                   fname, line, action);
1683                         return -EINVAL;
1684                 }
1685         }
1686
1687         if (boot && !arg_boot) {
1688                 log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
1689                           action, path);
1690                 return 0;
1691         }
1692
1693         i.type = action[0];
1694         i.force = force;
1695
1696         r = specifier_printf(path, specifier_table, NULL, &i.path);
1697         if (r < 0) {
1698                 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1699                 return r;
1700         }
1701
1702         switch (i.type) {
1703
1704         case CREATE_FILE:
1705         case TRUNCATE_FILE:
1706         case CREATE_DIRECTORY:
1707         case CREATE_SUBVOLUME:
1708         case TRUNCATE_DIRECTORY:
1709         case CREATE_FIFO:
1710         case IGNORE_PATH:
1711         case IGNORE_DIRECTORY_PATH:
1712         case REMOVE_PATH:
1713         case RECURSIVE_REMOVE_PATH:
1714         case ADJUST_MODE:
1715         case RELABEL_PATH:
1716         case RECURSIVE_RELABEL_PATH:
1717                 break;
1718
1719         case CREATE_SYMLINK:
1720                 if (!i.argument) {
1721                         i.argument = strappend("/usr/share/factory/", i.path);
1722                         if (!i.argument)
1723                                 return log_oom();
1724                 }
1725                 break;
1726
1727         case WRITE_FILE:
1728                 if (!i.argument) {
1729                         log_error("[%s:%u] Write file requires argument.", fname, line);
1730                         return -EBADMSG;
1731                 }
1732                 break;
1733
1734         case COPY_FILES:
1735                 if (!i.argument) {
1736                         i.argument = strappend("/usr/share/factory/", i.path);
1737                         if (!i.argument)
1738                                 return log_oom();
1739                 } else if (!path_is_absolute(i.argument)) {
1740                         log_error("[%s:%u] Source path is not absolute.", fname, line);
1741                         return -EBADMSG;
1742                 }
1743
1744                 path_kill_slashes(i.argument);
1745                 break;
1746
1747         case CREATE_CHAR_DEVICE:
1748         case CREATE_BLOCK_DEVICE: {
1749                 unsigned major, minor;
1750
1751                 if (!i.argument) {
1752                         log_error("[%s:%u] Device file requires argument.", fname, line);
1753                         return -EBADMSG;
1754                 }
1755
1756                 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1757                         log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1758                         return -EBADMSG;
1759                 }
1760
1761                 i.major_minor = makedev(major, minor);
1762                 break;
1763         }
1764
1765         case SET_XATTR:
1766         case RECURSIVE_SET_XATTR:
1767                 if (!i.argument) {
1768                         log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1769                         return -EBADMSG;
1770                 }
1771                 r = get_xattrs_from_arg(&i);
1772                 if (r < 0)
1773                         return r;
1774                 break;
1775
1776         case SET_ACL:
1777         case RECURSIVE_SET_ACL:
1778                 if (!i.argument) {
1779                         log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1780                         return -EBADMSG;
1781                 }
1782                 r = get_acls_from_arg(&i);
1783                 if (r < 0)
1784                         return r;
1785                 break;
1786
1787         case SET_ATTRIB:
1788         case RECURSIVE_SET_ATTRIB:
1789                 if (!i.argument) {
1790                         log_error("[%s:%u] Set attrib requires argument.", fname, line);
1791                         return -EBADMSG;
1792                 }
1793                 r = get_attrib_from_arg(&i);
1794                 if (r < 0)
1795                         return r;
1796                 break;
1797
1798         default:
1799                 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
1800                 return -EBADMSG;
1801         }
1802
1803         if (!path_is_absolute(i.path)) {
1804                 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1805                 return -EBADMSG;
1806         }
1807
1808         path_kill_slashes(i.path);
1809
1810         if (!should_include_path(i.path))
1811                 return 0;
1812
1813         if (arg_root) {
1814                 char *p;
1815
1816                 p = strappend(arg_root, i.path);
1817                 if (!p)
1818                         return log_oom();
1819
1820                 free(i.path);
1821                 i.path = p;
1822         }
1823
1824         if (user && !streq(user, "-")) {
1825                 const char *u = user;
1826
1827                 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1828                 if (r < 0) {
1829                         log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1830                         return r;
1831                 }
1832
1833                 i.uid_set = true;
1834         }
1835
1836         if (group && !streq(group, "-")) {
1837                 const char *g = group;
1838
1839                 r = get_group_creds(&g, &i.gid);
1840                 if (r < 0) {
1841                         log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1842                         return r;
1843                 }
1844
1845                 i.gid_set = true;
1846         }
1847
1848         if (mode && !streq(mode, "-")) {
1849                 const char *mm = mode;
1850                 unsigned m;
1851
1852                 if (*mm == '~') {
1853                         i.mask_perms = true;
1854                         mm++;
1855                 }
1856
1857                 if (sscanf(mm, "%o", &m) != 1) {
1858                         log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1859                         return -ENOENT;
1860                 }
1861
1862                 i.mode = m;
1863                 i.mode_set = true;
1864         } else
1865                 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1866                         ? 0755 : 0644;
1867
1868         if (age && !streq(age, "-")) {
1869                 const char *a = age;
1870
1871                 if (*a == '~') {
1872                         i.keep_first_level = true;
1873                         a++;
1874                 }
1875
1876                 if (parse_sec(a, &i.age) < 0) {
1877                         log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1878                         return -EBADMSG;
1879                 }
1880
1881                 i.age_set = true;
1882         }
1883
1884         h = needs_glob(i.type) ? globs : items;
1885
1886         existing = hashmap_get(h, i.path);
1887         if (existing) {
1888                 unsigned n;
1889
1890                 for (n = 0; n < existing->count; n++) {
1891                         if (!item_compatible(existing->items + n, &i)) {
1892                                 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1893                                             fname, line, i.path);
1894                                 return 0;
1895                         }
1896                 }
1897         } else {
1898                 existing = new0(ItemArray, 1);
1899                 r = hashmap_put(h, i.path, existing);
1900                 if (r < 0)
1901                         return log_oom();
1902         }
1903
1904         if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1905                 return log_oom();
1906
1907         memcpy(existing->items + existing->count++, &i, sizeof(i));
1908         zero(i);
1909         return 0;
1910 }
1911
1912 static void help(void) {
1913         printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1914                "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1915                "  -h --help                 Show this help\n"
1916                "     --version              Show package version\n"
1917                "     --create               Create marked files/directories\n"
1918                "     --clean                Clean up marked directories\n"
1919                "     --remove               Remove marked files/directories\n"
1920                "     --boot                 Execute actions only safe at boot\n"
1921                "     --prefix=PATH          Only apply rules with the specified prefix\n"
1922                "     --exclude-prefix=PATH  Ignore rules with the specified prefix\n"
1923                "     --root=PATH            Operate on an alternate filesystem root\n",
1924                program_invocation_short_name);
1925 }
1926
1927 static int parse_argv(int argc, char *argv[]) {
1928
1929         enum {
1930                 ARG_VERSION = 0x100,
1931                 ARG_CREATE,
1932                 ARG_CLEAN,
1933                 ARG_REMOVE,
1934                 ARG_BOOT,
1935                 ARG_PREFIX,
1936                 ARG_EXCLUDE_PREFIX,
1937                 ARG_ROOT,
1938         };
1939
1940         static const struct option options[] = {
1941                 { "help",           no_argument,         NULL, 'h'                },
1942                 { "version",        no_argument,         NULL, ARG_VERSION        },
1943                 { "create",         no_argument,         NULL, ARG_CREATE         },
1944                 { "clean",          no_argument,         NULL, ARG_CLEAN          },
1945                 { "remove",         no_argument,         NULL, ARG_REMOVE         },
1946                 { "boot",           no_argument,         NULL, ARG_BOOT           },
1947                 { "prefix",         required_argument,   NULL, ARG_PREFIX         },
1948                 { "exclude-prefix", required_argument,   NULL, ARG_EXCLUDE_PREFIX },
1949                 { "root",           required_argument,   NULL, ARG_ROOT           },
1950                 {}
1951         };
1952
1953         int c;
1954
1955         assert(argc >= 0);
1956         assert(argv);
1957
1958         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1959
1960                 switch (c) {
1961
1962                 case 'h':
1963                         help();
1964                         return 0;
1965
1966                 case ARG_VERSION:
1967                         puts(PACKAGE_STRING);
1968                         puts(SYSTEMD_FEATURES);
1969                         return 0;
1970
1971                 case ARG_CREATE:
1972                         arg_create = true;
1973                         break;
1974
1975                 case ARG_CLEAN:
1976                         arg_clean = true;
1977                         break;
1978
1979                 case ARG_REMOVE:
1980                         arg_remove = true;
1981                         break;
1982
1983                 case ARG_BOOT:
1984                         arg_boot = true;
1985                         break;
1986
1987                 case ARG_PREFIX:
1988                         if (strv_push(&arg_include_prefixes, optarg) < 0)
1989                                 return log_oom();
1990                         break;
1991
1992                 case ARG_EXCLUDE_PREFIX:
1993                         if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1994                                 return log_oom();
1995                         break;
1996
1997                 case ARG_ROOT:
1998                         free(arg_root);
1999                         arg_root = path_make_absolute_cwd(optarg);
2000                         if (!arg_root)
2001                                 return log_oom();
2002
2003                         path_kill_slashes(arg_root);
2004                         break;
2005
2006                 case '?':
2007                         return -EINVAL;
2008
2009                 default:
2010                         assert_not_reached("Unhandled option");
2011                 }
2012
2013         if (!arg_clean && !arg_create && !arg_remove) {
2014                 log_error("You need to specify at least one of --clean, --create or --remove.");
2015                 return -EINVAL;
2016         }
2017
2018         return 1;
2019 }
2020
2021 static int read_config_file(const char *fn, bool ignore_enoent) {
2022         _cleanup_fclose_ FILE *f = NULL;
2023         char line[LINE_MAX];
2024         Iterator iterator;
2025         unsigned v = 0;
2026         Item *i;
2027         int r;
2028
2029         assert(fn);
2030
2031         r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
2032         if (r < 0) {
2033                 if (ignore_enoent && r == -ENOENT) {
2034                         log_debug_errno(r, "Failed to open \"%s\": %m", fn);
2035                         return 0;
2036                 }
2037
2038                 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
2039         }
2040         log_debug("Reading config file \"%s\".", fn);
2041
2042         FOREACH_LINE(line, f, break) {
2043                 char *l;
2044                 int k;
2045
2046                 v++;
2047
2048                 l = strstrip(line);
2049                 if (*l == '#' || *l == 0)
2050                         continue;
2051
2052                 k = parse_line(fn, v, l);
2053                 if (k < 0 && r == 0)
2054                         r = k;
2055         }
2056
2057         /* we have to determine age parameter for each entry of type X */
2058         HASHMAP_FOREACH(i, globs, iterator) {
2059                 Iterator iter;
2060                 Item *j, *candidate_item = NULL;
2061
2062                 if (i->type != IGNORE_DIRECTORY_PATH)
2063                         continue;
2064
2065                 HASHMAP_FOREACH(j, items, iter) {
2066                         if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
2067                                 continue;
2068
2069                         if (path_equal(j->path, i->path)) {
2070                                 candidate_item = j;
2071                                 break;
2072                         }
2073
2074                         if ((!candidate_item && path_startswith(i->path, j->path)) ||
2075                             (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
2076                                 candidate_item = j;
2077                 }
2078
2079                 if (candidate_item && candidate_item->age_set) {
2080                         i->age = candidate_item->age;
2081                         i->age_set = true;
2082                 }
2083         }
2084
2085         if (ferror(f)) {
2086                 log_error_errno(errno, "Failed to read from file %s: %m", fn);
2087                 if (r == 0)
2088                         r = -EIO;
2089         }
2090
2091         return r;
2092 }
2093
2094 int main(int argc, char *argv[]) {
2095         int r, k;
2096         ItemArray *a;
2097         Iterator iterator;
2098
2099         r = parse_argv(argc, argv);
2100         if (r <= 0)
2101                 goto finish;
2102
2103         log_set_target(LOG_TARGET_AUTO);
2104         log_parse_environment();
2105         log_open();
2106
2107         umask(0022);
2108
2109         mac_selinux_init(NULL);
2110
2111         items = hashmap_new(&string_hash_ops);
2112         globs = hashmap_new(&string_hash_ops);
2113
2114         if (!items || !globs) {
2115                 r = log_oom();
2116                 goto finish;
2117         }
2118
2119         r = 0;
2120
2121         if (optind < argc) {
2122                 int j;
2123
2124                 for (j = optind; j < argc; j++) {
2125                         k = read_config_file(argv[j], false);
2126                         if (k < 0 && r == 0)
2127                                 r = k;
2128                 }
2129
2130         } else {
2131                 _cleanup_strv_free_ char **files = NULL;
2132                 char **f;
2133
2134                 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
2135                 if (r < 0) {
2136                         log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
2137                         goto finish;
2138                 }
2139
2140                 STRV_FOREACH(f, files) {
2141                         k = read_config_file(*f, true);
2142                         if (k < 0 && r == 0)
2143                                 r = k;
2144                 }
2145         }
2146
2147         HASHMAP_FOREACH(a, globs, iterator) {
2148                 k = process_item_array(a);
2149                 if (k < 0 && r == 0)
2150                         r = k;
2151         }
2152
2153         HASHMAP_FOREACH(a, items, iterator) {
2154                 k = process_item_array(a);
2155                 if (k < 0 && r == 0)
2156                         r = k;
2157         }
2158
2159 finish:
2160         while ((a = hashmap_steal_first(items)))
2161                 item_array_free(a);
2162
2163         while ((a = hashmap_steal_first(globs)))
2164                 item_array_free(a);
2165
2166         hashmap_free(items);
2167         hashmap_free(globs);
2168
2169         free(arg_include_prefixes);
2170         free(arg_exclude_prefixes);
2171         free(arg_root);
2172
2173         set_free_free(unix_sockets);
2174
2175         mac_selinux_finish();
2176
2177         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
2178 }