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