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