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>
48 #include "path-util.h"
52 #include "conf-files.h"
53 #include "capability.h"
55 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
56 * them in the file system. This is intended to be used to create
57 * properly owned directories beneath /tmp, /var/tmp, /run, which are
58 * volatile and hence need to be recreated on bootup. */
60 typedef enum ItemType {
61 /* These ones take file names */
65 CREATE_DIRECTORY = 'd',
66 TRUNCATE_DIRECTORY = 'D',
69 CREATE_CHAR_DEVICE = 'c',
70 CREATE_BLOCK_DEVICE = 'b',
72 /* These ones take globs */
74 IGNORE_DIRECTORY_PATH = 'X',
76 RECURSIVE_REMOVE_PATH = 'R',
78 RECURSIVE_RELABEL_PATH = 'Z'
98 bool keep_first_level:1;
101 static Hashmap *items = NULL, *globs = NULL;
102 static Set *unix_sockets = NULL;
104 static bool arg_create = false;
105 static bool arg_clean = false;
106 static bool arg_remove = false;
108 static char **include_prefixes = NULL;
109 static char **exclude_prefixes = NULL;
111 static const char conf_file_dirs[] =
114 "/usr/local/lib/tmpfiles.d\0"
115 "/usr/lib/tmpfiles.d\0"
116 #ifdef HAVE_SPLIT_USR
121 #define MAX_DEPTH 256
123 static bool needs_glob(ItemType t) {
124 return t == IGNORE_PATH || t == IGNORE_DIRECTORY_PATH || t == REMOVE_PATH || t == RECURSIVE_REMOVE_PATH || t == RELABEL_PATH || t == RECURSIVE_RELABEL_PATH;
127 static struct Item* find_glob(Hashmap *h, const char *match) {
131 HASHMAP_FOREACH(j, h, i)
132 if (fnmatch(j->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
138 static void load_unix_sockets(void) {
139 _cleanup_fclose_ FILE *f = NULL;
145 /* We maintain a cache of the sockets we found in
146 * /proc/net/unix to speed things up a little. */
148 unix_sockets = set_new(string_hash_func, string_compare_func);
152 f = fopen("/proc/net/unix", "re");
157 if (!fgets(line, sizeof(line), f))
164 if (!fgets(line, sizeof(line), f))
169 p = strchr(line, ':');
177 p += strspn(p, WHITESPACE);
178 p += strcspn(p, WHITESPACE); /* skip one more word */
179 p += strspn(p, WHITESPACE);
188 path_kill_slashes(s);
190 k = set_consume(unix_sockets, s);
191 if (k < 0 && k != -EEXIST)
198 set_free_free(unix_sockets);
202 static bool unix_socket_alive(const char *fn) {
208 return !!set_get(unix_sockets, (char*) fn);
210 /* We don't know, so assume yes */
214 static int dir_is_mount_point(DIR *d, const char *subdir) {
215 struct file_handle *h;
216 int mount_id_parent, mount_id;
219 h = alloca(MAX_HANDLE_SZ);
221 h->handle_bytes = MAX_HANDLE_SZ;
222 r_p = name_to_handle_at(dirfd(d), ".", h, &mount_id_parent, 0);
226 h->handle_bytes = MAX_HANDLE_SZ;
227 r = name_to_handle_at(dirfd(d), subdir, h, &mount_id, 0);
231 /* got no handle; make no assumptions, return error */
232 if (r_p < 0 && r < 0)
235 /* got both handles; if they differ, it is a mount point */
236 if (r_p >= 0 && r >= 0)
237 return mount_id_parent != mount_id;
239 /* got only one handle; assume different mount points if one
240 * of both queries was not supported by the filesystem */
241 if (r_p == -ENOSYS || r_p == -ENOTSUP || r == -ENOSYS || r == -ENOTSUP)
250 static int dir_cleanup(
254 const struct stat *ds,
259 bool keep_this_level)
262 struct timespec times[2];
263 bool deleted = false;
266 while ((dent = readdir(d))) {
269 _cleanup_free_ char *sub_path = NULL;
271 if (streq(dent->d_name, ".") ||
272 streq(dent->d_name, ".."))
275 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
277 if (errno != ENOENT) {
278 log_error("stat(%s/%s) failed: %m", p, dent->d_name);
285 /* Stay on the same filesystem */
286 if (s.st_dev != rootdev)
289 /* Try to detect bind mounts of the same filesystem instance; they
290 * do not differ in device major/minors. This type of query is not
291 * supported on all kernels or filesystem types though. */
292 if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0)
295 /* Do not delete read-only files owned by root */
296 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR))
299 if (asprintf(&sub_path, "%s/%s", p, dent->d_name) < 0) {
304 /* Is there an item configured for this path? */
305 if (hashmap_get(items, sub_path))
308 if (find_glob(globs, sub_path))
311 if (S_ISDIR(s.st_mode)) {
314 streq(dent->d_name, "lost+found") &&
319 log_warning("Reached max depth on %s.", sub_path);
321 _cleanup_closedir_ DIR *sub_dir;
324 sub_dir = xopendirat(dirfd(d), dent->d_name, O_NOFOLLOW|O_NOATIME);
325 if (sub_dir == NULL) {
326 if (errno != ENOENT) {
327 log_error("opendir(%s/%s) failed: %m", p, dent->d_name);
334 q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
340 /* Note: if you are wondering why we don't
341 * support the sticky bit for excluding
342 * directories from cleaning like we do it for
343 * other file system objects: well, the sticky
344 * bit already has a meaning for directories,
345 * so we don't want to overload that. */
350 /* Ignore ctime, we change it when deleting */
351 age = MAX(timespec_load(&s.st_mtim),
352 timespec_load(&s.st_atim));
356 if (i->type != IGNORE_DIRECTORY_PATH || !streq(dent->d_name, p)) {
357 log_debug("rmdir '%s'\n", sub_path);
359 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
360 if (errno != ENOENT && errno != ENOTEMPTY) {
361 log_error("rmdir(%s): %m", sub_path);
368 /* Skip files for which the sticky bit is
369 * set. These are semantics we define, and are
370 * unknown elsewhere. See XDG_RUNTIME_DIR
371 * specification for details. */
372 if (s.st_mode & S_ISVTX)
375 if (mountpoint && S_ISREG(s.st_mode)) {
376 if (streq(dent->d_name, ".journal") &&
380 if (streq(dent->d_name, "aquota.user") ||
381 streq(dent->d_name, "aquota.group"))
385 /* Ignore sockets that are listed in /proc/net/unix */
386 if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path))
389 /* Ignore device nodes */
390 if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode))
393 /* Keep files on this level around if this is
398 age = MAX3(timespec_load(&s.st_mtim),
399 timespec_load(&s.st_atim),
400 timespec_load(&s.st_ctim));
405 log_debug("unlink '%s'\n", sub_path);
407 if (unlinkat(dirfd(d), dent->d_name, 0) < 0) {
408 if (errno != ENOENT) {
409 log_error("unlink(%s): %m", sub_path);
420 /* Restore original directory timestamps */
421 times[0] = ds->st_atim;
422 times[1] = ds->st_mtim;
424 if (futimens(dirfd(d), times) < 0)
425 log_error("utimensat(%s): %m", p);
431 static int item_set_perms(Item *i, const char *path) {
432 /* not using i->path directly because it may be a glob */
434 if (chmod(path, i->mode) < 0) {
435 log_error("chmod(%s) failed: %m", path);
439 if (i->uid_set || i->gid_set)
441 i->uid_set ? i->uid : (uid_t) -1,
442 i->gid_set ? i->gid : (gid_t) -1) < 0) {
444 log_error("chown(%s) failed: %m", path);
448 return label_fix(path, false, false);
451 static int write_one_file(Item *i, const char *path) {
455 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND :
456 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC : 0;
459 label_context_set(path, S_IFREG);
460 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY|O_NOFOLLOW, i->mode);
462 label_context_clear();
467 if (i->type == WRITE_FILE && errno == ENOENT)
470 log_error("Failed to create file %s: %m", path);
477 _cleanup_free_ char *unescaped;
479 unescaped = cunescape(i->argument);
480 if (unescaped == NULL) {
481 close_nointr_nofail(fd);
485 l = strlen(unescaped);
486 n = write(fd, unescaped, l);
488 if (n < 0 || (size_t) n < l) {
489 log_error("Failed to write file %s: %s", path, n < 0 ? strerror(-n) : "Short write");
490 close_nointr_nofail(fd);
491 return n < 0 ? n : -EIO;
495 close_nointr_nofail(fd);
497 if (stat(path, &st) < 0) {
498 log_error("stat(%s) failed: %m", path);
502 if (!S_ISREG(st.st_mode)) {
503 log_error("%s is not a file.", path);
507 r = item_set_perms(i, path);
514 static int recursive_relabel_children(Item *i, const char *path) {
515 _cleanup_closedir_ DIR *d;
518 /* This returns the first error we run into, but nevertheless
523 return errno == ENOENT ? 0 : -errno;
527 union dirent_storage buf;
530 _cleanup_free_ char *entry_path = NULL;
532 r = readdir_r(d, &buf.de, &de);
542 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
545 if (asprintf(&entry_path, "%s/%s", path, de->d_name) < 0) {
551 if (de->d_type == DT_UNKNOWN) {
554 if (lstat(entry_path, &st) < 0) {
555 if (ret == 0 && errno != ENOENT)
560 is_dir = S_ISDIR(st.st_mode);
563 is_dir = de->d_type == DT_DIR;
565 r = item_set_perms(i, entry_path);
567 if (ret == 0 && r != -ENOENT)
573 r = recursive_relabel_children(i, entry_path);
574 if (r < 0 && ret == 0)
582 static int recursive_relabel(Item *i, const char *path) {
586 r = item_set_perms(i, path);
590 if (lstat(path, &st) < 0)
593 if (S_ISDIR(st.st_mode))
594 r = recursive_relabel_children(i, path);
599 static int glob_item(Item *i, int (*action)(Item *, const char *)) {
601 _cleanup_globfree_ glob_t g = {};
605 k = glob(i->path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
607 if (k != GLOB_NOMATCH) {
611 log_error("glob(%s) failed: %m", i->path);
615 STRV_FOREACH(fn, g.gl_pathv) {
624 static int create_item(Item *i) {
633 case IGNORE_DIRECTORY_PATH:
635 case RECURSIVE_REMOVE_PATH:
640 r = write_one_file(i, i->path);
645 r = glob_item(i, write_one_file);
651 case TRUNCATE_DIRECTORY:
652 case CREATE_DIRECTORY:
654 RUN_WITH_UMASK(0000) {
655 mkdir_parents_label(i->path, 0755);
656 r = mkdir(i->path, i->mode);
659 if (r < 0 && errno != EEXIST) {
660 log_error("Failed to create directory %s: %m", i->path);
664 if (stat(i->path, &st) < 0) {
665 log_error("stat(%s) failed: %m", i->path);
669 if (!S_ISDIR(st.st_mode)) {
670 log_error("%s is not a directory.", i->path);
674 r = item_set_perms(i, i->path);
682 RUN_WITH_UMASK(0000) {
683 r = mkfifo(i->path, i->mode);
686 if (r < 0 && errno != EEXIST) {
687 log_error("Failed to create fifo %s: %m", i->path);
691 if (stat(i->path, &st) < 0) {
692 log_error("stat(%s) failed: %m", i->path);
696 if (!S_ISFIFO(st.st_mode)) {
697 log_error("%s is not a fifo.", i->path);
701 r = item_set_perms(i, i->path);
707 case CREATE_SYMLINK: {
710 label_context_set(i->path, S_IFLNK);
711 r = symlink(i->argument, i->path);
713 label_context_clear();
716 if (r < 0 && errno != EEXIST) {
717 log_error("symlink(%s, %s) failed: %m", i->argument, i->path);
721 r = readlink_malloc(i->path, &x);
723 log_error("readlink(%s) failed: %s", i->path, strerror(-r));
727 if (!streq(i->argument, x)) {
729 log_error("%s is not the right symlinks.", i->path);
737 case CREATE_BLOCK_DEVICE:
738 case CREATE_CHAR_DEVICE: {
741 if (have_effective_cap(CAP_MKNOD) == 0) {
742 /* In a container we lack CAP_MKNOD. We
743 shouldn't attempt to create the device node in
744 that case to avoid noise, and we don't support
745 virtualized devices in containers anyway. */
747 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
751 file_type = (i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR);
753 RUN_WITH_UMASK(0000) {
754 label_context_set(i->path, file_type);
755 r = mknod(i->path, i->mode | file_type, i->major_minor);
757 label_context_clear();
761 if (r < 0 && errno != EEXIST) {
762 log_error("Failed to create device node %s: %m", i->path);
766 if (stat(i->path, &st) < 0) {
767 log_error("stat(%s) failed: %m", i->path);
771 if ((st.st_mode & S_IFMT) != file_type) {
772 log_error("%s is not a device node.", i->path);
776 r = item_set_perms(i, i->path);
785 r = glob_item(i, item_set_perms);
790 case RECURSIVE_RELABEL_PATH:
792 r = glob_item(i, recursive_relabel);
797 log_debug("%s created successfully.", i->path);
802 static int remove_item_instance(Item *i, const char *instance) {
811 case CREATE_DIRECTORY:
814 case CREATE_BLOCK_DEVICE:
815 case CREATE_CHAR_DEVICE:
817 case IGNORE_DIRECTORY_PATH:
819 case RECURSIVE_RELABEL_PATH:
824 if (remove(instance) < 0 && errno != ENOENT) {
825 log_error("remove(%s): %m", instance);
831 case TRUNCATE_DIRECTORY:
832 case RECURSIVE_REMOVE_PATH:
833 /* FIXME: we probably should use dir_cleanup() here
834 * instead of rm_rf() so that 'x' is honoured. */
835 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
836 if (r < 0 && r != -ENOENT) {
837 log_error("rm_rf(%s): %s", instance, strerror(-r));
847 static int remove_item(Item *i) {
856 case CREATE_DIRECTORY:
859 case CREATE_CHAR_DEVICE:
860 case CREATE_BLOCK_DEVICE:
862 case IGNORE_DIRECTORY_PATH:
864 case RECURSIVE_RELABEL_PATH:
869 case TRUNCATE_DIRECTORY:
870 case RECURSIVE_REMOVE_PATH:
871 r = glob_item(i, remove_item_instance);
878 static int clean_item_instance(Item *i, const char* instance) {
879 _cleanup_closedir_ DIR *d = NULL;
890 n = now(CLOCK_REALTIME);
896 d = opendir(instance);
898 if (errno == ENOENT || errno == ENOTDIR)
901 log_error("Failed to open directory %s: %m", i->path);
905 if (fstat(dirfd(d), &s) < 0) {
906 log_error("stat(%s) failed: %m", i->path);
910 if (!S_ISDIR(s.st_mode)) {
911 log_error("%s is not a directory.", i->path);
915 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0) {
916 log_error("stat(%s/..) failed: %m", i->path);
920 mountpoint = s.st_dev != ps.st_dev ||
921 (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
923 r = dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
924 MAX_DEPTH, i->keep_first_level);
928 static int clean_item(Item *i) {
934 case CREATE_DIRECTORY:
935 case TRUNCATE_DIRECTORY:
937 clean_item_instance(i, i->path);
939 case IGNORE_DIRECTORY_PATH:
940 r = glob_item(i, clean_item_instance);
949 static int process_item(Item *i) {
954 r = arg_create ? create_item(i) : 0;
955 q = arg_remove ? remove_item(i) : 0;
956 p = arg_clean ? clean_item(i) : 0;
967 static void item_free(Item *i) {
975 static inline void item_freep(Item **i) {
979 #define _cleanup_item_free_ _cleanup_(item_freep)
981 static bool item_equal(Item *a, Item *b) {
985 if (!streq_ptr(a->path, b->path))
988 if (a->type != b->type)
991 if (a->uid_set != b->uid_set ||
992 (a->uid_set && a->uid != b->uid))
995 if (a->gid_set != b->gid_set ||
996 (a->gid_set && a->gid != b->gid))
999 if (a->mode_set != b->mode_set ||
1000 (a->mode_set && a->mode != b->mode))
1003 if (a->age_set != b->age_set ||
1004 (a->age_set && a->age != b->age))
1007 if ((a->type == CREATE_FILE ||
1008 a->type == TRUNCATE_FILE ||
1009 a->type == WRITE_FILE ||
1010 a->type == CREATE_SYMLINK) &&
1011 !streq_ptr(a->argument, b->argument))
1014 if ((a->type == CREATE_CHAR_DEVICE ||
1015 a->type == CREATE_BLOCK_DEVICE) &&
1016 a->major_minor != b->major_minor)
1022 static bool should_include_path(const char *path) {
1025 STRV_FOREACH(prefix, exclude_prefixes) {
1026 if (path_startswith(path, *prefix))
1030 STRV_FOREACH(prefix, include_prefixes) {
1031 if (path_startswith(path, *prefix))
1035 /* no matches, so we should include this path only if we
1036 * have no whitelist at all */
1037 return strv_length(include_prefixes) == 0;
1040 static int parse_line(const char *fname, unsigned line, const char *buffer) {
1041 _cleanup_item_free_ Item *i = NULL;
1044 *mode = NULL, *user = NULL, *group = NULL, *age = NULL;
1058 "%c %ms %ms %ms %ms %ms %n",
1067 log_error("[%s:%u] Syntax error.", fname, line);
1072 n += strspn(buffer+n, WHITESPACE);
1073 if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) {
1074 i->argument = unquote(buffer+n, "\"");
1084 case CREATE_DIRECTORY:
1085 case TRUNCATE_DIRECTORY:
1088 case IGNORE_DIRECTORY_PATH:
1090 case RECURSIVE_REMOVE_PATH:
1092 case RECURSIVE_RELABEL_PATH:
1095 case CREATE_SYMLINK:
1097 log_error("[%s:%u] Symlink file requires argument.", fname, line);
1104 log_error("[%s:%u] Write file requires argument.", fname, line);
1109 case CREATE_CHAR_DEVICE:
1110 case CREATE_BLOCK_DEVICE: {
1111 unsigned major, minor;
1114 log_error("[%s:%u] Device file requires argument.", fname, line);
1118 if (sscanf(i->argument, "%u:%u", &major, &minor) != 2) {
1119 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i->argument);
1123 i->major_minor = makedev(major, minor);
1128 log_error("[%s:%u] Unknown file type '%c'.", fname, line, type);
1134 if (!path_is_absolute(i->path)) {
1135 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i->path);
1139 path_kill_slashes(i->path);
1141 if (!should_include_path(i->path))
1144 if (user && !streq(user, "-")) {
1145 const char *u = user;
1147 r = get_user_creds(&u, &i->uid, NULL, NULL, NULL);
1149 log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1156 if (group && !streq(group, "-")) {
1157 const char *g = group;
1159 r = get_group_creds(&g, &i->gid);
1161 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1168 if (mode && !streq(mode, "-")) {
1171 if (sscanf(mode, "%o", &m) != 1) {
1172 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1180 i->type == CREATE_DIRECTORY ||
1181 i->type == TRUNCATE_DIRECTORY ? 0755 : 0644;
1183 if (age && !streq(age, "-")) {
1184 const char *a = age;
1187 i->keep_first_level = true;
1191 if (parse_sec(a, &i->age) < 0) {
1192 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1199 h = needs_glob(i->type) ? globs : items;
1201 existing = hashmap_get(h, i->path);
1204 /* Two identical items are fine */
1205 if (!item_equal(existing, i))
1206 log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path);
1211 r = hashmap_put(h, i->path, i);
1213 log_error("Failed to insert item %s: %s", i->path, strerror(-r));
1217 i = NULL; /* avoid cleanup */
1222 static int help(void) {
1224 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1225 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1226 " -h --help Show this help\n"
1227 " --create Create marked files/directories\n"
1228 " --clean Clean up marked directories\n"
1229 " --remove Remove marked files/directories\n"
1230 " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n"
1231 " --exclude-prefix=PATH Ignore rules that apply to paths with the specified prefix\n",
1232 program_invocation_short_name);
1237 static int parse_argv(int argc, char *argv[]) {
1247 static const struct option options[] = {
1248 { "help", no_argument, NULL, 'h' },
1249 { "create", no_argument, NULL, ARG_CREATE },
1250 { "clean", no_argument, NULL, ARG_CLEAN },
1251 { "remove", no_argument, NULL, ARG_REMOVE },
1252 { "prefix", required_argument, NULL, ARG_PREFIX },
1253 { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
1254 { NULL, 0, NULL, 0 }
1262 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
1283 if (strv_extend(&include_prefixes, optarg) < 0)
1287 case ARG_EXCLUDE_PREFIX:
1288 if (strv_extend(&exclude_prefixes, optarg) < 0)
1296 log_error("Unknown option code %c", c);
1301 if (!arg_clean && !arg_create && !arg_remove) {
1302 log_error("You need to specify at least one of --clean, --create or --remove.");
1309 static int read_config_file(const char *fn, bool ignore_enoent) {
1318 r = search_and_fopen_nulstr(fn, "re", conf_file_dirs, &f);
1320 if (ignore_enoent && r == -ENOENT)
1323 log_error("Failed to open '%s', ignoring: %s", fn, strerror(-r));
1327 log_debug("apply: %s\n", fn);
1329 char line[LINE_MAX], *l;
1332 if (!(fgets(line, sizeof(line), f)))
1338 if (*l == '#' || *l == 0)
1341 if ((k = parse_line(fn, v, l)) < 0)
1346 /* we have to determine age parameter for each entry of type X */
1347 HASHMAP_FOREACH(i, globs, iterator) {
1349 Item *j, *candidate_item = NULL;
1351 if (i->type != IGNORE_DIRECTORY_PATH)
1354 HASHMAP_FOREACH(j, items, iter) {
1355 if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY)
1358 if (path_equal(j->path, i->path)) {
1363 if ((!candidate_item && path_startswith(i->path, j->path)) ||
1364 (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1368 if (candidate_item) {
1369 i->age = candidate_item->age;
1375 log_error("Failed to read from file %s: %m", fn);
1385 int main(int argc, char *argv[]) {
1390 r = parse_argv(argc, argv);
1392 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1394 log_set_target(LOG_TARGET_AUTO);
1395 log_parse_environment();
1402 items = hashmap_new(string_hash_func, string_compare_func);
1403 globs = hashmap_new(string_hash_func, string_compare_func);
1405 if (!items || !globs) {
1412 if (optind < argc) {
1415 for (j = optind; j < argc; j++) {
1416 k = read_config_file(argv[j], false);
1417 if (k < 0 && r == 0)
1422 _cleanup_strv_free_ char **files = NULL;
1425 r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
1427 log_error("Failed to enumerate tmpfiles.d files: %s", strerror(-r));
1431 STRV_FOREACH(f, files) {
1432 k = read_config_file(*f, true);
1433 if (k < 0 && r == 0)
1438 HASHMAP_FOREACH(i, globs, iterator)
1441 HASHMAP_FOREACH(i, items, iterator)
1445 while ((i = hashmap_steal_first(items)))
1448 while ((i = hashmap_steal_first(globs)))
1451 hashmap_free(items);
1452 hashmap_free(globs);
1454 strv_free(include_prefixes);
1456 set_free_free(unix_sockets);
1460 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;