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
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
37 #include <sys/types.h>
38 #include <sys/param.h>
41 #include <sys/capability.h>
47 #include "path-util.h"
51 #include "conf-files.h"
52 #include "capability.h"
54 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
55 * them in the file system. This is intended to be used to create
56 * properly owned directories beneath /tmp, /var/tmp, /run, which are
57 * volatile and hence need to be recreated on bootup. */
59 typedef enum ItemType {
60 /* These ones take file names */
64 CREATE_DIRECTORY = 'd',
65 TRUNCATE_DIRECTORY = 'D',
68 CREATE_CHAR_DEVICE = 'c',
69 CREATE_BLOCK_DEVICE = 'b',
71 /* These ones take globs */
73 IGNORE_DIRECTORY_PATH = 'X',
75 RECURSIVE_REMOVE_PATH = 'R',
77 RECURSIVE_RELABEL_PATH = 'Z'
97 bool keep_first_level:1;
100 static Hashmap *items = NULL, *globs = NULL;
101 static Set *unix_sockets = NULL;
103 static bool arg_create = false;
104 static bool arg_clean = false;
105 static bool arg_remove = false;
107 static const char *arg_prefix = NULL;
109 static const char conf_file_dirs[] =
112 "/usr/local/lib/tmpfiles.d\0"
113 "/usr/lib/tmpfiles.d\0"
114 #ifdef HAVE_SPLIT_USR
119 #define MAX_DEPTH 256
121 static bool needs_glob(ItemType t) {
122 return t == IGNORE_PATH || t == IGNORE_DIRECTORY_PATH || t == REMOVE_PATH || t == RECURSIVE_REMOVE_PATH || t == RELABEL_PATH || t == RECURSIVE_RELABEL_PATH;
125 static struct Item* find_glob(Hashmap *h, const char *match) {
129 HASHMAP_FOREACH(j, h, i)
130 if (fnmatch(j->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
136 static void load_unix_sockets(void) {
137 FILE _cleanup_fclose_ *f = NULL;
143 /* We maintain a cache of the sockets we found in
144 * /proc/net/unix to speed things up a little. */
146 unix_sockets = set_new(string_hash_func, string_compare_func);
150 f = fopen("/proc/net/unix", "re");
155 if (!fgets(line, sizeof(line), f))
162 if (!fgets(line, sizeof(line), f))
167 p = strchr(line, ':');
175 p += strspn(p, WHITESPACE);
176 p += strcspn(p, WHITESPACE); /* skip one more word */
177 p += strspn(p, WHITESPACE);
186 path_kill_slashes(s);
188 k = set_put(unix_sockets, s);
200 set_free_free(unix_sockets);
204 static bool unix_socket_alive(const char *fn) {
210 return !!set_get(unix_sockets, (char*) fn);
212 /* We don't know, so assume yes */
216 static int dir_cleanup(
220 const struct stat *ds,
225 bool keep_this_level)
228 struct timespec times[2];
229 bool deleted = false;
232 while ((dent = readdir(d))) {
235 char _cleanup_free_ *sub_path = NULL;
237 if (streq(dent->d_name, ".") ||
238 streq(dent->d_name, ".."))
241 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
243 if (errno != ENOENT) {
244 log_error("stat(%s/%s) failed: %m", p, dent->d_name);
251 /* Stay on the same filesystem */
252 if (s.st_dev != rootdev)
255 /* Do not delete read-only files owned by root */
256 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR))
259 if (asprintf(&sub_path, "%s/%s", p, dent->d_name) < 0) {
264 /* Is there an item configured for this path? */
265 if (hashmap_get(items, sub_path))
268 if (find_glob(globs, sub_path))
271 if (S_ISDIR(s.st_mode)) {
274 streq(dent->d_name, "lost+found") &&
279 log_warning("Reached max depth on %s.", sub_path);
281 DIR _cleanup_closedir_ *sub_dir;
284 sub_dir = xopendirat(dirfd(d), dent->d_name, O_NOFOLLOW|O_NOATIME);
285 if (sub_dir == NULL) {
286 if (errno != ENOENT) {
287 log_error("opendir(%s/%s) failed: %m", p, dent->d_name);
294 q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
300 /* Note: if you are wondering why we don't
301 * support the sticky bit for excluding
302 * directories from cleaning like we do it for
303 * other file system objects: well, the sticky
304 * bit already has a meaning for directories,
305 * so we don't want to overload that. */
310 /* Ignore ctime, we change it when deleting */
311 age = MAX(timespec_load(&s.st_mtim),
312 timespec_load(&s.st_atim));
316 if (i->type != IGNORE_DIRECTORY_PATH || !streq(dent->d_name, p)) {
317 log_debug("rmdir '%s'\n", sub_path);
319 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
320 if (errno != ENOENT && errno != ENOTEMPTY) {
321 log_error("rmdir(%s): %m", sub_path);
328 /* Skip files for which the sticky bit is
329 * set. These are semantics we define, and are
330 * unknown elsewhere. See XDG_RUNTIME_DIR
331 * specification for details. */
332 if (s.st_mode & S_ISVTX)
335 if (mountpoint && S_ISREG(s.st_mode)) {
336 if (streq(dent->d_name, ".journal") &&
340 if (streq(dent->d_name, "aquota.user") ||
341 streq(dent->d_name, "aquota.group"))
345 /* Ignore sockets that are listed in /proc/net/unix */
346 if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path))
349 /* Ignore device nodes */
350 if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode))
353 /* Keep files on this level around if this is
358 age = MAX3(timespec_load(&s.st_mtim),
359 timespec_load(&s.st_atim),
360 timespec_load(&s.st_ctim));
365 log_debug("unlink '%s'\n", sub_path);
367 if (unlinkat(dirfd(d), dent->d_name, 0) < 0) {
368 if (errno != ENOENT) {
369 log_error("unlink(%s): %m", sub_path);
380 /* Restore original directory timestamps */
381 times[0] = ds->st_atim;
382 times[1] = ds->st_mtim;
384 if (futimens(dirfd(d), times) < 0)
385 log_error("utimensat(%s): %m", p);
391 static int item_set_perms(Item *i, const char *path) {
392 /* not using i->path directly because it may be a glob */
394 if (chmod(path, i->mode) < 0) {
395 log_error("chmod(%s) failed: %m", path);
399 if (i->uid_set || i->gid_set)
401 i->uid_set ? i->uid : (uid_t) -1,
402 i->gid_set ? i->gid : (gid_t) -1) < 0) {
404 log_error("chown(%s) failed: %m", path);
408 return label_fix(path, false, false);
411 static int write_one_file(Item *i, const char *path) {
416 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND :
417 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC : 0;
420 label_context_set(path, S_IFREG);
421 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY|O_NOFOLLOW, i->mode);
423 label_context_clear();
428 if (i->type == WRITE_FILE && errno == ENOENT)
431 log_error("Failed to create file %s: %m", path);
438 _cleanup_free_ char *unescaped;
440 unescaped = cunescape(i->argument);
441 if (unescaped == NULL) {
442 close_nointr_nofail(fd);
446 l = strlen(unescaped);
447 n = write(fd, unescaped, l);
449 if (n < 0 || (size_t) n < l) {
450 log_error("Failed to write file %s: %s", path, n < 0 ? strerror(-n) : "Short write");
451 close_nointr_nofail(fd);
452 return n < 0 ? n : -EIO;
456 close_nointr_nofail(fd);
458 if (stat(path, &st) < 0) {
459 log_error("stat(%s) failed: %m", path);
463 if (!S_ISREG(st.st_mode)) {
464 log_error("%s is not a file.", path);
468 r = item_set_perms(i, path);
475 static int recursive_relabel_children(Item *i, const char *path) {
476 DIR _cleanup_closedir_ *d;
479 /* This returns the first error we run into, but nevertheless
484 return errno == ENOENT ? 0 : -errno;
488 union dirent_storage buf;
491 char _cleanup_free_ *entry_path = NULL;
493 r = readdir_r(d, &buf.de, &de);
503 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
506 if (asprintf(&entry_path, "%s/%s", path, de->d_name) < 0) {
512 if (de->d_type == DT_UNKNOWN) {
515 if (lstat(entry_path, &st) < 0) {
516 if (ret == 0 && errno != ENOENT)
521 is_dir = S_ISDIR(st.st_mode);
524 is_dir = de->d_type == DT_DIR;
526 r = item_set_perms(i, entry_path);
528 if (ret == 0 && r != -ENOENT)
534 r = recursive_relabel_children(i, entry_path);
535 if (r < 0 && ret == 0)
543 static int recursive_relabel(Item *i, const char *path) {
547 r = item_set_perms(i, path);
551 if (lstat(path, &st) < 0)
554 if (S_ISDIR(st.st_mode))
555 r = recursive_relabel_children(i, path);
560 static int glob_item(Item *i, int (*action)(Item *, const char *)) {
568 if ((k = glob(i->path, GLOB_NOSORT|GLOB_BRACE, NULL, &g)) != 0) {
570 if (k != GLOB_NOMATCH) {
574 log_error("glob(%s) failed: %m", i->path);
579 STRV_FOREACH(fn, g.gl_pathv)
580 if ((k = action(i, *fn)) < 0)
587 static int create_item(Item *i) {
597 case IGNORE_DIRECTORY_PATH:
599 case RECURSIVE_REMOVE_PATH:
604 r = write_one_file(i, i->path);
609 r = glob_item(i, write_one_file);
615 case TRUNCATE_DIRECTORY:
616 case CREATE_DIRECTORY:
619 mkdir_parents_label(i->path, 0755);
620 r = mkdir(i->path, i->mode);
623 if (r < 0 && errno != EEXIST) {
624 log_error("Failed to create directory %s: %m", i->path);
628 if (stat(i->path, &st) < 0) {
629 log_error("stat(%s) failed: %m", i->path);
633 if (!S_ISDIR(st.st_mode)) {
634 log_error("%s is not a directory.", i->path);
638 r = item_set_perms(i, i->path);
647 r = mkfifo(i->path, i->mode);
650 if (r < 0 && errno != EEXIST) {
651 log_error("Failed to create fifo %s: %m", i->path);
655 if (stat(i->path, &st) < 0) {
656 log_error("stat(%s) failed: %m", i->path);
660 if (!S_ISFIFO(st.st_mode)) {
661 log_error("%s is not a fifo.", i->path);
665 r = item_set_perms(i, i->path);
671 case CREATE_SYMLINK: {
674 label_context_set(i->path, S_IFLNK);
675 r = symlink(i->argument, i->path);
677 label_context_clear();
680 if (r < 0 && errno != EEXIST) {
681 log_error("symlink(%s, %s) failed: %m", i->argument, i->path);
685 r = readlink_malloc(i->path, &x);
687 log_error("readlink(%s) failed: %s", i->path, strerror(-r));
691 if (!streq(i->argument, x)) {
693 log_error("%s is not the right symlinks.", i->path);
701 case CREATE_BLOCK_DEVICE:
702 case CREATE_CHAR_DEVICE: {
705 if (have_effective_cap(CAP_MKNOD) == 0) {
706 /* In a container we lack CAP_MKNOD. We
707 shouldnt attempt to create the device node in
708 that case to avoid noise, and we don't support
709 virtualized devices in containers anyway. */
711 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
715 file_type = (i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR);
718 label_context_set(i->path, file_type);
719 r = mknod(i->path, i->mode | file_type, i->major_minor);
721 label_context_clear();
725 if (r < 0 && errno != EEXIST) {
726 log_error("Failed to create device node %s: %m", i->path);
730 if (stat(i->path, &st) < 0) {
731 log_error("stat(%s) failed: %m", i->path);
735 if ((st.st_mode & S_IFMT) != file_type) {
736 log_error("%s is not a device node.", i->path);
740 r = item_set_perms(i, i->path);
749 r = glob_item(i, item_set_perms);
754 case RECURSIVE_RELABEL_PATH:
756 r = glob_item(i, recursive_relabel);
761 log_debug("%s created successfully.", i->path);
766 static int remove_item_instance(Item *i, const char *instance) {
775 case CREATE_DIRECTORY:
778 case CREATE_BLOCK_DEVICE:
779 case CREATE_CHAR_DEVICE:
781 case IGNORE_DIRECTORY_PATH:
783 case RECURSIVE_RELABEL_PATH:
788 if (remove(instance) < 0 && errno != ENOENT) {
789 log_error("remove(%s): %m", instance);
795 case TRUNCATE_DIRECTORY:
796 case RECURSIVE_REMOVE_PATH:
797 /* FIXME: we probably should use dir_cleanup() here
798 * instead of rm_rf() so that 'x' is honoured. */
799 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
800 if (r < 0 && r != -ENOENT) {
801 log_error("rm_rf(%s): %s", instance, strerror(-r));
811 static int remove_item(Item *i) {
820 case CREATE_DIRECTORY:
823 case CREATE_CHAR_DEVICE:
824 case CREATE_BLOCK_DEVICE:
826 case IGNORE_DIRECTORY_PATH:
828 case RECURSIVE_RELABEL_PATH:
833 case TRUNCATE_DIRECTORY:
834 case RECURSIVE_REMOVE_PATH:
835 r = glob_item(i, remove_item_instance);
842 static int clean_item_instance(Item *i, const char* instance) {
843 DIR _cleanup_closedir_ *d = NULL;
854 n = now(CLOCK_REALTIME);
860 d = opendir(instance);
862 if (errno == ENOENT || errno == ENOTDIR)
865 log_error("Failed to open directory %s: %m", i->path);
869 if (fstat(dirfd(d), &s) < 0) {
870 log_error("stat(%s) failed: %m", i->path);
874 if (!S_ISDIR(s.st_mode)) {
875 log_error("%s is not a directory.", i->path);
879 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0) {
880 log_error("stat(%s/..) failed: %m", i->path);
884 mountpoint = s.st_dev != ps.st_dev ||
885 (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
887 r = dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
888 MAX_DEPTH, i->keep_first_level);
892 static int clean_item(Item *i) {
898 case CREATE_DIRECTORY:
899 case TRUNCATE_DIRECTORY:
901 clean_item_instance(i, i->path);
903 case IGNORE_DIRECTORY_PATH:
904 r = glob_item(i, clean_item_instance);
913 static int process_item(Item *i) {
918 r = arg_create ? create_item(i) : 0;
919 q = arg_remove ? remove_item(i) : 0;
920 p = arg_clean ? clean_item(i) : 0;
931 static void item_free(Item *i) {
939 static bool item_equal(Item *a, Item *b) {
943 if (!streq_ptr(a->path, b->path))
946 if (a->type != b->type)
949 if (a->uid_set != b->uid_set ||
950 (a->uid_set && a->uid != b->uid))
953 if (a->gid_set != b->gid_set ||
954 (a->gid_set && a->gid != b->gid))
957 if (a->mode_set != b->mode_set ||
958 (a->mode_set && a->mode != b->mode))
961 if (a->age_set != b->age_set ||
962 (a->age_set && a->age != b->age))
965 if ((a->type == CREATE_FILE ||
966 a->type == TRUNCATE_FILE ||
967 a->type == WRITE_FILE ||
968 a->type == CREATE_SYMLINK) &&
969 !streq_ptr(a->argument, b->argument))
972 if ((a->type == CREATE_CHAR_DEVICE ||
973 a->type == CREATE_BLOCK_DEVICE) &&
974 a->major_minor != b->major_minor)
980 static int parse_line(const char *fname, unsigned line, const char *buffer) {
983 *mode = NULL, *user = NULL, *group = NULL, *age = NULL;
997 "%c %ms %ms %ms %ms %ms %n",
1006 log_error("[%s:%u] Syntax error.", fname, line);
1012 n += strspn(buffer+n, WHITESPACE);
1013 if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) {
1014 i->argument = unquote(buffer+n, "\"");
1024 case CREATE_DIRECTORY:
1025 case TRUNCATE_DIRECTORY:
1028 case IGNORE_DIRECTORY_PATH:
1030 case RECURSIVE_REMOVE_PATH:
1032 case RECURSIVE_RELABEL_PATH:
1035 case CREATE_SYMLINK:
1037 log_error("[%s:%u] Symlink file requires argument.", fname, line);
1045 log_error("[%s:%u] Write file requires argument.", fname, line);
1051 case CREATE_CHAR_DEVICE:
1052 case CREATE_BLOCK_DEVICE: {
1053 unsigned major, minor;
1056 log_error("[%s:%u] Device file requires argument.", fname, line);
1061 if (sscanf(i->argument, "%u:%u", &major, &minor) != 2) {
1062 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i->argument);
1067 i->major_minor = makedev(major, minor);
1072 log_error("[%s:%u] Unknown file type '%c'.", fname, line, type);
1079 if (!path_is_absolute(i->path)) {
1080 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i->path);
1085 path_kill_slashes(i->path);
1087 if (arg_prefix && !path_startswith(i->path, arg_prefix)) {
1092 if (user && !streq(user, "-")) {
1093 const char *u = user;
1095 r = get_user_creds(&u, &i->uid, NULL, NULL, NULL);
1097 log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1104 if (group && !streq(group, "-")) {
1105 const char *g = group;
1107 r = get_group_creds(&g, &i->gid);
1109 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1116 if (mode && !streq(mode, "-")) {
1119 if (sscanf(mode, "%o", &m) != 1) {
1120 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1129 i->type == CREATE_DIRECTORY ||
1130 i->type == TRUNCATE_DIRECTORY ? 0755 : 0644;
1132 if (age && !streq(age, "-")) {
1133 const char *a = age;
1136 i->keep_first_level = true;
1140 if (parse_usec(a, &i->age) < 0) {
1141 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1149 h = needs_glob(i->type) ? globs : items;
1151 existing = hashmap_get(h, i->path);
1154 /* Two identical items are fine */
1155 if (!item_equal(existing, i))
1156 log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path);
1162 r = hashmap_put(h, i->path, i);
1164 log_error("Failed to insert item %s: %s", i->path, strerror(-r));
1178 static int help(void) {
1180 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1181 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1182 " -h --help Show this help\n"
1183 " --create Create marked files/directories\n"
1184 " --clean Clean up marked directories\n"
1185 " --remove Remove marked files/directories\n"
1186 " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n",
1187 program_invocation_short_name);
1192 static int parse_argv(int argc, char *argv[]) {
1201 static const struct option options[] = {
1202 { "help", no_argument, NULL, 'h' },
1203 { "create", no_argument, NULL, ARG_CREATE },
1204 { "clean", no_argument, NULL, ARG_CLEAN },
1205 { "remove", no_argument, NULL, ARG_REMOVE },
1206 { "prefix", required_argument, NULL, ARG_PREFIX },
1207 { NULL, 0, NULL, 0 }
1215 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
1236 arg_prefix = optarg;
1243 log_error("Unknown option code %c", c);
1248 if (!arg_clean && !arg_create && !arg_remove) {
1249 log_error("You need to specify at least one of --clean, --create or --remove.");
1256 static int read_config_file(const char *fn, bool ignore_enoent) {
1265 r = search_and_fopen_nulstr(fn, "re", conf_file_dirs, &f);
1267 if (ignore_enoent && r == -ENOENT)
1270 log_error("Failed to open '%s', ignoring: %s", fn, strerror(-r));
1274 log_debug("apply: %s\n", fn);
1276 char line[LINE_MAX], *l;
1279 if (!(fgets(line, sizeof(line), f)))
1285 if (*l == '#' || *l == 0)
1288 if ((k = parse_line(fn, v, l)) < 0)
1293 /* we have to determine age parameter for each entry of type X */
1294 HASHMAP_FOREACH(i, globs, iterator) {
1296 Item *j, *candidate_item = NULL;
1298 if (i->type != IGNORE_DIRECTORY_PATH)
1301 HASHMAP_FOREACH(j, items, iter) {
1302 if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY)
1305 if (path_equal(j->path, i->path)) {
1310 if ((!candidate_item && path_startswith(i->path, j->path)) ||
1311 (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1315 if (candidate_item) {
1316 i->age = candidate_item->age;
1322 log_error("Failed to read from file %s: %m", fn);
1332 int main(int argc, char *argv[]) {
1337 r = parse_argv(argc, argv);
1339 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1341 log_set_target(LOG_TARGET_AUTO);
1342 log_parse_environment();
1349 items = hashmap_new(string_hash_func, string_compare_func);
1350 globs = hashmap_new(string_hash_func, string_compare_func);
1352 if (!items || !globs) {
1359 if (optind < argc) {
1362 for (j = optind; j < argc; j++) {
1363 k = read_config_file(argv[j], false);
1364 if (k < 0 && r == 0)
1369 _cleanup_strv_free_ char **files = NULL;
1372 r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
1374 log_error("Failed to enumerate tmpfiles.d files: %s", strerror(-r));
1378 STRV_FOREACH(f, files) {
1379 k = read_config_file(*f, true);
1380 if (k < 0 && r == 0)
1385 HASHMAP_FOREACH(i, globs, iterator)
1388 HASHMAP_FOREACH(i, items, iterator)
1392 while ((i = hashmap_steal_first(items)))
1395 while ((i = hashmap_steal_first(globs)))
1398 hashmap_free(items);
1399 hashmap_free(globs);
1401 set_free_free(unix_sockets);
1405 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;