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