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 dup = NULL;
621 r = acls_for_file(path, type, acl, &dup);
625 r = calc_acl_mask_if_needed(&dup);
633 /* the mask was already added earlier if needed */
636 r = add_base_acls_if_needed(&dup, path);
640 r = acl_set_file(path, type, dup);
642 _cleanup_(acl_free_charpp) char *t;
645 t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
647 "Setting %s ACL \"%s\" on %s failed: %m",
648 type == ACL_TYPE_ACCESS ? "access" : "default",
655 static int path_set_acls(Item *item, const char *path) {
662 if (item->acl_access) {
663 r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
668 if (item->acl_default) {
669 r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
678 static int write_one_file(Item *i, const char *path) {
679 _cleanup_close_ int fd = -1;
686 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
687 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
689 RUN_WITH_UMASK(0000) {
690 mac_selinux_create_file_prepare(path, S_IFREG);
691 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
692 mac_selinux_create_file_clear();
696 if (i->type == WRITE_FILE && errno == ENOENT)
699 log_error_errno(errno, "Failed to create file %s: %m", path);
704 _cleanup_free_ char *unescaped;
708 unescaped = cunescape(i->argument);
712 l = strlen(unescaped);
713 n = write(fd, unescaped, l);
715 if (n < 0 || (size_t) n < l) {
716 log_error("Failed to write file %s: %s", path, n < 0 ? strerror(-n) : "Short write");
717 return n < 0 ? n : -EIO;
723 if (stat(path, &st) < 0)
724 return log_error_errno(errno, "stat(%s) failed: %m", path);
726 if (!S_ISREG(st.st_mode)) {
727 log_error("%s is not a file.", path);
731 r = path_set_perms(i, path);
738 typedef int (*action_t)(Item *, const char *);
740 static int item_do_children(Item *i, const char *path, action_t action) {
741 _cleanup_closedir_ DIR *d;
747 /* This returns the first error we run into, but nevertheless
752 return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
755 _cleanup_free_ char *p = NULL;
762 if (errno != 0 && r == 0)
768 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
771 p = strjoin(path, "/", de->d_name, NULL);
776 if (q < 0 && q != -ENOENT && r == 0)
779 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
780 q = item_do_children(i, p, action);
789 static int glob_item(Item *i, action_t action, bool recursive) {
790 _cleanup_globfree_ glob_t g = {};
795 k = glob(i->path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
796 if (k != 0 && k != GLOB_NOMATCH)
797 return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
799 STRV_FOREACH(fn, g.gl_pathv) {
805 k = item_do_children(i, *fn, action);
814 static int create_item(Item *i) {
823 case IGNORE_DIRECTORY_PATH:
825 case RECURSIVE_REMOVE_PATH:
830 r = write_one_file(i, i->path);
836 r = copy_tree(i->argument, i->path, false);
841 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
843 if (stat(i->argument, &a) < 0)
844 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
846 if (stat(i->path, &b) < 0)
847 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
849 if ((a.st_mode ^ b.st_mode) & S_IFMT) {
850 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
855 r = path_set_perms(i, i->path);
862 r = glob_item(i, write_one_file, false);
868 case CREATE_DIRECTORY:
869 case TRUNCATE_DIRECTORY:
870 case CREATE_SUBVOLUME:
873 mkdir_parents_label(i->path, 0755);
875 if (i->type == CREATE_SUBVOLUME) {
876 RUN_WITH_UMASK((~i->mode) & 0777)
877 r = btrfs_subvol_make(i->path);
881 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY) {
883 r = mkdir_label(i->path, i->mode);
888 return log_error_errno(r, "Failed to create directory or subvolume %s: %m", i->path);
890 if (stat(i->path, &st) < 0)
891 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
893 if (!S_ISDIR(st.st_mode)) {
894 log_debug("%s already exists and is not a directory.", i->path);
899 r = path_set_perms(i, i->path);
907 RUN_WITH_UMASK(0000) {
908 mac_selinux_create_file_prepare(i->path, S_IFIFO);
909 r = mkfifo(i->path, i->mode);
910 mac_selinux_create_file_clear();
915 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
917 if (stat(i->path, &st) < 0)
918 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
920 if (!S_ISFIFO(st.st_mode)) {
924 RUN_WITH_UMASK(0000) {
925 mac_selinux_create_file_prepare(i->path, S_IFIFO);
926 r = mkfifo_atomic(i->path, i->mode);
927 mac_selinux_create_file_clear();
931 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
933 log_debug("%s is not a fifo.", i->path);
939 r = path_set_perms(i, i->path);
947 mac_selinux_create_file_prepare(i->path, S_IFLNK);
948 r = symlink(i->argument, i->path);
949 mac_selinux_create_file_clear();
952 _cleanup_free_ char *x = NULL;
955 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
957 r = readlink_malloc(i->path, &x);
958 if (r < 0 || !streq(i->argument, x)) {
961 mac_selinux_create_file_prepare(i->path, S_IFLNK);
962 r = symlink_atomic(i->argument, i->path);
963 mac_selinux_create_file_clear();
966 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
968 log_debug("%s is not a symlink or does not point to the correct path.", i->path);
976 case CREATE_BLOCK_DEVICE:
977 case CREATE_CHAR_DEVICE: {
980 if (have_effective_cap(CAP_MKNOD) == 0) {
981 /* In a container we lack CAP_MKNOD. We
982 shouldn't attempt to create the device node in
983 that case to avoid noise, and we don't support
984 virtualized devices in containers anyway. */
986 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
990 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
992 RUN_WITH_UMASK(0000) {
993 mac_selinux_create_file_prepare(i->path, file_type);
994 r = mknod(i->path, i->mode | file_type, i->major_minor);
995 mac_selinux_create_file_clear();
999 if (errno == EPERM) {
1000 log_debug("We lack permissions, possibly because of cgroup configuration; "
1001 "skipping creation of device node %s.", i->path);
1005 if (errno != EEXIST)
1006 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1008 if (stat(i->path, &st) < 0)
1009 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1011 if ((st.st_mode & S_IFMT) != file_type) {
1015 RUN_WITH_UMASK(0000) {
1016 mac_selinux_create_file_prepare(i->path, file_type);
1017 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1018 mac_selinux_create_file_clear();
1022 return log_error_errno(r, "Failed to create device node %s: %m", i->path);
1024 log_debug("%s is not a device node.", i->path);
1030 r = path_set_perms(i, i->path);
1039 r = glob_item(i, path_set_perms, false);
1044 case RECURSIVE_RELABEL_PATH:
1045 r = glob_item(i, path_set_perms, true);
1051 r = glob_item(i, path_set_xattrs, false);
1056 case RECURSIVE_SET_XATTR:
1057 r = glob_item(i, path_set_xattrs, true);
1063 r = glob_item(i, path_set_acls, false);
1068 case RECURSIVE_SET_ACL:
1069 r = glob_item(i, path_set_acls, true);
1075 log_debug("%s created successfully.", i->path);
1080 static int remove_item_instance(Item *i, const char *instance) {
1089 case CREATE_DIRECTORY:
1090 case CREATE_SUBVOLUME:
1092 case CREATE_SYMLINK:
1093 case CREATE_BLOCK_DEVICE:
1094 case CREATE_CHAR_DEVICE:
1096 case IGNORE_DIRECTORY_PATH:
1099 case RECURSIVE_RELABEL_PATH:
1103 case RECURSIVE_SET_XATTR:
1105 case RECURSIVE_SET_ACL:
1109 if (remove(instance) < 0 && errno != ENOENT)
1110 return log_error_errno(errno, "rm(%s): %m", instance);
1114 case TRUNCATE_DIRECTORY:
1115 case RECURSIVE_REMOVE_PATH:
1116 /* FIXME: we probably should use dir_cleanup() here
1117 * instead of rm_rf() so that 'x' is honoured. */
1118 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1119 if (r < 0 && r != -ENOENT)
1120 return log_error_errno(r, "rm_rf(%s): %m", instance);
1128 static int remove_item(Item *i) {
1137 case CREATE_DIRECTORY:
1138 case CREATE_SUBVOLUME:
1140 case CREATE_SYMLINK:
1141 case CREATE_CHAR_DEVICE:
1142 case CREATE_BLOCK_DEVICE:
1144 case IGNORE_DIRECTORY_PATH:
1147 case RECURSIVE_RELABEL_PATH:
1151 case RECURSIVE_SET_XATTR:
1153 case RECURSIVE_SET_ACL:
1157 case TRUNCATE_DIRECTORY:
1158 case RECURSIVE_REMOVE_PATH:
1159 r = glob_item(i, remove_item_instance, false);
1166 static int clean_item_instance(Item *i, const char* instance) {
1167 _cleanup_closedir_ DIR *d = NULL;
1178 n = now(CLOCK_REALTIME);
1182 cutoff = n - i->age;
1184 d = opendir(instance);
1186 if (errno == ENOENT || errno == ENOTDIR)
1189 log_error_errno(errno, "Failed to open directory %s: %m", i->path);
1193 if (fstat(dirfd(d), &s) < 0)
1194 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1196 if (!S_ISDIR(s.st_mode)) {
1197 log_error("%s is not a directory.", i->path);
1201 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1202 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1204 mountpoint = s.st_dev != ps.st_dev ||
1205 (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1207 r = dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1208 MAX_DEPTH, i->keep_first_level);
1212 static int clean_item(Item *i) {
1218 case CREATE_DIRECTORY:
1219 case CREATE_SUBVOLUME:
1220 case TRUNCATE_DIRECTORY:
1223 clean_item_instance(i, i->path);
1225 case IGNORE_DIRECTORY_PATH:
1226 r = glob_item(i, clean_item_instance, false);
1235 static int process_item_array(ItemArray *array);
1237 static int process_item(Item *i) {
1239 _cleanup_free_ char *prefix = NULL;
1248 prefix = malloc(strlen(i->path) + 1);
1252 PATH_FOREACH_PREFIX(prefix, i->path) {
1255 j = hashmap_get(items, prefix);
1259 s = process_item_array(j);
1260 if (s < 0 && t == 0)
1265 r = arg_create ? create_item(i) : 0;
1266 q = arg_remove ? remove_item(i) : 0;
1267 p = arg_clean ? clean_item(i) : 0;
1275 static int process_item_array(ItemArray *array) {
1281 for (n = 0; n < array->count; n++) {
1282 k = process_item(array->items + n);
1283 if (k < 0 && r == 0)
1290 static void item_free_contents(Item *i) {
1294 strv_free(i->xattrs);
1297 acl_free(i->acl_access);
1298 acl_free(i->acl_default);
1302 static void item_array_free(ItemArray *a) {
1308 for (n = 0; n < a->count; n++)
1309 item_free_contents(a->items + n);
1314 static bool item_compatible(Item *a, Item *b) {
1317 assert(streq(a->path, b->path));
1319 if (takes_ownership(a->type) && takes_ownership(b->type))
1320 /* check if the items are the same */
1321 return streq_ptr(a->argument, b->argument) &&
1323 a->uid_set == b->uid_set &&
1326 a->gid_set == b->gid_set &&
1329 a->mode_set == b->mode_set &&
1330 a->mode == b->mode &&
1332 a->age_set == b->age_set &&
1335 a->mask_perms == b->mask_perms &&
1337 a->keep_first_level == b->keep_first_level &&
1339 a->major_minor == b->major_minor;
1344 static bool should_include_path(const char *path) {
1347 STRV_FOREACH(prefix, arg_exclude_prefixes)
1348 if (path_startswith(path, *prefix))
1351 STRV_FOREACH(prefix, arg_include_prefixes)
1352 if (path_startswith(path, *prefix))
1355 /* no matches, so we should include this path only if we
1356 * have no whitelist at all */
1357 return strv_length(arg_include_prefixes) == 0;
1360 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1362 static const Specifier specifier_table[] = {
1363 { 'm', specifier_machine_id, NULL },
1364 { 'b', specifier_boot_id, NULL },
1365 { 'H', specifier_host_name, NULL },
1366 { 'v', specifier_kernel_release, NULL },
1370 _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1371 _cleanup_(item_free_contents) Item i = {};
1372 ItemArray *existing;
1375 bool force = false, boot = false;
1382 "%ms %ms %ms %ms %ms %ms %n",
1391 log_error("[%s:%u] Syntax error.", fname, line);
1395 if (isempty(action)) {
1396 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1400 for (pos = 1; action[pos]; pos++) {
1401 if (action[pos] == '!' && !boot)
1403 else if (action[pos] == '+' && !force)
1406 log_error("[%s:%u] Unknown modifiers in command '%s'",
1407 fname, line, action);
1412 if (boot && !arg_boot)
1418 r = specifier_printf(path, specifier_table, NULL, &i.path);
1420 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1425 c += strspn(buffer+c, WHITESPACE);
1426 if (buffer[c] != 0 && (buffer[c] != '-' || buffer[c+1] != 0)) {
1427 i.argument = unquote(buffer+c, "\"");
1437 case CREATE_DIRECTORY:
1438 case CREATE_SUBVOLUME:
1439 case TRUNCATE_DIRECTORY:
1442 case IGNORE_DIRECTORY_PATH:
1444 case RECURSIVE_REMOVE_PATH:
1447 case RECURSIVE_RELABEL_PATH:
1450 case CREATE_SYMLINK:
1452 i.argument = strappend("/usr/share/factory/", i.path);
1460 log_error("[%s:%u] Write file requires argument.", fname, line);
1467 i.argument = strappend("/usr/share/factory/", i.path);
1470 } else if (!path_is_absolute(i.argument)) {
1471 log_error("[%s:%u] Source path is not absolute.", fname, line);
1475 path_kill_slashes(i.argument);
1478 case CREATE_CHAR_DEVICE:
1479 case CREATE_BLOCK_DEVICE: {
1480 unsigned major, minor;
1483 log_error("[%s:%u] Device file requires argument.", fname, line);
1487 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1488 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1492 i.major_minor = makedev(major, minor);
1497 case RECURSIVE_SET_XATTR:
1499 log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1502 r = get_xattrs_from_arg(&i);
1508 case RECURSIVE_SET_ACL:
1510 log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1513 r = get_acls_from_arg(&i);
1519 log_error("[%s:%u] Unknown command type '%c'.", fname, line, i.type);
1523 if (!path_is_absolute(i.path)) {
1524 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1528 path_kill_slashes(i.path);
1530 if (!should_include_path(i.path))
1536 p = strappend(arg_root, i.path);
1544 if (user && !streq(user, "-")) {
1545 const char *u = user;
1547 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1549 log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1556 if (group && !streq(group, "-")) {
1557 const char *g = group;
1559 r = get_group_creds(&g, &i.gid);
1561 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1568 if (mode && !streq(mode, "-")) {
1569 const char *mm = mode;
1573 i.mask_perms = true;
1577 if (sscanf(mm, "%o", &m) != 1) {
1578 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1585 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1588 if (age && !streq(age, "-")) {
1589 const char *a = age;
1592 i.keep_first_level = true;
1596 if (parse_sec(a, &i.age) < 0) {
1597 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1604 h = needs_glob(i.type) ? globs : items;
1606 existing = hashmap_get(h, i.path);
1610 for (n = 0; n < existing->count; n++) {
1611 if (!item_compatible(existing->items + n, &i))
1612 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1613 fname, line, i.path);
1616 existing = new0(ItemArray, 1);
1617 r = hashmap_put(h, i.path, existing);
1622 if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1625 memcpy(existing->items + existing->count++, &i, sizeof(i));
1630 static void help(void) {
1631 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1632 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1633 " -h --help Show this help\n"
1634 " --version Show package version\n"
1635 " --create Create marked files/directories\n"
1636 " --clean Clean up marked directories\n"
1637 " --remove Remove marked files/directories\n"
1638 " --boot Execute actions only safe at boot\n"
1639 " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n"
1640 " --exclude-prefix=PATH Ignore rules that apply to paths with the specified prefix\n"
1641 " --root=PATH Operate on an alternate filesystem root\n",
1642 program_invocation_short_name);
1645 static int parse_argv(int argc, char *argv[]) {
1648 ARG_VERSION = 0x100,
1658 static const struct option options[] = {
1659 { "help", no_argument, NULL, 'h' },
1660 { "version", no_argument, NULL, ARG_VERSION },
1661 { "create", no_argument, NULL, ARG_CREATE },
1662 { "clean", no_argument, NULL, ARG_CLEAN },
1663 { "remove", no_argument, NULL, ARG_REMOVE },
1664 { "boot", no_argument, NULL, ARG_BOOT },
1665 { "prefix", required_argument, NULL, ARG_PREFIX },
1666 { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
1667 { "root", required_argument, NULL, ARG_ROOT },
1676 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1685 puts(PACKAGE_STRING);
1686 puts(SYSTEMD_FEATURES);
1706 if (strv_push(&arg_include_prefixes, optarg) < 0)
1710 case ARG_EXCLUDE_PREFIX:
1711 if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1717 arg_root = path_make_absolute_cwd(optarg);
1721 path_kill_slashes(arg_root);
1728 assert_not_reached("Unhandled option");
1731 if (!arg_clean && !arg_create && !arg_remove) {
1732 log_error("You need to specify at least one of --clean, --create or --remove.");
1739 static int read_config_file(const char *fn, bool ignore_enoent) {
1740 _cleanup_fclose_ FILE *f = NULL;
1741 char line[LINE_MAX];
1749 r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
1751 if (ignore_enoent && r == -ENOENT)
1754 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
1757 FOREACH_LINE(line, f, break) {
1764 if (*l == '#' || *l == 0)
1767 k = parse_line(fn, v, l);
1768 if (k < 0 && r == 0)
1772 /* we have to determine age parameter for each entry of type X */
1773 HASHMAP_FOREACH(i, globs, iterator) {
1775 Item *j, *candidate_item = NULL;
1777 if (i->type != IGNORE_DIRECTORY_PATH)
1780 HASHMAP_FOREACH(j, items, iter) {
1781 if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
1784 if (path_equal(j->path, i->path)) {
1789 if ((!candidate_item && path_startswith(i->path, j->path)) ||
1790 (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1794 if (candidate_item && candidate_item->age_set) {
1795 i->age = candidate_item->age;
1801 log_error_errno(errno, "Failed to read from file %s: %m", fn);
1809 int main(int argc, char *argv[]) {
1814 r = parse_argv(argc, argv);
1818 log_set_target(LOG_TARGET_AUTO);
1819 log_parse_environment();
1824 mac_selinux_init(NULL);
1826 items = hashmap_new(&string_hash_ops);
1827 globs = hashmap_new(&string_hash_ops);
1829 if (!items || !globs) {
1836 if (optind < argc) {
1839 for (j = optind; j < argc; j++) {
1840 k = read_config_file(argv[j], false);
1841 if (k < 0 && r == 0)
1846 _cleanup_strv_free_ char **files = NULL;
1849 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
1851 log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
1855 STRV_FOREACH(f, files) {
1856 k = read_config_file(*f, true);
1857 if (k < 0 && r == 0)
1862 HASHMAP_FOREACH(a, globs, iterator) {
1863 k = process_item_array(a);
1864 if (k < 0 && r == 0)
1868 HASHMAP_FOREACH(a, items, iterator) {
1869 k = process_item_array(a);
1870 if (k < 0 && r == 0)
1875 while ((a = hashmap_steal_first(items)))
1878 while ((a = hashmap_steal_first(globs)))
1881 hashmap_free(items);
1882 hashmap_free(globs);
1884 free(arg_include_prefixes);
1885 free(arg_exclude_prefixes);
1888 set_free_free(unix_sockets);
1890 mac_selinux_finish();
1892 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;