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) {
179 IGNORE_DIRECTORY_PATH,
181 RECURSIVE_REMOVE_PATH);
184 static struct Item* find_glob(Hashmap *h, const char *match) {
188 HASHMAP_FOREACH(j, h, i) {
191 for (n = 0; n < j->count; n++) {
192 Item *item = j->items + n;
194 if (fnmatch(item->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
202 static void load_unix_sockets(void) {
203 _cleanup_fclose_ FILE *f = NULL;
209 /* We maintain a cache of the sockets we found in
210 * /proc/net/unix to speed things up a little. */
212 unix_sockets = set_new(&string_hash_ops);
216 f = fopen("/proc/net/unix", "re");
221 if (!fgets(line, sizeof(line), f))
228 if (!fgets(line, sizeof(line), f))
233 p = strchr(line, ':');
241 p += strspn(p, WHITESPACE);
242 p += strcspn(p, WHITESPACE); /* skip one more word */
243 p += strspn(p, WHITESPACE);
252 path_kill_slashes(s);
254 k = set_consume(unix_sockets, s);
255 if (k < 0 && k != -EEXIST)
262 set_free_free(unix_sockets);
266 static bool unix_socket_alive(const char *fn) {
272 return !!set_get(unix_sockets, (char*) fn);
274 /* We don't know, so assume yes */
278 static int dir_is_mount_point(DIR *d, const char *subdir) {
280 union file_handle_union h = FILE_HANDLE_INIT;
281 int mount_id_parent, mount_id;
284 r_p = name_to_handle_at(dirfd(d), ".", &h.handle, &mount_id_parent, 0);
288 h.handle.handle_bytes = MAX_HANDLE_SZ;
289 r = name_to_handle_at(dirfd(d), subdir, &h.handle, &mount_id, 0);
293 /* got no handle; make no assumptions, return error */
294 if (r_p < 0 && r < 0)
297 /* got both handles; if they differ, it is a mount point */
298 if (r_p >= 0 && r >= 0)
299 return mount_id_parent != mount_id;
301 /* got only one handle; assume different mount points if one
302 * of both queries was not supported by the filesystem */
303 if (r_p == -ENOSYS || r_p == -EOPNOTSUPP || r == -ENOSYS || r == -EOPNOTSUPP)
312 static DIR* xopendirat_nomod(int dirfd, const char *path) {
315 dir = xopendirat(dirfd, path, O_NOFOLLOW|O_NOATIME);
319 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m", dirfd == AT_FDCWD ? "" : "sub", path);
323 dir = xopendirat(dirfd, path, O_NOFOLLOW);
325 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m", dirfd == AT_FDCWD ? "" : "sub", path);
330 static DIR* opendir_nomod(const char *path) {
331 return xopendirat_nomod(AT_FDCWD, path);
334 static int dir_cleanup(
338 const struct stat *ds,
343 bool keep_this_level) {
346 struct timespec times[2];
347 bool deleted = false;
350 while ((dent = readdir(d))) {
353 _cleanup_free_ char *sub_path = NULL;
355 if (STR_IN_SET(dent->d_name, ".", ".."))
358 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
362 /* FUSE, NFS mounts, SELinux might return EACCES */
364 log_debug_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
366 log_error_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
371 /* Stay on the same filesystem */
372 if (s.st_dev != rootdev) {
373 log_debug("Ignoring \"%s/%s\": different filesystem.", p, dent->d_name);
377 /* Try to detect bind mounts of the same filesystem instance; they
378 * do not differ in device major/minors. This type of query is not
379 * supported on all kernels or filesystem types though. */
380 if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0) {
381 log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.",
386 /* Do not delete read-only files owned by root */
387 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR)) {
388 log_debug("Ignoring \"%s/%s\": read-only and owner by root.", p, dent->d_name);
392 sub_path = strjoin(p, "/", dent->d_name, NULL);
398 /* Is there an item configured for this path? */
399 if (hashmap_get(items, sub_path)) {
400 log_debug("Ignoring \"%s\": a separate entry exists.", sub_path);
404 if (find_glob(globs, sub_path)) {
405 log_debug("Ignoring \"%s\": a separate glob exists.", sub_path);
409 if (S_ISDIR(s.st_mode)) {
412 streq(dent->d_name, "lost+found") &&
414 log_debug("Ignoring \"%s\".", sub_path);
419 log_warning("Reached max depth on \"%s\".", sub_path);
421 _cleanup_closedir_ DIR *sub_dir;
424 sub_dir = xopendirat_nomod(dirfd(d), dent->d_name);
427 r = log_error_errno(errno, "opendir(%s) failed: %m", sub_path);
432 q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
437 /* Note: if you are wondering why we don't
438 * support the sticky bit for excluding
439 * directories from cleaning like we do it for
440 * other file system objects: well, the sticky
441 * bit already has a meaning for directories,
442 * so we don't want to overload that. */
444 if (keep_this_level) {
445 log_debug("Keeping \"%s\".", sub_path);
449 /* Ignore ctime, we change it when deleting */
450 age = timespec_load(&s.st_mtim);
452 char a[FORMAT_TIMESTAMP_MAX];
453 /* Follows spelling in stat(1). */
454 log_debug("Directory \"%s\": modify time %s is too new.",
456 format_timestamp_us(a, sizeof(a), age));
460 age = timespec_load(&s.st_atim);
462 char a[FORMAT_TIMESTAMP_MAX];
463 log_debug("Directory \"%s\": access time %s is too new.",
465 format_timestamp_us(a, sizeof(a), age));
469 log_debug("Removing directory \"%s\".", sub_path);
470 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0)
471 if (errno != ENOENT && errno != ENOTEMPTY) {
472 log_error_errno(errno, "rmdir(%s): %m", sub_path);
477 /* Skip files for which the sticky bit is
478 * set. These are semantics we define, and are
479 * unknown elsewhere. See XDG_RUNTIME_DIR
480 * specification for details. */
481 if (s.st_mode & S_ISVTX) {
482 log_debug("Skipping \"%s\": sticky bit set.", sub_path);
486 if (mountpoint && S_ISREG(s.st_mode))
487 if ((streq(dent->d_name, ".journal") && s.st_uid == 0) ||
488 streq(dent->d_name, "aquota.user") ||
489 streq(dent->d_name, "aquota.group")) {
490 log_debug("Skipping \"%s\".", sub_path);
494 /* Ignore sockets that are listed in /proc/net/unix */
495 if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path)) {
496 log_debug("Skipping \"%s\": live socket.", sub_path);
500 /* Ignore device nodes */
501 if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode)) {
502 log_debug("Skipping \"%s\": a device.", sub_path);
506 /* Keep files on this level around if this is
508 if (keep_this_level) {
509 log_debug("Keeping \"%s\".", sub_path);
513 age = timespec_load(&s.st_mtim);
515 char a[FORMAT_TIMESTAMP_MAX];
516 /* Follows spelling in stat(1). */
517 log_debug("File \"%s\": modify time %s is too new.",
519 format_timestamp_us(a, sizeof(a), age));
523 age = timespec_load(&s.st_atim);
525 char a[FORMAT_TIMESTAMP_MAX];
526 log_debug("File \"%s\": access time %s is too new.",
528 format_timestamp_us(a, sizeof(a), age));
532 age = timespec_load(&s.st_ctim);
534 char a[FORMAT_TIMESTAMP_MAX];
535 log_debug("File \"%s\": change time %s is too new.",
537 format_timestamp_us(a, sizeof(a), age));
541 log_debug("unlink \"%s\"", sub_path);
543 if (unlinkat(dirfd(d), dent->d_name, 0) < 0)
545 r = log_error_errno(errno, "unlink(%s): %m", sub_path);
554 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
556 /* Restore original directory timestamps */
557 times[0] = ds->st_atim;
558 times[1] = ds->st_mtim;
560 age1 = timespec_load(&ds->st_atim);
561 age2 = timespec_load(&ds->st_mtim);
562 log_debug("Restoring access and modification time on \"%s\": %s, %s",
564 format_timestamp_us(a, sizeof(a), age1),
565 format_timestamp_us(b, sizeof(b), age2));
566 if (futimens(dirfd(d), times) < 0)
567 log_error_errno(errno, "utimensat(%s): %m", p);
573 static int path_set_perms(Item *i, const char *path) {
580 st_valid = stat(path, &st) == 0;
582 /* not using i->path directly because it may be a glob */
586 if (i->mask_perms && st_valid) {
587 if (!(st.st_mode & 0111))
589 if (!(st.st_mode & 0222))
591 if (!(st.st_mode & 0444))
593 if (!S_ISDIR(st.st_mode))
594 m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
597 if (st_valid && m == (st.st_mode & 07777))
598 log_debug("\"%s\" has right mode %o", path, st.st_mode);
600 log_debug("chmod \"%s\" to mode %o", path, m);
601 if (chmod(path, m) < 0)
602 return log_error_errno(errno, "chmod(%s) failed: %m", path);
606 if ((!st_valid || i->uid != st.st_uid || i->gid != st.st_gid) &&
607 (i->uid_set || i->gid_set)) {
608 log_debug("chown \"%s\" to "UID_FMT"."GID_FMT,
610 i->uid_set ? i->uid : UID_INVALID,
611 i->gid_set ? i->gid : GID_INVALID);
613 i->uid_set ? i->uid : UID_INVALID,
614 i->gid_set ? i->gid : GID_INVALID) < 0)
616 return log_error_errno(errno, "chown(%s) failed: %m", path);
619 return label_fix(path, false, false);
622 static int get_xattrs_from_arg(Item *i) {
632 while ((r = unquote_first_word(&p, &xattr, false)) > 0) {
633 _cleanup_free_ char *tmp = NULL, *name = NULL,
634 *value = NULL, *value2 = NULL, *_xattr = xattr;
636 r = split_pair(xattr, "=", &name, &value);
638 log_warning("Illegal xattr found: \"%s\" - ignoring.", xattr);
642 if (strempty(name) || strempty(value)) {
643 log_warning("Malformed xattr found: \"%s\" - ignoring.", xattr);
647 tmp = unquote(value, "\"");
651 value2 = cunescape(tmp);
655 if (strv_push_pair(&i->xattrs, name, value2) < 0)
657 name = value2 = NULL;
663 static int path_set_xattrs(Item *i, const char *path) {
664 char **name, **value;
669 STRV_FOREACH_PAIR(name, value, i->xattrs) {
673 log_debug("\"%s\": setting xattr \"%s=%s\"", path, *name, *value);
674 if (lsetxattr(path, *name, *value, n, 0) < 0) {
675 log_error("Setting extended attribute %s=%s on %s failed: %m",
676 *name, *value, path);
683 static int get_acls_from_arg(Item *item) {
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(r, "Failed to parse ACL \"%s\": %m. Ignoring",
696 log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
703 static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
704 _cleanup_(acl_freep) acl_t dup = NULL;
706 _cleanup_(acl_free_charpp) char *t = NULL;
708 /* Returns 0 for success, positive error if already warned,
709 * negative error otherwise. */
712 r = acls_for_file(path, type, acl, &dup);
716 r = calc_acl_mask_if_needed(&dup);
724 /* the mask was already added earlier if needed */
727 r = add_base_acls_if_needed(&dup, path);
731 t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
732 log_debug("\"%s\": setting %s ACL \"%s\"", path,
733 type == ACL_TYPE_ACCESS ? "access" : "default",
736 r = acl_set_file(path, type, dup);
738 return -log_error_errno(errno,
739 "Setting %s ACL \"%s\" on %s failed: %m",
740 type == ACL_TYPE_ACCESS ? "access" : "default",
747 static int path_set_acls(Item *item, const char *path) {
753 if (item->acl_access)
754 r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
756 if (r == 0 && item->acl_default)
757 r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
760 return -r; /* already warned */
761 else if (r == -EOPNOTSUPP) {
762 log_debug_errno(r, "ACLs not supported by file system at %s", path);
765 log_error_errno(r, "ACL operation on \"%s\" failed: %m", path);
770 #define ALL_ATTRIBS \
779 FS_JOURNAL_DATA_FL | \
786 static int get_attrib_from_arg(Item *item) {
787 static const unsigned attributes[] = {
788 [(uint8_t)'A'] = FS_NOATIME_FL, /* do not update atime */
789 [(uint8_t)'S'] = FS_SYNC_FL, /* Synchronous updates */
790 [(uint8_t)'D'] = FS_DIRSYNC_FL, /* dirsync behaviour (directories only) */
791 [(uint8_t)'a'] = FS_APPEND_FL, /* writes to file may only append */
792 [(uint8_t)'c'] = FS_COMPR_FL, /* Compress file */
793 [(uint8_t)'d'] = FS_NODUMP_FL, /* do not dump file */
794 [(uint8_t)'e'] = FS_EXTENT_FL, /* Top of directory hierarchies*/
795 [(uint8_t)'i'] = FS_IMMUTABLE_FL, /* Immutable file */
796 [(uint8_t)'j'] = FS_JOURNAL_DATA_FL, /* Reserved for ext3 */
797 [(uint8_t)'s'] = FS_SECRM_FL, /* Secure deletion */
798 [(uint8_t)'u'] = FS_UNRM_FL, /* Undelete */
799 [(uint8_t)'t'] = FS_NOTAIL_FL, /* file tail should not be merged */
800 [(uint8_t)'T'] = FS_TOPDIR_FL, /* Top of directory hierarchies*/
801 [(uint8_t)'C'] = FS_NOCOW_FL, /* Do not cow file */
803 char *p = item->argument;
809 unsigned long value = 0, mask = 0;
812 log_error("\"%s\": setting ATTR need an argument", item->path);
819 } else if (*p == '-') {
822 } else if (*p == '=') {
827 if (!*p && mode != MODE_SET) {
828 log_error("\"%s\": setting ATTR: argument is empty", item->path);
832 if ((uint8_t)*p >= ELEMENTSOF(attributes) || attributes[(uint8_t)*p] == 0) {
833 log_error("\"%s\": setting ATTR: unknown attr '%c'", item->path, *p);
836 if (mode == MODE_ADD || mode == MODE_SET)
837 value |= attributes[(uint8_t)*p];
839 value &= ~attributes[(uint8_t)*p];
840 mask |= attributes[(uint8_t)*p];
843 if (mode == MODE_SET)
848 item->attrib_mask = mask;
849 item->attrib_value = value;
850 item->attrib_set = true;
856 static int path_set_attrib(Item *item, const char *path) {
857 _cleanup_close_ int fd = -1;
863 if (item->attrib_mask == 0 || !item->attrib_set)
866 * It is OK to ignore an lstat() error, because the error
867 * will be catch by the open() below anyway
869 if (lstat(path, &st) == 0 &&
870 !S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
874 fd = open(path, O_RDONLY|O_NONBLOCK|O_CLOEXEC);
877 return log_error_errno(errno, "Cannot open \"%s\": %m", path);
879 f = item->attrib_value & item->attrib_mask;
880 if (!S_ISDIR(st.st_mode))
882 r = change_attr_fd(fd, f, item->attrib_mask);
884 return log_error_errno(errno,
885 "Cannot set attrib for \"%s\", value=0x%08lx, mask=0x%08lx: %m",
886 path, item->attrib_value, item->attrib_mask);
891 static int write_one_file(Item *i, const char *path) {
892 _cleanup_close_ int fd = -1;
899 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
900 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
902 RUN_WITH_UMASK(0000) {
903 mac_selinux_create_file_prepare(path, S_IFREG);
904 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
905 mac_selinux_create_file_clear();
909 if (i->type == WRITE_FILE && errno == ENOENT) {
910 log_debug_errno(errno, "Not writing \"%s\": %m", path);
914 log_error_errno(errno, "Failed to create file %s: %m", path);
919 _cleanup_free_ char *unescaped;
921 log_debug("%s to \"%s\".",
922 i->type == CREATE_FILE ? "Appending" : "Writing", path);
924 unescaped = cunescape(i->argument);
928 r = loop_write(fd, unescaped, strlen(unescaped), false);
930 return log_error_errno(r, "Failed to write file \"%s\": %m", path);
932 log_debug("\"%s\" has been created.", path);
936 if (stat(path, &st) < 0)
937 return log_error_errno(errno, "stat(%s) failed: %m", path);
939 if (!S_ISREG(st.st_mode)) {
940 log_error("%s is not a file.", path);
944 r = path_set_perms(i, path);
951 typedef int (*action_t)(Item *, const char *);
953 static int item_do_children(Item *i, const char *path, action_t action) {
954 _cleanup_closedir_ DIR *d;
960 /* This returns the first error we run into, but nevertheless
963 d = opendir_nomod(path);
965 return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
968 _cleanup_free_ char *p = NULL;
975 if (errno != 0 && r == 0)
981 if (STR_IN_SET(de->d_name, ".", ".."))
984 p = strjoin(path, "/", de->d_name, NULL);
989 if (q < 0 && q != -ENOENT && r == 0)
992 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
993 q = item_do_children(i, p, action);
1002 static int glob_item(Item *i, action_t action, bool recursive) {
1003 _cleanup_globfree_ glob_t g = {
1004 .gl_closedir = (void (*)(void *)) closedir,
1005 .gl_readdir = (struct dirent *(*)(void *)) readdir,
1006 .gl_opendir = (void *(*)(const char *)) opendir_nomod,
1014 k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
1015 if (k != 0 && k != GLOB_NOMATCH)
1016 return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
1018 STRV_FOREACH(fn, g.gl_pathv) {
1020 if (k < 0 && r == 0)
1024 k = item_do_children(i, *fn, action);
1025 if (k < 0 && r == 0)
1038 _CREATION_MODE_INVALID = -1
1041 static const char *creation_mode_verb_table[_CREATION_MODE_MAX] = {
1042 [CREATION_NORMAL] = "Created",
1043 [CREATION_EXISTING] = "Found existing",
1044 [CREATION_FORCE] = "Created replacement",
1047 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(creation_mode_verb, CreationMode);
1049 static int create_item(Item *i) {
1052 CreationMode creation;
1056 log_debug("Running create action for entry %c %s", (char) i->type, i->path);
1061 case IGNORE_DIRECTORY_PATH:
1063 case RECURSIVE_REMOVE_PATH:
1068 r = write_one_file(i, i->path);
1074 log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
1075 r = copy_tree(i->argument, i->path, false);
1080 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
1082 if (stat(i->argument, &a) < 0)
1083 return log_error_errno(errno, "stat(%s) failed: %m", i->argument);
1085 if (stat(i->path, &b) < 0)
1086 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1088 if ((a.st_mode ^ b.st_mode) & S_IFMT) {
1089 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
1094 r = path_set_perms(i, i->path);
1101 r = glob_item(i, write_one_file, false);
1107 case CREATE_DIRECTORY:
1108 case TRUNCATE_DIRECTORY:
1109 case CREATE_SUBVOLUME:
1111 RUN_WITH_UMASK(0000)
1112 mkdir_parents_label(i->path, 0755);
1114 if (i->type == CREATE_SUBVOLUME)
1115 RUN_WITH_UMASK((~i->mode) & 0777) {
1116 r = btrfs_subvol_make(i->path);
1117 log_debug_errno(r, "Creating subvolume \"%s\": %m", i->path);
1122 if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
1123 RUN_WITH_UMASK(0000)
1124 r = mkdir_label(i->path, i->mode);
1128 return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);
1130 if (stat(i->path, &st) < 0)
1131 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1133 if (!S_ISDIR(st.st_mode)) {
1134 log_debug("\"%s\" already exists and is not a directory.", i->path);
1138 creation = CREATION_EXISTING;
1140 creation = CREATION_NORMAL;
1141 log_debug("%s directory \"%s\".", creation_mode_verb_to_string(creation), i->path);
1143 r = path_set_perms(i, i->path);
1151 RUN_WITH_UMASK(0000) {
1152 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1153 r = mkfifo(i->path, i->mode);
1154 mac_selinux_create_file_clear();
1158 if (errno != EEXIST)
1159 return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
1161 if (stat(i->path, &st) < 0)
1162 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1164 if (!S_ISFIFO(st.st_mode)) {
1168 RUN_WITH_UMASK(0000) {
1169 mac_selinux_create_file_prepare(i->path, S_IFIFO);
1170 r = mkfifo_atomic(i->path, i->mode);
1171 mac_selinux_create_file_clear();
1175 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
1176 creation = CREATION_FORCE;
1178 log_debug("%s is not a fifo.", i->path);
1182 creation = CREATION_EXISTING;
1184 creation = CREATION_NORMAL;
1185 log_debug("%s fifo \"%s\".", creation_mode_verb_to_string(creation), i->path);
1187 r = path_set_perms(i, i->path);
1193 case CREATE_SYMLINK:
1195 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1196 r = symlink(i->argument, i->path);
1197 mac_selinux_create_file_clear();
1200 _cleanup_free_ char *x = NULL;
1202 if (errno != EEXIST)
1203 return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path);
1205 r = readlink_malloc(i->path, &x);
1206 if (r < 0 || !streq(i->argument, x)) {
1209 mac_selinux_create_file_prepare(i->path, S_IFLNK);
1210 r = symlink_atomic(i->argument, i->path);
1211 mac_selinux_create_file_clear();
1214 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
1215 creation = CREATION_FORCE;
1217 log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
1221 creation = CREATION_EXISTING;
1223 creation = CREATION_NORMAL;
1224 log_debug("%s symlink \"%s\".", creation_mode_verb_to_string(creation), i->path);
1228 case CREATE_BLOCK_DEVICE:
1229 case CREATE_CHAR_DEVICE: {
1232 if (have_effective_cap(CAP_MKNOD) == 0) {
1233 /* In a container we lack CAP_MKNOD. We
1234 shouldn't attempt to create the device node in
1235 that case to avoid noise, and we don't support
1236 virtualized devices in containers anyway. */
1238 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
1242 file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
1244 RUN_WITH_UMASK(0000) {
1245 mac_selinux_create_file_prepare(i->path, file_type);
1246 r = mknod(i->path, i->mode | file_type, i->major_minor);
1247 mac_selinux_create_file_clear();
1251 if (errno == EPERM) {
1252 log_debug("We lack permissions, possibly because of cgroup configuration; "
1253 "skipping creation of device node %s.", i->path);
1257 if (errno != EEXIST)
1258 return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
1260 if (stat(i->path, &st) < 0)
1261 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1263 if ((st.st_mode & S_IFMT) != file_type) {
1267 RUN_WITH_UMASK(0000) {
1268 mac_selinux_create_file_prepare(i->path, file_type);
1269 r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
1270 mac_selinux_create_file_clear();
1274 return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path);
1275 creation = CREATION_FORCE;
1277 log_debug("%s is not a device node.", i->path);
1281 creation = CREATION_EXISTING;
1283 creation = CREATION_NORMAL;
1284 log_debug("%s %s device node \"%s\" %u:%u.",
1285 creation_mode_verb_to_string(creation),
1286 i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
1287 i->path, major(i->mode), minor(i->mode));
1289 r = path_set_perms(i, i->path);
1298 r = glob_item(i, path_set_perms, false);
1303 case RECURSIVE_RELABEL_PATH:
1304 r = glob_item(i, path_set_perms, true);
1310 r = glob_item(i, path_set_xattrs, false);
1315 case RECURSIVE_SET_XATTR:
1316 r = glob_item(i, path_set_xattrs, true);
1322 r = glob_item(i, path_set_acls, false);
1327 case RECURSIVE_SET_ACL:
1328 r = glob_item(i, path_set_acls, true);
1334 r = glob_item(i, path_set_attrib, false);
1339 case RECURSIVE_SET_ATTRIB:
1340 r = glob_item(i, path_set_attrib, true);
1349 static int remove_item_instance(Item *i, const char *instance) {
1357 if (remove(instance) < 0 && errno != ENOENT)
1358 return log_error_errno(errno, "rm(%s): %m", instance);
1362 case TRUNCATE_DIRECTORY:
1363 case RECURSIVE_REMOVE_PATH:
1364 /* FIXME: we probably should use dir_cleanup() here
1365 * instead of rm_rf() so that 'x' is honoured. */
1366 log_debug("rm -rf \"%s\"", instance);
1367 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
1368 if (r < 0 && r != -ENOENT)
1369 return log_error_errno(r, "rm_rf(%s): %m", instance);
1374 assert_not_reached("wut?");
1380 static int remove_item(Item *i) {
1385 log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
1391 case CREATE_DIRECTORY:
1392 case CREATE_SUBVOLUME:
1394 case CREATE_SYMLINK:
1395 case CREATE_CHAR_DEVICE:
1396 case CREATE_BLOCK_DEVICE:
1398 case IGNORE_DIRECTORY_PATH:
1401 case RECURSIVE_RELABEL_PATH:
1405 case RECURSIVE_SET_XATTR:
1407 case RECURSIVE_SET_ACL:
1409 case RECURSIVE_SET_ATTRIB:
1413 case TRUNCATE_DIRECTORY:
1414 case RECURSIVE_REMOVE_PATH:
1415 r = glob_item(i, remove_item_instance, false);
1422 static int clean_item_instance(Item *i, const char* instance) {
1423 _cleanup_closedir_ DIR *d = NULL;
1427 char timestamp[FORMAT_TIMESTAMP_MAX];
1434 n = now(CLOCK_REALTIME);
1438 cutoff = n - i->age;
1440 d = opendir_nomod(instance);
1442 if (errno == ENOENT || errno == ENOTDIR) {
1443 log_debug_errno(errno, "Directory \"%s\": %m", instance);
1447 log_error_errno(errno, "Failed to open directory %s: %m", instance);
1451 if (fstat(dirfd(d), &s) < 0)
1452 return log_error_errno(errno, "stat(%s) failed: %m", i->path);
1454 if (!S_ISDIR(s.st_mode)) {
1455 log_error("%s is not a directory.", i->path);
1459 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
1460 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
1462 mountpoint = s.st_dev != ps.st_dev ||
1463 (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
1465 log_debug("Cleanup threshold for %s \"%s\" is %s",
1466 mountpoint ? "mount point" : "directory",
1468 format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
1470 return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
1471 MAX_DEPTH, i->keep_first_level);
1474 static int clean_item(Item *i) {
1479 log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
1482 case CREATE_DIRECTORY:
1483 case CREATE_SUBVOLUME:
1484 case TRUNCATE_DIRECTORY:
1487 clean_item_instance(i, i->path);
1489 case IGNORE_DIRECTORY_PATH:
1490 r = glob_item(i, clean_item_instance, false);
1499 static int process_item_array(ItemArray *array);
1501 static int process_item(Item *i) {
1503 _cleanup_free_ char *prefix = NULL;
1512 prefix = malloc(strlen(i->path) + 1);
1516 PATH_FOREACH_PREFIX(prefix, i->path) {
1519 j = hashmap_get(items, prefix);
1523 s = process_item_array(j);
1524 if (s < 0 && t == 0)
1529 r = arg_create ? create_item(i) : 0;
1530 q = arg_remove ? remove_item(i) : 0;
1531 p = arg_clean ? clean_item(i) : 0;
1539 static int process_item_array(ItemArray *array) {
1545 for (n = 0; n < array->count; n++) {
1546 k = process_item(array->items + n);
1547 if (k < 0 && r == 0)
1554 static void item_free_contents(Item *i) {
1558 strv_free(i->xattrs);
1561 acl_free(i->acl_access);
1562 acl_free(i->acl_default);
1566 static void item_array_free(ItemArray *a) {
1572 for (n = 0; n < a->count; n++)
1573 item_free_contents(a->items + n);
1578 static bool item_compatible(Item *a, Item *b) {
1581 assert(streq(a->path, b->path));
1583 if (takes_ownership(a->type) && takes_ownership(b->type))
1584 /* check if the items are the same */
1585 return streq_ptr(a->argument, b->argument) &&
1587 a->uid_set == b->uid_set &&
1590 a->gid_set == b->gid_set &&
1593 a->mode_set == b->mode_set &&
1594 a->mode == b->mode &&
1596 a->age_set == b->age_set &&
1599 a->mask_perms == b->mask_perms &&
1601 a->keep_first_level == b->keep_first_level &&
1603 a->major_minor == b->major_minor;
1608 static bool should_include_path(const char *path) {
1611 STRV_FOREACH(prefix, arg_exclude_prefixes)
1612 if (path_startswith(path, *prefix)) {
1613 log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
1618 STRV_FOREACH(prefix, arg_include_prefixes)
1619 if (path_startswith(path, *prefix)) {
1620 log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
1624 /* no matches, so we should include this path only if we
1625 * have no whitelist at all */
1626 if (strv_length(arg_include_prefixes) == 0)
1629 log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
1633 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1635 static const Specifier specifier_table[] = {
1636 { 'm', specifier_machine_id, NULL },
1637 { 'b', specifier_boot_id, NULL },
1638 { 'H', specifier_host_name, NULL },
1639 { 'v', specifier_kernel_release, NULL },
1643 _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
1644 _cleanup_(item_free_contents) Item i = {};
1645 ItemArray *existing;
1648 bool force = false, boot = false;
1654 r = unquote_many_words(&buffer,
1664 return log_error_errno(r, "[%s:%u] Failed to parse line: %m", fname, line);
1666 log_error("[%s:%u] Syntax error.", fname, line);
1670 if (isempty(action)) {
1671 log_error("[%s:%u] Command too short '%s'.", fname, line, action);
1675 for (pos = 1; action[pos]; pos++) {
1676 if (action[pos] == '!' && !boot)
1678 else if (action[pos] == '+' && !force)
1681 log_error("[%s:%u] Unknown modifiers in command '%s'",
1682 fname, line, action);
1687 if (boot && !arg_boot) {
1688 log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
1696 r = specifier_printf(path, specifier_table, NULL, &i.path);
1698 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
1706 case CREATE_DIRECTORY:
1707 case CREATE_SUBVOLUME:
1708 case TRUNCATE_DIRECTORY:
1711 case IGNORE_DIRECTORY_PATH:
1713 case RECURSIVE_REMOVE_PATH:
1716 case RECURSIVE_RELABEL_PATH:
1719 case CREATE_SYMLINK:
1721 i.argument = strappend("/usr/share/factory/", i.path);
1729 log_error("[%s:%u] Write file requires argument.", fname, line);
1736 i.argument = strappend("/usr/share/factory/", i.path);
1739 } else if (!path_is_absolute(i.argument)) {
1740 log_error("[%s:%u] Source path is not absolute.", fname, line);
1744 path_kill_slashes(i.argument);
1747 case CREATE_CHAR_DEVICE:
1748 case CREATE_BLOCK_DEVICE: {
1749 unsigned major, minor;
1752 log_error("[%s:%u] Device file requires argument.", fname, line);
1756 if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
1757 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
1761 i.major_minor = makedev(major, minor);
1766 case RECURSIVE_SET_XATTR:
1768 log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
1771 r = get_xattrs_from_arg(&i);
1777 case RECURSIVE_SET_ACL:
1779 log_error("[%s:%u] Set ACLs requires argument.", fname, line);
1782 r = get_acls_from_arg(&i);
1788 case RECURSIVE_SET_ATTRIB:
1790 log_error("[%s:%u] Set attrib requires argument.", fname, line);
1793 r = get_attrib_from_arg(&i);
1799 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
1803 if (!path_is_absolute(i.path)) {
1804 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
1808 path_kill_slashes(i.path);
1810 if (!should_include_path(i.path))
1816 p = strappend(arg_root, i.path);
1824 if (user && !streq(user, "-")) {
1825 const char *u = user;
1827 r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
1829 log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1836 if (group && !streq(group, "-")) {
1837 const char *g = group;
1839 r = get_group_creds(&g, &i.gid);
1841 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1848 if (mode && !streq(mode, "-")) {
1849 const char *mm = mode;
1853 i.mask_perms = true;
1857 if (sscanf(mm, "%o", &m) != 1) {
1858 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1865 i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
1868 if (age && !streq(age, "-")) {
1869 const char *a = age;
1872 i.keep_first_level = true;
1876 if (parse_sec(a, &i.age) < 0) {
1877 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1884 h = needs_glob(i.type) ? globs : items;
1886 existing = hashmap_get(h, i.path);
1890 for (n = 0; n < existing->count; n++) {
1891 if (!item_compatible(existing->items + n, &i)) {
1892 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
1893 fname, line, i.path);
1898 existing = new0(ItemArray, 1);
1899 r = hashmap_put(h, i.path, existing);
1904 if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
1907 memcpy(existing->items + existing->count++, &i, sizeof(i));
1912 static void help(void) {
1913 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1914 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1915 " -h --help Show this help\n"
1916 " --version Show package version\n"
1917 " --create Create marked files/directories\n"
1918 " --clean Clean up marked directories\n"
1919 " --remove Remove marked files/directories\n"
1920 " --boot Execute actions only safe at boot\n"
1921 " --prefix=PATH Only apply rules with the specified prefix\n"
1922 " --exclude-prefix=PATH Ignore rules with the specified prefix\n"
1923 " --root=PATH Operate on an alternate filesystem root\n",
1924 program_invocation_short_name);
1927 static int parse_argv(int argc, char *argv[]) {
1930 ARG_VERSION = 0x100,
1940 static const struct option options[] = {
1941 { "help", no_argument, NULL, 'h' },
1942 { "version", no_argument, NULL, ARG_VERSION },
1943 { "create", no_argument, NULL, ARG_CREATE },
1944 { "clean", no_argument, NULL, ARG_CLEAN },
1945 { "remove", no_argument, NULL, ARG_REMOVE },
1946 { "boot", no_argument, NULL, ARG_BOOT },
1947 { "prefix", required_argument, NULL, ARG_PREFIX },
1948 { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
1949 { "root", required_argument, NULL, ARG_ROOT },
1958 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1967 puts(PACKAGE_STRING);
1968 puts(SYSTEMD_FEATURES);
1988 if (strv_push(&arg_include_prefixes, optarg) < 0)
1992 case ARG_EXCLUDE_PREFIX:
1993 if (strv_push(&arg_exclude_prefixes, optarg) < 0)
1999 arg_root = path_make_absolute_cwd(optarg);
2003 path_kill_slashes(arg_root);
2010 assert_not_reached("Unhandled option");
2013 if (!arg_clean && !arg_create && !arg_remove) {
2014 log_error("You need to specify at least one of --clean, --create or --remove.");
2021 static int read_config_file(const char *fn, bool ignore_enoent) {
2022 _cleanup_fclose_ FILE *f = NULL;
2023 char line[LINE_MAX];
2031 r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
2033 if (ignore_enoent && r == -ENOENT) {
2034 log_debug_errno(r, "Failed to open \"%s\": %m", fn);
2038 return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
2040 log_debug("Reading config file \"%s\".", fn);
2042 FOREACH_LINE(line, f, break) {
2049 if (*l == '#' || *l == 0)
2052 k = parse_line(fn, v, l);
2053 if (k < 0 && r == 0)
2057 /* we have to determine age parameter for each entry of type X */
2058 HASHMAP_FOREACH(i, globs, iterator) {
2060 Item *j, *candidate_item = NULL;
2062 if (i->type != IGNORE_DIRECTORY_PATH)
2065 HASHMAP_FOREACH(j, items, iter) {
2066 if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY && j->type != CREATE_SUBVOLUME)
2069 if (path_equal(j->path, i->path)) {
2074 if ((!candidate_item && path_startswith(i->path, j->path)) ||
2075 (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
2079 if (candidate_item && candidate_item->age_set) {
2080 i->age = candidate_item->age;
2086 log_error_errno(errno, "Failed to read from file %s: %m", fn);
2094 int main(int argc, char *argv[]) {
2099 r = parse_argv(argc, argv);
2103 log_set_target(LOG_TARGET_AUTO);
2104 log_parse_environment();
2109 mac_selinux_init(NULL);
2111 items = hashmap_new(&string_hash_ops);
2112 globs = hashmap_new(&string_hash_ops);
2114 if (!items || !globs) {
2121 if (optind < argc) {
2124 for (j = optind; j < argc; j++) {
2125 k = read_config_file(argv[j], false);
2126 if (k < 0 && r == 0)
2131 _cleanup_strv_free_ char **files = NULL;
2134 r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
2136 log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
2140 STRV_FOREACH(f, files) {
2141 k = read_config_file(*f, true);
2142 if (k < 0 && r == 0)
2147 HASHMAP_FOREACH(a, globs, iterator) {
2148 k = process_item_array(a);
2149 if (k < 0 && r == 0)
2153 HASHMAP_FOREACH(a, items, iterator) {
2154 k = process_item_array(a);
2155 if (k < 0 && r == 0)
2160 while ((a = hashmap_steal_first(items)))
2163 while ((a = hashmap_steal_first(globs)))
2166 hashmap_free(items);
2167 hashmap_free(globs);
2169 free(arg_include_prefixes);
2170 free(arg_exclude_prefixes);
2173 set_free_free(unix_sockets);
2175 mac_selinux_finish();
2177 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;