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