1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering, Kay Sievers
7 Copyright 2015 Zbigniew Jędrzejewski-Szmek
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
40 #include <sys/types.h>
41 #include <sys/param.h>
42 #include <sys/xattr.h>
49 #include "path-util.h"
53 #include "conf-files.h"
54 #include "capability.h"
55 #include "specifier.h"
58 #include "selinux-util.h"
59 #include "btrfs-util.h"
62 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
63 * them in the file system. This is intended to be used to create
64 * properly owned directories beneath /tmp, /var/tmp, /run, which are
65 * volatile and hence need to be recreated on bootup. */
67 typedef enum ItemType {
68 /* These ones take file names */
71 CREATE_DIRECTORY = 'd',
72 TRUNCATE_DIRECTORY = 'D',
73 CREATE_SUBVOLUME = 'v',
76 CREATE_CHAR_DEVICE = 'c',
77 CREATE_BLOCK_DEVICE = 'b',
80 /* These ones take globs */
82 RECURSIVE_SET_XATTR = 'T',
84 RECURSIVE_SET_ACL = 'A',
87 IGNORE_DIRECTORY_PATH = 'X',
89 RECURSIVE_REMOVE_PATH = 'R',
90 ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */
92 RECURSIVE_RELABEL_PATH = 'Z',
118 bool keep_first_level:1;
125 typedef struct ItemArray {
131 static bool arg_create = false;
132 static bool arg_clean = false;
133 static bool arg_remove = false;
134 static bool arg_boot = false;
136 static char **arg_include_prefixes = NULL;
137 static char **arg_exclude_prefixes = NULL;
138 static char *arg_root = NULL;
140 static const char conf_file_dirs[] = CONF_DIRS_NULSTR("tmpfiles");
142 #define MAX_DEPTH 256
144 static Hashmap *items = NULL, *globs = NULL;
145 static Set *unix_sockets = NULL;
147 static bool needs_glob(ItemType t) {
151 IGNORE_DIRECTORY_PATH,
153 RECURSIVE_REMOVE_PATH,
156 RECURSIVE_RELABEL_PATH,
163 static bool takes_ownership(ItemType t) {
178 IGNORE_DIRECTORY_PATH,
180 RECURSIVE_REMOVE_PATH);
183 static struct Item* find_glob(Hashmap *h, const char *match) {
187 HASHMAP_FOREACH(j, h, i) {
190 for (n = 0; n < j->count; n++) {
191 Item *item = j->items + n;
193 if (fnmatch(item->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
201 static void load_unix_sockets(void) {
202 _cleanup_fclose_ FILE *f = NULL;
208 /* We maintain a cache of the sockets we found in
209 * /proc/net/unix to speed things up a little. */
211 unix_sockets = set_new(&string_hash_ops);
215 f = fopen("/proc/net/unix", "re");
220 if (!fgets(line, sizeof(line), f))
227 if (!fgets(line, sizeof(line), f))
232 p = strchr(line, ':');
240 p += strspn(p, WHITESPACE);
241 p += strcspn(p, WHITESPACE); /* skip one more word */
242 p += strspn(p, WHITESPACE);
251 path_kill_slashes(s);
253 k = set_consume(unix_sockets, s);
254 if (k < 0 && k != -EEXIST)
261 set_free_free(unix_sockets);
265 static bool unix_socket_alive(const char *fn) {
271 return !!set_get(unix_sockets, (char*) fn);
273 /* We don't know, so assume yes */
277 static int dir_is_mount_point(DIR *d, const char *subdir) {
279 union file_handle_union h = FILE_HANDLE_INIT;
280 int mount_id_parent, mount_id;
283 r_p = name_to_handle_at(dirfd(d), ".", &h.handle, &mount_id_parent, 0);
287 h.handle.handle_bytes = MAX_HANDLE_SZ;
288 r = name_to_handle_at(dirfd(d), subdir, &h.handle, &mount_id, 0);
292 /* got no handle; make no assumptions, return error */
293 if (r_p < 0 && r < 0)
296 /* got both handles; if they differ, it is a mount point */
297 if (r_p >= 0 && r >= 0)
298 return mount_id_parent != mount_id;
300 /* got only one handle; assume different mount points if one
301 * of both queries was not supported by the filesystem */
302 if (r_p == -ENOSYS || r_p == -EOPNOTSUPP || r == -ENOSYS || r == -EOPNOTSUPP)
311 static int dir_cleanup(
315 const struct stat *ds,
320 bool keep_this_level) {
323 struct timespec times[2];
324 bool deleted = false;
327 while ((dent = readdir(d))) {
330 _cleanup_free_ char *sub_path = NULL;
332 if (streq(dent->d_name, ".") ||
333 streq(dent->d_name, ".."))
336 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
340 /* FUSE, NFS mounts, SELinux might return EACCES */
342 log_debug_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
344 log_error_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
349 /* Stay on the same filesystem */
350 if (s.st_dev != rootdev)
353 /* Try to detect bind mounts of the same filesystem instance; they
354 * do not differ in device major/minors. This type of query is not
355 * supported on all kernels or filesystem types though. */
356 if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0)
359 /* Do not delete read-only files owned by root */
360 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR))
363 sub_path = strjoin(p, "/", dent->d_name, NULL);
369 /* Is there an item configured for this path? */
370 if (hashmap_get(items, sub_path))
373 if (find_glob(globs, sub_path))
376 if (S_ISDIR(s.st_mode)) {
379 streq(dent->d_name, "lost+found") &&
384 log_warning("Reached max depth on %s.", sub_path);
386 _cleanup_closedir_ DIR *sub_dir;
389 sub_dir = xopendirat(dirfd(d), dent->d_name, O_NOFOLLOW|O_NOATIME);
391 if (errno != ENOENT) {
392 log_error_errno(errno, "opendir(%s/%s) failed: %m", p, dent->d_name);
399 q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
404 /* Note: if you are wondering why we don't
405 * support the sticky bit for excluding
406 * directories from cleaning like we do it for
407 * other file system objects: well, the sticky
408 * bit already has a meaning for directories,
409 * so we don't want to overload that. */
414 /* Ignore ctime, we change it when deleting */
415 age = MAX(timespec_load(&s.st_mtim),
416 timespec_load(&s.st_atim));
420 if (i->type != IGNORE_DIRECTORY_PATH || !streq(dent->d_name, p)) {
421 log_debug("rmdir '%s'", sub_path);
423 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
424 if (errno != ENOENT && errno != ENOTEMPTY) {
425 log_error_errno(errno, "rmdir(%s): %m", sub_path);
432 /* Skip files for which the sticky bit is
433 * set. These are semantics we define, and are
434 * unknown elsewhere. See XDG_RUNTIME_DIR
435 * specification for details. */
436 if (s.st_mode & S_ISVTX)
439 if (mountpoint && S_ISREG(s.st_mode)) {
440 if (streq(dent->d_name, ".journal") &&
444 if (streq(dent->d_name, "aquota.user") ||
445 streq(dent->d_name, "aquota.group"))
449 /* Ignore sockets that are listed in /proc/net/unix */
450 if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path))
453 /* Ignore device nodes */
454 if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode))
457 /* Keep files on this level around if this is
462 age = MAX3(timespec_load(&s.st_mtim),
463 timespec_load(&s.st_atim),
464 timespec_load(&s.st_ctim));
469 log_debug("unlink '%s'", sub_path);
471 if (unlinkat(dirfd(d), dent->d_name, 0) < 0) {
472 if (errno != ENOENT) {
473 log_error_errno(errno, "unlink(%s): %m", sub_path);
484 /* Restore original directory timestamps */
485 times[0] = ds->st_atim;
486 times[1] = ds->st_mtim;
488 if (futimens(dirfd(d), times) < 0)
489 log_error_errno(errno, "utimensat(%s): %m", p);
495 static int path_set_perms(Item *i, const char *path) {
502 st_valid = stat(path, &st) == 0;
504 /* not using i->path directly because it may be a glob */
508 if (i->mask_perms && st_valid) {
509 if (!(st.st_mode & 0111))
511 if (!(st.st_mode & 0222))
513 if (!(st.st_mode & 0444))
515 if (!S_ISDIR(st.st_mode))
516 m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
519 if (!st_valid || m != (st.st_mode & 07777)) {
520 if (chmod(path, m) < 0)
521 return log_error_errno(errno, "chmod(%s) failed: %m", path);
525 if ((!st_valid || (i->uid != st.st_uid || i->gid != st.st_gid)) &&
526 (i->uid_set || i->gid_set))
528 i->uid_set ? i->uid : UID_INVALID,
529 i->gid_set ? i->gid : GID_INVALID) < 0)
531 return log_error_errno(errno, "chown(%s) failed: %m", path);
533 return label_fix(path, false, false);
536 static int get_xattrs_from_arg(Item *i) {
546 while ((r = unquote_first_word(&p, &xattr, false)) > 0) {
547 _cleanup_free_ char *tmp = NULL, *name = NULL,
548 *value = NULL, *value2 = NULL, *_xattr = xattr;
550 r = split_pair(xattr, "=", &name, &value);
552 log_warning("Illegal xattr found: \"%s\" - ignoring.", xattr);
556 if (strempty(name) || strempty(value)) {
557 log_warning("Malformed xattr found: \"%s\" - ignoring.", xattr);
561 tmp = unquote(value, "\"");
565 value2 = cunescape(tmp);
569 if (strv_push_pair(&i->xattrs, name, value2) < 0)
571 name = value2 = NULL;
577 static int path_set_xattrs(Item *i, const char *path) {
578 char **name, **value;
583 STRV_FOREACH_PAIR(name, value, i->xattrs) {
587 if (lsetxattr(path, *name, *value, n, 0) < 0) {
588 log_error("Setting extended attribute %s=%s on %s failed: %m",
589 *name, *value, path);
596 static int get_acls_from_arg(Item *item) {
599 _cleanup_(acl_freep) acl_t a = NULL, d = NULL;
603 /* If force (= modify) is set, we will not modify the acl
604 * afterwards, so the mask can be added now if necessary. */
605 r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
607 log_warning_errno(errno, "Failed to parse ACL \"%s\": %m. Ignoring",
610 log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
616 static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
617 _cleanup_(acl_freep) acl_t cleanme = NULL;
621 r = acls_for_file(path, type, acl, &cleanme);
627 r = acl_set_file(path, type, acl);
629 _cleanup_(acl_free_charpp) char *t;
632 t = acl_to_any_text(acl, NULL, ',', TEXT_ABBREVIATE);
634 "Setting %s ACL \"%s\" on %s failed: %m",
635 type == ACL_TYPE_ACCESS ? "access" : "default",
642 static int path_set_acls(Item *item, const char *path) {
649 if (item->acl_access) {
650 r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
655 if (item->acl_default) {
656 r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
665 static int write_one_file(Item *i, const char *path) {
666 _cleanup_close_ int fd = -1;
673 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
674 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
676 RUN_WITH_UMASK(0000) {
677 mac_selinux_create_file_prepare(path, S_IFREG);
678 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
679 mac_selinux_create_file_clear();
683 if (i->type == WRITE_FILE && errno == ENOENT)
686 log_error_errno(errno, "Failed to create file %s: %m", path);
691 _cleanup_free_ char *unescaped;
695 unescaped = cunescape(i->argument);
699 l = strlen(unescaped);
700 n = write(fd, unescaped, l);
702 if (n < 0 || (size_t) n < l) {
703 log_error("Failed to write file %s: %s", path, n < 0 ? strerror(-n) : "Short write");
704 return n < 0 ? n : -EIO;
710 if (stat(path, &st) < 0)
711 return log_error_errno(errno, "stat(%s) failed: %m", path);
713 if (!S_ISREG(st.st_mode)) {
714 log_error("%s is not a file.", path);
718 r = path_set_perms(i, path);
725 typedef int (*action_t)(Item *, const char *);
727 static int item_do_children(Item *i, const char *path, action_t action) {
728 _cleanup_closedir_ DIR *d;
734 /* This returns the first error we run into, but nevertheless
739 return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
742 _cleanup_free_ char *p = NULL;
749 if (errno != 0 && r == 0)
755 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
758 p = strjoin(path, "/", de->d_name, NULL);
763 if (q < 0 && q != -ENOENT && r == 0)
766 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
767 q = item_do_children(i, p, action);
776 static int glob_item(Item *i, action_t action, bool recursive) {
777 _cleanup_globfree_ glob_t g = {};
782 k = glob(i->path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
783 if (k != 0 && k != GLOB_NOMATCH)
784 return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
786 STRV_FOREACH(fn, g.gl_pathv) {
792 k = item_do_children(i, *fn, action);
801 static int create_item(Item *i) {
810 case IGNORE_DIRECTORY_PATH:
812 case RECURSIVE_REMOVE_PATH:
817 r = write_one_file(i, i->path);
823 r = copy_tree(i->argument, i->path, false);
828 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
830 if (stat(i->argument, &a) < 0)
831 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
833 if (stat(i->path, &b) < 0)
834 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
836 if ((a.st_mode ^ b.st_mode) & S_IFMT) {
837 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
842 r = path_set_perms(i, i->path);
849 r = glob_item(i, write_one_file, false);
855 case CREATE_DIRECTORY:
856 case TRUNCATE_DIRECTORY:
857 case CREATE_SUBVOLUME:
860 mkdir_parents_label(i->path, 0755);
862 if (i->type == CREATE_SUBVOLUME) {
863 RUN_WITH_UMASK((~i->mode) & 0777)
864 r = btrfs_subvol_make(i->path);
868 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY) {
870 r = mkdir_label(i->path, i->mode);
875 return log_error_errno(r, "Failed to create directory or subvolume %s: %m", i->path);
877 if (stat(i->path, &st) < 0)
878 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
880 if (!S_ISDIR(st.st_mode)) {
881 log_debug("%s already exists and is not a directory.", i->path);
886 r = path_set_perms(i, i->path);
894 RUN_WITH_UMASK(0000) {
895 mac_selinux_create_file_prepare(i->path, S_IFIFO);
896 r = mkfifo(i->path, i->mode);
897 mac_selinux_create_file_clear();
902 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
904 if (stat(i->path, &st) < 0)
905 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
907 if (!S_ISFIFO(st.st_mode)) {
911 RUN_WITH_UMASK(0000) {
912 mac_selinux_create_file_prepare(i->path, S_IFIFO);
913 r = mkfifo_atomic(i->path, i->mode);
914 mac_selinux_create_file_clear();
918 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
920 log_debug("%s is not a fifo.", i->path);
926 r = path_set_perms(i, i->path);
934 mac_selinux_create_file_prepare(i->path, S_IFLNK);
935 r = symlink(i->argument, i->path);
936 mac_selinux_create_file_clear();
939 _cleanup_free_ char *x = NULL;
942 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
944 r = readlink_malloc(i->path, &x);
945 if (r < 0 || !streq(i->argument, x)) {
948 mac_selinux_create_file_prepare(i->path, S_IFLNK);
949 r = symlink_atomic(i->argument, i->path);
950 mac_selinux_create_file_clear();
953 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
955 log_debug("%s is not a symlink or does not point to the correct path.", i->path);
963 case CREATE_BLOCK_DEVICE:
964 case CREATE_CHAR_DEVICE: {
967 if (have_effective_cap(CAP_MKNOD) == 0) {
968 /* In a container we lack CAP_MKNOD. We
969 shouldn't attempt to create the device node in
970 that case to avoid noise, and we don't support
971 virtualized devices in containers anyway. */
973 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
977 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
979 RUN_WITH_UMASK(0000) {
980 mac_selinux_create_file_prepare(i->path, file_type);
981 r = mknod(i->path, i->mode | file_type, i->major_minor);
982 mac_selinux_create_file_clear();
986 if (errno == EPERM) {
987 log_debug("We lack permissions, possibly because of cgroup configuration; "
988 "skipping creation of device node %s.", i->path);
993 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
995 if (stat(i->path, &st) < 0)
996 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
998 if ((st.st_mode & S_IFMT) != file_type) {
1002 RUN_WITH_UMASK(0000) {
1003 mac_selinux_create_file_prepare(i->path, file_type);
1004 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1005 mac_selinux_create_file_clear();
1009 return log_error_errno(r, "Failed to create device node %s: %m", i->path);
1011 log_debug("%s is not a device node.", i->path);
1017 r = path_set_perms(i, i->path);
1026 r = glob_item(i, path_set_perms, false);
1031 case RECURSIVE_RELABEL_PATH:
1032 r = glob_item(i, path_set_perms, true);
1038 r = glob_item(i, path_set_xattrs, false);
1043 case RECURSIVE_SET_XATTR:
1044 r = glob_item(i, path_set_xattrs, true);
1050 r = glob_item(i, path_set_acls, false);
1055 case RECURSIVE_SET_ACL:
1056 r = glob_item(i, path_set_acls, true);
1062 log_debug("%s created successfully.", i->path);
1067 static int remove_item_instance(Item *i, const char *instance) {
1076 case CREATE_DIRECTORY:
1077 case CREATE_SUBVOLUME:
1079 case CREATE_SYMLINK:
1080 case CREATE_BLOCK_DEVICE:
1081 case CREATE_CHAR_DEVICE:
1083 case IGNORE_DIRECTORY_PATH:
1086 case RECURSIVE_RELABEL_PATH:
1090 case RECURSIVE_SET_XATTR:
1092 case RECURSIVE_SET_ACL:
1096 if (remove(instance) < 0 && errno != ENOENT)
1097 return log_error_errno(errno, "rm(%s): %m", instance);
1101 case TRUNCATE_DIRECTORY:
1102 case RECURSIVE_REMOVE_PATH:
1103 /* FIXME: we probably should use dir_cleanup() here
1104 * instead of rm_rf() so that 'x' is honoured. */
1105 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1106 if (r < 0 && r != -ENOENT)
1107 return log_error_errno(r, "rm_rf(%s): %m", instance);
1115 static int remove_item(Item *i) {
1124 case CREATE_DIRECTORY:
1125 case CREATE_SUBVOLUME:
1127 case CREATE_SYMLINK:
1128 case CREATE_CHAR_DEVICE:
1129 case CREATE_BLOCK_DEVICE:
1131 case IGNORE_DIRECTORY_PATH:
1134 case RECURSIVE_RELABEL_PATH:
1138 case RECURSIVE_SET_XATTR:
1140 case RECURSIVE_SET_ACL:
1144 case TRUNCATE_DIRECTORY:
1145 case RECURSIVE_REMOVE_PATH:
1146 r = glob_item(i, remove_item_instance, false);
1153 static int clean_item_instance(Item *i, const char* instance) {
1154 _cleanup_closedir_ DIR *d = NULL;
1165 n = now(CLOCK_REALTIME);
1169 cutoff = n - i->age;
1171 d = opendir(instance);
1173 if (errno == ENOENT || errno == ENOTDIR)
1176 log_error_errno(errno, "Failed to open directory %s: %m", i->path);
1180 if (fstat(dirfd(d), &s) < 0)
1181 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1183 if (!S_ISDIR(s.st_mode)) {
1184 log_error("%s is not a directory.", i->path);
1188 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1189 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1191 mountpoint = s.st_dev != ps.st_dev ||
1192 (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1194 r = dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1195 MAX_DEPTH, i->keep_first_level);
1199 static int clean_item(Item *i) {
1205 case CREATE_DIRECTORY:
1206 case CREATE_SUBVOLUME:
1207 case TRUNCATE_DIRECTORY:
1210 clean_item_instance(i, i->path);
1212 case IGNORE_DIRECTORY_PATH:
1213 r = glob_item(i, clean_item_instance, false);
1222 static int process_item_array(ItemArray *array);
1224 static int process_item(Item *i) {
1226 _cleanup_free_ char *prefix = NULL;
1235 prefix = malloc(strlen(i->path) + 1);
1239 PATH_FOREACH_PREFIX(prefix, i->path) {
1242 j = hashmap_get(items, prefix);
1246 s = process_item_array(j);
1247 if (s < 0 && t == 0)
1252 r = arg_create ? create_item(i) : 0;
1253 q = arg_remove ? remove_item(i) : 0;
1254 p = arg_clean ? clean_item(i) : 0;
1262 static int process_item_array(ItemArray *array) {
1268 for (n = 0; n < array->count; n++) {
1269 k = process_item(array->items + n);
1270 if (k < 0 && r == 0)
1277 static void item_free_contents(Item *i) {
1281 strv_free(i->xattrs);
1284 acl_free(i->acl_access);
1285 acl_free(i->acl_default);
1289 static void item_array_free(ItemArray *a) {
1295 for (n = 0; n < a->count; n++)
1296 item_free_contents(a->items + n);
1301 static bool item_compatible(Item *a, Item *b) {
1304 assert(streq(a->path, b->path));
1306 if (takes_ownership(a->type) && takes_ownership(b->type))
1307 /* check if the items are the same */
1308 return streq_ptr(a->argument, b->argument) &&
1310 a->uid_set == b->uid_set &&
1313 a->gid_set == b->gid_set &&
1316 a->mode_set == b->mode_set &&
1317 a->mode == b->mode &&
1319 a->age_set == b->age_set &&
1322 a->mask_perms == b->mask_perms &&
1324 a->keep_first_level == b->keep_first_level &&
1326 a->major_minor == b->major_minor;
1331 static bool should_include_path(const char *path) {
1334 STRV_FOREACH(prefix, arg_exclude_prefixes)
1335 if (path_startswith(path, *prefix))
1338 STRV_FOREACH(prefix, arg_include_prefixes)
1339 if (path_startswith(path, *prefix))
1342 /* no matches, so we should include this path only if we
1343 * have no whitelist at all */
1344 return strv_length(arg_include_prefixes) == 0;
1347 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1349 static const Specifier specifier_table[] = {
1350 { 'm', specifier_machine_id, NULL },
1351 { 'b', specifier_boot_id, NULL },
1352 { 'H', specifier_host_name, NULL },
1353 { 'v', specifier_kernel_release, NULL },
1357 _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1358 _cleanup_(item_free_contents) Item i = {};
1359 ItemArray *existing;
1362 bool force = false, boot = false;
1369 "%ms %ms %ms %ms %ms %ms %n",
1378 log_error("[%s:%u] Syntax error.", fname, line);
1382 if (isempty(action)) {
1383 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1387 for (pos = 1; action[pos]; pos++) {
1388 if (action[pos] == '!' && !boot)
1390 else if (action[pos] == '+' && !force)
1393 log_error("[%s:%u] Unknown modifiers in command '%s'",
1394 fname, line, action);
1399 if (boot && !arg_boot)
1405 r = specifier_printf(path, specifier_table, NULL, &i.path);
1407 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1412 c += strspn(buffer+c, WHITESPACE);
1413 if (buffer[c] != 0 && (buffer[c] != '-' || buffer[c+1] != 0)) {
1414 i.argument = unquote(buffer+c, "\"");
1424 case CREATE_DIRECTORY:
1425 case CREATE_SUBVOLUME:
1426 case TRUNCATE_DIRECTORY:
1429 case IGNORE_DIRECTORY_PATH:
1431 case RECURSIVE_REMOVE_PATH:
1434 case RECURSIVE_RELABEL_PATH:
1437 case CREATE_SYMLINK:
1439 i.argument = strappend("/usr/share/factory/", i.path);
1447 log_error("[%s:%u] Write file requires argument.", fname, line);
1454 i.argument = strappend("/usr/share/factory/", i.path);
1457 } else if (!path_is_absolute(i.argument)) {
1458 log_error("[%s:%u] Source path is not absolute.", fname, line);
1462 path_kill_slashes(i.argument);
1465 case CREATE_CHAR_DEVICE:
1466 case CREATE_BLOCK_DEVICE: {
1467 unsigned major, minor;
1470 log_error("[%s:%u] Device file requires argument.", fname, line);
1474 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1475 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1479 i.major_minor = makedev(major, minor);
1484 case RECURSIVE_SET_XATTR:
1486 log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1489 r = get_xattrs_from_arg(&i);
1495 case RECURSIVE_SET_ACL:
1497 log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1500 r = get_acls_from_arg(&i);
1506 log_error("[%s:%u] Unknown command type '%c'.", fname, line, i.type);
1510 if (!path_is_absolute(i.path)) {
1511 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1515 path_kill_slashes(i.path);
1517 if (!should_include_path(i.path))
1523 p = strappend(arg_root, i.path);
1531 if (user && !streq(user, "-")) {
1532 const char *u = user;
1534 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1536 log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1543 if (group && !streq(group, "-")) {
1544 const char *g = group;
1546 r = get_group_creds(&g, &i.gid);
1548 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1555 if (mode && !streq(mode, "-")) {
1556 const char *mm = mode;
1560 i.mask_perms = true;
1564 if (sscanf(mm, "%o", &m) != 1) {
1565 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1572 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1575 if (age && !streq(age, "-")) {
1576 const char *a = age;
1579 i.keep_first_level = true;
1583 if (parse_sec(a, &i.age) < 0) {
1584 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1591 h = needs_glob(i.type) ? globs : items;
1593 existing = hashmap_get(h, i.path);
1597 for (n = 0; n < existing->count; n++) {
1598 if (!item_compatible(existing->items + n, &i))
1599 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1600 fname, line, i.path);
1603 existing = new0(ItemArray, 1);
1604 r = hashmap_put(h, i.path, existing);
1609 if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1612 memcpy(existing->items + existing->count++, &i, sizeof(i));
1617 static void help(void) {
1618 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1619 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1620 " -h --help Show this help\n"
1621 " --version Show package version\n"
1622 " --create Create marked files/directories\n"
1623 " --clean Clean up marked directories\n"
1624 " --remove Remove marked files/directories\n"
1625 " --boot Execute actions only safe at boot\n"
1626 " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n"
1627 " --exclude-prefix=PATH Ignore rules that apply to paths with the specified prefix\n"
1628 " --root=PATH Operate on an alternate filesystem root\n",
1629 program_invocation_short_name);
1632 static int parse_argv(int argc, char *argv[]) {
1635 ARG_VERSION = 0x100,
1645 static const struct option options[] = {
1646 { "help", no_argument, NULL, 'h' },
1647 { "version", no_argument, NULL, ARG_VERSION },
1648 { "create", no_argument, NULL, ARG_CREATE },
1649 { "clean", no_argument, NULL, ARG_CLEAN },
1650 { "remove", no_argument, NULL, ARG_REMOVE },
1651 { "boot", no_argument, NULL, ARG_BOOT },
1652 { "prefix", required_argument, NULL, ARG_PREFIX },
1653 { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
1654 { "root", required_argument, NULL, ARG_ROOT },
1663 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1672 puts(PACKAGE_STRING);
1673 puts(SYSTEMD_FEATURES);
1693 if (strv_push(&arg_include_prefixes, optarg) < 0)
1697 case ARG_EXCLUDE_PREFIX:
1698 if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1704 arg_root = path_make_absolute_cwd(optarg);
1708 path_kill_slashes(arg_root);
1715 assert_not_reached("Unhandled option");
1718 if (!arg_clean && !arg_create && !arg_remove) {
1719 log_error("You need to specify at least one of --clean, --create or --remove.");
1726 static int read_config_file(const char *fn, bool ignore_enoent) {
1727 _cleanup_fclose_ FILE *f = NULL;
1728 char line[LINE_MAX];
1736 r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
1738 if (ignore_enoent && r == -ENOENT)
1741 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
1744 FOREACH_LINE(line, f, break) {
1751 if (*l == '#' || *l == 0)
1754 k = parse_line(fn, v, l);
1755 if (k < 0 && r == 0)
1759 /* we have to determine age parameter for each entry of type X */
1760 HASHMAP_FOREACH(i, globs, iterator) {
1762 Item *j, *candidate_item = NULL;
1764 if (i->type != IGNORE_DIRECTORY_PATH)
1767 HASHMAP_FOREACH(j, items, iter) {
1768 if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
1771 if (path_equal(j->path, i->path)) {
1776 if ((!candidate_item && path_startswith(i->path, j->path)) ||
1777 (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1781 if (candidate_item && candidate_item->age_set) {
1782 i->age = candidate_item->age;
1788 log_error_errno(errno, "Failed to read from file %s: %m", fn);
1796 int main(int argc, char *argv[]) {
1801 r = parse_argv(argc, argv);
1805 log_set_target(LOG_TARGET_AUTO);
1806 log_parse_environment();
1811 mac_selinux_init(NULL);
1813 items = hashmap_new(&string_hash_ops);
1814 globs = hashmap_new(&string_hash_ops);
1816 if (!items || !globs) {
1823 if (optind < argc) {
1826 for (j = optind; j < argc; j++) {
1827 k = read_config_file(argv[j], false);
1828 if (k < 0 && r == 0)
1833 _cleanup_strv_free_ char **files = NULL;
1836 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
1838 log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
1842 STRV_FOREACH(f, files) {
1843 k = read_config_file(*f, true);
1844 if (k < 0 && r == 0)
1849 HASHMAP_FOREACH(a, globs, iterator) {
1850 k = process_item_array(a);
1851 if (k < 0 && r == 0)
1855 HASHMAP_FOREACH(a, items, iterator) {
1856 k = process_item_array(a);
1857 if (k < 0 && r == 0)
1862 while ((a = hashmap_steal_first(items)))
1865 while ((a = hashmap_steal_first(globs)))
1868 hashmap_free(items);
1869 hashmap_free(globs);
1871 free(arg_include_prefixes);
1872 free(arg_exclude_prefixes);
1875 set_free_free(unix_sockets);
1877 mac_selinux_finish();
1879 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;