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