chiark / gitweb /
readahead: remove misleading error messages
[elogind.git] / src / tmpfiles.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering, Kay Sievers
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
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   General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <limits.h>
28 #include <dirent.h>
29 #include <grp.h>
30 #include <pwd.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stddef.h>
34 #include <getopt.h>
35 #include <stdbool.h>
36 #include <time.h>
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <glob.h>
40 #include <fnmatch.h>
41
42 #include "log.h"
43 #include "util.h"
44 #include "strv.h"
45 #include "label.h"
46 #include "set.h"
47
48 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
49  * them in the file system. This is intended to be used to create
50  * properly owned directories beneath /tmp, /var/tmp, /var/run and
51  * /var/lock which are volatile and hence need to be recreated on
52  * bootup. */
53
54 enum {
55         /* These ones take file names */
56         CREATE_FILE = 'f',
57         TRUNCATE_FILE = 'F',
58         CREATE_DIRECTORY = 'd',
59         TRUNCATE_DIRECTORY = 'D',
60
61         /* These ones take globs */
62         IGNORE_PATH = 'x',
63         REMOVE_PATH = 'r',
64         RECURSIVE_REMOVE_PATH = 'R'
65 };
66
67 typedef struct Item {
68         char type;
69
70         char *path;
71         uid_t uid;
72         gid_t gid;
73         mode_t mode;
74         usec_t age;
75
76         bool uid_set:1;
77         bool gid_set:1;
78         bool mode_set:1;
79         bool age_set:1;
80 } Item;
81
82 static Hashmap *items = NULL, *globs = NULL;
83 static Set *unix_sockets = NULL;
84
85 static bool arg_create = false;
86 static bool arg_clean = false;
87 static bool arg_remove = false;
88
89 static const char *arg_prefix = NULL;
90
91 #define MAX_DEPTH 256
92
93 static bool needs_glob(int t) {
94         return t == IGNORE_PATH || t == REMOVE_PATH || t == RECURSIVE_REMOVE_PATH;
95 }
96
97 static struct Item* find_glob(Hashmap *h, const char *match) {
98         Item *j;
99         Iterator i;
100
101         HASHMAP_FOREACH(j, h, i)
102                 if (fnmatch(j->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
103                         return j;
104
105         return NULL;
106 }
107
108 static void load_unix_sockets(void) {
109         FILE *f = NULL;
110         char line[LINE_MAX];
111
112         if (unix_sockets)
113                 return;
114
115         /* We maintain a cache of the sockets we found in
116          * /proc/net/unix to speed things up a little. */
117
118         if (!(unix_sockets = set_new(string_hash_func, string_compare_func)))
119                 return;
120
121         if (!(f = fopen("/proc/net/unix", "re")))
122                 return;
123
124         if (!(fgets(line, sizeof(line), f)))
125                 goto fail;
126
127         for (;;) {
128                 char *p, *s;
129                 int k;
130
131                 if (!(fgets(line, sizeof(line), f)))
132                         break;
133
134                 truncate_nl(line);
135
136                 if (strlen(line) < 53)
137                         continue;
138
139                 p = line + 53;
140                 p += strspn(p, WHITESPACE);
141                 p += strcspn(p, WHITESPACE);
142                 p += strspn(p, WHITESPACE);
143
144                 if (*p != '/')
145                         continue;
146
147                 if (!(s = strdup(p)))
148                         goto fail;
149
150                 path_kill_slashes(s);
151
152                 if ((k = set_put(unix_sockets, s)) < 0) {
153                         free(s);
154
155                         if (k != -EEXIST)
156                                 goto fail;
157                 }
158         }
159
160         return;
161
162 fail:
163         set_free_free(unix_sockets);
164         unix_sockets = NULL;
165
166         if (f)
167                 fclose(f);
168 }
169
170 static bool unix_socket_alive(const char *fn) {
171         assert(fn);
172
173         load_unix_sockets();
174
175         if (unix_sockets)
176                 return !!set_get(unix_sockets, (char*) fn);
177
178         /* We don't know, so assume yes */
179         return true;
180 }
181
182 static int dir_cleanup(
183                 const char *p,
184                 DIR *d,
185                 const struct stat *ds,
186                 usec_t cutoff,
187                 dev_t rootdev,
188                 bool mountpoint,
189                 int maxdepth)
190 {
191         struct dirent *dent;
192         struct timespec times[2];
193         bool deleted = false;
194         char *sub_path = NULL;
195         int r = 0;
196
197         while ((dent = readdir(d))) {
198                 struct stat s;
199                 usec_t age;
200
201                 if (streq(dent->d_name, ".") ||
202                     streq(dent->d_name, ".."))
203                         continue;
204
205                 if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
206
207                         if (errno != ENOENT) {
208                                 log_error("stat(%s/%s) failed: %m", p, dent->d_name);
209                                 r = -errno;
210                         }
211
212                         continue;
213                 }
214
215                 /* Stay on the same filesystem */
216                 if (s.st_dev != rootdev)
217                         continue;
218
219                 /* Do not delete read-only files owned by root */
220                 if (s.st_uid == 0 && !(s.st_mode & S_IWUSR))
221                         continue;
222
223                 free(sub_path);
224                 sub_path = NULL;
225
226                 if (asprintf(&sub_path, "%s/%s", p, dent->d_name) < 0) {
227                         log_error("Out of memory");
228                         r = -ENOMEM;
229                         goto finish;
230                 }
231
232                 /* Is there an item configured for this path? */
233                 if (hashmap_get(items, sub_path))
234                         continue;
235
236                 if (find_glob(globs, sub_path))
237                         continue;
238
239                 if (S_ISDIR(s.st_mode)) {
240
241                         if (mountpoint &&
242                             streq(dent->d_name, "lost+found") &&
243                             s.st_uid == 0)
244                                 continue;
245
246                         if (maxdepth <= 0)
247                                 log_warning("Reached max depth on %s.", sub_path);
248                         else {
249                                 DIR *sub_dir;
250                                 int q;
251
252                                 sub_dir = xopendirat(dirfd(d), dent->d_name, O_NOFOLLOW);
253                                 if (sub_dir == NULL) {
254                                         if (errno != ENOENT) {
255                                                 log_error("opendir(%s/%s) failed: %m", p, dent->d_name);
256                                                 r = -errno;
257                                         }
258
259                                         continue;
260                                 }
261
262                                 q = dir_cleanup(sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1);
263                                 closedir(sub_dir);
264
265                                 if (q < 0)
266                                         r = q;
267                         }
268
269                         /* Ignore ctime, we change it when deleting */
270                         age = MAX(timespec_load(&s.st_mtim),
271                                   timespec_load(&s.st_atim));
272                         if (age >= cutoff)
273                                 continue;
274
275                         log_debug("rmdir '%s'\n", sub_path);
276
277                         if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
278                                 if (errno != ENOENT && errno != ENOTEMPTY) {
279                                         log_error("rmdir(%s): %m", sub_path);
280                                         r = -errno;
281                                 }
282                         }
283
284                 } else {
285                         /* Skip files for which the sticky bit is
286                          * set. These are semantics we define, and are
287                          * unknown elsewhere. See XDG_RUNTIME_DIR
288                          * specification for details. */
289                         if (s.st_mode & S_ISVTX)
290                                 continue;
291
292                         if (mountpoint && S_ISREG(s.st_mode)) {
293                                 if (streq(dent->d_name, ".journal") &&
294                                     s.st_uid == 0)
295                                         continue;
296
297                                 if (streq(dent->d_name, "aquota.user") ||
298                                     streq(dent->d_name, "aquota.group"))
299                                         continue;
300                         }
301
302                         /* Ignore sockets that are listed in /proc/net/unix */
303                         if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path))
304                                 continue;
305
306                         age = MAX3(timespec_load(&s.st_mtim),
307                                    timespec_load(&s.st_atim),
308                                    timespec_load(&s.st_ctim));
309
310                         if (age >= cutoff)
311                                 continue;
312
313                         log_debug("unlink '%s'\n", sub_path);
314
315                         if (unlinkat(dirfd(d), dent->d_name, 0) < 0) {
316                                 if (errno != ENOENT) {
317                                         log_error("unlink(%s): %m", sub_path);
318                                         r = -errno;
319                                 }
320                         }
321
322                         deleted = true;
323                 }
324         }
325
326 finish:
327         if (deleted) {
328                 /* Restore original directory timestamps */
329                 times[0] = ds->st_atim;
330                 times[1] = ds->st_mtim;
331
332                 if (futimens(dirfd(d), times) < 0)
333                         log_error("utimensat(%s): %m", p);
334         }
335
336         free(sub_path);
337
338         return r;
339 }
340
341 static int clean_item(Item *i) {
342         DIR *d;
343         struct stat s, ps;
344         bool mountpoint;
345         int r;
346         usec_t cutoff, n;
347
348         assert(i);
349
350         if (i->type != CREATE_DIRECTORY &&
351             i->type != TRUNCATE_DIRECTORY &&
352             i->type != IGNORE_PATH)
353                 return 0;
354
355         if (!i->age_set || i->age <= 0)
356                 return 0;
357
358         n = now(CLOCK_REALTIME);
359         if (n < i->age)
360                 return 0;
361
362         cutoff = n - i->age;
363
364         d = opendir(i->path);
365         if (!d) {
366                 if (errno == ENOENT)
367                         return 0;
368
369                 log_error("Failed to open directory %s: %m", i->path);
370                 return -errno;
371         }
372
373         if (fstat(dirfd(d), &s) < 0) {
374                 log_error("stat(%s) failed: %m", i->path);
375                 r = -errno;
376                 goto finish;
377         }
378
379         if (!S_ISDIR(s.st_mode)) {
380                 log_error("%s is not a directory.", i->path);
381                 r = -ENOTDIR;
382                 goto finish;
383         }
384
385         if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0) {
386                 log_error("stat(%s/..) failed: %m", i->path);
387                 r = -errno;
388                 goto finish;
389         }
390
391         mountpoint = s.st_dev != ps.st_dev ||
392                      (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
393
394         r = dir_cleanup(i->path, d, &s, cutoff, s.st_dev, mountpoint, MAX_DEPTH);
395
396 finish:
397         if (d)
398                 closedir(d);
399
400         return r;
401 }
402
403 static int create_item(Item *i) {
404         int fd = -1, r;
405         mode_t u;
406         struct stat st;
407
408         assert(i);
409
410         switch (i->type) {
411
412         case IGNORE_PATH:
413         case REMOVE_PATH:
414         case RECURSIVE_REMOVE_PATH:
415                 return 0;
416
417         case CREATE_FILE:
418         case TRUNCATE_FILE:
419
420                 u = umask(0);
421                 fd = open(i->path, O_CREAT|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY|O_NOFOLLOW|
422                           (i->type == TRUNCATE_FILE ? O_TRUNC : 0), i->mode);
423                 umask(u);
424
425                 if (fd < 0) {
426                         log_error("Failed to create file %s: %m", i->path);
427                         r = -errno;
428                         goto finish;
429                 }
430
431                 if (fstat(fd, &st) < 0) {
432                         log_error("stat(%s) failed: %m", i->path);
433                         r = -errno;
434                         goto finish;
435                 }
436
437                 if (!S_ISREG(st.st_mode)) {
438                         log_error("%s is not a file.", i->path);
439                         r = -EEXIST;
440                         goto finish;
441                 }
442
443                 if (i->mode_set)
444                         if (fchmod(fd, i->mode) < 0) {
445                                 log_error("chmod(%s) failed: %m", i->path);
446                                 r = -errno;
447                                 goto finish;
448                         }
449
450                 if (i->uid_set || i->gid_set)
451                         if (fchown(fd,
452                                    i->uid_set ? i->uid : (uid_t) -1,
453                                    i->gid_set ? i->gid : (gid_t) -1) < 0) {
454                                 log_error("chown(%s) failed: %m", i->path);
455                                 r = -errno;
456                                 goto finish;
457                         }
458
459                 break;
460
461         case TRUNCATE_DIRECTORY:
462         case CREATE_DIRECTORY:
463
464                 u = umask(0);
465                 r = mkdir(i->path, i->mode);
466                 umask(u);
467
468                 if (r < 0 && errno != EEXIST) {
469                         log_error("Failed to create directory %s: %m", i->path);
470                         r = -errno;
471                         goto finish;
472                 }
473
474                 if (stat(i->path, &st) < 0) {
475                         log_error("stat(%s) failed: %m", i->path);
476                         r = -errno;
477                         goto finish;
478                 }
479
480                 if (!S_ISDIR(st.st_mode)) {
481                         log_error("%s is not a directory.", i->path);
482                         r = -EEXIST;
483                         goto finish;
484                 }
485
486                 if (i->mode_set)
487                         if (chmod(i->path, i->mode) < 0) {
488                                 log_error("chmod(%s) failed: %m", i->path);
489                                 r = -errno;
490                                 goto finish;
491                         }
492
493                 if (i->uid_set || i->gid_set)
494                         if (chown(i->path,
495                                   i->uid_set ? i->uid : (uid_t) -1,
496                                   i->gid_set ? i->gid : (gid_t) -1) < 0) {
497
498                                 log_error("chown(%s) failed: %m", i->path);
499                                 r = -errno;
500                                 goto finish;
501                         }
502
503                 break;
504         }
505
506         if ((r = label_fix(i->path)) < 0)
507                 goto finish;
508
509         log_debug("%s created successfully.", i->path);
510
511 finish:
512         if (fd >= 0)
513                 close_nointr_nofail(fd);
514
515         return r;
516 }
517
518 static int remove_item(Item *i, const char *instance) {
519         int r;
520
521         assert(i);
522
523         switch (i->type) {
524
525         case CREATE_FILE:
526         case TRUNCATE_FILE:
527         case CREATE_DIRECTORY:
528         case IGNORE_PATH:
529                 break;
530
531         case REMOVE_PATH:
532                 if (remove(instance) < 0 && errno != ENOENT) {
533                         log_error("remove(%s): %m", instance);
534                         return -errno;
535                 }
536
537                 break;
538
539         case TRUNCATE_DIRECTORY:
540         case RECURSIVE_REMOVE_PATH:
541                 if ((r = rm_rf(instance, false, i->type == RECURSIVE_REMOVE_PATH)) < 0 &&
542                     r != -ENOENT) {
543                         log_error("rm_rf(%s): %s", instance, strerror(-r));
544                         return r;
545                 }
546
547                 break;
548         }
549
550         return 0;
551 }
552
553 static int remove_item_glob(Item *i) {
554         assert(i);
555
556         switch (i->type) {
557
558         case CREATE_FILE:
559         case TRUNCATE_FILE:
560         case CREATE_DIRECTORY:
561         case IGNORE_PATH:
562                 break;
563
564         case REMOVE_PATH:
565         case TRUNCATE_DIRECTORY:
566         case RECURSIVE_REMOVE_PATH: {
567                 int r = 0, k;
568                 glob_t g;
569                 char **fn;
570
571                 zero(g);
572
573                 errno = 0;
574                 if ((k = glob(i->path, GLOB_NOSORT|GLOB_BRACE, NULL, &g)) != 0) {
575
576                         if (k != GLOB_NOMATCH) {
577                                 if (errno != 0)
578                                         errno = EIO;
579
580                                 log_error("glob(%s) failed: %m", i->path);
581                                 return -errno;
582                         }
583                 }
584
585                 STRV_FOREACH(fn, g.gl_pathv)
586                         if ((k = remove_item(i, *fn)) < 0)
587                                 r = k;
588
589                 globfree(&g);
590                 return r;
591         }
592         }
593
594         return 0;
595 }
596
597 static int process_item(Item *i) {
598         int r, q, p;
599
600         assert(i);
601
602         r = arg_create ? create_item(i) : 0;
603         q = arg_remove ? remove_item_glob(i) : 0;
604         p = arg_clean ? clean_item(i) : 0;
605
606         if (r < 0)
607                 return r;
608
609         if (q < 0)
610                 return q;
611
612         return p;
613 }
614
615 static void item_free(Item *i) {
616         assert(i);
617
618         free(i->path);
619         free(i);
620 }
621
622 static int parse_line(const char *fname, unsigned line, const char *buffer) {
623         Item *i;
624         char *mode = NULL, *user = NULL, *group = NULL, *age = NULL;
625         int r;
626
627         assert(fname);
628         assert(line >= 1);
629         assert(buffer);
630
631         if (!(i = new0(Item, 1))) {
632                 log_error("Out of memory");
633                 return -ENOMEM;
634         }
635
636         if (sscanf(buffer,
637                    "%c "
638                    "%ms "
639                    "%ms "
640                    "%ms "
641                    "%ms "
642                    "%ms",
643                    &i->type,
644                    &i->path,
645                    &mode,
646                    &user,
647                    &group,
648                    &age) < 2) {
649                 log_error("[%s:%u] Syntax error.", fname, line);
650                 r = -EIO;
651                 goto finish;
652         }
653
654         if (i->type != CREATE_FILE &&
655             i->type != TRUNCATE_FILE &&
656             i->type != CREATE_DIRECTORY &&
657             i->type != TRUNCATE_DIRECTORY &&
658             i->type != IGNORE_PATH &&
659             i->type != REMOVE_PATH &&
660             i->type != RECURSIVE_REMOVE_PATH) {
661                 log_error("[%s:%u] Unknown file type '%c'.", fname, line, i->type);
662                 r = -EBADMSG;
663                 goto finish;
664         }
665
666         if (!path_is_absolute(i->path)) {
667                 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i->path);
668                 r = -EBADMSG;
669                 goto finish;
670         }
671
672         path_kill_slashes(i->path);
673
674         if (arg_prefix && !path_startswith(i->path, arg_prefix)) {
675                 r = 0;
676                 goto finish;
677         }
678
679         if (user && !streq(user, "-")) {
680                 unsigned long lu;
681                 struct passwd *p;
682
683                 if (streq(user, "root") || streq(user, "0"))
684                         i->uid = 0;
685                 else if (safe_atolu(user, &lu) >= 0)
686                         i->uid = (uid_t) lu;
687                 else if ((p = getpwnam(user)))
688                         i->uid = p->pw_uid;
689                 else {
690                         log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
691                         r = -ENOENT;
692                         goto finish;
693                 }
694
695                 i->uid_set = true;
696         }
697
698         if (group && !streq(group, "-")) {
699                 unsigned long lu;
700                 struct group *g;
701
702                 if (streq(group, "root") || streq(group, "0"))
703                         i->gid = 0;
704                 else if (safe_atolu(group, &lu) >= 0)
705                         i->gid = (gid_t) lu;
706                 else if ((g = getgrnam(group)))
707                         i->gid = g->gr_gid;
708                 else {
709                         log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
710                         r = -ENOENT;
711                         goto finish;
712                 }
713
714                 i->gid_set = true;
715         }
716
717         if (mode && !streq(mode, "-")) {
718                 unsigned m;
719
720                 if (sscanf(mode, "%o", &m) != 1) {
721                         log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
722                         r = -ENOENT;
723                         goto finish;
724                 }
725
726                 i->mode = m;
727                 i->mode_set = true;
728         } else
729                 i->mode = i->type == CREATE_DIRECTORY ? 0755 : 0644;
730
731         if (age && !streq(age, "-")) {
732                 if (parse_usec(age, &i->age) < 0) {
733                         log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
734                         r = -EBADMSG;
735                         goto finish;
736                 }
737
738                 i->age_set = true;
739         }
740
741         if ((r = hashmap_put(needs_glob(i->type) ? globs : items, i->path, i)) < 0) {
742                 if (r == -EEXIST) {
743                         log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path);
744                         r = 0;
745                         goto finish;
746                 }
747
748                 log_error("Failed to insert item %s: %s", i->path, strerror(-r));
749                 goto finish;
750         }
751
752         i = NULL;
753         r = 0;
754
755 finish:
756         free(user);
757         free(group);
758         free(mode);
759         free(age);
760
761         if (i)
762                 item_free(i);
763
764         return r;
765 }
766
767 static int scandir_filter(const struct dirent *d) {
768         assert(d);
769
770         if (ignore_file(d->d_name))
771                 return 0;
772
773         if (d->d_type != DT_REG &&
774             d->d_type != DT_LNK)
775                 return 0;
776
777         return endswith(d->d_name, ".conf");
778 }
779
780 static int help(void) {
781
782         printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
783                "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
784                "  -h --help             Show this help\n"
785                "     --create           Create marked files/directories\n"
786                "     --clean            Clean up marked directories\n"
787                "     --remove           Remove marked files/directories\n"
788                "     --prefix=PATH      Only apply rules that apply to paths with the specified prefix\n",
789                program_invocation_short_name);
790
791         return 0;
792 }
793
794 static int parse_argv(int argc, char *argv[]) {
795
796         enum {
797                 ARG_CREATE,
798                 ARG_CLEAN,
799                 ARG_REMOVE,
800                 ARG_PREFIX
801         };
802
803         static const struct option options[] = {
804                 { "help",      no_argument,       NULL, 'h'           },
805                 { "create",    no_argument,       NULL, ARG_CREATE    },
806                 { "clean",     no_argument,       NULL, ARG_CLEAN     },
807                 { "remove",    no_argument,       NULL, ARG_REMOVE    },
808                 { "prefix",    required_argument, NULL, ARG_PREFIX    },
809                 { NULL,        0,                 NULL, 0             }
810         };
811
812         int c;
813
814         assert(argc >= 0);
815         assert(argv);
816
817         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
818
819                 switch (c) {
820
821                 case 'h':
822                         help();
823                         return 0;
824
825                 case ARG_CREATE:
826                         arg_create = true;
827                         break;
828
829                 case ARG_CLEAN:
830                         arg_clean = true;
831                         break;
832
833                 case ARG_REMOVE:
834                         arg_remove = true;
835                         break;
836
837                 case ARG_PREFIX:
838                         arg_prefix = optarg;
839                         break;
840
841                 case '?':
842                         return -EINVAL;
843
844                 default:
845                         log_error("Unknown option code %c", c);
846                         return -EINVAL;
847                 }
848         }
849
850         if (!arg_clean && !arg_create && !arg_remove) {
851                 log_error("You need to specify at leat one of --clean, --create or --remove.");
852                 return -EINVAL;
853         }
854
855         return 1;
856 }
857
858 static int read_config_file(const char *fn, bool ignore_enoent) {
859         FILE *f;
860         unsigned v = 0;
861         int r = 0;
862
863         assert(fn);
864
865         if (!(f = fopen(fn, "re"))) {
866
867                 if (ignore_enoent && errno == ENOENT)
868                         return 0;
869
870                 log_error("Failed to open %s: %m", fn);
871                 return -errno;
872         }
873
874         for (;;) {
875                 char line[LINE_MAX], *l;
876                 int k;
877
878                 if (!(fgets(line, sizeof(line), f)))
879                         break;
880
881                 v++;
882
883                 l = strstrip(line);
884                 if (*l == '#' || *l == 0)
885                         continue;
886
887                 if ((k = parse_line(fn, v, l)) < 0)
888                         if (r == 0)
889                                 r = k;
890         }
891
892         if (ferror(f)) {
893                 log_error("Failed to read from file %s: %m", fn);
894                 if (r == 0)
895                         r = -EIO;
896         }
897
898         fclose(f);
899
900         return r;
901 }
902
903 int main(int argc, char *argv[]) {
904         int r;
905         Item *i;
906         Iterator iterator;
907
908         if ((r = parse_argv(argc, argv)) <= 0)
909                 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
910
911         log_set_target(LOG_TARGET_AUTO);
912         log_parse_environment();
913         log_open();
914
915         label_init();
916
917         items = hashmap_new(string_hash_func, string_compare_func);
918         globs = hashmap_new(string_hash_func, string_compare_func);
919
920         if (!items || !globs) {
921                 log_error("Out of memory");
922                 r = EXIT_FAILURE;
923                 goto finish;
924         }
925
926         r = EXIT_SUCCESS;
927
928         if (optind < argc) {
929                 int j;
930
931                 for (j = optind; j < argc; j++)
932                         if (read_config_file(argv[j], false) < 0)
933                                 r = EXIT_FAILURE;
934
935         } else {
936                 int n, j;
937                 struct dirent **de = NULL;
938
939                 if ((n = scandir("/etc/tmpfiles.d/", &de, scandir_filter, alphasort)) < 0) {
940
941                         if (errno != ENOENT) {
942                                 log_error("Failed to enumerate /etc/tmpfiles.d/ files: %m");
943                                 r = EXIT_FAILURE;
944                         }
945
946                         goto finish;
947                 }
948
949                 for (j = 0; j < n; j++) {
950                         int k;
951                         char *fn;
952
953                         k = asprintf(&fn, "/etc/tmpfiles.d/%s", de[j]->d_name);
954                         free(de[j]);
955
956                         if (k < 0) {
957                                 log_error("Failed to allocate file name.");
958                                 r = EXIT_FAILURE;
959                                 continue;
960                         }
961
962                         if (read_config_file(fn, true) < 0)
963                                 r = EXIT_FAILURE;
964
965                         free(fn);
966                 }
967
968                 free(de);
969         }
970
971         HASHMAP_FOREACH(i, globs, iterator)
972                 if (process_item(i) < 0)
973                         r = EXIT_FAILURE;
974
975         HASHMAP_FOREACH(i, items, iterator)
976                 if (process_item(i) < 0)
977                         r = EXIT_FAILURE;
978
979 finish:
980         while ((i = hashmap_steal_first(items)))
981                 item_free(i);
982
983         while ((i = hashmap_steal_first(globs)))
984                 item_free(i);
985
986         hashmap_free(items);
987         hashmap_free(globs);
988
989         set_free_free(unix_sockets);
990
991         label_finish();
992
993         return r;
994 }