chiark / gitweb /
machinectl: issue all bus commands while allowing interactive auth
[elogind.git] / src / tmpfiles / tmpfiles.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering, Kay Sievers
7   Copyright 2015 Zbigniew JÄ™drzejewski-Szmek
8
9   systemd is free software; you can redistribute it and/or modify it
10   under the terms of the GNU Lesser General Public License as published by
11   the Free Software Foundation; either version 2.1 of the License, or
12   (at your option) any later version.
13
14   systemd is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <limits.h>
28 #include <dirent.h>
29 #include <grp.h>
30 #include <pwd.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stddef.h>
34 #include <getopt.h>
35 #include <stdbool.h>
36 #include <time.h>
37 #include <glob.h>
38 #include <fnmatch.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <sys/param.h>
42 #include <sys/xattr.h>
43
44 #include "log.h"
45 #include "util.h"
46 #include "macro.h"
47 #include "missing.h"
48 #include "mkdir.h"
49 #include "path-util.h"
50 #include "strv.h"
51 #include "label.h"
52 #include "set.h"
53 #include "conf-files.h"
54 #include "capability.h"
55 #include "specifier.h"
56 #include "build.h"
57 #include "copy.h"
58 #include "selinux-util.h"
59 #include "btrfs-util.h"
60 #include "acl-util.h"
61
62 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
63  * them in the file system. This is intended to be used to create
64  * properly owned directories beneath /tmp, /var/tmp, /run, which are
65  * volatile and hence need to be recreated on bootup. */
66
67 typedef enum ItemType {
68         /* These ones take file names */
69         CREATE_FILE = 'f',
70         TRUNCATE_FILE = 'F',
71         CREATE_DIRECTORY = 'd',
72         TRUNCATE_DIRECTORY = 'D',
73         CREATE_SUBVOLUME = 'v',
74         CREATE_FIFO = 'p',
75         CREATE_SYMLINK = 'L',
76         CREATE_CHAR_DEVICE = 'c',
77         CREATE_BLOCK_DEVICE = 'b',
78         COPY_FILES = 'C',
79
80         /* These ones take globs */
81         SET_XATTR = 't',
82         RECURSIVE_SET_XATTR = 'T',
83         SET_ACL = 'a',
84         RECURSIVE_SET_ACL = 'A',
85         WRITE_FILE = 'w',
86         IGNORE_PATH = 'x',
87         IGNORE_DIRECTORY_PATH = 'X',
88         REMOVE_PATH = 'r',
89         RECURSIVE_REMOVE_PATH = 'R',
90         ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */
91         RELABEL_PATH = 'z',
92         RECURSIVE_RELABEL_PATH = 'Z',
93 } ItemType;
94
95 typedef struct Item {
96         ItemType type;
97
98         char *path;
99         char *argument;
100         char **xattrs;
101 #ifdef HAVE_ACL
102         acl_t acl_access;
103         acl_t acl_default;
104 #endif
105         uid_t uid;
106         gid_t gid;
107         mode_t mode;
108         usec_t age;
109
110         dev_t major_minor;
111
112         bool uid_set:1;
113         bool gid_set:1;
114         bool mode_set:1;
115         bool age_set:1;
116         bool mask_perms:1;
117
118         bool keep_first_level:1;
119
120         bool force:1;
121
122         bool done:1;
123 } Item;
124
125 typedef struct ItemArray {
126         Item *items;
127         size_t count;
128         size_t size;
129 } ItemArray;
130
131 static bool arg_create = false;
132 static bool arg_clean = false;
133 static bool arg_remove = false;
134 static bool arg_boot = false;
135
136 static char **arg_include_prefixes = NULL;
137 static char **arg_exclude_prefixes = NULL;
138 static char *arg_root = NULL;
139
140 static const char conf_file_dirs[] = CONF_DIRS_NULSTR("tmpfiles");
141
142 #define MAX_DEPTH 256
143
144 static Hashmap *items = NULL, *globs = NULL;
145 static Set *unix_sockets = NULL;
146
147 static bool needs_glob(ItemType t) {
148         return IN_SET(t,
149                       WRITE_FILE,
150                       IGNORE_PATH,
151                       IGNORE_DIRECTORY_PATH,
152                       REMOVE_PATH,
153                       RECURSIVE_REMOVE_PATH,
154                       ADJUST_MODE,
155                       RELABEL_PATH,
156                       RECURSIVE_RELABEL_PATH,
157                       SET_XATTR,
158                       RECURSIVE_SET_XATTR,
159                       SET_ACL,
160                       RECURSIVE_SET_ACL);
161 }
162
163 static bool takes_ownership(ItemType t) {
164         return IN_SET(t,
165                       CREATE_FILE,
166                       TRUNCATE_FILE,
167                       CREATE_DIRECTORY,
168                       TRUNCATE_DIRECTORY,
169                       CREATE_SUBVOLUME,
170                       CREATE_FIFO,
171                       CREATE_SYMLINK,
172                       CREATE_CHAR_DEVICE,
173                       CREATE_BLOCK_DEVICE,
174                       COPY_FILES,
175
176                       WRITE_FILE,
177                       IGNORE_PATH,
178                       IGNORE_DIRECTORY_PATH,
179                       REMOVE_PATH,
180                       RECURSIVE_REMOVE_PATH);
181 }
182
183 static struct Item* find_glob(Hashmap *h, const char *match) {
184         ItemArray *j;
185         Iterator i;
186
187         HASHMAP_FOREACH(j, h, i) {
188                 unsigned n;
189
190                 for (n = 0; n < j->count; n++) {
191                         Item *item = j->items + n;
192
193                         if (fnmatch(item->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
194                                 return item;
195                 }
196         }
197
198         return NULL;
199 }
200
201 static void load_unix_sockets(void) {
202         _cleanup_fclose_ FILE *f = NULL;
203         char line[LINE_MAX];
204
205         if (unix_sockets)
206                 return;
207
208         /* We maintain a cache of the sockets we found in
209          * /proc/net/unix to speed things up a little. */
210
211         unix_sockets = set_new(&string_hash_ops);
212         if (!unix_sockets)
213                 return;
214
215         f = fopen("/proc/net/unix", "re");
216         if (!f)
217                 return;
218
219         /* Skip header */
220         if (!fgets(line, sizeof(line), f))
221                 goto fail;
222
223         for (;;) {
224                 char *p, *s;
225                 int k;
226
227                 if (!fgets(line, sizeof(line), f))
228                         break;
229
230                 truncate_nl(line);
231
232                 p = strchr(line, ':');
233                 if (!p)
234                         continue;
235
236                 if (strlen(p) < 37)
237                         continue;
238
239                 p += 37;
240                 p += strspn(p, WHITESPACE);
241                 p += strcspn(p, WHITESPACE); /* skip one more word */
242                 p += strspn(p, WHITESPACE);
243
244                 if (*p != '/')
245                         continue;
246
247                 s = strdup(p);
248                 if (!s)
249                         goto fail;
250
251                 path_kill_slashes(s);
252
253                 k = set_consume(unix_sockets, s);
254                 if (k < 0 && k != -EEXIST)
255                         goto fail;
256         }
257
258         return;
259
260 fail:
261         set_free_free(unix_sockets);
262         unix_sockets = NULL;
263 }
264
265 static bool unix_socket_alive(const char *fn) {
266         assert(fn);
267
268         load_unix_sockets();
269
270         if (unix_sockets)
271                 return !!set_get(unix_sockets, (char*) fn);
272
273         /* We don't know, so assume yes */
274         return true;
275 }
276
277 static int dir_is_mount_point(DIR *d, const char *subdir) {
278
279         union file_handle_union h = FILE_HANDLE_INIT;
280         int mount_id_parent, mount_id;
281         int r_p, r;
282
283         r_p = name_to_handle_at(dirfd(d), ".", &h.handle, &mount_id_parent, 0);
284         if (r_p < 0)
285                 r_p = -errno;
286
287         h.handle.handle_bytes = MAX_HANDLE_SZ;
288         r = name_to_handle_at(dirfd(d), subdir, &h.handle, &mount_id, 0);
289         if (r < 0)
290                 r = -errno;
291
292         /* got no handle; make no assumptions, return error */
293         if (r_p < 0 && r < 0)
294                 return r_p;
295
296         /* got both handles; if they differ, it is a mount point */
297         if (r_p >= 0 && r >= 0)
298                 return mount_id_parent != mount_id;
299
300         /* got only one handle; assume different mount points if one
301          * of both queries was not supported by the filesystem */
302         if (r_p == -ENOSYS || r_p == -EOPNOTSUPP || r == -ENOSYS || r == -EOPNOTSUPP)
303                 return true;
304
305         /* return error */
306         if (r_p < 0)
307                 return r_p;
308         return r;
309 }
310
311 static DIR* xopendirat_nomod(int dirfd, const char *path) {
312         DIR *dir;
313
314         dir = xopendirat(dirfd, path, O_NOFOLLOW|O_NOATIME);
315         if (!dir) {
316                 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m",
317                                 dirfd == AT_FDCWD ? "" : "sub", path);
318                 if (errno == EPERM) {
319                         dir = xopendirat(dirfd, path, O_NOFOLLOW);
320                         if (!dir)
321                                 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m",
322                                                 dirfd == AT_FDCWD ? "" : "sub", path);
323                 }
324         }
325
326         return dir;
327 }
328
329 static DIR* opendir_nomod(const char *path) {
330         return xopendirat_nomod(AT_FDCWD, path);
331 }
332
333 static int dir_cleanup(
334                 Item *i,
335                 const char *p,
336                 DIR *d,
337                 const struct stat *ds,
338                 usec_t cutoff,
339                 dev_t rootdev,
340                 bool mountpoint,
341                 int maxdepth,
342                 bool keep_this_level) {
343
344         struct dirent *dent;
345         struct timespec times[2];
346         bool deleted = false;
347         int r = 0;
348
349         while ((dent = readdir(d))) {
350                 struct stat s;
351                 usec_t age;
352                 _cleanup_free_ char *sub_path = NULL;
353
354                 if (STR_IN_SET(dent->d_name, ".", ".."))
355                         continue;
356
357                 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
358                         if (errno == ENOENT)
359                                 continue;
360
361                         /* FUSE, NFS mounts, SELinux might return EACCES */
362                         if (errno == EACCES)
363                                 log_debug_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
364                         else
365                                 log_error_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
366                         r = -errno;
367                         continue;
368                 }
369
370                 /* Stay on the same filesystem */
371                 if (s.st_dev != rootdev) {
372                         log_debug("Ignoring \"%s/%s\": different filesystem.", p, dent->d_name);
373                         continue;
374                 }
375
376                 /* Try to detect bind mounts of the same filesystem instance; they
377                  * do not differ in device major/minors. This type of query is not
378                  * supported on all kernels or filesystem types though. */
379                 if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0) {
380                         log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.",
381                                   p, dent->d_name);
382                         continue;
383                 }
384
385                 /* Do not delete read-only files owned by root */
386                 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR)) {
387                         log_debug("Ignoring \"%s/%s\": read-only and owner by root.", p, dent->d_name);
388                         continue;
389                 }
390
391                 sub_path = strjoin(p, "/", dent->d_name, NULL);
392                 if (!sub_path) {
393                         r = log_oom();
394                         goto finish;
395                 }
396
397                 /* Is there an item configured for this path? */
398                 if (hashmap_get(items, sub_path)) {
399                         log_debug("Ignoring \"%s\": a separate entry exists.", sub_path);
400                         continue;
401                 }
402
403                 if (find_glob(globs, sub_path)) {
404                         log_debug("Ignoring \"%s\": a separate glob exists.", sub_path);
405                         continue;
406                 }
407
408                 if (S_ISDIR(s.st_mode)) {
409
410                         if (mountpoint &&
411                             streq(dent->d_name, "lost+found") &&
412                             s.st_uid == 0) {
413                                 log_debug("Ignoring \"%s\".", sub_path);
414                                 continue;
415                         }
416
417                         if (maxdepth <= 0)
418                                 log_warning("Reached max depth on \"%s\".", sub_path);
419                         else {
420                                 _cleanup_closedir_ DIR *sub_dir;
421                                 int q;
422
423                                 sub_dir = xopendirat_nomod(dirfd(d), dent->d_name);
424                                 if (!sub_dir) {
425                                         if (errno != ENOENT)
426                                                 r = log_error_errno(errno, "opendir(%s) failed: %m", sub_path);
427
428                                         continue;
429                                 }
430
431                                 q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
432                                 if (q < 0)
433                                         r = q;
434                         }
435
436                         /* Note: if you are wondering why we don't
437                          * support the sticky bit for excluding
438                          * directories from cleaning like we do it for
439                          * other file system objects: well, the sticky
440                          * bit already has a meaning for directories,
441                          * so we don't want to overload that. */
442
443                         if (keep_this_level) {
444                                 log_debug("Keeping \"%s\".", sub_path);
445                                 continue;
446                         }
447
448                         /* Ignore ctime, we change it when deleting */
449                         age = timespec_load(&s.st_mtim);
450                         if (age >= cutoff) {
451                                 char a[FORMAT_TIMESTAMP_MAX];
452                                 /* Follows spelling in stat(1). */
453                                 log_debug("Directory \"%s\": modify time %s is too new.",
454                                           sub_path,
455                                           format_timestamp_us(a, sizeof(a), age));
456                                 continue;
457                         }
458
459                         age = timespec_load(&s.st_atim);
460                         if (age >= cutoff) {
461                                 char a[FORMAT_TIMESTAMP_MAX];
462                                 log_debug("Directory \"%s\": access time %s is too new.",
463                                           sub_path,
464                                           format_timestamp_us(a, sizeof(a), age));
465                                 continue;
466                         }
467
468                         log_debug("Removing directory \"%s\".", sub_path);
469                         if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0)
470                                 if (errno != ENOENT && errno != ENOTEMPTY) {
471                                         log_error_errno(errno, "rmdir(%s): %m", sub_path);
472                                         r = -errno;
473                                 }
474
475                 } else {
476                         /* Skip files for which the sticky bit is
477                          * set. These are semantics we define, and are
478                          * unknown elsewhere. See XDG_RUNTIME_DIR
479                          * specification for details. */
480                         if (s.st_mode & S_ISVTX) {
481                                 log_debug("Skipping \"%s\": sticky bit set.", sub_path);
482                                 continue;
483                         }
484
485                         if (mountpoint && S_ISREG(s.st_mode))
486                                 if ((streq(dent->d_name, ".journal") && s.st_uid == 0) ||
487                                     streq(dent->d_name, "aquota.user") ||
488                                     streq(dent->d_name, "aquota.group")) {
489                                         log_debug("Skipping \"%s\".", sub_path);
490                                         continue;
491                                 }
492
493                         /* Ignore sockets that are listed in /proc/net/unix */
494                         if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path)) {
495                                 log_debug("Skipping \"%s\": live socket.", sub_path);
496                                 continue;
497                         }
498
499                         /* Ignore device nodes */
500                         if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode)) {
501                                 log_debug("Skipping \"%s\": a device.", sub_path);
502                                 continue;
503                         }
504
505                         /* Keep files on this level around if this is
506                          * requested */
507                         if (keep_this_level) {
508                                 log_debug("Keeping \"%s\".", sub_path);
509                                 continue;
510                         }
511
512                         age = timespec_load(&s.st_mtim);
513                         if (age >= cutoff) {
514                                 char a[FORMAT_TIMESTAMP_MAX];
515                                 /* Follows spelling in stat(1). */
516                                 log_debug("File \"%s\": modify time %s is too new.",
517                                           sub_path,
518                                           format_timestamp_us(a, sizeof(a), age));
519                                 continue;
520                         }
521
522                         age = timespec_load(&s.st_atim);
523                         if (age >= cutoff) {
524                                 char a[FORMAT_TIMESTAMP_MAX];
525                                 log_debug("File \"%s\": access time %s is too new.",
526                                           sub_path,
527                                           format_timestamp_us(a, sizeof(a), age));
528                                 continue;
529                         }
530
531                         age = timespec_load(&s.st_ctim);
532                         if (age >= cutoff) {
533                                 char a[FORMAT_TIMESTAMP_MAX];
534                                 log_debug("File \"%s\": change time %s is too new.",
535                                           sub_path,
536                                           format_timestamp_us(a, sizeof(a), age));
537                                 continue;
538                         }
539
540                         log_debug("unlink \"%s\"", sub_path);
541
542                         if (unlinkat(dirfd(d), dent->d_name, 0) < 0)
543                                 if (errno != ENOENT)
544                                         r = log_error_errno(errno, "unlink(%s): %m", sub_path);
545
546                         deleted = true;
547                 }
548         }
549
550 finish:
551         if (deleted) {
552                 usec_t age1, age2;
553                 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
554
555                 /* Restore original directory timestamps */
556                 times[0] = ds->st_atim;
557                 times[1] = ds->st_mtim;
558
559                 age1 = timespec_load(&ds->st_atim);
560                 age2 = timespec_load(&ds->st_mtim);
561                 log_debug("Restoring access and modification time on \"%s\": %s, %s",
562                           p,
563                           format_timestamp_us(a, sizeof(a), age1),
564                           format_timestamp_us(b, sizeof(b), age2));
565                 if (futimens(dirfd(d), times) < 0)
566                         log_error_errno(errno, "utimensat(%s): %m", p);
567         }
568
569         return r;
570 }
571
572 static int path_set_perms(Item *i, const char *path) {
573         struct stat st;
574         bool st_valid;
575
576         assert(i);
577         assert(path);
578
579         st_valid = stat(path, &st) == 0;
580
581         /* not using i->path directly because it may be a glob */
582         if (i->mode_set) {
583                 mode_t m = i->mode;
584
585                 if (i->mask_perms && st_valid) {
586                         if (!(st.st_mode & 0111))
587                                 m &= ~0111;
588                         if (!(st.st_mode & 0222))
589                                 m &= ~0222;
590                         if (!(st.st_mode & 0444))
591                                 m &= ~0444;
592                         if (!S_ISDIR(st.st_mode))
593                                 m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
594                 }
595
596                 if (st_valid && m == (st.st_mode & 07777))
597                         log_debug("\"%s\" has right mode %o", path, st.st_mode);
598                 else {
599                         log_debug("chmod \"%s\" to mode %o", path, m);
600                         if (chmod(path, m) < 0)
601                                 return log_error_errno(errno, "chmod(%s) failed: %m", path);
602                 }
603         }
604
605         if ((!st_valid || i->uid != st.st_uid || i->gid != st.st_gid) &&
606             (i->uid_set || i->gid_set)) {
607                 log_debug("chown \"%s\" to "UID_FMT"."GID_FMT,
608                           path,
609                           i->uid_set ? i->uid : UID_INVALID,
610                           i->gid_set ? i->gid : GID_INVALID);
611                 if (chown(path,
612                           i->uid_set ? i->uid : UID_INVALID,
613                           i->gid_set ? i->gid : GID_INVALID) < 0)
614
615                         return log_error_errno(errno, "chown(%s) failed: %m", path);
616         }
617
618         return label_fix(path, false, false);
619 }
620
621 static int get_xattrs_from_arg(Item *i) {
622         char *xattr;
623         const char *p;
624         int r;
625
626         assert(i);
627         assert(i->argument);
628
629         p = i->argument;
630
631         while ((r = unquote_first_word(&p, &xattr, false)) > 0) {
632                 _cleanup_free_ char *tmp = NULL, *name = NULL,
633                         *value = NULL, *value2 = NULL, *_xattr = xattr;
634
635                 r = split_pair(xattr, "=", &name, &value);
636                 if (r < 0) {
637                         log_warning("Illegal xattr found: \"%s\" - ignoring.", xattr);
638                         continue;
639                 }
640
641                 if (strempty(name) || strempty(value)) {
642                         log_warning("Malformed xattr found: \"%s\" - ignoring.", xattr);
643                         continue;
644                 }
645
646                 tmp = unquote(value, "\"");
647                 if (!tmp)
648                         return log_oom();
649
650                 value2 = cunescape(tmp);
651                 if (!value2)
652                         return log_oom();
653
654                 if (strv_push_pair(&i->xattrs, name, value2) < 0)
655                         return log_oom();
656                 name = value2 = NULL;
657         }
658
659         return r;
660 }
661
662 static int path_set_xattrs(Item *i, const char *path) {
663         char **name, **value;
664
665         assert(i);
666         assert(path);
667
668         STRV_FOREACH_PAIR(name, value, i->xattrs) {
669                 int n;
670
671                 n = strlen(*value);
672                 log_debug("\"%s\": setting xattr \"%s=%s\"", path, *name, *value);
673                 if (lsetxattr(path, *name, *value, n, 0) < 0) {
674                         log_error("Setting extended attribute %s=%s on %s failed: %m",
675                                   *name, *value, path);
676                         return -errno;
677                 }
678         }
679         return 0;
680 }
681
682 static int get_acls_from_arg(Item *item) {
683 #ifdef HAVE_ACL
684         int r;
685
686         assert(item);
687
688         /* If force (= modify) is set, we will not modify the acl
689          * afterwards, so the mask can be added now if necessary. */
690         r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
691         if (r < 0)
692                 log_warning_errno(r, "Failed to parse ACL \"%s\": %m. Ignoring",
693                                   item->argument);
694 #else
695         log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
696 #endif
697
698         return 0;
699 }
700
701 #ifdef HAVE_ACL
702 static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
703         _cleanup_(acl_freep) acl_t dup = NULL;
704         int r;
705         _cleanup_(acl_free_charpp) char *t = NULL;
706
707         if (modify) {
708                 r = acls_for_file(path, type, acl, &dup);
709                 if (r < 0)
710                         return r;
711
712                 r = calc_acl_mask_if_needed(&dup);
713                 if (r < 0)
714                         return r;
715         } else {
716                 dup = acl_dup(acl);
717                 if (!dup)
718                         return -errno;
719
720                 /* the mask was already added earlier if needed */
721         }
722
723         r = add_base_acls_if_needed(&dup, path);
724         if (r < 0)
725                 return r;
726
727         t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
728         log_debug("\"%s\": setting %s ACL \"%s\"", path,
729                   type == ACL_TYPE_ACCESS ? "access" : "default",
730                   strna(t));
731
732         r = acl_set_file(path, type, dup);
733         if (r < 0)
734                 return log_error_errno(-errno,
735                                        "Setting %s ACL \"%s\" on %s failed: %m",
736                                        type == ACL_TYPE_ACCESS ? "access" : "default",
737                                        strna(t), path);
738         return 0;
739 }
740 #endif
741
742 static int path_set_acls(Item *item, const char *path) {
743 #ifdef HAVE_ACL
744         int r;
745
746         assert(item);
747         assert(path);
748
749         if (item->acl_access) {
750                 r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
751                 if (r < 0)
752                         return r;
753         }
754
755         if (item->acl_default) {
756                 r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
757                 if (r < 0)
758                         return r;
759         }
760 #endif
761
762         return 0;
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, c = -1, pos;
1510         bool force = false, boot = false;
1511
1512         assert(fname);
1513         assert(line >= 1);
1514         assert(buffer);
1515
1516         r = sscanf(buffer,
1517                    "%ms %ms %ms %ms %ms %ms %n",
1518                    &action,
1519                    &path,
1520                    &mode,
1521                    &user,
1522                    &group,
1523                    &age,
1524                    &c);
1525         if (r < 2) {
1526                 log_error("[%s:%u] Syntax error.", fname, line);
1527                 return -EIO;
1528         }
1529
1530         if (isempty(action)) {
1531                 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1532                 return -EINVAL;
1533         }
1534
1535         for (pos = 1; action[pos]; pos++) {
1536                 if (action[pos] == '!' && !boot)
1537                         boot = true;
1538                 else if (action[pos] == '+' && !force)
1539                         force = true;
1540                 else {
1541                         log_error("[%s:%u] Unknown modifiers in command '%s'",
1542                                   fname, line, action);
1543                         return -EINVAL;
1544                 }
1545         }
1546
1547         if (boot && !arg_boot) {
1548                 log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
1549                           action, path);
1550                 return 0;
1551         }
1552
1553         i.type = action[0];
1554         i.force = force;
1555
1556         r = specifier_printf(path, specifier_table, NULL, &i.path);
1557         if (r < 0) {
1558                 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1559                 return r;
1560         }
1561
1562         if (c >= 0)  {
1563                 c += strspn(buffer+c, WHITESPACE);
1564                 if (buffer[c] != 0 && (buffer[c] != '-' || buffer[c+1] != 0)) {
1565                         i.argument = unquote(buffer+c, "\"");
1566                         if (!i.argument)
1567                                 return log_oom();
1568                 }
1569         }
1570
1571         switch (i.type) {
1572
1573         case CREATE_FILE:
1574         case TRUNCATE_FILE:
1575         case CREATE_DIRECTORY:
1576         case CREATE_SUBVOLUME:
1577         case TRUNCATE_DIRECTORY:
1578         case CREATE_FIFO:
1579         case IGNORE_PATH:
1580         case IGNORE_DIRECTORY_PATH:
1581         case REMOVE_PATH:
1582         case RECURSIVE_REMOVE_PATH:
1583         case ADJUST_MODE:
1584         case RELABEL_PATH:
1585         case RECURSIVE_RELABEL_PATH:
1586                 break;
1587
1588         case CREATE_SYMLINK:
1589                 if (!i.argument) {
1590                         i.argument = strappend("/usr/share/factory/", i.path);
1591                         if (!i.argument)
1592                                 return log_oom();
1593                 }
1594                 break;
1595
1596         case WRITE_FILE:
1597                 if (!i.argument) {
1598                         log_error("[%s:%u] Write file requires argument.", fname, line);
1599                         return -EBADMSG;
1600                 }
1601                 break;
1602
1603         case COPY_FILES:
1604                 if (!i.argument) {
1605                         i.argument = strappend("/usr/share/factory/", i.path);
1606                         if (!i.argument)
1607                                 return log_oom();
1608                 } else if (!path_is_absolute(i.argument)) {
1609                         log_error("[%s:%u] Source path is not absolute.", fname, line);
1610                         return -EBADMSG;
1611                 }
1612
1613                 path_kill_slashes(i.argument);
1614                 break;
1615
1616         case CREATE_CHAR_DEVICE:
1617         case CREATE_BLOCK_DEVICE: {
1618                 unsigned major, minor;
1619
1620                 if (!i.argument) {
1621                         log_error("[%s:%u] Device file requires argument.", fname, line);
1622                         return -EBADMSG;
1623                 }
1624
1625                 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1626                         log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1627                         return -EBADMSG;
1628                 }
1629
1630                 i.major_minor = makedev(major, minor);
1631                 break;
1632         }
1633
1634         case SET_XATTR:
1635         case RECURSIVE_SET_XATTR:
1636                 if (!i.argument) {
1637                         log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1638                         return -EBADMSG;
1639                 }
1640                 r = get_xattrs_from_arg(&i);
1641                 if (r < 0)
1642                         return r;
1643                 break;
1644
1645         case SET_ACL:
1646         case RECURSIVE_SET_ACL:
1647                 if (!i.argument) {
1648                         log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1649                         return -EBADMSG;
1650                 }
1651                 r = get_acls_from_arg(&i);
1652                 if (r < 0)
1653                         return r;
1654                 break;
1655
1656         default:
1657                 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
1658                 return -EBADMSG;
1659         }
1660
1661         if (!path_is_absolute(i.path)) {
1662                 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1663                 return -EBADMSG;
1664         }
1665
1666         path_kill_slashes(i.path);
1667
1668         if (!should_include_path(i.path))
1669                 return 0;
1670
1671         if (arg_root) {
1672                 char *p;
1673
1674                 p = strappend(arg_root, i.path);
1675                 if (!p)
1676                         return log_oom();
1677
1678                 free(i.path);
1679                 i.path = p;
1680         }
1681
1682         if (user && !streq(user, "-")) {
1683                 const char *u = user;
1684
1685                 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1686                 if (r < 0) {
1687                         log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1688                         return r;
1689                 }
1690
1691                 i.uid_set = true;
1692         }
1693
1694         if (group && !streq(group, "-")) {
1695                 const char *g = group;
1696
1697                 r = get_group_creds(&g, &i.gid);
1698                 if (r < 0) {
1699                         log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1700                         return r;
1701                 }
1702
1703                 i.gid_set = true;
1704         }
1705
1706         if (mode && !streq(mode, "-")) {
1707                 const char *mm = mode;
1708                 unsigned m;
1709
1710                 if (*mm == '~') {
1711                         i.mask_perms = true;
1712                         mm++;
1713                 }
1714
1715                 if (sscanf(mm, "%o", &m) != 1) {
1716                         log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1717                         return -ENOENT;
1718                 }
1719
1720                 i.mode = m;
1721                 i.mode_set = true;
1722         } else
1723                 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1724                         ? 0755 : 0644;
1725
1726         if (age && !streq(age, "-")) {
1727                 const char *a = age;
1728
1729                 if (*a == '~') {
1730                         i.keep_first_level = true;
1731                         a++;
1732                 }
1733
1734                 if (parse_sec(a, &i.age) < 0) {
1735                         log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1736                         return -EBADMSG;
1737                 }
1738
1739                 i.age_set = true;
1740         }
1741
1742         h = needs_glob(i.type) ? globs : items;
1743
1744         existing = hashmap_get(h, i.path);
1745         if (existing) {
1746                 unsigned n;
1747
1748                 for (n = 0; n < existing->count; n++) {
1749                         if (!item_compatible(existing->items + n, &i))
1750                                 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1751                                             fname, line, i.path);
1752                 }
1753         } else {
1754                 existing = new0(ItemArray, 1);
1755                 r = hashmap_put(h, i.path, existing);
1756                 if (r < 0)
1757                         return log_oom();
1758         }
1759
1760         if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1761                 return log_oom();
1762
1763         memcpy(existing->items + existing->count++, &i, sizeof(i));
1764         zero(i);
1765         return 0;
1766 }
1767
1768 static void help(void) {
1769         printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1770                "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1771                "  -h --help                 Show this help\n"
1772                "     --version              Show package version\n"
1773                "     --create               Create marked files/directories\n"
1774                "     --clean                Clean up marked directories\n"
1775                "     --remove               Remove marked files/directories\n"
1776                "     --boot                 Execute actions only safe at boot\n"
1777                "     --prefix=PATH          Only apply rules with the specified prefix\n"
1778                "     --exclude-prefix=PATH  Ignore rules with the specified prefix\n"
1779                "     --root=PATH            Operate on an alternate filesystem root\n",
1780                program_invocation_short_name);
1781 }
1782
1783 static int parse_argv(int argc, char *argv[]) {
1784
1785         enum {
1786                 ARG_VERSION = 0x100,
1787                 ARG_CREATE,
1788                 ARG_CLEAN,
1789                 ARG_REMOVE,
1790                 ARG_BOOT,
1791                 ARG_PREFIX,
1792                 ARG_EXCLUDE_PREFIX,
1793                 ARG_ROOT,
1794         };
1795
1796         static const struct option options[] = {
1797                 { "help",           no_argument,         NULL, 'h'                },
1798                 { "version",        no_argument,         NULL, ARG_VERSION        },
1799                 { "create",         no_argument,         NULL, ARG_CREATE         },
1800                 { "clean",          no_argument,         NULL, ARG_CLEAN          },
1801                 { "remove",         no_argument,         NULL, ARG_REMOVE         },
1802                 { "boot",           no_argument,         NULL, ARG_BOOT           },
1803                 { "prefix",         required_argument,   NULL, ARG_PREFIX         },
1804                 { "exclude-prefix", required_argument,   NULL, ARG_EXCLUDE_PREFIX },
1805                 { "root",           required_argument,   NULL, ARG_ROOT           },
1806                 {}
1807         };
1808
1809         int c;
1810
1811         assert(argc >= 0);
1812         assert(argv);
1813
1814         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1815
1816                 switch (c) {
1817
1818                 case 'h':
1819                         help();
1820                         return 0;
1821
1822                 case ARG_VERSION:
1823                         puts(PACKAGE_STRING);
1824                         puts(SYSTEMD_FEATURES);
1825                         return 0;
1826
1827                 case ARG_CREATE:
1828                         arg_create = true;
1829                         break;
1830
1831                 case ARG_CLEAN:
1832                         arg_clean = true;
1833                         break;
1834
1835                 case ARG_REMOVE:
1836                         arg_remove = true;
1837                         break;
1838
1839                 case ARG_BOOT:
1840                         arg_boot = true;
1841                         break;
1842
1843                 case ARG_PREFIX:
1844                         if (strv_push(&arg_include_prefixes, optarg) < 0)
1845                                 return log_oom();
1846                         break;
1847
1848                 case ARG_EXCLUDE_PREFIX:
1849                         if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1850                                 return log_oom();
1851                         break;
1852
1853                 case ARG_ROOT:
1854                         free(arg_root);
1855                         arg_root = path_make_absolute_cwd(optarg);
1856                         if (!arg_root)
1857                                 return log_oom();
1858
1859                         path_kill_slashes(arg_root);
1860                         break;
1861
1862                 case '?':
1863                         return -EINVAL;
1864
1865                 default:
1866                         assert_not_reached("Unhandled option");
1867                 }
1868
1869         if (!arg_clean && !arg_create && !arg_remove) {
1870                 log_error("You need to specify at least one of --clean, --create or --remove.");
1871                 return -EINVAL;
1872         }
1873
1874         return 1;
1875 }
1876
1877 static int read_config_file(const char *fn, bool ignore_enoent) {
1878         _cleanup_fclose_ FILE *f = NULL;
1879         char line[LINE_MAX];
1880         Iterator iterator;
1881         unsigned v = 0;
1882         Item *i;
1883         int r;
1884
1885         assert(fn);
1886
1887         r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
1888         if (r < 0) {
1889                 if (ignore_enoent && r == -ENOENT) {
1890                         log_debug_errno(r, "Failed to open \"%s\": %m", fn);
1891                         return 0;
1892                 }
1893
1894                 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
1895         }
1896         log_debug("Reading config file \"%s\".", fn);
1897
1898         FOREACH_LINE(line, f, break) {
1899                 char *l;
1900                 int k;
1901
1902                 v++;
1903
1904                 l = strstrip(line);
1905                 if (*l == '#' || *l == 0)
1906                         continue;
1907
1908                 k = parse_line(fn, v, l);
1909                 if (k < 0 && r == 0)
1910                         r = k;
1911         }
1912
1913         /* we have to determine age parameter for each entry of type X */
1914         HASHMAP_FOREACH(i, globs, iterator) {
1915                 Iterator iter;
1916                 Item *j, *candidate_item = NULL;
1917
1918                 if (i->type != IGNORE_DIRECTORY_PATH)
1919                         continue;
1920
1921                 HASHMAP_FOREACH(j, items, iter) {
1922                         if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
1923                                 continue;
1924
1925                         if (path_equal(j->path, i->path)) {
1926                                 candidate_item = j;
1927                                 break;
1928                         }
1929
1930                         if ((!candidate_item && path_startswith(i->path, j->path)) ||
1931                             (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1932                                 candidate_item = j;
1933                 }
1934
1935                 if (candidate_item && candidate_item->age_set) {
1936                         i->age = candidate_item->age;
1937                         i->age_set = true;
1938                 }
1939         }
1940
1941         if (ferror(f)) {
1942                 log_error_errno(errno, "Failed to read from file %s: %m", fn);
1943                 if (r == 0)
1944                         r = -EIO;
1945         }
1946
1947         return r;
1948 }
1949
1950 int main(int argc, char *argv[]) {
1951         int r, k;
1952         ItemArray *a;
1953         Iterator iterator;
1954
1955         r = parse_argv(argc, argv);
1956         if (r <= 0)
1957                 goto finish;
1958
1959         log_set_target(LOG_TARGET_AUTO);
1960         log_parse_environment();
1961         log_open();
1962
1963         umask(0022);
1964
1965         mac_selinux_init(NULL);
1966
1967         items = hashmap_new(&string_hash_ops);
1968         globs = hashmap_new(&string_hash_ops);
1969
1970         if (!items || !globs) {
1971                 r = log_oom();
1972                 goto finish;
1973         }
1974
1975         r = 0;
1976
1977         if (optind < argc) {
1978                 int j;
1979
1980                 for (j = optind; j < argc; j++) {
1981                         k = read_config_file(argv[j], false);
1982                         if (k < 0 && r == 0)
1983                                 r = k;
1984                 }
1985
1986         } else {
1987                 _cleanup_strv_free_ char **files = NULL;
1988                 char **f;
1989
1990                 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
1991                 if (r < 0) {
1992                         log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
1993                         goto finish;
1994                 }
1995
1996                 STRV_FOREACH(f, files) {
1997                         k = read_config_file(*f, true);
1998                         if (k < 0 && r == 0)
1999                                 r = k;
2000                 }
2001         }
2002
2003         HASHMAP_FOREACH(a, globs, iterator) {
2004                 k = process_item_array(a);
2005                 if (k < 0 && r == 0)
2006                         r = k;
2007         }
2008
2009         HASHMAP_FOREACH(a, items, iterator) {
2010                 k = process_item_array(a);
2011                 if (k < 0 && r == 0)
2012                         r = k;
2013         }
2014
2015 finish:
2016         while ((a = hashmap_steal_first(items)))
2017                 item_array_free(a);
2018
2019         while ((a = hashmap_steal_first(globs)))
2020                 item_array_free(a);
2021
2022         hashmap_free(items);
2023         hashmap_free(globs);
2024
2025         free(arg_include_prefixes);
2026         free(arg_exclude_prefixes);
2027         free(arg_root);
2028
2029         set_free_free(unix_sockets);
2030
2031         mac_selinux_finish();
2032
2033         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
2034 }