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_is_mount_point(DIR *d, const char *subdir) {
217 struct file_handle *h;
218 int mount_id_parent, mount_id;
221 h = alloca(MAX_HANDLE_SZ);
223 h->handle_bytes = MAX_HANDLE_SZ;
224 r_p = name_to_handle_at(dirfd(d), ".", h, &mount_id_parent, 0);
228 h->handle_bytes = MAX_HANDLE_SZ;
229 r = name_to_handle_at(dirfd(d), subdir, h, &mount_id, 0);
233 /* got no handle; make no assumptions, return error */
234 if (r_p < 0 && r < 0)
237 /* got both handles; if they differ, it is a mount point */
238 if (r_p >= 0 && r >= 0)
239 return mount_id_parent != mount_id;
241 /* got only one handle; assume different mount points if one
242 * of both queries was not supported by the filesystem */
243 if (r_p == -ENOSYS || r_p == -ENOTSUP || r == -ENOSYS || r == -ENOTSUP)
252 static int dir_cleanup(
256 const struct stat *ds,
261 bool keep_this_level)
264 struct timespec times[2];
265 bool deleted = false;
268 while ((dent = readdir(d))) {
271 char _cleanup_free_ *sub_path = NULL;
273 if (streq(dent->d_name, ".") ||
274 streq(dent->d_name, ".."))
277 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
279 if (errno != ENOENT) {
280 log_error("stat(%s/%s) failed: %m", p, dent->d_name);
287 /* Stay on the same filesystem */
288 if (s.st_dev != rootdev)
291 /* Try to detect bind mounts of the same filesystem instance; they
292 * do not differ in device major/minors. This type of query is not
293 * supported on all kernels or filesystem types though. */
294 if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0)
297 /* Do not delete read-only files owned by root */
298 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR))
301 if (asprintf(&sub_path, "%s/%s", p, dent->d_name) < 0) {
306 /* Is there an item configured for this path? */
307 if (hashmap_get(items, sub_path))
310 if (find_glob(globs, sub_path))
313 if (S_ISDIR(s.st_mode)) {
316 streq(dent->d_name, "lost+found") &&
321 log_warning("Reached max depth on %s.", sub_path);
323 DIR _cleanup_closedir_ *sub_dir;
326 sub_dir = xopendirat(dirfd(d), dent->d_name, O_NOFOLLOW|O_NOATIME);
327 if (sub_dir == NULL) {
328 if (errno != ENOENT) {
329 log_error("opendir(%s/%s) failed: %m", p, dent->d_name);
336 q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
342 /* Note: if you are wondering why we don't
343 * support the sticky bit for excluding
344 * directories from cleaning like we do it for
345 * other file system objects: well, the sticky
346 * bit already has a meaning for directories,
347 * so we don't want to overload that. */
352 /* Ignore ctime, we change it when deleting */
353 age = MAX(timespec_load(&s.st_mtim),
354 timespec_load(&s.st_atim));
358 if (i->type != IGNORE_DIRECTORY_PATH || !streq(dent->d_name, p)) {
359 log_debug("rmdir '%s'\n", sub_path);
361 if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
362 if (errno != ENOENT && errno != ENOTEMPTY) {
363 log_error("rmdir(%s): %m", sub_path);
370 /* Skip files for which the sticky bit is
371 * set. These are semantics we define, and are
372 * unknown elsewhere. See XDG_RUNTIME_DIR
373 * specification for details. */
374 if (s.st_mode & S_ISVTX)
377 if (mountpoint && S_ISREG(s.st_mode)) {
378 if (streq(dent->d_name, ".journal") &&
382 if (streq(dent->d_name, "aquota.user") ||
383 streq(dent->d_name, "aquota.group"))
387 /* Ignore sockets that are listed in /proc/net/unix */
388 if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path))
391 /* Ignore device nodes */
392 if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode))
395 /* Keep files on this level around if this is
400 age = MAX3(timespec_load(&s.st_mtim),
401 timespec_load(&s.st_atim),
402 timespec_load(&s.st_ctim));
407 log_debug("unlink '%s'\n", sub_path);
409 if (unlinkat(dirfd(d), dent->d_name, 0) < 0) {
410 if (errno != ENOENT) {
411 log_error("unlink(%s): %m", sub_path);
422 /* Restore original directory timestamps */
423 times[0] = ds->st_atim;
424 times[1] = ds->st_mtim;
426 if (futimens(dirfd(d), times) < 0)
427 log_error("utimensat(%s): %m", p);
433 static int item_set_perms(Item *i, const char *path) {
434 /* not using i->path directly because it may be a glob */
436 if (chmod(path, i->mode) < 0) {
437 log_error("chmod(%s) failed: %m", path);
441 if (i->uid_set || i->gid_set)
443 i->uid_set ? i->uid : (uid_t) -1,
444 i->gid_set ? i->gid : (gid_t) -1) < 0) {
446 log_error("chown(%s) failed: %m", path);
450 return label_fix(path, false, false);
453 static int write_one_file(Item *i, const char *path) {
458 flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND :
459 i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC : 0;
462 label_context_set(path, S_IFREG);
463 fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY|O_NOFOLLOW, i->mode);
465 label_context_clear();
470 if (i->type == WRITE_FILE && errno == ENOENT)
473 log_error("Failed to create file %s: %m", path);
480 _cleanup_free_ char *unescaped;
482 unescaped = cunescape(i->argument);
483 if (unescaped == NULL) {
484 close_nointr_nofail(fd);
488 l = strlen(unescaped);
489 n = write(fd, unescaped, l);
491 if (n < 0 || (size_t) n < l) {
492 log_error("Failed to write file %s: %s", path, n < 0 ? strerror(-n) : "Short write");
493 close_nointr_nofail(fd);
494 return n < 0 ? n : -EIO;
498 close_nointr_nofail(fd);
500 if (stat(path, &st) < 0) {
501 log_error("stat(%s) failed: %m", path);
505 if (!S_ISREG(st.st_mode)) {
506 log_error("%s is not a file.", path);
510 r = item_set_perms(i, path);
517 static int recursive_relabel_children(Item *i, const char *path) {
518 DIR _cleanup_closedir_ *d;
521 /* This returns the first error we run into, but nevertheless
526 return errno == ENOENT ? 0 : -errno;
530 union dirent_storage buf;
533 char _cleanup_free_ *entry_path = NULL;
535 r = readdir_r(d, &buf.de, &de);
545 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
548 if (asprintf(&entry_path, "%s/%s", path, de->d_name) < 0) {
554 if (de->d_type == DT_UNKNOWN) {
557 if (lstat(entry_path, &st) < 0) {
558 if (ret == 0 && errno != ENOENT)
563 is_dir = S_ISDIR(st.st_mode);
566 is_dir = de->d_type == DT_DIR;
568 r = item_set_perms(i, entry_path);
570 if (ret == 0 && r != -ENOENT)
576 r = recursive_relabel_children(i, entry_path);
577 if (r < 0 && ret == 0)
585 static int recursive_relabel(Item *i, const char *path) {
589 r = item_set_perms(i, path);
593 if (lstat(path, &st) < 0)
596 if (S_ISDIR(st.st_mode))
597 r = recursive_relabel_children(i, path);
602 static int glob_item(Item *i, int (*action)(Item *, const char *)) {
610 if ((k = glob(i->path, GLOB_NOSORT|GLOB_BRACE, NULL, &g)) != 0) {
612 if (k != GLOB_NOMATCH) {
616 log_error("glob(%s) failed: %m", i->path);
621 STRV_FOREACH(fn, g.gl_pathv)
622 if ((k = action(i, *fn)) < 0)
629 static int create_item(Item *i) {
639 case IGNORE_DIRECTORY_PATH:
641 case RECURSIVE_REMOVE_PATH:
646 r = write_one_file(i, i->path);
651 r = glob_item(i, write_one_file);
657 case TRUNCATE_DIRECTORY:
658 case CREATE_DIRECTORY:
661 mkdir_parents_label(i->path, 0755);
662 r = mkdir(i->path, i->mode);
665 if (r < 0 && errno != EEXIST) {
666 log_error("Failed to create directory %s: %m", i->path);
670 if (stat(i->path, &st) < 0) {
671 log_error("stat(%s) failed: %m", i->path);
675 if (!S_ISDIR(st.st_mode)) {
676 log_error("%s is not a directory.", i->path);
680 r = item_set_perms(i, i->path);
689 r = mkfifo(i->path, i->mode);
692 if (r < 0 && errno != EEXIST) {
693 log_error("Failed to create fifo %s: %m", i->path);
697 if (stat(i->path, &st) < 0) {
698 log_error("stat(%s) failed: %m", i->path);
702 if (!S_ISFIFO(st.st_mode)) {
703 log_error("%s is not a fifo.", i->path);
707 r = item_set_perms(i, i->path);
713 case CREATE_SYMLINK: {
716 label_context_set(i->path, S_IFLNK);
717 r = symlink(i->argument, i->path);
719 label_context_clear();
722 if (r < 0 && errno != EEXIST) {
723 log_error("symlink(%s, %s) failed: %m", i->argument, i->path);
727 r = readlink_malloc(i->path, &x);
729 log_error("readlink(%s) failed: %s", i->path, strerror(-r));
733 if (!streq(i->argument, x)) {
735 log_error("%s is not the right symlinks.", i->path);
743 case CREATE_BLOCK_DEVICE:
744 case CREATE_CHAR_DEVICE: {
747 if (have_effective_cap(CAP_MKNOD) == 0) {
748 /* In a container we lack CAP_MKNOD. We
749 shouldnt attempt to create the device node in
750 that case to avoid noise, and we don't support
751 virtualized devices in containers anyway. */
753 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
757 file_type = (i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR);
760 label_context_set(i->path, file_type);
761 r = mknod(i->path, i->mode | file_type, i->major_minor);
763 label_context_clear();
767 if (r < 0 && errno != EEXIST) {
768 log_error("Failed to create device node %s: %m", i->path);
772 if (stat(i->path, &st) < 0) {
773 log_error("stat(%s) failed: %m", i->path);
777 if ((st.st_mode & S_IFMT) != file_type) {
778 log_error("%s is not a device node.", i->path);
782 r = item_set_perms(i, i->path);
791 r = glob_item(i, item_set_perms);
796 case RECURSIVE_RELABEL_PATH:
798 r = glob_item(i, recursive_relabel);
803 log_debug("%s created successfully.", i->path);
808 static int remove_item_instance(Item *i, const char *instance) {
817 case CREATE_DIRECTORY:
820 case CREATE_BLOCK_DEVICE:
821 case CREATE_CHAR_DEVICE:
823 case IGNORE_DIRECTORY_PATH:
825 case RECURSIVE_RELABEL_PATH:
830 if (remove(instance) < 0 && errno != ENOENT) {
831 log_error("remove(%s): %m", instance);
837 case TRUNCATE_DIRECTORY:
838 case RECURSIVE_REMOVE_PATH:
839 /* FIXME: we probably should use dir_cleanup() here
840 * instead of rm_rf() so that 'x' is honoured. */
841 r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
842 if (r < 0 && r != -ENOENT) {
843 log_error("rm_rf(%s): %s", instance, strerror(-r));
853 static int remove_item(Item *i) {
862 case CREATE_DIRECTORY:
865 case CREATE_CHAR_DEVICE:
866 case CREATE_BLOCK_DEVICE:
868 case IGNORE_DIRECTORY_PATH:
870 case RECURSIVE_RELABEL_PATH:
875 case TRUNCATE_DIRECTORY:
876 case RECURSIVE_REMOVE_PATH:
877 r = glob_item(i, remove_item_instance);
884 static int clean_item_instance(Item *i, const char* instance) {
885 DIR _cleanup_closedir_ *d = NULL;
896 n = now(CLOCK_REALTIME);
902 d = opendir(instance);
904 if (errno == ENOENT || errno == ENOTDIR)
907 log_error("Failed to open directory %s: %m", i->path);
911 if (fstat(dirfd(d), &s) < 0) {
912 log_error("stat(%s) failed: %m", i->path);
916 if (!S_ISDIR(s.st_mode)) {
917 log_error("%s is not a directory.", i->path);
921 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0) {
922 log_error("stat(%s/..) failed: %m", i->path);
926 mountpoint = s.st_dev != ps.st_dev ||
927 (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
929 r = dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
930 MAX_DEPTH, i->keep_first_level);
934 static int clean_item(Item *i) {
940 case CREATE_DIRECTORY:
941 case TRUNCATE_DIRECTORY:
943 clean_item_instance(i, i->path);
945 case IGNORE_DIRECTORY_PATH:
946 r = glob_item(i, clean_item_instance);
955 static int process_item(Item *i) {
960 r = arg_create ? create_item(i) : 0;
961 q = arg_remove ? remove_item(i) : 0;
962 p = arg_clean ? clean_item(i) : 0;
973 static void item_free(Item *i) {
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 int parse_line(const char *fname, unsigned line, const char *buffer) {
1025 *mode = NULL, *user = NULL, *group = NULL, *age = NULL;
1039 "%c %ms %ms %ms %ms %ms %n",
1048 log_error("[%s:%u] Syntax error.", fname, line);
1054 n += strspn(buffer+n, WHITESPACE);
1055 if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) {
1056 i->argument = unquote(buffer+n, "\"");
1066 case CREATE_DIRECTORY:
1067 case TRUNCATE_DIRECTORY:
1070 case IGNORE_DIRECTORY_PATH:
1072 case RECURSIVE_REMOVE_PATH:
1074 case RECURSIVE_RELABEL_PATH:
1077 case CREATE_SYMLINK:
1079 log_error("[%s:%u] Symlink file requires argument.", fname, line);
1087 log_error("[%s:%u] Write file requires argument.", fname, line);
1093 case CREATE_CHAR_DEVICE:
1094 case CREATE_BLOCK_DEVICE: {
1095 unsigned major, minor;
1098 log_error("[%s:%u] Device file requires argument.", fname, line);
1103 if (sscanf(i->argument, "%u:%u", &major, &minor) != 2) {
1104 log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i->argument);
1109 i->major_minor = makedev(major, minor);
1114 log_error("[%s:%u] Unknown file type '%c'.", fname, line, type);
1121 if (!path_is_absolute(i->path)) {
1122 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i->path);
1127 path_kill_slashes(i->path);
1129 if (arg_prefix && !path_startswith(i->path, arg_prefix)) {
1134 if (user && !streq(user, "-")) {
1135 const char *u = user;
1137 r = get_user_creds(&u, &i->uid, NULL, NULL, NULL);
1139 log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
1146 if (group && !streq(group, "-")) {
1147 const char *g = group;
1149 r = get_group_creds(&g, &i->gid);
1151 log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
1158 if (mode && !streq(mode, "-")) {
1161 if (sscanf(mode, "%o", &m) != 1) {
1162 log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
1171 i->type == CREATE_DIRECTORY ||
1172 i->type == TRUNCATE_DIRECTORY ? 0755 : 0644;
1174 if (age && !streq(age, "-")) {
1175 const char *a = age;
1178 i->keep_first_level = true;
1182 if (parse_usec(a, &i->age) < 0) {
1183 log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
1191 h = needs_glob(i->type) ? globs : items;
1193 existing = hashmap_get(h, i->path);
1196 /* Two identical items are fine */
1197 if (!item_equal(existing, i))
1198 log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path);
1204 r = hashmap_put(h, i->path, i);
1206 log_error("Failed to insert item %s: %s", i->path, strerror(-r));
1220 static int help(void) {
1222 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
1223 "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
1224 " -h --help Show this help\n"
1225 " --create Create marked files/directories\n"
1226 " --clean Clean up marked directories\n"
1227 " --remove Remove marked files/directories\n"
1228 " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n",
1229 program_invocation_short_name);
1234 static int parse_argv(int argc, char *argv[]) {
1243 static const struct option options[] = {
1244 { "help", no_argument, NULL, 'h' },
1245 { "create", no_argument, NULL, ARG_CREATE },
1246 { "clean", no_argument, NULL, ARG_CLEAN },
1247 { "remove", no_argument, NULL, ARG_REMOVE },
1248 { "prefix", required_argument, NULL, ARG_PREFIX },
1249 { NULL, 0, NULL, 0 }
1257 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
1278 arg_prefix = optarg;
1285 log_error("Unknown option code %c", c);
1290 if (!arg_clean && !arg_create && !arg_remove) {
1291 log_error("You need to specify at least one of --clean, --create or --remove.");
1298 static int read_config_file(const char *fn, bool ignore_enoent) {
1307 r = search_and_fopen_nulstr(fn, "re", conf_file_dirs, &f);
1309 if (ignore_enoent && r == -ENOENT)
1312 log_error("Failed to open '%s', ignoring: %s", fn, strerror(-r));
1316 log_debug("apply: %s\n", fn);
1318 char line[LINE_MAX], *l;
1321 if (!(fgets(line, sizeof(line), f)))
1327 if (*l == '#' || *l == 0)
1330 if ((k = parse_line(fn, v, l)) < 0)
1335 /* we have to determine age parameter for each entry of type X */
1336 HASHMAP_FOREACH(i, globs, iterator) {
1338 Item *j, *candidate_item = NULL;
1340 if (i->type != IGNORE_DIRECTORY_PATH)
1343 HASHMAP_FOREACH(j, items, iter) {
1344 if (j->type != CREATE_DIRECTORY && j->type != TRUNCATE_DIRECTORY)
1347 if (path_equal(j->path, i->path)) {
1352 if ((!candidate_item && path_startswith(i->path, j->path)) ||
1353 (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
1357 if (candidate_item) {
1358 i->age = candidate_item->age;
1364 log_error("Failed to read from file %s: %m", fn);
1374 int main(int argc, char *argv[]) {
1379 r = parse_argv(argc, argv);
1381 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1383 log_set_target(LOG_TARGET_AUTO);
1384 log_parse_environment();
1391 items = hashmap_new(string_hash_func, string_compare_func);
1392 globs = hashmap_new(string_hash_func, string_compare_func);
1394 if (!items || !globs) {
1401 if (optind < argc) {
1404 for (j = optind; j < argc; j++) {
1405 k = read_config_file(argv[j], false);
1406 if (k < 0 && r == 0)
1411 _cleanup_strv_free_ char **files = NULL;
1414 r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
1416 log_error("Failed to enumerate tmpfiles.d files: %s", strerror(-r));
1420 STRV_FOREACH(f, files) {
1421 k = read_config_file(*f, true);
1422 if (k < 0 && r == 0)
1427 HASHMAP_FOREACH(i, globs, iterator)
1430 HASHMAP_FOREACH(i, items, iterator)
1434 while ((i = hashmap_steal_first(items)))
1437 while ((i = hashmap_steal_first(globs)))
1440 hashmap_free(items);
1441 hashmap_free(globs);
1443 set_free_free(unix_sockets);
1447 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;