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