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 * const conf_file_dirs[] = {
112 "/usr/local/lib/tmpfiles.d",
113 "/usr/lib/tmpfiles.d",
114 #ifdef HAVE_SPLIT_USR
120 #define MAX_DEPTH 256
122 static bool needs_glob(ItemType t) {
123 return t == IGNORE_PATH || t == IGNORE_DIRECTORY_PATH || t == REMOVE_PATH || t == RECURSIVE_REMOVE_PATH || t == RELABEL_PATH || t == RECURSIVE_RELABEL_PATH;
126 static struct Item* find_glob(Hashmap *h, const char *match) {
130 HASHMAP_FOREACH(j, h, i)
131 if (fnmatch(j->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
137 static void load_unix_sockets(void) {
144 /* We maintain a cache of the sockets we found in
145 * /proc/net/unix to speed things up a little. */
147 unix_sockets = set_new(string_hash_func, string_compare_func);
151 f = fopen("/proc/net/unix", "re");
156 if (!fgets(line, sizeof(line), f))
163 if (!fgets(line, sizeof(line), f))
168 p = strchr(line, ':');
176 p += strspn(p, WHITESPACE);
177 p += strcspn(p, WHITESPACE); /* skip one more word */
178 p += strspn(p, WHITESPACE);
187 path_kill_slashes(s);
189 k = set_put(unix_sockets, s);
202 set_free_free(unix_sockets);
209 static bool unix_socket_alive(const char *fn) {
215 return !!set_get(unix_sockets, (char*) fn);
217 /* We don't know, so assume yes */
221 static int dir_cleanup(
225 const struct stat *ds,
230 bool keep_this_level)
233 struct timespec times[2];
234 bool deleted = false;
235 char *sub_path = NULL;
238 while ((dent = readdir(d))) {
242 if (streq(dent->d_name, ".") ||
243 streq(dent->d_name, ".."))
246 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
248 if (errno != ENOENT) {
249 log_error("stat(%s/%s) failed: %m", p, dent->d_name);
256 /* Stay on the same filesystem */
257 if (s.st_dev != rootdev)
260 /* Do not delete read-only files owned by root */
261 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR))
267 if (asprintf(&sub_path, "%s/%s", p, dent->d_name) < 0) {
272 /* Is there an item configured for this path? */
273 if (hashmap_get(items, sub_path))
276 if (find_glob(globs, sub_path))
279 if (S_ISDIR(s.st_mode)) {
282 streq(dent->d_name, "lost+found") &&
287 log_warning("Reached max depth on %s.", sub_path);
292 sub_dir = xopendirat(dirfd(d), dent->d_name, O_NOFOLLOW|O_NOATIME);
293 if (sub_dir == NULL) {
294 if (errno != ENOENT) {
295 log_error("opendir(%s/%s) failed: %m", p, dent->d_name);
302 q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
309 /* Note: if you are wondering why we don't
310 * support the sticky bit for excluding
311 * directories from cleaning like we do it for
312 * other file system objects: well, the sticky
313 * bit already has a meaning for directories,
314 * so we don't want to overload that. */
319 /* Ignore ctime, we change it when deleting */
320 age = MAX(timespec_load(&s.st_mtim),
321 timespec_load(&s.st_atim));
325 if (!i->type == IGNORE_DIRECTORY_PATH || !streq(dent->d_name, p)) {
326 log_debug("rmdir '%s'\n", sub_path);
328 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
329 if (errno != ENOENT && errno != ENOTEMPTY) {
330 log_error("rmdir(%s): %m", sub_path);
337 /* Skip files for which the sticky bit is
338 * set. These are semantics we define, and are
339 * unknown elsewhere. See XDG_RUNTIME_DIR
340 * specification for details. */
341 if (s.st_mode & S_ISVTX)
344 if (mountpoint && S_ISREG(s.st_mode)) {
345 if (streq(dent->d_name, ".journal") &&
349 if (streq(dent->d_name, "aquota.user") ||
350 streq(dent->d_name, "aquota.group"))
354 /* Ignore sockets that are listed in /proc/net/unix */
355 if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path))
358 /* Ignore device nodes */
359 if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode))
362 /* Keep files on this level around if this is
367 age = MAX3(timespec_load(&s.st_mtim),
368 timespec_load(&s.st_atim),
369 timespec_load(&s.st_ctim));
374 log_debug("unlink '%s'\n", sub_path);
376 if (unlinkat(dirfd(d), dent->d_name, 0) < 0) {
377 if (errno != ENOENT) {
378 log_error("unlink(%s): %m", sub_path);
389 /* Restore original directory timestamps */
390 times[0] = ds->st_atim;
391 times[1] = ds->st_mtim;
393 if (futimens(dirfd(d), times) < 0)
394 log_error("utimensat(%s): %m", p);
402 static int item_set_perms(Item *i, const char *path) {
403 /* not using i->path directly because it may be a glob */
405 if (chmod(path, i->mode) < 0) {
406 log_error("chmod(%s) failed: %m", path);
410 if (i->uid_set || i->gid_set)
412 i->uid_set ? i->uid : (uid_t) -1,
413 i->gid_set ? i->gid : (gid_t) -1) < 0) {
415 log_error("chown(%s) failed: %m", path);
419 return label_fix(path, false, false);
422 static int write_one_file(Item *i, const char *path) {
427 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND :
428 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC : 0;
431 label_context_set(path, S_IFREG);
432 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY|O_NOFOLLOW, i->mode);
434 label_context_clear();
439 if (i->type == WRITE_FILE && errno == ENOENT)
442 log_error("Failed to create file %s: %m", path);
449 _cleanup_free_ char *unescaped;
451 unescaped = cunescape(i->argument);
452 if (unescaped == NULL) {
453 close_nointr_nofail(fd);
457 l = strlen(unescaped);
458 n = write(fd, unescaped, l);
460 if (n < 0 || (size_t) n < l) {
461 log_error("Failed to write file %s: %s", path, n < 0 ? strerror(-n) : "Short write");
462 close_nointr_nofail(fd);
463 return n < 0 ? n : -EIO;
467 close_nointr_nofail(fd);
469 if (stat(path, &st) < 0) {
470 log_error("stat(%s) failed: %m", path);
474 if (!S_ISREG(st.st_mode)) {
475 log_error("%s is not a file.", path);
479 r = item_set_perms(i, path);
486 static int recursive_relabel_children(Item *i, const char *path) {
490 /* This returns the first error we run into, but nevertheless
495 return errno == ENOENT ? 0 : -errno;
499 union dirent_storage buf;
504 r = readdir_r(d, &buf.de, &de);
514 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
517 if (asprintf(&entry_path, "%s/%s", path, de->d_name) < 0) {
523 if (de->d_type == DT_UNKNOWN) {
526 if (lstat(entry_path, &st) < 0) {
527 if (ret == 0 && errno != ENOENT)
533 is_dir = S_ISDIR(st.st_mode);
536 is_dir = de->d_type == DT_DIR;
538 r = item_set_perms(i, entry_path);
540 if (ret == 0 && r != -ENOENT)
547 r = recursive_relabel_children(i, entry_path);
548 if (r < 0 && ret == 0)
560 static int recursive_relabel(Item *i, const char *path) {
564 r = item_set_perms(i, path);
568 if (lstat(path, &st) < 0)
571 if (S_ISDIR(st.st_mode))
572 r = recursive_relabel_children(i, path);
577 static int glob_item(Item *i, int (*action)(Item *, const char *)) {
585 if ((k = glob(i->path, GLOB_NOSORT|GLOB_BRACE, NULL, &g)) != 0) {
587 if (k != GLOB_NOMATCH) {
591 log_error("glob(%s) failed: %m", i->path);
596 STRV_FOREACH(fn, g.gl_pathv)
597 if ((k = action(i, *fn)) < 0)
604 static int create_item(Item *i) {
614 case IGNORE_DIRECTORY_PATH:
616 case RECURSIVE_REMOVE_PATH:
621 r = write_one_file(i, i->path);
626 r = glob_item(i, write_one_file);
632 case TRUNCATE_DIRECTORY:
633 case CREATE_DIRECTORY:
636 mkdir_parents_label(i->path, 0755);
637 r = mkdir(i->path, i->mode);
640 if (r < 0 && errno != EEXIST) {
641 log_error("Failed to create directory %s: %m", i->path);
645 if (stat(i->path, &st) < 0) {
646 log_error("stat(%s) failed: %m", i->path);
650 if (!S_ISDIR(st.st_mode)) {
651 log_error("%s is not a directory.", i->path);
655 r = item_set_perms(i, i->path);
664 r = mkfifo(i->path, i->mode);
667 if (r < 0 && errno != EEXIST) {
668 log_error("Failed to create fifo %s: %m", i->path);
672 if (stat(i->path, &st) < 0) {
673 log_error("stat(%s) failed: %m", i->path);
677 if (!S_ISFIFO(st.st_mode)) {
678 log_error("%s is not a fifo.", i->path);
682 r = item_set_perms(i, i->path);
688 case CREATE_SYMLINK: {
691 label_context_set(i->path, S_IFLNK);
692 r = symlink(i->argument, i->path);
694 label_context_clear();
697 if (r < 0 && errno != EEXIST) {
698 log_error("symlink(%s, %s) failed: %m", i->argument, i->path);
702 r = readlink_malloc(i->path, &x);
704 log_error("readlink(%s) failed: %s", i->path, strerror(-r));
708 if (!streq(i->argument, x)) {
710 log_error("%s is not the right symlinks.", i->path);
718 case CREATE_BLOCK_DEVICE:
719 case CREATE_CHAR_DEVICE: {
722 if (have_effective_cap(CAP_MKNOD) == 0) {
723 /* In a container we lack CAP_MKNOD. We
724 shouldnt attempt to create the device node in
725 that case to avoid noise, and we don't support
726 virtualized devices in containers anyway. */
728 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
732 file_type = (i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR);
735 label_context_set(i->path, file_type);
736 r = mknod(i->path, i->mode | file_type, i->major_minor);
738 label_context_clear();
742 if (r < 0 && errno != EEXIST) {
743 log_error("Failed to create device node %s: %m", i->path);
747 if (stat(i->path, &st) < 0) {
748 log_error("stat(%s) failed: %m", i->path);
752 if ((st.st_mode & S_IFMT) != file_type) {
753 log_error("%s is not a device node.", i->path);
757 r = item_set_perms(i, i->path);
766 r = glob_item(i, item_set_perms);
771 case RECURSIVE_RELABEL_PATH:
773 r = glob_item(i, recursive_relabel);
778 log_debug("%s created successfully.", i->path);
783 static int remove_item_instance(Item *i, const char *instance) {
792 case CREATE_DIRECTORY:
795 case CREATE_BLOCK_DEVICE:
796 case CREATE_CHAR_DEVICE:
798 case IGNORE_DIRECTORY_PATH:
800 case RECURSIVE_RELABEL_PATH:
805 if (remove(instance) < 0 && errno != ENOENT) {
806 log_error("remove(%s): %m", instance);
812 case TRUNCATE_DIRECTORY:
813 case RECURSIVE_REMOVE_PATH:
814 /* FIXME: we probably should use dir_cleanup() here
815 * instead of rm_rf() so that 'x' is honoured. */
816 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
817 if (r < 0 && r != -ENOENT) {
818 log_error("rm_rf(%s): %s", instance, strerror(-r));
828 static int remove_item(Item *i) {
837 case CREATE_DIRECTORY:
840 case CREATE_CHAR_DEVICE:
841 case CREATE_BLOCK_DEVICE:
843 case IGNORE_DIRECTORY_PATH:
845 case RECURSIVE_RELABEL_PATH:
850 case TRUNCATE_DIRECTORY:
851 case RECURSIVE_REMOVE_PATH:
852 r = glob_item(i, remove_item_instance);
859 static int clean_item_instance(Item *i, const char* instance) {
871 n = now(CLOCK_REALTIME);
877 d = opendir(instance);
879 if (errno == ENOENT || errno == ENOTDIR)
882 log_error("Failed to open directory %s: %m", i->path);
886 if (fstat(dirfd(d), &s) < 0) {
887 log_error("stat(%s) failed: %m", i->path);
892 if (!S_ISDIR(s.st_mode)) {
893 log_error("%s is not a directory.", i->path);
898 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0) {
899 log_error("stat(%s/..) failed: %m", i->path);
904 mountpoint = s.st_dev != ps.st_dev ||
905 (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
907 r = dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint, MAX_DEPTH, i->keep_first_level);
916 static int clean_item(Item *i) {
922 case CREATE_DIRECTORY:
923 case TRUNCATE_DIRECTORY:
925 clean_item_instance(i, i->path);
927 case IGNORE_DIRECTORY_PATH:
928 r = glob_item(i, clean_item_instance);
937 static int process_item(Item *i) {
942 r = arg_create ? create_item(i) : 0;
943 q = arg_remove ? remove_item(i) : 0;
944 p = arg_clean ? clean_item(i) : 0;
955 static void item_free(Item *i) {
963 static bool item_equal(Item *a, Item *b) {
967 if (!streq_ptr(a->path, b->path))
970 if (a->type != b->type)
973 if (a->uid_set != b->uid_set ||
974 (a->uid_set && a->uid != b->uid))
977 if (a->gid_set != b->gid_set ||
978 (a->gid_set && a->gid != b->gid))
981 if (a->mode_set != b->mode_set ||
982 (a->mode_set && a->mode != b->mode))
985 if (a->age_set != b->age_set ||
986 (a->age_set && a->age != b->age))
989 if ((a->type == CREATE_FILE ||
990 a->type == TRUNCATE_FILE ||
991 a->type == WRITE_FILE ||
992 a->type == CREATE_SYMLINK) &&
993 !streq_ptr(a->argument, b->argument))
996 if ((a->type == CREATE_CHAR_DEVICE ||
997 a->type == CREATE_BLOCK_DEVICE) &&
998 a->major_minor != b->major_minor)
1004 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1006 char *mode = NULL, *user = NULL, *group = NULL, *age = NULL;
1034 log_error("[%s:%u] Syntax error.", fname, line);
1040 n += strspn(buffer+n, WHITESPACE);
1041 if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) {
1042 i->argument = unquote(buffer+n, "\"");
1052 case CREATE_DIRECTORY:
1053 case TRUNCATE_DIRECTORY:
1056 case IGNORE_DIRECTORY_PATH:
1058 case RECURSIVE_REMOVE_PATH:
1060 case RECURSIVE_RELABEL_PATH:
1063 case CREATE_SYMLINK:
1065 log_error("[%s:%u] Symlink file requires argument.", fname, line);
1073 log_error("[%s:%u] Write file requires argument.", fname, line);
1079 case CREATE_CHAR_DEVICE:
1080 case CREATE_BLOCK_DEVICE: {
1081 unsigned major, minor;
1084 log_error("[%s:%u] Device file requires argument.", fname, line);
1089 if (sscanf(i->argument, "%u:%u", &major, &minor) != 2) {
1090 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i->argument);
1095 i->major_minor = makedev(major, minor);
1100 log_error("[%s:%u] Unknown file type '%c'.", fname, line, type);
1107 if (!path_is_absolute(i->path)) {
1108 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i->path);
1113 path_kill_slashes(i->path);
1115 if (arg_prefix && !path_startswith(i->path, arg_prefix)) {
1120 if (user && !streq(user, "-")) {
1121 const char *u = user;
1123 r = get_user_creds(&u, &i->uid, NULL, NULL, NULL);
1125 log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1132 if (group && !streq(group, "-")) {
1133 const char *g = group;
1135 r = get_group_creds(&g, &i->gid);
1137 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1144 if (mode && !streq(mode, "-")) {
1147 if (sscanf(mode, "%o", &m) != 1) {
1148 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1157 i->type == CREATE_DIRECTORY ||
1158 i->type == TRUNCATE_DIRECTORY ? 0755 : 0644;
1160 if (age && !streq(age, "-")) {
1161 const char *a = age;
1164 i->keep_first_level = true;
1168 if (parse_usec(a, &i->age) < 0) {
1169 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1177 h = needs_glob(i->type) ? globs : items;
1179 existing = hashmap_get(h, i->path);
1182 /* Two identical items are fine */
1183 if (!item_equal(existing, i))
1184 log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path);
1190 r = hashmap_put(h, i->path, i);
1192 log_error("Failed to insert item %s: %s", i->path, strerror(-r));
1211 static int help(void) {
1213 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1214 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1215 " -h --help Show this help\n"
1216 " --create Create marked files/directories\n"
1217 " --clean Clean up marked directories\n"
1218 " --remove Remove marked files/directories\n"
1219 " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n",
1220 program_invocation_short_name);
1225 static int parse_argv(int argc, char *argv[]) {
1234 static const struct option options[] = {
1235 { "help", no_argument, NULL, 'h' },
1236 { "create", no_argument, NULL, ARG_CREATE },
1237 { "clean", no_argument, NULL, ARG_CLEAN },
1238 { "remove", no_argument, NULL, ARG_REMOVE },
1239 { "prefix", required_argument, NULL, ARG_PREFIX },
1240 { NULL, 0, NULL, 0 }
1248 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
1269 arg_prefix = optarg;
1276 log_error("Unknown option code %c", c);
1281 if (!arg_clean && !arg_create && !arg_remove) {
1282 log_error("You need to specify at least one of --clean, --create or --remove.");
1289 static int read_config_file(const char *fn, bool ignore_enoent) {
1298 f = fopen(fn, "re");
1301 if (ignore_enoent && errno == ENOENT)
1304 log_error("Failed to open %s: %m", fn);
1308 log_debug("apply: %s\n", fn);
1310 char line[LINE_MAX], *l;
1313 if (!(fgets(line, sizeof(line), f)))
1319 if (*l == '#' || *l == 0)
1322 if ((k = parse_line(fn, v, l)) < 0)
1327 /* we have to determine age parameter for each entry of type X */
1328 HASHMAP_FOREACH(i, globs, iterator) {
1330 Item *j, *candidate_item = NULL;
1332 if (i->type != IGNORE_DIRECTORY_PATH)
1335 HASHMAP_FOREACH(j, items, iter) {
1336 if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY)
1339 if (path_equal(j->path, i->path)) {
1344 if ((!candidate_item && path_startswith(i->path, j->path)) ||
1345 (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1349 if (candidate_item) {
1350 i->age = candidate_item->age;
1356 log_error("Failed to read from file %s: %m", fn);
1366 static char *resolve_fragment(const char *fragment, const char **search_paths) {
1368 char *resolved_path;
1370 if (is_path(fragment))
1371 return strdup(fragment);
1373 STRV_FOREACH(p, search_paths) {
1374 resolved_path = strjoin(*p, "/", fragment, NULL);
1375 if (resolved_path == NULL) {
1380 if (access(resolved_path, F_OK) == 0)
1381 return resolved_path;
1383 free(resolved_path);
1390 int main(int argc, char *argv[]) {
1395 r = parse_argv(argc, argv);
1397 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1399 log_set_target(LOG_TARGET_AUTO);
1400 log_parse_environment();
1407 items = hashmap_new(string_hash_func, string_compare_func);
1408 globs = hashmap_new(string_hash_func, string_compare_func);
1410 if (!items || !globs) {
1418 if (optind < argc) {
1421 for (j = optind; j < argc; j++) {
1424 fragment = resolve_fragment(argv[j], (const char **)conf_file_dirs);
1426 log_error("Failed to find a %s file: %m", argv[j]);
1430 if (read_config_file(fragment, false) < 0)
1438 r = conf_files_list_strv(&files, ".conf", NULL, (const char **)conf_file_dirs);
1440 log_error("Failed to enumerate tmpfiles.d files: %s", strerror(-r));
1445 STRV_FOREACH(f, files) {
1446 if (read_config_file(*f, true) < 0)
1453 HASHMAP_FOREACH(i, globs, iterator)
1456 HASHMAP_FOREACH(i, items, iterator)
1460 while ((i = hashmap_steal_first(items)))
1463 while ((i = hashmap_steal_first(globs)))
1466 hashmap_free(items);
1467 hashmap_free(globs);
1469 set_free_free(unix_sockets);