chiark / gitweb /
bff95271f526e5ab160c94f69834b4914a5c2e63
[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
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <sys/stat.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 <sys/types.h>
38 #include <sys/param.h>
39 #include <glob.h>
40 #include <fnmatch.h>
41 #include <sys/capability.h>
42
43 #include "log.h"
44 #include "util.h"
45 #include "macro.h"
46 #include "missing.h"
47 #include "mkdir.h"
48 #include "path-util.h"
49 #include "strv.h"
50 #include "label.h"
51 #include "set.h"
52 #include "conf-files.h"
53 #include "capability.h"
54 #include "specifier.h"
55 #include "build.h"
56
57 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
58  * them in the file system. This is intended to be used to create
59  * properly owned directories beneath /tmp, /var/tmp, /run, which are
60  * volatile and hence need to be recreated on bootup. */
61
62 typedef enum ItemType {
63         /* These ones take file names */
64         CREATE_FILE = 'f',
65         TRUNCATE_FILE = 'F',
66         WRITE_FILE = 'w',
67         CREATE_DIRECTORY = 'd',
68         TRUNCATE_DIRECTORY = 'D',
69         CREATE_FIFO = 'p',
70         CREATE_SYMLINK = 'L',
71         CREATE_CHAR_DEVICE = 'c',
72         CREATE_BLOCK_DEVICE = 'b',
73         ADJUST_MODE = 'm',
74
75         /* These ones take globs */
76         IGNORE_PATH = 'x',
77         IGNORE_DIRECTORY_PATH = 'X',
78         REMOVE_PATH = 'r',
79         RECURSIVE_REMOVE_PATH = 'R',
80         RELABEL_PATH = 'z',
81         RECURSIVE_RELABEL_PATH = 'Z'
82 } ItemType;
83
84 typedef struct Item {
85         ItemType type;
86
87         char *path;
88         char *argument;
89         uid_t uid;
90         gid_t gid;
91         mode_t mode;
92         usec_t age;
93
94         dev_t major_minor;
95
96         bool uid_set:1;
97         bool gid_set:1;
98         bool mode_set:1;
99         bool age_set:1;
100
101         bool keep_first_level:1;
102 } Item;
103
104 static Hashmap *items = NULL, *globs = NULL;
105 static Set *unix_sockets = NULL;
106
107 static bool arg_create = false;
108 static bool arg_clean = false;
109 static bool arg_remove = false;
110 static bool arg_boot = false;
111
112 static char **include_prefixes = NULL;
113 static char **exclude_prefixes = NULL;
114
115 static const char conf_file_dirs[] =
116         "/etc/tmpfiles.d\0"
117         "/run/tmpfiles.d\0"
118         "/usr/local/lib/tmpfiles.d\0"
119         "/usr/lib/tmpfiles.d\0"
120 #ifdef HAVE_SPLIT_USR
121         "/lib/tmpfiles.d\0"
122 #endif
123         ;
124
125 #define MAX_DEPTH 256
126
127 static bool needs_glob(ItemType t) {
128         return t == IGNORE_PATH || t == IGNORE_DIRECTORY_PATH || t == REMOVE_PATH || t == RECURSIVE_REMOVE_PATH || t == RELABEL_PATH || t == RECURSIVE_RELABEL_PATH;
129 }
130
131 static struct Item* find_glob(Hashmap *h, const char *match) {
132         Item *j;
133         Iterator i;
134
135         HASHMAP_FOREACH(j, h, i)
136                 if (fnmatch(j->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
137                         return j;
138
139         return NULL;
140 }
141
142 static void load_unix_sockets(void) {
143         _cleanup_fclose_ FILE *f = NULL;
144         char line[LINE_MAX];
145
146         if (unix_sockets)
147                 return;
148
149         /* We maintain a cache of the sockets we found in
150          * /proc/net/unix to speed things up a little. */
151
152         unix_sockets = set_new(string_hash_func, string_compare_func);
153         if (!unix_sockets)
154                 return;
155
156         f = fopen("/proc/net/unix", "re");
157         if (!f)
158                 return;
159
160         /* Skip header */
161         if (!fgets(line, sizeof(line), f))
162                 goto fail;
163
164         for (;;) {
165                 char *p, *s;
166                 int k;
167
168                 if (!fgets(line, sizeof(line), f))
169                         break;
170
171                 truncate_nl(line);
172
173                 p = strchr(line, ':');
174                 if (!p)
175                         continue;
176
177                 if (strlen(p) < 37)
178                         continue;
179
180                 p += 37;
181                 p += strspn(p, WHITESPACE);
182                 p += strcspn(p, WHITESPACE); /* skip one more word */
183                 p += strspn(p, WHITESPACE);
184
185                 if (*p != '/')
186                         continue;
187
188                 s = strdup(p);
189                 if (!s)
190                         goto fail;
191
192                 path_kill_slashes(s);
193
194                 k = set_consume(unix_sockets, s);
195                 if (k < 0 && k != -EEXIST)
196                         goto fail;
197         }
198
199         return;
200
201 fail:
202         set_free_free(unix_sockets);
203         unix_sockets = NULL;
204 }
205
206 static bool unix_socket_alive(const char *fn) {
207         assert(fn);
208
209         load_unix_sockets();
210
211         if (unix_sockets)
212                 return !!set_get(unix_sockets, (char*) fn);
213
214         /* We don't know, so assume yes */
215         return true;
216 }
217
218 static int dir_is_mount_point(DIR *d, const char *subdir) {
219         struct file_handle *h;
220         int mount_id_parent, mount_id;
221         int r_p, r;
222
223         h = alloca(MAX_HANDLE_SZ);
224
225         h->handle_bytes = MAX_HANDLE_SZ;
226         r_p = name_to_handle_at(dirfd(d), ".", h, &mount_id_parent, 0);
227         if (r_p < 0)
228                 r_p = -errno;
229
230         h->handle_bytes = MAX_HANDLE_SZ;
231         r = name_to_handle_at(dirfd(d), subdir, h, &mount_id, 0);
232         if (r < 0)
233                 r = -errno;
234
235         /* got no handle; make no assumptions, return error */
236         if (r_p < 0 && r < 0)
237                 return r_p;
238
239         /* got both handles; if they differ, it is a mount point */
240         if (r_p >= 0 && r >= 0)
241                 return mount_id_parent != mount_id;
242
243         /* got only one handle; assume different mount points if one
244          * of both queries was not supported by the filesystem */
245         if (r_p == -ENOSYS || r_p == -ENOTSUP || r == -ENOSYS || r == -ENOTSUP)
246                 return true;
247
248         /* return error */
249         if (r_p < 0)
250                 return r_p;
251         return r;
252 }
253
254 static int dir_cleanup(
255                 Item *i,
256                 const char *p,
257                 DIR *d,
258                 const struct stat *ds,
259                 usec_t cutoff,
260                 dev_t rootdev,
261                 bool mountpoint,
262                 int maxdepth,
263                 bool keep_this_level) {
264
265         struct dirent *dent;
266         struct timespec times[2];
267         bool deleted = false;
268         int r = 0;
269
270         while ((dent = readdir(d))) {
271                 struct stat s;
272                 usec_t age;
273                 _cleanup_free_ char *sub_path = NULL;
274
275                 if (streq(dent->d_name, ".") ||
276                     streq(dent->d_name, ".."))
277                         continue;
278
279                 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
280                         if (errno == ENOENT)
281                                 continue;
282
283                         /* FUSE, NFS mounts, SELinux might return EACCES */
284                         if (errno == EACCES)
285                                 log_debug("stat(%s/%s) failed: %m", p, dent->d_name);
286                         else
287                                 log_error("stat(%s/%s) failed: %m", p, dent->d_name);
288                         r = -errno;
289                         continue;
290                 }
291
292                 /* Stay on the same filesystem */
293                 if (s.st_dev != rootdev)
294                         continue;
295
296                 /* Try to detect bind mounts of the same filesystem instance; they
297                  * do not differ in device major/minors. This type of query is not
298                  * supported on all kernels or filesystem types though. */
299                 if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0)
300                         continue;
301
302                 /* Do not delete read-only files owned by root */
303                 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR))
304                         continue;
305
306                 if (asprintf(&sub_path, "%s/%s", p, dent->d_name) < 0) {
307                         r = log_oom();
308                         goto finish;
309                 }
310
311                 /* Is there an item configured for this path? */
312                 if (hashmap_get(items, sub_path))
313                         continue;
314
315                 if (find_glob(globs, sub_path))
316                         continue;
317
318                 if (S_ISDIR(s.st_mode)) {
319
320                         if (mountpoint &&
321                             streq(dent->d_name, "lost+found") &&
322                             s.st_uid == 0)
323                                 continue;
324
325                         if (maxdepth <= 0)
326                                 log_warning("Reached max depth on %s.", sub_path);
327                         else {
328                                 _cleanup_closedir_ DIR *sub_dir;
329                                 int q;
330
331                                 sub_dir = xopendirat(dirfd(d), dent->d_name, O_NOFOLLOW|O_NOATIME);
332                                 if (sub_dir == NULL) {
333                                         if (errno != ENOENT) {
334                                                 log_error("opendir(%s/%s) failed: %m", p, dent->d_name);
335                                                 r = -errno;
336                                         }
337
338                                         continue;
339                                 }
340
341                                 q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
342
343                                 if (q < 0)
344                                         r = q;
345                         }
346
347                         /* Note: if you are wondering why we don't
348                          * support the sticky bit for excluding
349                          * directories from cleaning like we do it for
350                          * other file system objects: well, the sticky
351                          * bit already has a meaning for directories,
352                          * so we don't want to overload that. */
353
354                         if (keep_this_level)
355                                 continue;
356
357                         /* Ignore ctime, we change it when deleting */
358                         age = MAX(timespec_load(&s.st_mtim),
359                                   timespec_load(&s.st_atim));
360                         if (age >= cutoff)
361                                 continue;
362
363                         if (i->type != IGNORE_DIRECTORY_PATH || !streq(dent->d_name, p)) {
364                                 log_debug("rmdir '%s'", sub_path);
365
366                                 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
367                                         if (errno != ENOENT && errno != ENOTEMPTY) {
368                                                 log_error("rmdir(%s): %m", sub_path);
369                                                 r = -errno;
370                                         }
371                                 }
372                         }
373
374                 } else {
375                         /* Skip files for which the sticky bit is
376                          * set. These are semantics we define, and are
377                          * unknown elsewhere. See XDG_RUNTIME_DIR
378                          * specification for details. */
379                         if (s.st_mode & S_ISVTX)
380                                 continue;
381
382                         if (mountpoint && S_ISREG(s.st_mode)) {
383                                 if (streq(dent->d_name, ".journal") &&
384                                     s.st_uid == 0)
385                                         continue;
386
387                                 if (streq(dent->d_name, "aquota.user") ||
388                                     streq(dent->d_name, "aquota.group"))
389                                         continue;
390                         }
391
392                         /* Ignore sockets that are listed in /proc/net/unix */
393                         if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path))
394                                 continue;
395
396                         /* Ignore device nodes */
397                         if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode))
398                                 continue;
399
400                         /* Keep files on this level around if this is
401                          * requested */
402                         if (keep_this_level)
403                                 continue;
404
405                         age = MAX3(timespec_load(&s.st_mtim),
406                                    timespec_load(&s.st_atim),
407                                    timespec_load(&s.st_ctim));
408
409                         if (age >= cutoff)
410                                 continue;
411
412                         log_debug("unlink '%s'", sub_path);
413
414                         if (unlinkat(dirfd(d), dent->d_name, 0) < 0) {
415                                 if (errno != ENOENT) {
416                                         log_error("unlink(%s): %m", sub_path);
417                                         r = -errno;
418                                 }
419                         }
420
421                         deleted = true;
422                 }
423         }
424
425 finish:
426         if (deleted) {
427                 /* Restore original directory timestamps */
428                 times[0] = ds->st_atim;
429                 times[1] = ds->st_mtim;
430
431                 if (futimens(dirfd(d), times) < 0)
432                         log_error("utimensat(%s): %m", p);
433         }
434
435         return r;
436 }
437
438 static int item_set_perms_full(Item *i, const char *path, bool ignore_enoent) {
439         /* not using i->path directly because it may be a glob */
440         if (i->mode_set)
441                 if (chmod(path, i->mode) < 0) {
442                         if (errno != ENOENT || !ignore_enoent) {
443                                 log_error("chmod(%s) failed: %m", path);
444                                 return -errno;
445                         }
446                 }
447
448         if (i->uid_set || i->gid_set)
449                 if (chown(path,
450                           i->uid_set ? i->uid : (uid_t) -1,
451                           i->gid_set ? i->gid : (gid_t) -1) < 0) {
452
453                         if (errno != ENOENT || !ignore_enoent) {
454                                 log_error("chown(%s) failed: %m", path);
455                                 return -errno;
456                         }
457                 }
458
459         return label_fix(path, ignore_enoent, false);
460 }
461
462 static int item_set_perms(Item *i, const char *path) {
463         return item_set_perms_full(i, path, false);
464 }
465
466 static int write_one_file(Item *i, const char *path) {
467         int e, flags;
468         int fd = -1;
469         struct stat st;
470         int r = 0;
471
472         flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND :
473                 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC : 0;
474
475         RUN_WITH_UMASK(0) {
476                 label_context_set(path, S_IFREG);
477                 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY|O_NOFOLLOW, i->mode);
478                 e = errno;
479                 label_context_clear();
480                 errno = e;
481         }
482
483         if (fd < 0) {
484                 if (i->type == WRITE_FILE && errno == ENOENT)
485                         return 0;
486
487                 log_error("Failed to create file %s: %m", path);
488                 return -errno;
489         }
490
491         if (i->argument) {
492                 ssize_t n;
493                 size_t l;
494                 _cleanup_free_ char *unescaped;
495
496                 unescaped = cunescape(i->argument);
497                 if (unescaped == NULL) {
498                         close_nointr_nofail(fd);
499                         return log_oom();
500                 }
501
502                 l = strlen(unescaped);
503                 n = write(fd, unescaped, l);
504
505                 if (n < 0 || (size_t) n < l) {
506                         log_error("Failed to write file %s: %s", path, n < 0 ? strerror(-n) : "Short write");
507                         close_nointr_nofail(fd);
508                         return n < 0 ? n : -EIO;
509                 }
510         }
511
512         close_nointr_nofail(fd);
513
514         if (stat(path, &st) < 0) {
515                 log_error("stat(%s) failed: %m", path);
516                 return -errno;
517         }
518
519         if (!S_ISREG(st.st_mode)) {
520                 log_error("%s is not a file.", path);
521                 return -EEXIST;
522         }
523
524         r = item_set_perms(i, path);
525         if (r < 0)
526                 return r;
527
528         return 0;
529 }
530
531 static int recursive_relabel_children(Item *i, const char *path) {
532         _cleanup_closedir_ DIR *d;
533         int ret = 0;
534
535         /* This returns the first error we run into, but nevertheless
536          * tries to go on */
537
538         d = opendir(path);
539         if (!d)
540                 return errno == ENOENT ? 0 : -errno;
541
542         for (;;) {
543                 struct dirent *de;
544                 bool is_dir;
545                 int r;
546                 _cleanup_free_ char *entry_path = NULL;
547
548                 errno = 0;
549                 de = readdir(d);
550                 if (!de && errno != 0) {
551                         if (ret == 0)
552                                 ret = -errno;
553                         break;
554                 }
555
556                 if (!de)
557                         break;
558
559                 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
560                         continue;
561
562                 if (asprintf(&entry_path, "%s/%s", path, de->d_name) < 0) {
563                         if (ret == 0)
564                                 ret = -ENOMEM;
565                         continue;
566                 }
567
568                 if (de->d_type == DT_UNKNOWN) {
569                         struct stat st;
570
571                         if (lstat(entry_path, &st) < 0) {
572                                 if (ret == 0 && errno != ENOENT)
573                                         ret = -errno;
574                                 continue;
575                         }
576
577                         is_dir = S_ISDIR(st.st_mode);
578
579                 } else
580                         is_dir = de->d_type == DT_DIR;
581
582                 r = item_set_perms(i, entry_path);
583                 if (r < 0) {
584                         if (ret == 0 && r != -ENOENT)
585                                 ret = r;
586                         continue;
587                 }
588
589                 if (is_dir) {
590                         r = recursive_relabel_children(i, entry_path);
591                         if (r < 0 && ret == 0)
592                                 ret = r;
593                 }
594         }
595
596         return ret;
597 }
598
599 static int recursive_relabel(Item *i, const char *path) {
600         int r;
601         struct stat st;
602
603         r = item_set_perms(i, path);
604         if (r < 0)
605                 return r;
606
607         if (lstat(path, &st) < 0)
608                 return -errno;
609
610         if (S_ISDIR(st.st_mode))
611                 r = recursive_relabel_children(i, path);
612
613         return r;
614 }
615
616 static int glob_item(Item *i, int (*action)(Item *, const char *)) {
617         int r = 0, k;
618         _cleanup_globfree_ glob_t g = {};
619         char **fn;
620
621         errno = 0;
622         k = glob(i->path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
623         if (k != 0)
624                 if (k != GLOB_NOMATCH) {
625                         if (errno > 0)
626                                 errno = EIO;
627
628                         log_error("glob(%s) failed: %m", i->path);
629                         return -errno;
630                 }
631
632         STRV_FOREACH(fn, g.gl_pathv) {
633                 k = action(i, *fn);
634                 if (k < 0)
635                         r = k;
636         }
637
638         return r;
639 }
640
641 static int create_item(Item *i) {
642         int e;
643         struct stat st;
644         int r = 0;
645
646         assert(i);
647
648         switch (i->type) {
649
650         case IGNORE_PATH:
651         case IGNORE_DIRECTORY_PATH:
652         case REMOVE_PATH:
653         case RECURSIVE_REMOVE_PATH:
654                 return 0;
655
656         case CREATE_FILE:
657         case TRUNCATE_FILE:
658                 r = write_one_file(i, i->path);
659                 if (r < 0)
660                         return r;
661                 break;
662
663         case WRITE_FILE:
664                 r = glob_item(i, write_one_file);
665                 if (r < 0)
666                         return r;
667
668                 break;
669
670         case ADJUST_MODE:
671                 r = item_set_perms_full(i, i->path, true);
672                 if (r < 0)
673                         return r;
674
675                 break;
676
677         case TRUNCATE_DIRECTORY:
678         case CREATE_DIRECTORY:
679
680                 RUN_WITH_UMASK(0000) {
681                         mkdir_parents_label(i->path, 0755);
682                         r = mkdir(i->path, i->mode);
683                 }
684
685                 if (r < 0 && errno != EEXIST) {
686                         log_error("Failed to create directory %s: %m", i->path);
687                         return -errno;
688                 }
689
690                 if (stat(i->path, &st) < 0) {
691                         log_error("stat(%s) failed: %m", i->path);
692                         return -errno;
693                 }
694
695                 if (!S_ISDIR(st.st_mode)) {
696                         log_error("%s is not a directory.", i->path);
697                         return -EEXIST;
698                 }
699
700                 r = item_set_perms(i, i->path);
701                 if (r < 0)
702                         return r;
703
704                 break;
705
706         case CREATE_FIFO:
707
708                 RUN_WITH_UMASK(0000) {
709                         r = mkfifo(i->path, i->mode);
710                 }
711
712                 if (r < 0 && errno != EEXIST) {
713                         log_error("Failed to create fifo %s: %m", i->path);
714                         return -errno;
715                 }
716
717                 if (stat(i->path, &st) < 0) {
718                         log_error("stat(%s) failed: %m", i->path);
719                         return -errno;
720                 }
721
722                 if (!S_ISFIFO(st.st_mode)) {
723                         log_error("%s is not a fifo.", i->path);
724                         return -EEXIST;
725                 }
726
727                 r = item_set_perms(i, i->path);
728                 if (r < 0)
729                         return r;
730
731                 break;
732
733         case CREATE_SYMLINK: {
734                 char *x;
735
736                 label_context_set(i->path, S_IFLNK);
737                 r = symlink(i->argument, i->path);
738                 e = errno;
739                 label_context_clear();
740                 errno = e;
741
742                 if (r < 0 && errno != EEXIST) {
743                         log_error("symlink(%s, %s) failed: %m", i->argument, i->path);
744                         return -errno;
745                 }
746
747                 r = readlink_malloc(i->path, &x);
748                 if (r < 0) {
749                         log_error("readlink(%s) failed: %s", i->path, strerror(-r));
750                         return -errno;
751                 }
752
753                 if (!streq(i->argument, x)) {
754                         free(x);
755                         log_error("%s is not the right symlinks.", i->path);
756                         return -EEXIST;
757                 }
758
759                 free(x);
760                 break;
761         }
762
763         case CREATE_BLOCK_DEVICE:
764         case CREATE_CHAR_DEVICE: {
765                 mode_t file_type;
766
767                 if (have_effective_cap(CAP_MKNOD) == 0) {
768                         /* In a container we lack CAP_MKNOD. We
769                         shouldn't attempt to create the device node in
770                         that case to avoid noise, and we don't support
771                         virtualized devices in containers anyway. */
772
773                         log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
774                         return 0;
775                 }
776
777                 file_type = (i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR);
778
779                 RUN_WITH_UMASK(0000) {
780                         label_context_set(i->path, file_type);
781                         r = mknod(i->path, i->mode | file_type, i->major_minor);
782                         e = errno;
783                         label_context_clear();
784                         errno = e;
785                 }
786
787                 if (r < 0 && errno != EEXIST) {
788                         log_error("Failed to create device node %s: %m", i->path);
789                         return -errno;
790                 }
791
792                 if (stat(i->path, &st) < 0) {
793                         log_error("stat(%s) failed: %m", i->path);
794                         return -errno;
795                 }
796
797                 if ((st.st_mode & S_IFMT) != file_type) {
798                         log_error("%s is not a device node.", i->path);
799                         return -EEXIST;
800                 }
801
802                 r = item_set_perms(i, i->path);
803                 if (r < 0)
804                         return r;
805
806                 break;
807         }
808
809         case RELABEL_PATH:
810
811                 r = glob_item(i, item_set_perms);
812                 if (r < 0)
813                         return r;
814                 break;
815
816         case RECURSIVE_RELABEL_PATH:
817
818                 r = glob_item(i, recursive_relabel);
819                 if (r < 0)
820                         return r;
821         }
822
823         log_debug("%s created successfully.", i->path);
824
825         return 0;
826 }
827
828 static int remove_item_instance(Item *i, const char *instance) {
829         int r;
830
831         assert(i);
832
833         switch (i->type) {
834
835         case CREATE_FILE:
836         case TRUNCATE_FILE:
837         case CREATE_DIRECTORY:
838         case CREATE_FIFO:
839         case CREATE_SYMLINK:
840         case CREATE_BLOCK_DEVICE:
841         case CREATE_CHAR_DEVICE:
842         case IGNORE_PATH:
843         case IGNORE_DIRECTORY_PATH:
844         case RELABEL_PATH:
845         case RECURSIVE_RELABEL_PATH:
846         case WRITE_FILE:
847         case ADJUST_MODE:
848                 break;
849
850         case REMOVE_PATH:
851                 if (remove(instance) < 0 && errno != ENOENT) {
852                         log_error("remove(%s): %m", instance);
853                         return -errno;
854                 }
855
856                 break;
857
858         case TRUNCATE_DIRECTORY:
859         case RECURSIVE_REMOVE_PATH:
860                 /* FIXME: we probably should use dir_cleanup() here
861                  * instead of rm_rf() so that 'x' is honoured. */
862                 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
863                 if (r < 0 && r != -ENOENT) {
864                         log_error("rm_rf(%s): %s", instance, strerror(-r));
865                         return r;
866                 }
867
868                 break;
869         }
870
871         return 0;
872 }
873
874 static int remove_item(Item *i) {
875         int r = 0;
876
877         assert(i);
878
879         switch (i->type) {
880
881         case CREATE_FILE:
882         case TRUNCATE_FILE:
883         case CREATE_DIRECTORY:
884         case CREATE_FIFO:
885         case CREATE_SYMLINK:
886         case CREATE_CHAR_DEVICE:
887         case CREATE_BLOCK_DEVICE:
888         case IGNORE_PATH:
889         case IGNORE_DIRECTORY_PATH:
890         case RELABEL_PATH:
891         case RECURSIVE_RELABEL_PATH:
892         case WRITE_FILE:
893         case ADJUST_MODE:
894                 break;
895
896         case REMOVE_PATH:
897         case TRUNCATE_DIRECTORY:
898         case RECURSIVE_REMOVE_PATH:
899                 r = glob_item(i, remove_item_instance);
900                 break;
901         }
902
903         return r;
904 }
905
906 static int clean_item_instance(Item *i, const char* instance) {
907         _cleanup_closedir_ DIR *d = NULL;
908         struct stat s, ps;
909         bool mountpoint;
910         int r;
911         usec_t cutoff, n;
912
913         assert(i);
914
915         if (!i->age_set)
916                 return 0;
917
918         n = now(CLOCK_REALTIME);
919         if (n < i->age)
920                 return 0;
921
922         cutoff = n - i->age;
923
924         d = opendir(instance);
925         if (!d) {
926                 if (errno == ENOENT || errno == ENOTDIR)
927                         return 0;
928
929                 log_error("Failed to open directory %s: %m", i->path);
930                 return -errno;
931         }
932
933         if (fstat(dirfd(d), &s) < 0) {
934                 log_error("stat(%s) failed: %m", i->path);
935                 return -errno;
936         }
937
938         if (!S_ISDIR(s.st_mode)) {
939                 log_error("%s is not a directory.", i->path);
940                 return -ENOTDIR;
941         }
942
943         if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0) {
944                 log_error("stat(%s/..) failed: %m", i->path);
945                 return -errno;
946         }
947
948         mountpoint = s.st_dev != ps.st_dev ||
949                      (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
950
951         r = dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
952                         MAX_DEPTH, i->keep_first_level);
953         return r;
954 }
955
956 static int clean_item(Item *i) {
957         int r = 0;
958
959         assert(i);
960
961         switch (i->type) {
962         case CREATE_DIRECTORY:
963         case TRUNCATE_DIRECTORY:
964         case IGNORE_PATH:
965                 clean_item_instance(i, i->path);
966                 break;
967         case IGNORE_DIRECTORY_PATH:
968                 r = glob_item(i, clean_item_instance);
969                 break;
970         default:
971                 break;
972         }
973
974         return r;
975 }
976
977 static int process_item(Item *i) {
978         int r, q, p;
979
980         assert(i);
981
982         r = arg_create ? create_item(i) : 0;
983         q = arg_remove ? remove_item(i) : 0;
984         p = arg_clean ? clean_item(i) : 0;
985
986         if (r < 0)
987                 return r;
988
989         if (q < 0)
990                 return q;
991
992         return p;
993 }
994
995 static void item_free(Item *i) {
996         assert(i);
997
998         free(i->path);
999         free(i->argument);
1000         free(i);
1001 }
1002
1003 DEFINE_TRIVIAL_CLEANUP_FUNC(Item*, item_free);
1004 #define _cleanup_item_free_ _cleanup_(item_freep)
1005
1006 static bool item_equal(Item *a, Item *b) {
1007         assert(a);
1008         assert(b);
1009
1010         if (!streq_ptr(a->path, b->path))
1011                 return false;
1012
1013         if (a->type != b->type)
1014                 return false;
1015
1016         if (a->uid_set != b->uid_set ||
1017             (a->uid_set && a->uid != b->uid))
1018             return false;
1019
1020         if (a->gid_set != b->gid_set ||
1021             (a->gid_set && a->gid != b->gid))
1022             return false;
1023
1024         if (a->mode_set != b->mode_set ||
1025             (a->mode_set && a->mode != b->mode))
1026             return false;
1027
1028         if (a->age_set != b->age_set ||
1029             (a->age_set && a->age != b->age))
1030             return false;
1031
1032         if ((a->type == CREATE_FILE ||
1033              a->type == TRUNCATE_FILE ||
1034              a->type == WRITE_FILE ||
1035              a->type == CREATE_SYMLINK) &&
1036             !streq_ptr(a->argument, b->argument))
1037                 return false;
1038
1039         if ((a->type == CREATE_CHAR_DEVICE ||
1040              a->type == CREATE_BLOCK_DEVICE) &&
1041             a->major_minor != b->major_minor)
1042                 return false;
1043
1044         return true;
1045 }
1046
1047 static bool should_include_path(const char *path) {
1048         char **prefix;
1049
1050         STRV_FOREACH(prefix, exclude_prefixes) {
1051                 if (path_startswith(path, *prefix))
1052                         return false;
1053         }
1054
1055         STRV_FOREACH(prefix, include_prefixes) {
1056                 if (path_startswith(path, *prefix))
1057                         return true;
1058         }
1059
1060         /* no matches, so we should include this path only if we
1061          * have no whitelist at all */
1062         return strv_length(include_prefixes) == 0;
1063 }
1064
1065 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1066
1067         static const Specifier specifier_table[] = {
1068                 { 'm', specifier_machine_id, NULL },
1069                 { 'b', specifier_boot_id, NULL },
1070                 { 'H', specifier_host_name, NULL },
1071                 { 'v', specifier_kernel_release, NULL },
1072                 {}
1073         };
1074
1075         _cleanup_item_free_ Item *i = NULL;
1076         Item *existing;
1077         _cleanup_free_ char
1078                 *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1079         char type;
1080         Hashmap *h;
1081         int r, n = -1;
1082
1083         assert(fname);
1084         assert(line >= 1);
1085         assert(buffer);
1086
1087         r = sscanf(buffer,
1088                    "%ms %ms %ms %ms %ms %ms %n",
1089                    &action,
1090                    &path,
1091                    &mode,
1092                    &user,
1093                    &group,
1094                    &age,
1095                    &n);
1096         if (r < 2) {
1097                 log_error("[%s:%u] Syntax error.", fname, line);
1098                 return -EIO;
1099         }
1100
1101         if (strlen(action) > 2 || (strlen(action) > 1 && action[1] != '!')) {
1102                 log_error("[%s:%u] Unknown modifier '%s'", fname, line, action);
1103                 return -EINVAL;
1104         } else if (strlen(action) > 1 && !arg_boot)
1105                 return 0;
1106
1107         type = action[0];
1108
1109         i = new0(Item, 1);
1110         if (!i)
1111                 return log_oom();
1112
1113         r = specifier_printf(path, specifier_table, NULL, &i->path);
1114         if (r < 0) {
1115                 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1116                 return r;
1117         }
1118
1119         if (n >= 0)  {
1120                 n += strspn(buffer+n, WHITESPACE);
1121                 if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) {
1122                         i->argument = unquote(buffer+n, "\"");
1123                         if (!i->argument)
1124                                 return log_oom();
1125                 }
1126         }
1127
1128         switch(type) {
1129
1130         case CREATE_FILE:
1131         case TRUNCATE_FILE:
1132         case CREATE_DIRECTORY:
1133         case TRUNCATE_DIRECTORY:
1134         case CREATE_FIFO:
1135         case IGNORE_PATH:
1136         case IGNORE_DIRECTORY_PATH:
1137         case REMOVE_PATH:
1138         case RECURSIVE_REMOVE_PATH:
1139         case RELABEL_PATH:
1140         case RECURSIVE_RELABEL_PATH:
1141         case ADJUST_MODE:
1142                 break;
1143
1144         case CREATE_SYMLINK:
1145                 if (!i->argument) {
1146                         log_error("[%s:%u] Symlink file requires argument.", fname, line);
1147                         return -EBADMSG;
1148                 }
1149                 break;
1150
1151         case WRITE_FILE:
1152                 if (!i->argument) {
1153                         log_error("[%s:%u] Write file requires argument.", fname, line);
1154                         return -EBADMSG;
1155                 }
1156                 break;
1157
1158         case CREATE_CHAR_DEVICE:
1159         case CREATE_BLOCK_DEVICE: {
1160                 unsigned major, minor;
1161
1162                 if (!i->argument) {
1163                         log_error("[%s:%u] Device file requires argument.", fname, line);
1164                         return -EBADMSG;
1165                 }
1166
1167                 if (sscanf(i->argument, "%u:%u", &major, &minor) != 2) {
1168                         log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i->argument);
1169                         return -EBADMSG;
1170                 }
1171
1172                 i->major_minor = makedev(major, minor);
1173                 break;
1174         }
1175
1176         default:
1177                 log_error("[%s:%u] Unknown file type '%c'.", fname, line, type);
1178                 return -EBADMSG;
1179         }
1180
1181         i->type = type;
1182
1183         if (!path_is_absolute(i->path)) {
1184                 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i->path);
1185                 return -EBADMSG;
1186         }
1187
1188         path_kill_slashes(i->path);
1189
1190         if (!should_include_path(i->path))
1191                 return 0;
1192
1193         if (user && !streq(user, "-")) {
1194                 const char *u = user;
1195
1196                 r = get_user_creds(&u, &i->uid, NULL, NULL, NULL);
1197                 if (r < 0) {
1198                         log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1199                         return r;
1200                 }
1201
1202                 i->uid_set = true;
1203         }
1204
1205         if (group && !streq(group, "-")) {
1206                 const char *g = group;
1207
1208                 r = get_group_creds(&g, &i->gid);
1209                 if (r < 0) {
1210                         log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1211                         return r;
1212                 }
1213
1214                 i->gid_set = true;
1215         }
1216
1217         if (mode && !streq(mode, "-")) {
1218                 unsigned m;
1219
1220                 if (sscanf(mode, "%o", &m) != 1) {
1221                         log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1222                         return -ENOENT;
1223                 }
1224
1225                 i->mode = m;
1226                 i->mode_set = true;
1227         } else
1228                 i->mode =
1229                         i->type == CREATE_DIRECTORY ||
1230                         i->type == TRUNCATE_DIRECTORY ? 0755 : 0644;
1231
1232         if (age && !streq(age, "-")) {
1233                 const char *a = age;
1234
1235                 if (*a == '~') {
1236                         i->keep_first_level = true;
1237                         a++;
1238                 }
1239
1240                 if (parse_sec(a, &i->age) < 0) {
1241                         log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1242                         return -EBADMSG;
1243                 }
1244
1245                 i->age_set = true;
1246         }
1247
1248         h = needs_glob(i->type) ? globs : items;
1249
1250         existing = hashmap_get(h, i->path);
1251         if (existing) {
1252
1253                 /* Two identical items are fine */
1254                 if (!item_equal(existing, i))
1255                         log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path);
1256
1257                 return 0;
1258         }
1259
1260         r = hashmap_put(h, i->path, i);
1261         if (r < 0) {
1262                 log_error("Failed to insert item %s: %s", i->path, strerror(-r));
1263                 return r;
1264         }
1265
1266         i = NULL; /* avoid cleanup */
1267
1268         return 0;
1269 }
1270
1271 static int help(void) {
1272
1273         printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1274                "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1275                "  -h --help                 Show this help\n"
1276                "     --version              Show package version\n"
1277                "     --create               Create marked files/directories\n"
1278                "     --clean                Clean up marked directories\n"
1279                "     --remove               Remove marked files/directories\n"
1280                "     --boot                 Execute actions only safe at boot\n"
1281                "     --prefix=PATH          Only apply rules that apply to paths with the specified prefix\n"
1282                "     --exclude-prefix=PATH  Ignore rules that apply to paths with the specified prefix\n",
1283                program_invocation_short_name);
1284
1285         return 0;
1286 }
1287
1288 static int parse_argv(int argc, char *argv[]) {
1289
1290         enum {
1291                 ARG_VERSION = 0x100,
1292                 ARG_CREATE,
1293                 ARG_CLEAN,
1294                 ARG_REMOVE,
1295                 ARG_BOOT,
1296                 ARG_PREFIX,
1297                 ARG_EXCLUDE_PREFIX,
1298         };
1299
1300         static const struct option options[] = {
1301                 { "help",           no_argument,         NULL, 'h'                },
1302                 { "version",        no_argument,         NULL, ARG_VERSION        },
1303                 { "create",         no_argument,         NULL, ARG_CREATE         },
1304                 { "clean",          no_argument,         NULL, ARG_CLEAN          },
1305                 { "remove",         no_argument,         NULL, ARG_REMOVE         },
1306                 { "boot",           no_argument,         NULL, ARG_BOOT           },
1307                 { "prefix",         required_argument,   NULL, ARG_PREFIX         },
1308                 { "exclude-prefix", required_argument,   NULL, ARG_EXCLUDE_PREFIX },
1309                 {}
1310         };
1311
1312         int c;
1313
1314         assert(argc >= 0);
1315         assert(argv);
1316
1317         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
1318
1319                 switch (c) {
1320
1321                 case 'h':
1322                         return help();
1323
1324                 case ARG_VERSION:
1325                         puts(PACKAGE_STRING);
1326                         puts(SYSTEMD_FEATURES);
1327                         return 0;
1328
1329                 case ARG_CREATE:
1330                         arg_create = true;
1331                         break;
1332
1333                 case ARG_CLEAN:
1334                         arg_clean = true;
1335                         break;
1336
1337                 case ARG_REMOVE:
1338                         arg_remove = true;
1339                         break;
1340
1341                 case ARG_BOOT:
1342                         arg_boot = true;
1343                         break;
1344
1345                 case ARG_PREFIX:
1346                         if (strv_extend(&include_prefixes, optarg) < 0)
1347                                 return log_oom();
1348                         break;
1349
1350                 case ARG_EXCLUDE_PREFIX:
1351                         if (strv_extend(&exclude_prefixes, optarg) < 0)
1352                                 return log_oom();
1353                         break;
1354
1355                 case '?':
1356                         return -EINVAL;
1357
1358                 default:
1359                         assert_not_reached("Unhandled option");
1360                 }
1361         }
1362
1363         if (!arg_clean && !arg_create && !arg_remove) {
1364                 log_error("You need to specify at least one of --clean, --create or --remove.");
1365                 return -EINVAL;
1366         }
1367
1368         return 1;
1369 }
1370
1371 static int read_config_file(const char *fn, bool ignore_enoent) {
1372         _cleanup_fclose_ FILE *f = NULL;
1373         char line[LINE_MAX];
1374         Iterator iterator;
1375         unsigned v = 0;
1376         Item *i;
1377         int r;
1378
1379         assert(fn);
1380
1381         r = search_and_fopen_nulstr(fn, "re", conf_file_dirs, &f);
1382         if (r < 0) {
1383                 if (ignore_enoent && r == -ENOENT)
1384                         return 0;
1385
1386                 log_error("Failed to open '%s', ignoring: %s", fn, strerror(-r));
1387                 return r;
1388         }
1389
1390         FOREACH_LINE(line, f, break) {
1391                 char *l;
1392                 int k;
1393
1394                 v++;
1395
1396                 l = strstrip(line);
1397                 if (*l == '#' || *l == 0)
1398                         continue;
1399
1400                 k = parse_line(fn, v, l);
1401                 if (k < 0 && r == 0)
1402                         r = k;
1403         }
1404
1405         /* we have to determine age parameter for each entry of type X */
1406         HASHMAP_FOREACH(i, globs, iterator) {
1407                 Iterator iter;
1408                 Item *j, *candidate_item = NULL;
1409
1410                 if (i->type != IGNORE_DIRECTORY_PATH)
1411                         continue;
1412
1413                 HASHMAP_FOREACH(j, items, iter) {
1414                         if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY)
1415                                 continue;
1416
1417                         if (path_equal(j->path, i->path)) {
1418                                 candidate_item = j;
1419                                 break;
1420                         }
1421
1422                         if ((!candidate_item && path_startswith(i->path, j->path)) ||
1423                             (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1424                                 candidate_item = j;
1425                 }
1426
1427                 if (candidate_item) {
1428                         i->age = candidate_item->age;
1429                         i->age_set = true;
1430                 }
1431         }
1432
1433         if (ferror(f)) {
1434                 log_error("Failed to read from file %s: %m", fn);
1435                 if (r == 0)
1436                         r = -EIO;
1437         }
1438
1439         return r;
1440 }
1441
1442 int main(int argc, char *argv[]) {
1443         int r, k;
1444         Item *i;
1445         Iterator iterator;
1446
1447         r = parse_argv(argc, argv);
1448         if (r <= 0)
1449                 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1450
1451         log_set_target(LOG_TARGET_AUTO);
1452         log_parse_environment();
1453         log_open();
1454
1455         umask(0022);
1456
1457         label_init(NULL);
1458
1459         items = hashmap_new(string_hash_func, string_compare_func);
1460         globs = hashmap_new(string_hash_func, string_compare_func);
1461
1462         if (!items || !globs) {
1463                 r = log_oom();
1464                 goto finish;
1465         }
1466
1467         r = 0;
1468
1469         if (optind < argc) {
1470                 int j;
1471
1472                 for (j = optind; j < argc; j++) {
1473                         k = read_config_file(argv[j], false);
1474                         if (k < 0 && r == 0)
1475                                 r = k;
1476                 }
1477
1478         } else {
1479                 _cleanup_strv_free_ char **files = NULL;
1480                 char **f;
1481
1482                 r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
1483                 if (r < 0) {
1484                         log_error("Failed to enumerate tmpfiles.d files: %s", strerror(-r));
1485                         goto finish;
1486                 }
1487
1488                 STRV_FOREACH(f, files) {
1489                         k = read_config_file(*f, true);
1490                         if (k < 0 && r == 0)
1491                                 r = k;
1492                 }
1493         }
1494
1495         HASHMAP_FOREACH(i, globs, iterator)
1496                 process_item(i);
1497
1498         HASHMAP_FOREACH(i, items, iterator)
1499                 process_item(i);
1500
1501 finish:
1502         while ((i = hashmap_steal_first(items)))
1503                 item_free(i);
1504
1505         while ((i = hashmap_steal_first(globs)))
1506                 item_free(i);
1507
1508         hashmap_free(items);
1509         hashmap_free(globs);
1510
1511         strv_free(include_prefixes);
1512
1513         set_free_free(unix_sockets);
1514
1515         label_finish();
1516
1517         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1518 }