chiark / gitweb /
bb4d41ae0715079a4c8f0a3474451c4eb468c839
[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 == -EOPNOTSUPP) {
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         return 0;
1209 }
1210
1211 static int remove_item_instance(Item *i, const char *instance) {
1212         int r;
1213
1214         assert(i);
1215
1216         switch (i->type) {
1217
1218         case REMOVE_PATH:
1219                 if (remove(instance) < 0 && errno != ENOENT)
1220                         return log_error_errno(errno, "rm(%s): %m", instance);
1221
1222                 break;
1223
1224         case TRUNCATE_DIRECTORY:
1225         case RECURSIVE_REMOVE_PATH:
1226                 /* FIXME: we probably should use dir_cleanup() here
1227                  * instead of rm_rf() so that 'x' is honoured. */
1228                 log_debug("rm -rf \"%s\"", instance);
1229                 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1230                 if (r < 0 && r != -ENOENT)
1231                         return log_error_errno(r, "rm_rf(%s): %m", instance);
1232
1233                 break;
1234
1235         default:
1236                 assert_not_reached("wut?");
1237         }
1238
1239         return 0;
1240 }
1241
1242 static int remove_item(Item *i) {
1243         int r = 0;
1244
1245         assert(i);
1246
1247         log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
1248
1249         switch (i->type) {
1250
1251         case CREATE_FILE:
1252         case TRUNCATE_FILE:
1253         case CREATE_DIRECTORY:
1254         case CREATE_SUBVOLUME:
1255         case CREATE_FIFO:
1256         case CREATE_SYMLINK:
1257         case CREATE_CHAR_DEVICE:
1258         case CREATE_BLOCK_DEVICE:
1259         case IGNORE_PATH:
1260         case IGNORE_DIRECTORY_PATH:
1261         case ADJUST_MODE:
1262         case RELABEL_PATH:
1263         case RECURSIVE_RELABEL_PATH:
1264         case WRITE_FILE:
1265         case COPY_FILES:
1266         case SET_XATTR:
1267         case RECURSIVE_SET_XATTR:
1268         case SET_ACL:
1269         case RECURSIVE_SET_ACL:
1270                 break;
1271
1272         case REMOVE_PATH:
1273         case TRUNCATE_DIRECTORY:
1274         case RECURSIVE_REMOVE_PATH:
1275                 r = glob_item(i, remove_item_instance, false);
1276                 break;
1277         }
1278
1279         return r;
1280 }
1281
1282 static int clean_item_instance(Item *i, const char* instance) {
1283         _cleanup_closedir_ DIR *d = NULL;
1284         struct stat s, ps;
1285         bool mountpoint;
1286         usec_t cutoff, n;
1287         char timestamp[FORMAT_TIMESTAMP_MAX];
1288
1289         assert(i);
1290
1291         if (!i->age_set)
1292                 return 0;
1293
1294         n = now(CLOCK_REALTIME);
1295         if (n < i->age)
1296                 return 0;
1297
1298         cutoff = n - i->age;
1299
1300         d = opendir_nomod(instance);
1301         if (!d) {
1302                 if (errno == ENOENT || errno == ENOTDIR) {
1303                         log_debug_errno(errno, "Directory \"%s\": %m", instance);
1304                         return 0;
1305                 }
1306
1307                 log_error_errno(errno, "Failed to open directory %s: %m", instance);
1308                 return -errno;
1309         }
1310
1311         if (fstat(dirfd(d), &s) < 0)
1312                 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1313
1314         if (!S_ISDIR(s.st_mode)) {
1315                 log_error("%s is not a directory.", i->path);
1316                 return -ENOTDIR;
1317         }
1318
1319         if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1320                 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1321
1322         mountpoint = s.st_dev != ps.st_dev ||
1323                      (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1324
1325         log_debug("Cleanup threshold for %s \"%s\" is %s",
1326                   mountpoint ? "mount point" : "directory",
1327                   instance,
1328                   format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
1329
1330         return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1331                            MAX_DEPTH, i->keep_first_level);
1332 }
1333
1334 static int clean_item(Item *i) {
1335         int r = 0;
1336
1337         assert(i);
1338
1339         log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
1340
1341         switch (i->type) {
1342         case CREATE_DIRECTORY:
1343         case CREATE_SUBVOLUME:
1344         case TRUNCATE_DIRECTORY:
1345         case IGNORE_PATH:
1346         case COPY_FILES:
1347                 clean_item_instance(i, i->path);
1348                 break;
1349         case IGNORE_DIRECTORY_PATH:
1350                 r = glob_item(i, clean_item_instance, false);
1351                 break;
1352         default:
1353                 break;
1354         }
1355
1356         return r;
1357 }
1358
1359 static int process_item_array(ItemArray *array);
1360
1361 static int process_item(Item *i) {
1362         int r, q, p, t = 0;
1363         _cleanup_free_ char *prefix = NULL;
1364
1365         assert(i);
1366
1367         if (i->done)
1368                 return 0;
1369
1370         i->done = true;
1371
1372         prefix = malloc(strlen(i->path) + 1);
1373         if (!prefix)
1374                 return log_oom();
1375
1376         PATH_FOREACH_PREFIX(prefix, i->path) {
1377                 ItemArray *j;
1378
1379                 j = hashmap_get(items, prefix);
1380                 if (j) {
1381                         int s;
1382
1383                         s = process_item_array(j);
1384                         if (s < 0 && t == 0)
1385                                 t = s;
1386                 }
1387         }
1388
1389         r = arg_create ? create_item(i) : 0;
1390         q = arg_remove ? remove_item(i) : 0;
1391         p = arg_clean ? clean_item(i) : 0;
1392
1393         return t < 0 ? t :
1394                 r < 0 ? r :
1395                 q < 0 ? q :
1396                 p;
1397 }
1398
1399 static int process_item_array(ItemArray *array) {
1400         unsigned n;
1401         int r = 0, k;
1402
1403         assert(array);
1404
1405         for (n = 0; n < array->count; n++) {
1406                 k = process_item(array->items + n);
1407                 if (k < 0 && r == 0)
1408                         r = k;
1409         }
1410
1411         return r;
1412 }
1413
1414 static void item_free_contents(Item *i) {
1415         assert(i);
1416         free(i->path);
1417         free(i->argument);
1418         strv_free(i->xattrs);
1419
1420 #ifdef HAVE_ACL
1421         acl_free(i->acl_access);
1422         acl_free(i->acl_default);
1423 #endif
1424 }
1425
1426 static void item_array_free(ItemArray *a) {
1427         unsigned n;
1428
1429         if (!a)
1430                 return;
1431
1432         for (n = 0; n < a->count; n++)
1433                 item_free_contents(a->items + n);
1434         free(a->items);
1435         free(a);
1436 }
1437
1438 static bool item_compatible(Item *a, Item *b) {
1439         assert(a);
1440         assert(b);
1441         assert(streq(a->path, b->path));
1442
1443         if (takes_ownership(a->type) && takes_ownership(b->type))
1444                 /* check if the items are the same */
1445                 return  streq_ptr(a->argument, b->argument) &&
1446
1447                         a->uid_set == b->uid_set &&
1448                         a->uid == b->uid &&
1449
1450                         a->gid_set == b->gid_set &&
1451                         a->gid == b->gid &&
1452
1453                         a->mode_set == b->mode_set &&
1454                         a->mode == b->mode &&
1455
1456                         a->age_set == b->age_set &&
1457                         a->age == b->age &&
1458
1459                         a->mask_perms == b->mask_perms &&
1460
1461                         a->keep_first_level == b->keep_first_level &&
1462
1463                         a->major_minor == b->major_minor;
1464
1465         return true;
1466 }
1467
1468 static bool should_include_path(const char *path) {
1469         char **prefix;
1470
1471         STRV_FOREACH(prefix, arg_exclude_prefixes)
1472                 if (path_startswith(path, *prefix)) {
1473                         log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
1474                                   path, *prefix);
1475                         return false;
1476                 }
1477
1478         STRV_FOREACH(prefix, arg_include_prefixes)
1479                 if (path_startswith(path, *prefix)) {
1480                         log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
1481                         return true;
1482                 }
1483
1484         /* no matches, so we should include this path only if we
1485          * have no whitelist at all */
1486         if (strv_length(arg_include_prefixes) == 0)
1487                 return true;
1488
1489         log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
1490         return false;
1491 }
1492
1493 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1494
1495         static const Specifier specifier_table[] = {
1496                 { 'm', specifier_machine_id, NULL },
1497                 { 'b', specifier_boot_id, NULL },
1498                 { 'H', specifier_host_name, NULL },
1499                 { 'v', specifier_kernel_release, NULL },
1500                 {}
1501         };
1502
1503         _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1504         _cleanup_(item_free_contents) Item i = {};
1505         ItemArray *existing;
1506         Hashmap *h;
1507         int r, pos;
1508         bool force = false, boot = false;
1509
1510         assert(fname);
1511         assert(line >= 1);
1512         assert(buffer);
1513
1514         r = unquote_many_words(&buffer,
1515                    &action,
1516                    &path,
1517                    &mode,
1518                    &user,
1519                    &group,
1520                    &age,
1521                    &i.argument,
1522                    NULL);
1523         if (r < 0)
1524                 return log_error_errno(r, "[%s:%u] Failed to parse line: %m", fname, line);
1525         else 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         switch (i.type) {
1563
1564         case CREATE_FILE:
1565         case TRUNCATE_FILE:
1566         case CREATE_DIRECTORY:
1567         case CREATE_SUBVOLUME:
1568         case TRUNCATE_DIRECTORY:
1569         case CREATE_FIFO:
1570         case IGNORE_PATH:
1571         case IGNORE_DIRECTORY_PATH:
1572         case REMOVE_PATH:
1573         case RECURSIVE_REMOVE_PATH:
1574         case ADJUST_MODE:
1575         case RELABEL_PATH:
1576         case RECURSIVE_RELABEL_PATH:
1577                 break;
1578
1579         case CREATE_SYMLINK:
1580                 if (!i.argument) {
1581                         i.argument = strappend("/usr/share/factory/", i.path);
1582                         if (!i.argument)
1583                                 return log_oom();
1584                 }
1585                 break;
1586
1587         case WRITE_FILE:
1588                 if (!i.argument) {
1589                         log_error("[%s:%u] Write file requires argument.", fname, line);
1590                         return -EBADMSG;
1591                 }
1592                 break;
1593
1594         case COPY_FILES:
1595                 if (!i.argument) {
1596                         i.argument = strappend("/usr/share/factory/", i.path);
1597                         if (!i.argument)
1598                                 return log_oom();
1599                 } else if (!path_is_absolute(i.argument)) {
1600                         log_error("[%s:%u] Source path is not absolute.", fname, line);
1601                         return -EBADMSG;
1602                 }
1603
1604                 path_kill_slashes(i.argument);
1605                 break;
1606
1607         case CREATE_CHAR_DEVICE:
1608         case CREATE_BLOCK_DEVICE: {
1609                 unsigned major, minor;
1610
1611                 if (!i.argument) {
1612                         log_error("[%s:%u] Device file requires argument.", fname, line);
1613                         return -EBADMSG;
1614                 }
1615
1616                 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1617                         log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1618                         return -EBADMSG;
1619                 }
1620
1621                 i.major_minor = makedev(major, minor);
1622                 break;
1623         }
1624
1625         case SET_XATTR:
1626         case RECURSIVE_SET_XATTR:
1627                 if (!i.argument) {
1628                         log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1629                         return -EBADMSG;
1630                 }
1631                 r = get_xattrs_from_arg(&i);
1632                 if (r < 0)
1633                         return r;
1634                 break;
1635
1636         case SET_ACL:
1637         case RECURSIVE_SET_ACL:
1638                 if (!i.argument) {
1639                         log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1640                         return -EBADMSG;
1641                 }
1642                 r = get_acls_from_arg(&i);
1643                 if (r < 0)
1644                         return r;
1645                 break;
1646
1647         default:
1648                 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
1649                 return -EBADMSG;
1650         }
1651
1652         if (!path_is_absolute(i.path)) {
1653                 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1654                 return -EBADMSG;
1655         }
1656
1657         path_kill_slashes(i.path);
1658
1659         if (!should_include_path(i.path))
1660                 return 0;
1661
1662         if (arg_root) {
1663                 char *p;
1664
1665                 p = strappend(arg_root, i.path);
1666                 if (!p)
1667                         return log_oom();
1668
1669                 free(i.path);
1670                 i.path = p;
1671         }
1672
1673         if (user && !streq(user, "-")) {
1674                 const char *u = user;
1675
1676                 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1677                 if (r < 0) {
1678                         log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1679                         return r;
1680                 }
1681
1682                 i.uid_set = true;
1683         }
1684
1685         if (group && !streq(group, "-")) {
1686                 const char *g = group;
1687
1688                 r = get_group_creds(&g, &i.gid);
1689                 if (r < 0) {
1690                         log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1691                         return r;
1692                 }
1693
1694                 i.gid_set = true;
1695         }
1696
1697         if (mode && !streq(mode, "-")) {
1698                 const char *mm = mode;
1699                 unsigned m;
1700
1701                 if (*mm == '~') {
1702                         i.mask_perms = true;
1703                         mm++;
1704                 }
1705
1706                 if (sscanf(mm, "%o", &m) != 1) {
1707                         log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1708                         return -ENOENT;
1709                 }
1710
1711                 i.mode = m;
1712                 i.mode_set = true;
1713         } else
1714                 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1715                         ? 0755 : 0644;
1716
1717         if (age && !streq(age, "-")) {
1718                 const char *a = age;
1719
1720                 if (*a == '~') {
1721                         i.keep_first_level = true;
1722                         a++;
1723                 }
1724
1725                 if (parse_sec(a, &i.age) < 0) {
1726                         log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1727                         return -EBADMSG;
1728                 }
1729
1730                 i.age_set = true;
1731         }
1732
1733         h = needs_glob(i.type) ? globs : items;
1734
1735         existing = hashmap_get(h, i.path);
1736         if (existing) {
1737                 unsigned n;
1738
1739                 for (n = 0; n < existing->count; n++) {
1740                         if (!item_compatible(existing->items + n, &i)) {
1741                                 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1742                                             fname, line, i.path);
1743                                 return 0;
1744                         }
1745                 }
1746         } else {
1747                 existing = new0(ItemArray, 1);
1748                 r = hashmap_put(h, i.path, existing);
1749                 if (r < 0)
1750                         return log_oom();
1751         }
1752
1753         if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1754                 return log_oom();
1755
1756         memcpy(existing->items + existing->count++, &i, sizeof(i));
1757         zero(i);
1758         return 0;
1759 }
1760
1761 static void help(void) {
1762         printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1763                "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1764                "  -h --help                 Show this help\n"
1765                "     --version              Show package version\n"
1766                "     --create               Create marked files/directories\n"
1767                "     --clean                Clean up marked directories\n"
1768                "     --remove               Remove marked files/directories\n"
1769                "     --boot                 Execute actions only safe at boot\n"
1770                "     --prefix=PATH          Only apply rules with the specified prefix\n"
1771                "     --exclude-prefix=PATH  Ignore rules with the specified prefix\n"
1772                "     --root=PATH            Operate on an alternate filesystem root\n",
1773                program_invocation_short_name);
1774 }
1775
1776 static int parse_argv(int argc, char *argv[]) {
1777
1778         enum {
1779                 ARG_VERSION = 0x100,
1780                 ARG_CREATE,
1781                 ARG_CLEAN,
1782                 ARG_REMOVE,
1783                 ARG_BOOT,
1784                 ARG_PREFIX,
1785                 ARG_EXCLUDE_PREFIX,
1786                 ARG_ROOT,
1787         };
1788
1789         static const struct option options[] = {
1790                 { "help",           no_argument,         NULL, 'h'                },
1791                 { "version",        no_argument,         NULL, ARG_VERSION        },
1792                 { "create",         no_argument,         NULL, ARG_CREATE         },
1793                 { "clean",          no_argument,         NULL, ARG_CLEAN          },
1794                 { "remove",         no_argument,         NULL, ARG_REMOVE         },
1795                 { "boot",           no_argument,         NULL, ARG_BOOT           },
1796                 { "prefix",         required_argument,   NULL, ARG_PREFIX         },
1797                 { "exclude-prefix", required_argument,   NULL, ARG_EXCLUDE_PREFIX },
1798                 { "root",           required_argument,   NULL, ARG_ROOT           },
1799                 {}
1800         };
1801
1802         int c;
1803
1804         assert(argc >= 0);
1805         assert(argv);
1806
1807         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1808
1809                 switch (c) {
1810
1811                 case 'h':
1812                         help();
1813                         return 0;
1814
1815                 case ARG_VERSION:
1816                         puts(PACKAGE_STRING);
1817                         puts(SYSTEMD_FEATURES);
1818                         return 0;
1819
1820                 case ARG_CREATE:
1821                         arg_create = true;
1822                         break;
1823
1824                 case ARG_CLEAN:
1825                         arg_clean = true;
1826                         break;
1827
1828                 case ARG_REMOVE:
1829                         arg_remove = true;
1830                         break;
1831
1832                 case ARG_BOOT:
1833                         arg_boot = true;
1834                         break;
1835
1836                 case ARG_PREFIX:
1837                         if (strv_push(&arg_include_prefixes, optarg) < 0)
1838                                 return log_oom();
1839                         break;
1840
1841                 case ARG_EXCLUDE_PREFIX:
1842                         if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1843                                 return log_oom();
1844                         break;
1845
1846                 case ARG_ROOT:
1847                         free(arg_root);
1848                         arg_root = path_make_absolute_cwd(optarg);
1849                         if (!arg_root)
1850                                 return log_oom();
1851
1852                         path_kill_slashes(arg_root);
1853                         break;
1854
1855                 case '?':
1856                         return -EINVAL;
1857
1858                 default:
1859                         assert_not_reached("Unhandled option");
1860                 }
1861
1862         if (!arg_clean && !arg_create && !arg_remove) {
1863                 log_error("You need to specify at least one of --clean, --create or --remove.");
1864                 return -EINVAL;
1865         }
1866
1867         return 1;
1868 }
1869
1870 static int read_config_file(const char *fn, bool ignore_enoent) {
1871         _cleanup_fclose_ FILE *f = NULL;
1872         char line[LINE_MAX];
1873         Iterator iterator;
1874         unsigned v = 0;
1875         Item *i;
1876         int r;
1877
1878         assert(fn);
1879
1880         r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
1881         if (r < 0) {
1882                 if (ignore_enoent && r == -ENOENT) {
1883                         log_debug_errno(r, "Failed to open \"%s\": %m", fn);
1884                         return 0;
1885                 }
1886
1887                 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
1888         }
1889         log_debug("Reading config file \"%s\".", fn);
1890
1891         FOREACH_LINE(line, f, break) {
1892                 char *l;
1893                 int k;
1894
1895                 v++;
1896
1897                 l = strstrip(line);
1898                 if (*l == '#' || *l == 0)
1899                         continue;
1900
1901                 k = parse_line(fn, v, l);
1902                 if (k < 0 && r == 0)
1903                         r = k;
1904         }
1905
1906         /* we have to determine age parameter for each entry of type X */
1907         HASHMAP_FOREACH(i, globs, iterator) {
1908                 Iterator iter;
1909                 Item *j, *candidate_item = NULL;
1910
1911                 if (i->type != IGNORE_DIRECTORY_PATH)
1912                         continue;
1913
1914                 HASHMAP_FOREACH(j, items, iter) {
1915                         if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
1916                                 continue;
1917
1918                         if (path_equal(j->path, i->path)) {
1919                                 candidate_item = j;
1920                                 break;
1921                         }
1922
1923                         if ((!candidate_item && path_startswith(i->path, j->path)) ||
1924                             (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1925                                 candidate_item = j;
1926                 }
1927
1928                 if (candidate_item && candidate_item->age_set) {
1929                         i->age = candidate_item->age;
1930                         i->age_set = true;
1931                 }
1932         }
1933
1934         if (ferror(f)) {
1935                 log_error_errno(errno, "Failed to read from file %s: %m", fn);
1936                 if (r == 0)
1937                         r = -EIO;
1938         }
1939
1940         return r;
1941 }
1942
1943 int main(int argc, char *argv[]) {
1944         int r, k;
1945         ItemArray *a;
1946         Iterator iterator;
1947
1948         r = parse_argv(argc, argv);
1949         if (r <= 0)
1950                 goto finish;
1951
1952         log_set_target(LOG_TARGET_AUTO);
1953         log_parse_environment();
1954         log_open();
1955
1956         umask(0022);
1957
1958         mac_selinux_init(NULL);
1959
1960         items = hashmap_new(&string_hash_ops);
1961         globs = hashmap_new(&string_hash_ops);
1962
1963         if (!items || !globs) {
1964                 r = log_oom();
1965                 goto finish;
1966         }
1967
1968         r = 0;
1969
1970         if (optind < argc) {
1971                 int j;
1972
1973                 for (j = optind; j < argc; j++) {
1974                         k = read_config_file(argv[j], false);
1975                         if (k < 0 && r == 0)
1976                                 r = k;
1977                 }
1978
1979         } else {
1980                 _cleanup_strv_free_ char **files = NULL;
1981                 char **f;
1982
1983                 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
1984                 if (r < 0) {
1985                         log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
1986                         goto finish;
1987                 }
1988
1989                 STRV_FOREACH(f, files) {
1990                         k = read_config_file(*f, true);
1991                         if (k < 0 && r == 0)
1992                                 r = k;
1993                 }
1994         }
1995
1996         HASHMAP_FOREACH(a, globs, iterator) {
1997                 k = process_item_array(a);
1998                 if (k < 0 && r == 0)
1999                         r = k;
2000         }
2001
2002         HASHMAP_FOREACH(a, items, iterator) {
2003                 k = process_item_array(a);
2004                 if (k < 0 && r == 0)
2005                         r = k;
2006         }
2007
2008 finish:
2009         while ((a = hashmap_steal_first(items)))
2010                 item_array_free(a);
2011
2012         while ((a = hashmap_steal_first(globs)))
2013                 item_array_free(a);
2014
2015         hashmap_free(items);
2016         hashmap_free(globs);
2017
2018         free(arg_include_prefixes);
2019         free(arg_exclude_prefixes);
2020         free(arg_root);
2021
2022         set_free_free(unix_sockets);
2023
2024         mac_selinux_finish();
2025
2026         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
2027 }