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/>.
38 #include <sys/xattr.h>
46 #include "path-util.h"
50 #include "conf-files.h"
51 #include "capability.h"
52 #include "specifier.h"
55 #include "selinux-util.h"
56 #include "btrfs-util.h"
59 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
60 * them in the file system. This is intended to be used to create
61 * properly owned directories beneath /tmp, /var/tmp, /run, which are
62 * volatile and hence need to be recreated on bootup. */
64 typedef enum ItemType {
65 /* These ones take file names */
68 CREATE_DIRECTORY = 'd',
69 TRUNCATE_DIRECTORY = 'D',
70 CREATE_SUBVOLUME = 'v',
73 CREATE_CHAR_DEVICE = 'c',
74 CREATE_BLOCK_DEVICE = 'b',
77 /* These ones take globs */
79 RECURSIVE_SET_XATTR = 'T',
81 RECURSIVE_SET_ACL = 'A',
84 IGNORE_DIRECTORY_PATH = 'X',
86 RECURSIVE_REMOVE_PATH = 'R',
87 ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */
89 RECURSIVE_RELABEL_PATH = 'Z',
91 RECURSIVE_SET_ATTRIB = 'H',
110 unsigned long attrib_value;
111 unsigned long attrib_mask;
120 bool keep_first_level:1;
127 typedef struct ItemArray {
133 static bool arg_create = false;
134 static bool arg_clean = false;
135 static bool arg_remove = false;
136 static bool arg_boot = false;
138 static char **arg_include_prefixes = NULL;
139 static char **arg_exclude_prefixes = NULL;
140 static char *arg_root = NULL;
142 static const char conf_file_dirs[] = CONF_DIRS_NULSTR("tmpfiles");
144 #define MAX_DEPTH 256
146 static Hashmap *items = NULL, *globs = NULL;
147 static Set *unix_sockets = NULL;
149 static bool needs_glob(ItemType t) {
153 IGNORE_DIRECTORY_PATH,
155 RECURSIVE_REMOVE_PATH,
158 RECURSIVE_RELABEL_PATH,
165 static bool takes_ownership(ItemType t) {
180 IGNORE_DIRECTORY_PATH,
182 RECURSIVE_REMOVE_PATH);
185 static struct Item* find_glob(Hashmap *h, const char *match) {
189 HASHMAP_FOREACH(j, h, i) {
192 for (n = 0; n < j->count; n++) {
193 Item *item = j->items + n;
195 if (fnmatch(item->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
203 static void load_unix_sockets(void) {
204 _cleanup_fclose_ FILE *f = NULL;
210 /* We maintain a cache of the sockets we found in
211 * /proc/net/unix to speed things up a little. */
213 unix_sockets = set_new(&string_hash_ops);
217 f = fopen("/proc/net/unix", "re");
222 if (!fgets(line, sizeof(line), f))
229 if (!fgets(line, sizeof(line), f))
234 p = strchr(line, ':');
242 p += strspn(p, WHITESPACE);
243 p += strcspn(p, WHITESPACE); /* skip one more word */
244 p += strspn(p, WHITESPACE);
253 path_kill_slashes(s);
255 k = set_consume(unix_sockets, s);
256 if (k < 0 && k != -EEXIST)
263 set_free_free(unix_sockets);
267 static bool unix_socket_alive(const char *fn) {
273 return !!set_get(unix_sockets, (char*) fn);
275 /* We don't know, so assume yes */
279 static int dir_is_mount_point(DIR *d, const char *subdir) {
281 union file_handle_union h = FILE_HANDLE_INIT;
282 int mount_id_parent, mount_id;
285 r_p = name_to_handle_at(dirfd(d), ".", &h.handle, &mount_id_parent, 0);
289 h.handle.handle_bytes = MAX_HANDLE_SZ;
290 r = name_to_handle_at(dirfd(d), subdir, &h.handle, &mount_id, 0);
294 /* got no handle; make no assumptions, return error */
295 if (r_p < 0 && r < 0)
298 /* got both handles; if they differ, it is a mount point */
299 if (r_p >= 0 && r >= 0)
300 return mount_id_parent != mount_id;
302 /* got only one handle; assume different mount points if one
303 * of both queries was not supported by the filesystem */
304 if (r_p == -ENOSYS || r_p == -EOPNOTSUPP || r == -ENOSYS || r == -EOPNOTSUPP)
313 static DIR* xopendirat_nomod(int dirfd, const char *path) {
316 dir = xopendirat(dirfd, path, O_NOFOLLOW|O_NOATIME);
318 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m",
319 dirfd == AT_FDCWD ? "" : "sub", path);
320 if (errno == EPERM) {
321 dir = xopendirat(dirfd, path, O_NOFOLLOW);
323 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m",
324 dirfd == AT_FDCWD ? "" : "sub", path);
331 static DIR* opendir_nomod(const char *path) {
332 return xopendirat_nomod(AT_FDCWD, path);
335 static int dir_cleanup(
339 const struct stat *ds,
344 bool keep_this_level) {
347 struct timespec times[2];
348 bool deleted = false;
351 while ((dent = readdir(d))) {
354 _cleanup_free_ char *sub_path = NULL;
356 if (STR_IN_SET(dent->d_name, ".", ".."))
359 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
363 /* FUSE, NFS mounts, SELinux might return EACCES */
365 log_debug_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
367 log_error_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
372 /* Stay on the same filesystem */
373 if (s.st_dev != rootdev) {
374 log_debug("Ignoring \"%s/%s\": different filesystem.", p, dent->d_name);
378 /* Try to detect bind mounts of the same filesystem instance; they
379 * do not differ in device major/minors. This type of query is not
380 * supported on all kernels or filesystem types though. */
381 if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0) {
382 log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.",
387 /* Do not delete read-only files owned by root */
388 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR)) {
389 log_debug("Ignoring \"%s/%s\": read-only and owner by root.", p, dent->d_name);
393 sub_path = strjoin(p, "/", dent->d_name, NULL);
399 /* Is there an item configured for this path? */
400 if (hashmap_get(items, sub_path)) {
401 log_debug("Ignoring \"%s\": a separate entry exists.", sub_path);
405 if (find_glob(globs, sub_path)) {
406 log_debug("Ignoring \"%s\": a separate glob exists.", sub_path);
410 if (S_ISDIR(s.st_mode)) {
413 streq(dent->d_name, "lost+found") &&
415 log_debug("Ignoring \"%s\".", sub_path);
420 log_warning("Reached max depth on \"%s\".", sub_path);
422 _cleanup_closedir_ DIR *sub_dir;
425 sub_dir = xopendirat_nomod(dirfd(d), dent->d_name);
428 r = log_error_errno(errno, "opendir(%s) failed: %m", sub_path);
433 q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
438 /* Note: if you are wondering why we don't
439 * support the sticky bit for excluding
440 * directories from cleaning like we do it for
441 * other file system objects: well, the sticky
442 * bit already has a meaning for directories,
443 * so we don't want to overload that. */
445 if (keep_this_level) {
446 log_debug("Keeping \"%s\".", sub_path);
450 /* Ignore ctime, we change it when deleting */
451 age = timespec_load(&s.st_mtim);
453 char a[FORMAT_TIMESTAMP_MAX];
454 /* Follows spelling in stat(1). */
455 log_debug("Directory \"%s\": modify time %s is too new.",
457 format_timestamp_us(a, sizeof(a), age));
461 age = timespec_load(&s.st_atim);
463 char a[FORMAT_TIMESTAMP_MAX];
464 log_debug("Directory \"%s\": access time %s is too new.",
466 format_timestamp_us(a, sizeof(a), age));
470 log_debug("Removing directory \"%s\".", sub_path);
471 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0)
472 if (errno != ENOENT && errno != ENOTEMPTY) {
473 log_error_errno(errno, "rmdir(%s): %m", sub_path);
478 /* Skip files for which the sticky bit is
479 * set. These are semantics we define, and are
480 * unknown elsewhere. See XDG_RUNTIME_DIR
481 * specification for details. */
482 if (s.st_mode & S_ISVTX) {
483 log_debug("Skipping \"%s\": sticky bit set.", sub_path);
487 if (mountpoint && S_ISREG(s.st_mode))
488 if ((streq(dent->d_name, ".journal") && s.st_uid == 0) ||
489 streq(dent->d_name, "aquota.user") ||
490 streq(dent->d_name, "aquota.group")) {
491 log_debug("Skipping \"%s\".", sub_path);
495 /* Ignore sockets that are listed in /proc/net/unix */
496 if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path)) {
497 log_debug("Skipping \"%s\": live socket.", sub_path);
501 /* Ignore device nodes */
502 if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode)) {
503 log_debug("Skipping \"%s\": a device.", sub_path);
507 /* Keep files on this level around if this is
509 if (keep_this_level) {
510 log_debug("Keeping \"%s\".", sub_path);
514 age = timespec_load(&s.st_mtim);
516 char a[FORMAT_TIMESTAMP_MAX];
517 /* Follows spelling in stat(1). */
518 log_debug("File \"%s\": modify time %s is too new.",
520 format_timestamp_us(a, sizeof(a), age));
524 age = timespec_load(&s.st_atim);
526 char a[FORMAT_TIMESTAMP_MAX];
527 log_debug("File \"%s\": access time %s is too new.",
529 format_timestamp_us(a, sizeof(a), age));
533 age = timespec_load(&s.st_ctim);
535 char a[FORMAT_TIMESTAMP_MAX];
536 log_debug("File \"%s\": change time %s is too new.",
538 format_timestamp_us(a, sizeof(a), age));
542 log_debug("unlink \"%s\"", sub_path);
544 if (unlinkat(dirfd(d), dent->d_name, 0) < 0)
546 r = log_error_errno(errno, "unlink(%s): %m", sub_path);
555 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
557 /* Restore original directory timestamps */
558 times[0] = ds->st_atim;
559 times[1] = ds->st_mtim;
561 age1 = timespec_load(&ds->st_atim);
562 age2 = timespec_load(&ds->st_mtim);
563 log_debug("Restoring access and modification time on \"%s\": %s, %s",
565 format_timestamp_us(a, sizeof(a), age1),
566 format_timestamp_us(b, sizeof(b), age2));
567 if (futimens(dirfd(d), times) < 0)
568 log_error_errno(errno, "utimensat(%s): %m", p);
574 static int path_set_perms(Item *i, const char *path) {
581 st_valid = stat(path, &st) == 0;
583 /* not using i->path directly because it may be a glob */
587 if (i->mask_perms && st_valid) {
588 if (!(st.st_mode & 0111))
590 if (!(st.st_mode & 0222))
592 if (!(st.st_mode & 0444))
594 if (!S_ISDIR(st.st_mode))
595 m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
598 if (st_valid && m == (st.st_mode & 07777))
599 log_debug("\"%s\" has right mode %o", path, st.st_mode);
601 log_debug("chmod \"%s\" to mode %o", path, m);
602 if (chmod(path, m) < 0)
603 return log_error_errno(errno, "chmod(%s) failed: %m", path);
607 if ((!st_valid || i->uid != st.st_uid || i->gid != st.st_gid) &&
608 (i->uid_set || i->gid_set)) {
609 log_debug("chown \"%s\" to "UID_FMT"."GID_FMT,
611 i->uid_set ? i->uid : UID_INVALID,
612 i->gid_set ? i->gid : GID_INVALID);
614 i->uid_set ? i->uid : UID_INVALID,
615 i->gid_set ? i->gid : GID_INVALID) < 0)
617 return log_error_errno(errno, "chown(%s) failed: %m", path);
620 return label_fix(path, false, false);
623 static int get_xattrs_from_arg(Item *i) {
633 while ((r = unquote_first_word(&p, &xattr, false)) > 0) {
634 _cleanup_free_ char *tmp = NULL, *name = NULL,
635 *value = NULL, *value2 = NULL, *_xattr = xattr;
637 r = split_pair(xattr, "=", &name, &value);
639 log_warning("Illegal xattr found: \"%s\" - ignoring.", xattr);
643 if (strempty(name) || strempty(value)) {
644 log_warning("Malformed xattr found: \"%s\" - ignoring.", xattr);
648 tmp = unquote(value, "\"");
652 value2 = cunescape(tmp);
656 if (strv_push_pair(&i->xattrs, name, value2) < 0)
658 name = value2 = NULL;
664 static int path_set_xattrs(Item *i, const char *path) {
665 char **name, **value;
670 STRV_FOREACH_PAIR(name, value, i->xattrs) {
674 log_debug("\"%s\": setting xattr \"%s=%s\"", path, *name, *value);
675 if (lsetxattr(path, *name, *value, n, 0) < 0) {
676 log_error("Setting extended attribute %s=%s on %s failed: %m",
677 *name, *value, path);
684 static int get_acls_from_arg(Item *item) {
690 /* If force (= modify) is set, we will not modify the acl
691 * afterwards, so the mask can be added now if necessary. */
692 r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
694 log_warning_errno(r, "Failed to parse ACL \"%s\": %m. Ignoring",
697 log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
704 static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
705 _cleanup_(acl_freep) acl_t dup = NULL;
707 _cleanup_(acl_free_charpp) char *t = NULL;
709 /* Returns 0 for success, positive error if already warned,
710 * negative error otherwise. */
713 r = acls_for_file(path, type, acl, &dup);
717 r = calc_acl_mask_if_needed(&dup);
725 /* the mask was already added earlier if needed */
728 r = add_base_acls_if_needed(&dup, path);
732 t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
733 log_debug("\"%s\": setting %s ACL \"%s\"", path,
734 type == ACL_TYPE_ACCESS ? "access" : "default",
737 r = acl_set_file(path, type, dup);
739 return -log_error_errno(errno,
740 "Setting %s ACL \"%s\" on %s failed: %m",
741 type == ACL_TYPE_ACCESS ? "access" : "default",
748 static int path_set_acls(Item *item, const char *path) {
754 if (item->acl_access)
755 r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
757 if (r == 0 && item->acl_default)
758 r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
761 return -r; /* already warned */
762 else if (r == -EOPNOTSUPP) {
763 log_debug_errno(r, "ACLs not supported by file system at %s", path);
766 log_error_errno(r, "ACL operation on \"%s\" failed: %m", path);
771 #define ALL_ATTRIBS \
780 FS_JOURNAL_DATA_FL | \
787 static int get_attrib_from_arg(Item *item) {
788 static const unsigned attributes[] = {
789 [(uint8_t)'A'] = FS_NOATIME_FL, /* do not update atime */
790 [(uint8_t)'S'] = FS_SYNC_FL, /* Synchronous updates */
791 [(uint8_t)'D'] = FS_DIRSYNC_FL, /* dirsync behaviour (directories only) */
792 [(uint8_t)'a'] = FS_APPEND_FL, /* writes to file may only append */
793 [(uint8_t)'c'] = FS_COMPR_FL, /* Compress file */
794 [(uint8_t)'d'] = FS_NODUMP_FL, /* do not dump file */
795 [(uint8_t)'e'] = FS_EXTENT_FL, /* Top of directory hierarchies*/
796 [(uint8_t)'i'] = FS_IMMUTABLE_FL, /* Immutable file */
797 [(uint8_t)'j'] = FS_JOURNAL_DATA_FL, /* Reserved for ext3 */
798 [(uint8_t)'s'] = FS_SECRM_FL, /* Secure deletion */
799 [(uint8_t)'u'] = FS_UNRM_FL, /* Undelete */
800 [(uint8_t)'t'] = FS_NOTAIL_FL, /* file tail should not be merged */
801 [(uint8_t)'T'] = FS_TOPDIR_FL, /* Top of directory hierarchies*/
802 [(uint8_t)'C'] = FS_NOCOW_FL, /* Do not cow file */
804 char *p = item->argument;
810 unsigned long value = 0, mask = 0;
813 log_error("\"%s\": setting ATTR need an argument", item->path);
820 } else if (*p == '-') {
823 } else if (*p == '=') {
828 if (!*p && mode != MODE_SET) {
829 log_error("\"%s\": setting ATTR: argument is empty", item->path);
833 if ((uint8_t)*p >= ELEMENTSOF(attributes) || attributes[(uint8_t)*p] == 0) {
834 log_error("\"%s\": setting ATTR: unknown attr '%c'", item->path, *p);
837 if (mode == MODE_ADD || mode == MODE_SET)
838 value |= attributes[(uint8_t)*p];
840 value &= ~attributes[(uint8_t)*p];
841 mask |= attributes[(uint8_t)*p];
844 if (mode == MODE_SET)
849 item->attrib_mask = mask;
850 item->attrib_value = value;
851 item->attrib_set = true;
857 static int path_set_attrib(Item *item, const char *path) {
858 _cleanup_close_ int fd = -1;
864 if (item->attrib_mask == 0 || !item->attrib_set)
867 * It is OK to ignore an lstat() error, because the error
868 * will be catch by the open() below anyway
870 if (lstat(path, &st) == 0 &&
871 !S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
875 fd = open(path, O_RDONLY|O_NONBLOCK|O_CLOEXEC);
878 return log_error_errno(errno, "Cannot open \"%s\": %m", path);
880 f = item->attrib_value & item->attrib_mask;
881 if (!S_ISDIR(st.st_mode))
883 r = change_attr_fd(fd, f, item->attrib_mask);
885 return log_error_errno(errno,
886 "Cannot set attrib for \"%s\", value=0x%08lx, mask=0x%08lx: %m",
887 path, item->attrib_value, item->attrib_mask);
892 static int write_one_file(Item *i, const char *path) {
893 _cleanup_close_ int fd = -1;
900 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
901 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
903 RUN_WITH_UMASK(0000) {
904 mac_selinux_create_file_prepare(path, S_IFREG);
905 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
906 mac_selinux_create_file_clear();
910 if (i->type == WRITE_FILE && errno == ENOENT) {
911 log_debug_errno(errno, "Not writing \"%s\": %m", path);
915 log_error_errno(errno, "Failed to create file %s: %m", path);
920 _cleanup_free_ char *unescaped;
922 log_debug("%s to \"%s\".",
923 i->type == CREATE_FILE ? "Appending" : "Writing", path);
925 unescaped = cunescape(i->argument);
929 r = loop_write(fd, unescaped, strlen(unescaped), false);
931 return log_error_errno(r, "Failed to write file \"%s\": %m", path);
933 log_debug("\"%s\" has been created.", path);
937 if (stat(path, &st) < 0)
938 return log_error_errno(errno, "stat(%s) failed: %m", path);
940 if (!S_ISREG(st.st_mode)) {
941 log_error("%s is not a file.", path);
945 r = path_set_perms(i, path);
952 typedef int (*action_t)(Item *, const char *);
954 static int item_do_children(Item *i, const char *path, action_t action) {
955 _cleanup_closedir_ DIR *d;
961 /* This returns the first error we run into, but nevertheless
964 d = opendir_nomod(path);
966 return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
969 _cleanup_free_ char *p = NULL;
976 if (errno != 0 && r == 0)
982 if (STR_IN_SET(de->d_name, ".", ".."))
985 p = strjoin(path, "/", de->d_name, NULL);
990 if (q < 0 && q != -ENOENT && r == 0)
993 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
994 q = item_do_children(i, p, action);
1003 static int glob_item(Item *i, action_t action, bool recursive) {
1004 _cleanup_globfree_ glob_t g = {
1005 .gl_closedir = (void (*)(void *)) closedir,
1006 .gl_readdir = (struct dirent *(*)(void *)) readdir,
1007 .gl_opendir = (void *(*)(const char *)) opendir_nomod,
1015 k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
1016 if (k != 0 && k != GLOB_NOMATCH)
1017 return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
1019 STRV_FOREACH(fn, g.gl_pathv) {
1021 if (k < 0 && r == 0)
1025 k = item_do_children(i, *fn, action);
1026 if (k < 0 && r == 0)
1039 _CREATION_MODE_INVALID = -1
1042 static const char *creation_mode_verb_table[_CREATION_MODE_MAX] = {
1043 [CREATION_NORMAL] = "Created",
1044 [CREATION_EXISTING] = "Found existing",
1045 [CREATION_FORCE] = "Created replacement",
1048 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(creation_mode_verb, CreationMode);
1050 static int create_item(Item *i) {
1053 CreationMode creation;
1057 log_debug("Running create action for entry %c %s", (char) i->type, i->path);
1062 case IGNORE_DIRECTORY_PATH:
1064 case RECURSIVE_REMOVE_PATH:
1069 r = write_one_file(i, i->path);
1075 log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
1076 r = copy_tree(i->argument, i->path, false);
1081 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
1083 if (stat(i->argument, &a) < 0)
1084 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
1086 if (stat(i->path, &b) < 0)
1087 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1089 if ((a.st_mode ^ b.st_mode) & S_IFMT) {
1090 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
1095 r = path_set_perms(i, i->path);
1102 r = glob_item(i, write_one_file, false);
1108 case CREATE_DIRECTORY:
1109 case TRUNCATE_DIRECTORY:
1110 case CREATE_SUBVOLUME:
1112 RUN_WITH_UMASK(0000)
1113 mkdir_parents_label(i->path, 0755);
1115 if (i->type == CREATE_SUBVOLUME)
1116 RUN_WITH_UMASK((~i->mode) & 0777) {
1117 r = btrfs_subvol_make(i->path);
1118 log_debug_errno(r, "Creating subvolume \"%s\": %m", i->path);
1123 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
1124 RUN_WITH_UMASK(0000)
1125 r = mkdir_label(i->path, i->mode);
1129 return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);
1131 if (stat(i->path, &st) < 0)
1132 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1134 if (!S_ISDIR(st.st_mode)) {
1135 log_debug("\"%s\" already exists and is not a directory.", i->path);
1139 creation = CREATION_EXISTING;
1141 creation = CREATION_NORMAL;
1142 log_debug("%s directory \"%s\".", creation_mode_verb_to_string(creation), i->path);
1144 r = path_set_perms(i, i->path);
1152 RUN_WITH_UMASK(0000) {
1153 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1154 r = mkfifo(i->path, i->mode);
1155 mac_selinux_create_file_clear();
1159 if (errno != EEXIST)
1160 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
1162 if (stat(i->path, &st) < 0)
1163 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1165 if (!S_ISFIFO(st.st_mode)) {
1169 RUN_WITH_UMASK(0000) {
1170 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1171 r = mkfifo_atomic(i->path, i->mode);
1172 mac_selinux_create_file_clear();
1176 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
1177 creation = CREATION_FORCE;
1179 log_debug("%s is not a fifo.", i->path);
1183 creation = CREATION_EXISTING;
1185 creation = CREATION_NORMAL;
1186 log_debug("%s fifo \"%s\".", creation_mode_verb_to_string(creation), i->path);
1188 r = path_set_perms(i, i->path);
1194 case CREATE_SYMLINK:
1196 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1197 r = symlink(i->argument, i->path);
1198 mac_selinux_create_file_clear();
1201 _cleanup_free_ char *x = NULL;
1203 if (errno != EEXIST)
1204 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
1206 r = readlink_malloc(i->path, &x);
1207 if (r < 0 || !streq(i->argument, x)) {
1210 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1211 r = symlink_atomic(i->argument, i->path);
1212 mac_selinux_create_file_clear();
1215 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
1216 creation = CREATION_FORCE;
1218 log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
1222 creation = CREATION_EXISTING;
1224 creation = CREATION_NORMAL;
1225 log_debug("%s symlink \"%s\".", creation_mode_verb_to_string(creation), i->path);
1229 case CREATE_BLOCK_DEVICE:
1230 case CREATE_CHAR_DEVICE: {
1233 if (have_effective_cap(CAP_MKNOD) == 0) {
1234 /* In a container we lack CAP_MKNOD. We
1235 shouldn't attempt to create the device node in
1236 that case to avoid noise, and we don't support
1237 virtualized devices in containers anyway. */
1239 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
1243 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
1245 RUN_WITH_UMASK(0000) {
1246 mac_selinux_create_file_prepare(i->path, file_type);
1247 r = mknod(i->path, i->mode | file_type, i->major_minor);
1248 mac_selinux_create_file_clear();
1252 if (errno == EPERM) {
1253 log_debug("We lack permissions, possibly because of cgroup configuration; "
1254 "skipping creation of device node %s.", i->path);
1258 if (errno != EEXIST)
1259 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1261 if (stat(i->path, &st) < 0)
1262 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1264 if ((st.st_mode & S_IFMT) != file_type) {
1268 RUN_WITH_UMASK(0000) {
1269 mac_selinux_create_file_prepare(i->path, file_type);
1270 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1271 mac_selinux_create_file_clear();
1275 return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path);
1276 creation = CREATION_FORCE;
1278 log_debug("%s is not a device node.", i->path);
1282 creation = CREATION_EXISTING;
1284 creation = CREATION_NORMAL;
1285 log_debug("%s %s device node \"%s\" %u:%u.",
1286 creation_mode_verb_to_string(creation),
1287 i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
1288 i->path, major(i->mode), minor(i->mode));
1290 r = path_set_perms(i, i->path);
1299 r = glob_item(i, path_set_perms, false);
1304 case RECURSIVE_RELABEL_PATH:
1305 r = glob_item(i, path_set_perms, true);
1311 r = glob_item(i, path_set_xattrs, false);
1316 case RECURSIVE_SET_XATTR:
1317 r = glob_item(i, path_set_xattrs, true);
1323 r = glob_item(i, path_set_acls, false);
1328 case RECURSIVE_SET_ACL:
1329 r = glob_item(i, path_set_acls, true);
1335 r = glob_item(i, path_set_attrib, false);
1340 case RECURSIVE_SET_ATTRIB:
1341 r = glob_item(i, path_set_attrib, true);
1350 static int remove_item_instance(Item *i, const char *instance) {
1358 if (remove(instance) < 0 && errno != ENOENT)
1359 return log_error_errno(errno, "rm(%s): %m", instance);
1363 case TRUNCATE_DIRECTORY:
1364 case RECURSIVE_REMOVE_PATH:
1365 /* FIXME: we probably should use dir_cleanup() here
1366 * instead of rm_rf() so that 'x' is honoured. */
1367 log_debug("rm -rf \"%s\"", instance);
1368 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1369 if (r < 0 && r != -ENOENT)
1370 return log_error_errno(r, "rm_rf(%s): %m", instance);
1375 assert_not_reached("wut?");
1381 static int remove_item(Item *i) {
1386 log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
1392 case CREATE_DIRECTORY:
1393 case CREATE_SUBVOLUME:
1395 case CREATE_SYMLINK:
1396 case CREATE_CHAR_DEVICE:
1397 case CREATE_BLOCK_DEVICE:
1399 case IGNORE_DIRECTORY_PATH:
1402 case RECURSIVE_RELABEL_PATH:
1406 case RECURSIVE_SET_XATTR:
1408 case RECURSIVE_SET_ACL:
1410 case RECURSIVE_SET_ATTRIB:
1414 case TRUNCATE_DIRECTORY:
1415 case RECURSIVE_REMOVE_PATH:
1416 r = glob_item(i, remove_item_instance, false);
1423 static int clean_item_instance(Item *i, const char* instance) {
1424 _cleanup_closedir_ DIR *d = NULL;
1428 char timestamp[FORMAT_TIMESTAMP_MAX];
1435 n = now(CLOCK_REALTIME);
1439 cutoff = n - i->age;
1441 d = opendir_nomod(instance);
1443 if (errno == ENOENT || errno == ENOTDIR) {
1444 log_debug_errno(errno, "Directory \"%s\": %m", instance);
1448 log_error_errno(errno, "Failed to open directory %s: %m", instance);
1452 if (fstat(dirfd(d), &s) < 0)
1453 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1455 if (!S_ISDIR(s.st_mode)) {
1456 log_error("%s is not a directory.", i->path);
1460 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1461 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1463 mountpoint = s.st_dev != ps.st_dev ||
1464 (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1466 log_debug("Cleanup threshold for %s \"%s\" is %s",
1467 mountpoint ? "mount point" : "directory",
1469 format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
1471 return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1472 MAX_DEPTH, i->keep_first_level);
1475 static int clean_item(Item *i) {
1480 log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
1483 case CREATE_DIRECTORY:
1484 case CREATE_SUBVOLUME:
1485 case TRUNCATE_DIRECTORY:
1488 clean_item_instance(i, i->path);
1490 case IGNORE_DIRECTORY_PATH:
1491 r = glob_item(i, clean_item_instance, false);
1500 static int process_item_array(ItemArray *array);
1502 static int process_item(Item *i) {
1504 _cleanup_free_ char *prefix = NULL;
1513 prefix = malloc(strlen(i->path) + 1);
1517 PATH_FOREACH_PREFIX(prefix, i->path) {
1520 j = hashmap_get(items, prefix);
1524 s = process_item_array(j);
1525 if (s < 0 && t == 0)
1530 r = arg_create ? create_item(i) : 0;
1531 q = arg_remove ? remove_item(i) : 0;
1532 p = arg_clean ? clean_item(i) : 0;
1540 static int process_item_array(ItemArray *array) {
1546 for (n = 0; n < array->count; n++) {
1547 k = process_item(array->items + n);
1548 if (k < 0 && r == 0)
1555 static void item_free_contents(Item *i) {
1559 strv_free(i->xattrs);
1562 acl_free(i->acl_access);
1563 acl_free(i->acl_default);
1567 static void item_array_free(ItemArray *a) {
1573 for (n = 0; n < a->count; n++)
1574 item_free_contents(a->items + n);
1579 static bool item_compatible(Item *a, Item *b) {
1582 assert(streq(a->path, b->path));
1584 if (takes_ownership(a->type) && takes_ownership(b->type))
1585 /* check if the items are the same */
1586 return streq_ptr(a->argument, b->argument) &&
1588 a->uid_set == b->uid_set &&
1591 a->gid_set == b->gid_set &&
1594 a->mode_set == b->mode_set &&
1595 a->mode == b->mode &&
1597 a->age_set == b->age_set &&
1600 a->mask_perms == b->mask_perms &&
1602 a->keep_first_level == b->keep_first_level &&
1604 a->major_minor == b->major_minor;
1609 static bool should_include_path(const char *path) {
1612 STRV_FOREACH(prefix, arg_exclude_prefixes)
1613 if (path_startswith(path, *prefix)) {
1614 log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
1619 STRV_FOREACH(prefix, arg_include_prefixes)
1620 if (path_startswith(path, *prefix)) {
1621 log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
1625 /* no matches, so we should include this path only if we
1626 * have no whitelist at all */
1627 if (strv_length(arg_include_prefixes) == 0)
1630 log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
1634 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1636 static const Specifier specifier_table[] = {
1637 { 'm', specifier_machine_id, NULL },
1638 { 'b', specifier_boot_id, NULL },
1639 { 'H', specifier_host_name, NULL },
1640 { 'v', specifier_kernel_release, NULL },
1644 _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1645 _cleanup_(item_free_contents) Item i = {};
1646 ItemArray *existing;
1649 bool force = false, boot = false;
1655 r = unquote_many_words(&buffer,
1665 return log_error_errno(r, "[%s:%u] Failed to parse line: %m", fname, line);
1667 log_error("[%s:%u] Syntax error.", fname, line);
1671 if (isempty(action)) {
1672 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1676 for (pos = 1; action[pos]; pos++) {
1677 if (action[pos] == '!' && !boot)
1679 else if (action[pos] == '+' && !force)
1682 log_error("[%s:%u] Unknown modifiers in command '%s'",
1683 fname, line, action);
1688 if (boot && !arg_boot) {
1689 log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
1697 r = specifier_printf(path, specifier_table, NULL, &i.path);
1699 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1707 case CREATE_DIRECTORY:
1708 case CREATE_SUBVOLUME:
1709 case TRUNCATE_DIRECTORY:
1712 case IGNORE_DIRECTORY_PATH:
1714 case RECURSIVE_REMOVE_PATH:
1717 case RECURSIVE_RELABEL_PATH:
1720 case CREATE_SYMLINK:
1722 i.argument = strappend("/usr/share/factory/", i.path);
1730 log_error("[%s:%u] Write file requires argument.", fname, line);
1737 i.argument = strappend("/usr/share/factory/", i.path);
1740 } else if (!path_is_absolute(i.argument)) {
1741 log_error("[%s:%u] Source path is not absolute.", fname, line);
1745 path_kill_slashes(i.argument);
1748 case CREATE_CHAR_DEVICE:
1749 case CREATE_BLOCK_DEVICE: {
1750 unsigned major, minor;
1753 log_error("[%s:%u] Device file requires argument.", fname, line);
1757 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1758 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1762 i.major_minor = makedev(major, minor);
1767 case RECURSIVE_SET_XATTR:
1769 log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1772 r = get_xattrs_from_arg(&i);
1778 case RECURSIVE_SET_ACL:
1780 log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1783 r = get_acls_from_arg(&i);
1789 case RECURSIVE_SET_ATTRIB:
1791 log_error("[%s:%u] Set attrib requires argument.", fname, line);
1794 r = get_attrib_from_arg(&i);
1800 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
1804 if (!path_is_absolute(i.path)) {
1805 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1809 path_kill_slashes(i.path);
1811 if (!should_include_path(i.path))
1817 p = strappend(arg_root, i.path);
1825 if (user && !streq(user, "-")) {
1826 const char *u = user;
1828 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1830 log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1837 if (group && !streq(group, "-")) {
1838 const char *g = group;
1840 r = get_group_creds(&g, &i.gid);
1842 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1849 if (mode && !streq(mode, "-")) {
1850 const char *mm = mode;
1854 i.mask_perms = true;
1858 if (sscanf(mm, "%o", &m) != 1) {
1859 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1866 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1869 if (age && !streq(age, "-")) {
1870 const char *a = age;
1873 i.keep_first_level = true;
1877 if (parse_sec(a, &i.age) < 0) {
1878 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1885 h = needs_glob(i.type) ? globs : items;
1887 existing = hashmap_get(h, i.path);
1891 for (n = 0; n < existing->count; n++) {
1892 if (!item_compatible(existing->items + n, &i)) {
1893 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1894 fname, line, i.path);
1899 existing = new0(ItemArray, 1);
1900 r = hashmap_put(h, i.path, existing);
1905 if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1908 memcpy(existing->items + existing->count++, &i, sizeof(i));
1913 static void help(void) {
1914 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1915 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1916 " -h --help Show this help\n"
1917 " --version Show package version\n"
1918 " --create Create marked files/directories\n"
1919 " --clean Clean up marked directories\n"
1920 " --remove Remove marked files/directories\n"
1921 " --boot Execute actions only safe at boot\n"
1922 " --prefix=PATH Only apply rules with the specified prefix\n"
1923 " --exclude-prefix=PATH Ignore rules with the specified prefix\n"
1924 " --root=PATH Operate on an alternate filesystem root\n",
1925 program_invocation_short_name);
1928 static int parse_argv(int argc, char *argv[]) {
1931 ARG_VERSION = 0x100,
1941 static const struct option options[] = {
1942 { "help", no_argument, NULL, 'h' },
1943 { "version", no_argument, NULL, ARG_VERSION },
1944 { "create", no_argument, NULL, ARG_CREATE },
1945 { "clean", no_argument, NULL, ARG_CLEAN },
1946 { "remove", no_argument, NULL, ARG_REMOVE },
1947 { "boot", no_argument, NULL, ARG_BOOT },
1948 { "prefix", required_argument, NULL, ARG_PREFIX },
1949 { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
1950 { "root", required_argument, NULL, ARG_ROOT },
1959 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1968 puts(PACKAGE_STRING);
1969 puts(SYSTEMD_FEATURES);
1989 if (strv_push(&arg_include_prefixes, optarg) < 0)
1993 case ARG_EXCLUDE_PREFIX:
1994 if (strv_push(&arg_exclude_prefixes, optarg) < 0)
2000 arg_root = path_make_absolute_cwd(optarg);
2004 path_kill_slashes(arg_root);
2011 assert_not_reached("Unhandled option");
2014 if (!arg_clean && !arg_create && !arg_remove) {
2015 log_error("You need to specify at least one of --clean, --create or --remove.");
2022 static int read_config_file(const char *fn, bool ignore_enoent) {
2023 _cleanup_fclose_ FILE *f = NULL;
2024 char line[LINE_MAX];
2032 r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
2034 if (ignore_enoent && r == -ENOENT) {
2035 log_debug_errno(r, "Failed to open \"%s\": %m", fn);
2039 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
2041 log_debug("Reading config file \"%s\".", fn);
2043 FOREACH_LINE(line, f, break) {
2050 if (*l == '#' || *l == 0)
2053 k = parse_line(fn, v, l);
2054 if (k < 0 && r == 0)
2058 /* we have to determine age parameter for each entry of type X */
2059 HASHMAP_FOREACH(i, globs, iterator) {
2061 Item *j, *candidate_item = NULL;
2063 if (i->type != IGNORE_DIRECTORY_PATH)
2066 HASHMAP_FOREACH(j, items, iter) {
2067 if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
2070 if (path_equal(j->path, i->path)) {
2075 if ((!candidate_item && path_startswith(i->path, j->path)) ||
2076 (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
2080 if (candidate_item && candidate_item->age_set) {
2081 i->age = candidate_item->age;
2087 log_error_errno(errno, "Failed to read from file %s: %m", fn);
2095 int main(int argc, char *argv[]) {
2100 r = parse_argv(argc, argv);
2104 log_set_target(LOG_TARGET_AUTO);
2105 log_parse_environment();
2110 mac_selinux_init(NULL);
2112 items = hashmap_new(&string_hash_ops);
2113 globs = hashmap_new(&string_hash_ops);
2115 if (!items || !globs) {
2122 if (optind < argc) {
2125 for (j = optind; j < argc; j++) {
2126 k = read_config_file(argv[j], false);
2127 if (k < 0 && r == 0)
2132 _cleanup_strv_free_ char **files = NULL;
2135 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
2137 log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
2141 STRV_FOREACH(f, files) {
2142 k = read_config_file(*f, true);
2143 if (k < 0 && r == 0)
2148 HASHMAP_FOREACH(a, globs, iterator) {
2149 k = process_item_array(a);
2150 if (k < 0 && r == 0)
2154 HASHMAP_FOREACH(a, items, iterator) {
2155 k = process_item_array(a);
2156 if (k < 0 && r == 0)
2161 while ((a = hashmap_steal_first(items)))
2164 while ((a = hashmap_steal_first(globs)))
2167 hashmap_free(items);
2168 hashmap_free(globs);
2170 free(arg_include_prefixes);
2171 free(arg_exclude_prefixes);
2174 set_free_free(unix_sockets);
2176 mac_selinux_finish();
2178 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;