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 DIR* xopendirat_nomod(int dirfd, const char *path) {
314 dir = xopendirat(dirfd, path, O_NOFOLLOW|O_NOATIME);
316 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m",
317 dirfd == AT_FDCWD ? "" : "sub", path);
318 if (errno == EPERM) {
319 dir = xopendirat(dirfd, path, O_NOFOLLOW);
321 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m",
322 dirfd == AT_FDCWD ? "" : "sub", path);
329 static DIR* opendir_nomod(const char *path) {
330 return xopendirat_nomod(AT_FDCWD, path);
333 static int dir_cleanup(
337 const struct stat *ds,
342 bool keep_this_level) {
345 struct timespec times[2];
346 bool deleted = false;
349 while ((dent = readdir(d))) {
352 _cleanup_free_ char *sub_path = NULL;
354 if (STR_IN_SET(dent->d_name, ".", ".."))
357 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
361 /* FUSE, NFS mounts, SELinux might return EACCES */
363 log_debug_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
365 log_error_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
370 /* Stay on the same filesystem */
371 if (s.st_dev != rootdev) {
372 log_debug("Ignoring \"%s/%s\": different filesystem.", p, dent->d_name);
376 /* Try to detect bind mounts of the same filesystem instance; they
377 * do not differ in device major/minors. This type of query is not
378 * supported on all kernels or filesystem types though. */
379 if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0) {
380 log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.",
385 /* Do not delete read-only files owned by root */
386 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR)) {
387 log_debug("Ignoring \"%s/%s\": read-only and owner by root.", p, dent->d_name);
391 sub_path = strjoin(p, "/", dent->d_name, NULL);
397 /* Is there an item configured for this path? */
398 if (hashmap_get(items, sub_path)) {
399 log_debug("Ignoring \"%s\": a separate entry exists.", sub_path);
403 if (find_glob(globs, sub_path)) {
404 log_debug("Ignoring \"%s\": a separate glob exists.", sub_path);
408 if (S_ISDIR(s.st_mode)) {
411 streq(dent->d_name, "lost+found") &&
413 log_debug("Ignoring \"%s\".", sub_path);
418 log_warning("Reached max depth on \"%s\".", sub_path);
420 _cleanup_closedir_ DIR *sub_dir;
423 sub_dir = xopendirat_nomod(dirfd(d), dent->d_name);
426 r = log_error_errno(errno, "opendir(%s) failed: %m", sub_path);
431 q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
436 /* Note: if you are wondering why we don't
437 * support the sticky bit for excluding
438 * directories from cleaning like we do it for
439 * other file system objects: well, the sticky
440 * bit already has a meaning for directories,
441 * so we don't want to overload that. */
443 if (keep_this_level) {
444 log_debug("Keeping \"%s\".", sub_path);
448 /* Ignore ctime, we change it when deleting */
449 age = timespec_load(&s.st_mtim);
451 char a[FORMAT_TIMESTAMP_MAX];
452 /* Follows spelling in stat(1). */
453 log_debug("Directory \"%s\": modify time %s is too new.",
455 format_timestamp_us(a, sizeof(a), age));
459 age = timespec_load(&s.st_atim);
461 char a[FORMAT_TIMESTAMP_MAX];
462 log_debug("Directory \"%s\": access time %s is too new.",
464 format_timestamp_us(a, sizeof(a), age));
468 log_debug("Removing directory \"%s\".", sub_path);
469 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0)
470 if (errno != ENOENT && errno != ENOTEMPTY) {
471 log_error_errno(errno, "rmdir(%s): %m", sub_path);
476 /* Skip files for which the sticky bit is
477 * set. These are semantics we define, and are
478 * unknown elsewhere. See XDG_RUNTIME_DIR
479 * specification for details. */
480 if (s.st_mode & S_ISVTX) {
481 log_debug("Skipping \"%s\": sticky bit set.", sub_path);
485 if (mountpoint && S_ISREG(s.st_mode))
486 if ((streq(dent->d_name, ".journal") && s.st_uid == 0) ||
487 streq(dent->d_name, "aquota.user") ||
488 streq(dent->d_name, "aquota.group")) {
489 log_debug("Skipping \"%s\".", sub_path);
493 /* Ignore sockets that are listed in /proc/net/unix */
494 if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path)) {
495 log_debug("Skipping \"%s\": live socket.", sub_path);
499 /* Ignore device nodes */
500 if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode)) {
501 log_debug("Skipping \"%s\": a device.", sub_path);
505 /* Keep files on this level around if this is
507 if (keep_this_level) {
508 log_debug("Keeping \"%s\".", sub_path);
512 age = timespec_load(&s.st_mtim);
514 char a[FORMAT_TIMESTAMP_MAX];
515 /* Follows spelling in stat(1). */
516 log_debug("File \"%s\": modify time %s is too new.",
518 format_timestamp_us(a, sizeof(a), age));
522 age = timespec_load(&s.st_atim);
524 char a[FORMAT_TIMESTAMP_MAX];
525 log_debug("File \"%s\": access time %s is too new.",
527 format_timestamp_us(a, sizeof(a), age));
531 age = timespec_load(&s.st_ctim);
533 char a[FORMAT_TIMESTAMP_MAX];
534 log_debug("File \"%s\": change time %s is too new.",
536 format_timestamp_us(a, sizeof(a), age));
540 log_debug("unlink \"%s\"", sub_path);
542 if (unlinkat(dirfd(d), dent->d_name, 0) < 0)
544 r = log_error_errno(errno, "unlink(%s): %m", sub_path);
553 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
555 /* Restore original directory timestamps */
556 times[0] = ds->st_atim;
557 times[1] = ds->st_mtim;
559 age1 = timespec_load(&ds->st_atim);
560 age2 = timespec_load(&ds->st_mtim);
561 log_debug("Restoring access and modification time on \"%s\": %s, %s",
563 format_timestamp_us(a, sizeof(a), age1),
564 format_timestamp_us(b, sizeof(b), age2));
565 if (futimens(dirfd(d), times) < 0)
566 log_error_errno(errno, "utimensat(%s): %m", p);
572 static int path_set_perms(Item *i, const char *path) {
579 st_valid = stat(path, &st) == 0;
581 /* not using i->path directly because it may be a glob */
585 if (i->mask_perms && st_valid) {
586 if (!(st.st_mode & 0111))
588 if (!(st.st_mode & 0222))
590 if (!(st.st_mode & 0444))
592 if (!S_ISDIR(st.st_mode))
593 m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
596 if (st_valid && m == (st.st_mode & 07777))
597 log_debug("\"%s\" has right mode %o", path, st.st_mode);
599 log_debug("chmod \"%s\" to mode %o", path, m);
600 if (chmod(path, m) < 0)
601 return log_error_errno(errno, "chmod(%s) failed: %m", path);
605 if ((!st_valid || i->uid != st.st_uid || i->gid != st.st_gid) &&
606 (i->uid_set || i->gid_set)) {
607 log_debug("chown \"%s\" to "UID_FMT"."GID_FMT,
609 i->uid_set ? i->uid : UID_INVALID,
610 i->gid_set ? i->gid : GID_INVALID);
612 i->uid_set ? i->uid : UID_INVALID,
613 i->gid_set ? i->gid : GID_INVALID) < 0)
615 return log_error_errno(errno, "chown(%s) failed: %m", path);
618 return label_fix(path, false, false);
621 static int get_xattrs_from_arg(Item *i) {
631 while ((r = unquote_first_word(&p, &xattr, false)) > 0) {
632 _cleanup_free_ char *tmp = NULL, *name = NULL,
633 *value = NULL, *value2 = NULL, *_xattr = xattr;
635 r = split_pair(xattr, "=", &name, &value);
637 log_warning("Illegal xattr found: \"%s\" - ignoring.", xattr);
641 if (strempty(name) || strempty(value)) {
642 log_warning("Malformed xattr found: \"%s\" - ignoring.", xattr);
646 tmp = unquote(value, "\"");
650 value2 = cunescape(tmp);
654 if (strv_push_pair(&i->xattrs, name, value2) < 0)
656 name = value2 = NULL;
662 static int path_set_xattrs(Item *i, const char *path) {
663 char **name, **value;
668 STRV_FOREACH_PAIR(name, value, i->xattrs) {
672 log_debug("\"%s\": setting xattr \"%s=%s\"", path, *name, *value);
673 if (lsetxattr(path, *name, *value, n, 0) < 0) {
674 log_error("Setting extended attribute %s=%s on %s failed: %m",
675 *name, *value, path);
682 static int get_acls_from_arg(Item *item) {
685 _cleanup_(acl_freep) acl_t a = NULL, d = NULL;
689 /* If force (= modify) is set, we will not modify the acl
690 * afterwards, so the mask can be added now if necessary. */
691 r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
693 log_warning_errno(errno, "Failed to parse ACL \"%s\": %m. Ignoring",
696 log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
702 static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
703 _cleanup_(acl_freep) acl_t dup = NULL;
705 _cleanup_(acl_free_charpp) char *t = NULL;
708 r = acls_for_file(path, type, acl, &dup);
712 r = calc_acl_mask_if_needed(&dup);
720 /* the mask was already added earlier if needed */
723 r = add_base_acls_if_needed(&dup, path);
727 t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
728 log_debug("\"%s\": setting %s ACL \"%s\"", path,
729 type == ACL_TYPE_ACCESS ? "access" : "default",
732 r = acl_set_file(path, type, dup);
734 return log_error_errno(-errno,
735 "Setting %s ACL \"%s\" on %s failed: %m",
736 type == ACL_TYPE_ACCESS ? "access" : "default",
741 static int path_set_acls(Item *item, const char *path) {
748 if (item->acl_access) {
749 r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
754 if (item->acl_default) {
755 r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
764 static int write_one_file(Item *i, const char *path) {
765 _cleanup_close_ int fd = -1;
772 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
773 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
775 RUN_WITH_UMASK(0000) {
776 mac_selinux_create_file_prepare(path, S_IFREG);
777 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
778 mac_selinux_create_file_clear();
782 if (i->type == WRITE_FILE && errno == ENOENT) {
783 log_debug_errno(errno, "Not writing \"%s\": %m", path);
787 log_error_errno(errno, "Failed to create file %s: %m", path);
792 _cleanup_free_ char *unescaped;
794 log_debug("%s to \"%s\".",
795 i->type == CREATE_FILE ? "Appending" : "Writing", path);
797 unescaped = cunescape(i->argument);
801 r = loop_write(fd, unescaped, strlen(unescaped), false);
803 return log_error_errno(r, "Failed to write file \"%s\": %m", path);
805 log_debug("\"%s\" has been created.", path);
809 if (stat(path, &st) < 0)
810 return log_error_errno(errno, "stat(%s) failed: %m", path);
812 if (!S_ISREG(st.st_mode)) {
813 log_error("%s is not a file.", path);
817 r = path_set_perms(i, path);
824 typedef int (*action_t)(Item *, const char *);
826 static int item_do_children(Item *i, const char *path, action_t action) {
827 _cleanup_closedir_ DIR *d;
833 /* This returns the first error we run into, but nevertheless
836 d = opendir_nomod(path);
838 return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
841 _cleanup_free_ char *p = NULL;
848 if (errno != 0 && r == 0)
854 if (STR_IN_SET(de->d_name, ".", ".."))
857 p = strjoin(path, "/", de->d_name, NULL);
862 if (q < 0 && q != -ENOENT && r == 0)
865 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
866 q = item_do_children(i, p, action);
875 static int glob_item(Item *i, action_t action, bool recursive) {
876 _cleanup_globfree_ glob_t g = {
877 .gl_closedir = (void (*)(void *)) closedir,
878 .gl_readdir = (struct dirent *(*)(void *)) readdir,
879 .gl_opendir = (void *(*)(const char *)) opendir_nomod,
887 k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
888 if (k != 0 && k != GLOB_NOMATCH)
889 return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
891 STRV_FOREACH(fn, g.gl_pathv) {
897 k = item_do_children(i, *fn, action);
906 static int create_item(Item *i) {
912 log_debug("Running create action for entry %c %s", (char) i->type, i->path);
917 case IGNORE_DIRECTORY_PATH:
919 case RECURSIVE_REMOVE_PATH:
924 r = write_one_file(i, i->path);
930 log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
931 r = copy_tree(i->argument, i->path, false);
936 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
938 if (stat(i->argument, &a) < 0)
939 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
941 if (stat(i->path, &b) < 0)
942 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
944 if ((a.st_mode ^ b.st_mode) & S_IFMT) {
945 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
950 r = path_set_perms(i, i->path);
957 r = glob_item(i, write_one_file, false);
963 case CREATE_DIRECTORY:
964 case TRUNCATE_DIRECTORY:
965 case CREATE_SUBVOLUME:
968 mkdir_parents_label(i->path, 0755);
970 if (i->type == CREATE_SUBVOLUME)
971 RUN_WITH_UMASK((~i->mode) & 0777) {
972 r = btrfs_subvol_make(i->path);
973 log_debug_errno(r, "Creating subvolume \"%s\": %m", i->path);
978 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
980 r = mkdir_label(i->path, i->mode);
984 return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);
986 if (stat(i->path, &st) < 0)
987 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
989 if (!S_ISDIR(st.st_mode)) {
990 log_debug("\"%s\" already exists and is not a directory.", i->path);
994 log_debug("Created directory \"%s\".", i->path);
996 r = path_set_perms(i, i->path);
1004 RUN_WITH_UMASK(0000) {
1005 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1006 r = mkfifo(i->path, i->mode);
1007 mac_selinux_create_file_clear();
1011 if (errno != EEXIST)
1012 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
1014 if (stat(i->path, &st) < 0)
1015 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1017 if (!S_ISFIFO(st.st_mode)) {
1021 RUN_WITH_UMASK(0000) {
1022 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1023 r = mkfifo_atomic(i->path, i->mode);
1024 mac_selinux_create_file_clear();
1028 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
1030 log_debug("%s is not a fifo.", i->path);
1035 log_debug("Created fifo \"%s\".", i->path);
1037 r = path_set_perms(i, i->path);
1043 case CREATE_SYMLINK:
1045 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1046 r = symlink(i->argument, i->path);
1047 mac_selinux_create_file_clear();
1050 _cleanup_free_ char *x = NULL;
1052 if (errno != EEXIST)
1053 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
1055 r = readlink_malloc(i->path, &x);
1056 if (r < 0 || !streq(i->argument, x)) {
1059 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1060 r = symlink_atomic(i->argument, i->path);
1061 mac_selinux_create_file_clear();
1064 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
1066 log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
1071 log_debug("Created symlink \"%s\".", i->path);
1075 case CREATE_BLOCK_DEVICE:
1076 case CREATE_CHAR_DEVICE: {
1079 if (have_effective_cap(CAP_MKNOD) == 0) {
1080 /* In a container we lack CAP_MKNOD. We
1081 shouldn't attempt to create the device node in
1082 that case to avoid noise, and we don't support
1083 virtualized devices in containers anyway. */
1085 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
1089 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
1091 RUN_WITH_UMASK(0000) {
1092 mac_selinux_create_file_prepare(i->path, file_type);
1093 r = mknod(i->path, i->mode | file_type, i->major_minor);
1094 mac_selinux_create_file_clear();
1098 if (errno == EPERM) {
1099 log_debug("We lack permissions, possibly because of cgroup configuration; "
1100 "skipping creation of device node %s.", i->path);
1104 if (errno != EEXIST)
1105 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1107 if (stat(i->path, &st) < 0)
1108 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1110 if ((st.st_mode & S_IFMT) != file_type) {
1114 RUN_WITH_UMASK(0000) {
1115 mac_selinux_create_file_prepare(i->path, file_type);
1116 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1117 mac_selinux_create_file_clear();
1121 return log_error_errno(r, "Failed to create device node %s: %m", i->path);
1123 log_debug("%s is not a device node.", i->path);
1128 log_debug("Created %s device node \"%s\" %u:%u.",
1129 i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
1130 i->path, major(i->mode), minor(i->mode));
1132 r = path_set_perms(i, i->path);
1141 r = glob_item(i, path_set_perms, false);
1146 case RECURSIVE_RELABEL_PATH:
1147 r = glob_item(i, path_set_perms, true);
1153 r = glob_item(i, path_set_xattrs, false);
1158 case RECURSIVE_SET_XATTR:
1159 r = glob_item(i, path_set_xattrs, true);
1165 r = glob_item(i, path_set_acls, false);
1170 case RECURSIVE_SET_ACL:
1171 r = glob_item(i, path_set_acls, true);
1177 log_debug("%s created successfully.", i->path);
1182 static int remove_item_instance(Item *i, const char *instance) {
1190 if (remove(instance) < 0 && errno != ENOENT)
1191 return log_error_errno(errno, "rm(%s): %m", instance);
1195 case TRUNCATE_DIRECTORY:
1196 case RECURSIVE_REMOVE_PATH:
1197 /* FIXME: we probably should use dir_cleanup() here
1198 * instead of rm_rf() so that 'x' is honoured. */
1199 log_debug("rm -rf \"%s\"", instance);
1200 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1201 if (r < 0 && r != -ENOENT)
1202 return log_error_errno(r, "rm_rf(%s): %m", instance);
1207 assert_not_reached("wut?");
1213 static int remove_item(Item *i) {
1218 log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
1224 case CREATE_DIRECTORY:
1225 case CREATE_SUBVOLUME:
1227 case CREATE_SYMLINK:
1228 case CREATE_CHAR_DEVICE:
1229 case CREATE_BLOCK_DEVICE:
1231 case IGNORE_DIRECTORY_PATH:
1234 case RECURSIVE_RELABEL_PATH:
1238 case RECURSIVE_SET_XATTR:
1240 case RECURSIVE_SET_ACL:
1244 case TRUNCATE_DIRECTORY:
1245 case RECURSIVE_REMOVE_PATH:
1246 r = glob_item(i, remove_item_instance, false);
1253 static int clean_item_instance(Item *i, const char* instance) {
1254 _cleanup_closedir_ DIR *d = NULL;
1258 char timestamp[FORMAT_TIMESTAMP_MAX];
1265 n = now(CLOCK_REALTIME);
1269 cutoff = n - i->age;
1271 d = opendir_nomod(instance);
1273 if (errno == ENOENT || errno == ENOTDIR) {
1274 log_debug_errno(errno, "Directory \"%s\": %m", instance);
1278 log_error_errno(errno, "Failed to open directory %s: %m", instance);
1282 if (fstat(dirfd(d), &s) < 0)
1283 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1285 if (!S_ISDIR(s.st_mode)) {
1286 log_error("%s is not a directory.", i->path);
1290 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1291 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1293 mountpoint = s.st_dev != ps.st_dev ||
1294 (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1296 log_debug("Cleanup threshold for %s \"%s\" is %s",
1297 mountpoint ? "mount point" : "directory",
1299 format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
1301 return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1302 MAX_DEPTH, i->keep_first_level);
1305 static int clean_item(Item *i) {
1310 log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
1313 case CREATE_DIRECTORY:
1314 case CREATE_SUBVOLUME:
1315 case TRUNCATE_DIRECTORY:
1318 clean_item_instance(i, i->path);
1320 case IGNORE_DIRECTORY_PATH:
1321 r = glob_item(i, clean_item_instance, false);
1330 static int process_item_array(ItemArray *array);
1332 static int process_item(Item *i) {
1334 _cleanup_free_ char *prefix = NULL;
1343 prefix = malloc(strlen(i->path) + 1);
1347 PATH_FOREACH_PREFIX(prefix, i->path) {
1350 j = hashmap_get(items, prefix);
1354 s = process_item_array(j);
1355 if (s < 0 && t == 0)
1360 r = arg_create ? create_item(i) : 0;
1361 q = arg_remove ? remove_item(i) : 0;
1362 p = arg_clean ? clean_item(i) : 0;
1370 static int process_item_array(ItemArray *array) {
1376 for (n = 0; n < array->count; n++) {
1377 k = process_item(array->items + n);
1378 if (k < 0 && r == 0)
1385 static void item_free_contents(Item *i) {
1389 strv_free(i->xattrs);
1392 acl_free(i->acl_access);
1393 acl_free(i->acl_default);
1397 static void item_array_free(ItemArray *a) {
1403 for (n = 0; n < a->count; n++)
1404 item_free_contents(a->items + n);
1409 static bool item_compatible(Item *a, Item *b) {
1412 assert(streq(a->path, b->path));
1414 if (takes_ownership(a->type) && takes_ownership(b->type))
1415 /* check if the items are the same */
1416 return streq_ptr(a->argument, b->argument) &&
1418 a->uid_set == b->uid_set &&
1421 a->gid_set == b->gid_set &&
1424 a->mode_set == b->mode_set &&
1425 a->mode == b->mode &&
1427 a->age_set == b->age_set &&
1430 a->mask_perms == b->mask_perms &&
1432 a->keep_first_level == b->keep_first_level &&
1434 a->major_minor == b->major_minor;
1439 static bool should_include_path(const char *path) {
1442 STRV_FOREACH(prefix, arg_exclude_prefixes)
1443 if (path_startswith(path, *prefix)) {
1444 log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
1449 STRV_FOREACH(prefix, arg_include_prefixes)
1450 if (path_startswith(path, *prefix)) {
1451 log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
1455 /* no matches, so we should include this path only if we
1456 * have no whitelist at all */
1457 if (strv_length(arg_include_prefixes) == 0)
1460 log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
1464 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1466 static const Specifier specifier_table[] = {
1467 { 'm', specifier_machine_id, NULL },
1468 { 'b', specifier_boot_id, NULL },
1469 { 'H', specifier_host_name, NULL },
1470 { 'v', specifier_kernel_release, NULL },
1474 _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1475 _cleanup_(item_free_contents) Item i = {};
1476 ItemArray *existing;
1479 bool force = false, boot = false;
1486 "%ms %ms %ms %ms %ms %ms %n",
1495 log_error("[%s:%u] Syntax error.", fname, line);
1499 if (isempty(action)) {
1500 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1504 for (pos = 1; action[pos]; pos++) {
1505 if (action[pos] == '!' && !boot)
1507 else if (action[pos] == '+' && !force)
1510 log_error("[%s:%u] Unknown modifiers in command '%s'",
1511 fname, line, action);
1516 if (boot && !arg_boot) {
1517 log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
1525 r = specifier_printf(path, specifier_table, NULL, &i.path);
1527 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1532 c += strspn(buffer+c, WHITESPACE);
1533 if (buffer[c] != 0 && (buffer[c] != '-' || buffer[c+1] != 0)) {
1534 i.argument = unquote(buffer+c, "\"");
1544 case CREATE_DIRECTORY:
1545 case CREATE_SUBVOLUME:
1546 case TRUNCATE_DIRECTORY:
1549 case IGNORE_DIRECTORY_PATH:
1551 case RECURSIVE_REMOVE_PATH:
1554 case RECURSIVE_RELABEL_PATH:
1557 case CREATE_SYMLINK:
1559 i.argument = strappend("/usr/share/factory/", i.path);
1567 log_error("[%s:%u] Write file requires argument.", fname, line);
1574 i.argument = strappend("/usr/share/factory/", i.path);
1577 } else if (!path_is_absolute(i.argument)) {
1578 log_error("[%s:%u] Source path is not absolute.", fname, line);
1582 path_kill_slashes(i.argument);
1585 case CREATE_CHAR_DEVICE:
1586 case CREATE_BLOCK_DEVICE: {
1587 unsigned major, minor;
1590 log_error("[%s:%u] Device file requires argument.", fname, line);
1594 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1595 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1599 i.major_minor = makedev(major, minor);
1604 case RECURSIVE_SET_XATTR:
1606 log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1609 r = get_xattrs_from_arg(&i);
1615 case RECURSIVE_SET_ACL:
1617 log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1620 r = get_acls_from_arg(&i);
1626 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
1630 if (!path_is_absolute(i.path)) {
1631 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1635 path_kill_slashes(i.path);
1637 if (!should_include_path(i.path))
1643 p = strappend(arg_root, i.path);
1651 if (user && !streq(user, "-")) {
1652 const char *u = user;
1654 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1656 log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1663 if (group && !streq(group, "-")) {
1664 const char *g = group;
1666 r = get_group_creds(&g, &i.gid);
1668 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1675 if (mode && !streq(mode, "-")) {
1676 const char *mm = mode;
1680 i.mask_perms = true;
1684 if (sscanf(mm, "%o", &m) != 1) {
1685 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1692 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1695 if (age && !streq(age, "-")) {
1696 const char *a = age;
1699 i.keep_first_level = true;
1703 if (parse_sec(a, &i.age) < 0) {
1704 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1711 h = needs_glob(i.type) ? globs : items;
1713 existing = hashmap_get(h, i.path);
1717 for (n = 0; n < existing->count; n++) {
1718 if (!item_compatible(existing->items + n, &i))
1719 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1720 fname, line, i.path);
1723 existing = new0(ItemArray, 1);
1724 r = hashmap_put(h, i.path, existing);
1729 if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1732 memcpy(existing->items + existing->count++, &i, sizeof(i));
1737 static void help(void) {
1738 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1739 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1740 " -h --help Show this help\n"
1741 " --version Show package version\n"
1742 " --create Create marked files/directories\n"
1743 " --clean Clean up marked directories\n"
1744 " --remove Remove marked files/directories\n"
1745 " --boot Execute actions only safe at boot\n"
1746 " --prefix=PATH Only apply rules with the specified prefix\n"
1747 " --exclude-prefix=PATH Ignore rules with the specified prefix\n"
1748 " --root=PATH Operate on an alternate filesystem root\n",
1749 program_invocation_short_name);
1752 static int parse_argv(int argc, char *argv[]) {
1755 ARG_VERSION = 0x100,
1765 static const struct option options[] = {
1766 { "help", no_argument, NULL, 'h' },
1767 { "version", no_argument, NULL, ARG_VERSION },
1768 { "create", no_argument, NULL, ARG_CREATE },
1769 { "clean", no_argument, NULL, ARG_CLEAN },
1770 { "remove", no_argument, NULL, ARG_REMOVE },
1771 { "boot", no_argument, NULL, ARG_BOOT },
1772 { "prefix", required_argument, NULL, ARG_PREFIX },
1773 { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
1774 { "root", required_argument, NULL, ARG_ROOT },
1783 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1792 puts(PACKAGE_STRING);
1793 puts(SYSTEMD_FEATURES);
1813 if (strv_push(&arg_include_prefixes, optarg) < 0)
1817 case ARG_EXCLUDE_PREFIX:
1818 if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1824 arg_root = path_make_absolute_cwd(optarg);
1828 path_kill_slashes(arg_root);
1835 assert_not_reached("Unhandled option");
1838 if (!arg_clean && !arg_create && !arg_remove) {
1839 log_error("You need to specify at least one of --clean, --create or --remove.");
1846 static int read_config_file(const char *fn, bool ignore_enoent) {
1847 _cleanup_fclose_ FILE *f = NULL;
1848 char line[LINE_MAX];
1856 r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
1858 if (ignore_enoent && r == -ENOENT) {
1859 log_debug_errno(r, "Failed to open \"%s\": %m", fn);
1863 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
1865 log_debug("Reading config file \"%s\".", fn);
1867 FOREACH_LINE(line, f, break) {
1874 if (*l == '#' || *l == 0)
1877 k = parse_line(fn, v, l);
1878 if (k < 0 && r == 0)
1882 /* we have to determine age parameter for each entry of type X */
1883 HASHMAP_FOREACH(i, globs, iterator) {
1885 Item *j, *candidate_item = NULL;
1887 if (i->type != IGNORE_DIRECTORY_PATH)
1890 HASHMAP_FOREACH(j, items, iter) {
1891 if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
1894 if (path_equal(j->path, i->path)) {
1899 if ((!candidate_item && path_startswith(i->path, j->path)) ||
1900 (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1904 if (candidate_item && candidate_item->age_set) {
1905 i->age = candidate_item->age;
1911 log_error_errno(errno, "Failed to read from file %s: %m", fn);
1919 int main(int argc, char *argv[]) {
1924 r = parse_argv(argc, argv);
1928 log_set_target(LOG_TARGET_AUTO);
1929 log_parse_environment();
1934 mac_selinux_init(NULL);
1936 items = hashmap_new(&string_hash_ops);
1937 globs = hashmap_new(&string_hash_ops);
1939 if (!items || !globs) {
1946 if (optind < argc) {
1949 for (j = optind; j < argc; j++) {
1950 k = read_config_file(argv[j], false);
1951 if (k < 0 && r == 0)
1956 _cleanup_strv_free_ char **files = NULL;
1959 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
1961 log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
1965 STRV_FOREACH(f, files) {
1966 k = read_config_file(*f, true);
1967 if (k < 0 && r == 0)
1972 HASHMAP_FOREACH(a, globs, iterator) {
1973 k = process_item_array(a);
1974 if (k < 0 && r == 0)
1978 HASHMAP_FOREACH(a, items, iterator) {
1979 k = process_item_array(a);
1980 if (k < 0 && r == 0)
1985 while ((a = hashmap_steal_first(items)))
1988 while ((a = hashmap_steal_first(globs)))
1991 hashmap_free(items);
1992 hashmap_free(globs);
1994 free(arg_include_prefixes);
1995 free(arg_exclude_prefixes);
1998 set_free_free(unix_sockets);
2000 mac_selinux_finish();
2002 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;