Make errors from regfile_iter_new() non-fatal.
authorAndre Noll <maan@tuebingen.mpg.de>
Sun, 16 Jun 2019 12:04:44 +0000 (14:04 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Wed, 19 Jun 2019 09:33:08 +0000 (11:33 +0200)
The callers of the regfile iter API already handle the case of no
epigrams or tag expressions just fine. In particular, the stats
command can still print meaningful output if the tag expression
directory does not exist, which is a perfectly valid setup.

This patch modifies regfile_iter_new() to no longer abort but merely
print a log message and return NULL if opendir() fails. The various
accessors of the regfile iter API have to be adjusted to deal with
NULL pointers but no changes to tfortune.c are required.

util.c

diff --git a/util.c b/util.c
index 69c759e..b4234d8 100644 (file)
--- a/util.c
+++ b/util.c
@@ -236,13 +236,16 @@ void regfile_iter_next(struct regfile_iter *iter)
 
 void regfile_iter_new(const char *dirname, struct regfile_iter **result)
 {
-       struct regfile_iter *iter = xmalloc(sizeof(*iter));
+       struct regfile_iter *iter;
+       DIR *dir = opendir(dirname);
 
-       iter->dir = opendir(dirname);
-       if (!iter->dir) {
-               EMERG_LOG("opendir %s: %s\n", dirname, strerror(errno));
-               exit(EXIT_FAILURE);
+       if (!dir) {
+               NOTICE_LOG("opendir %s: %s\n", dirname, strerror(errno));
+               *result = NULL;
+               return;
        }
+       iter = xmalloc(sizeof(*iter));
+       iter->dir = dir;
        iter->dfd = dirfd(iter->dir);
        assert(iter->dfd >= 0);
        regfile_iter_next(iter);
@@ -285,7 +288,7 @@ bool regfile_iter_map(const struct regfile_iter *iter, struct iovec *result)
        void *map;
        const char *path;
 
-       if (!iter->entry)
+       if (!iter || !iter->entry)
                return false;
        path = iter->entry->d_name;
        ret = openat(iter->dfd, path, O_RDONLY, 0);
@@ -303,18 +306,20 @@ bool regfile_iter_map(const struct regfile_iter *iter, struct iovec *result)
 
 const char *regfile_iter_basename(const struct regfile_iter *iter)
 {
-       if (!iter->entry)
+       if (!iter || !iter->entry)
                return NULL;
        return iter->entry->d_name;
 }
 
 const struct stat *regfile_iter_stat(const struct regfile_iter *iter)
 {
-       return &iter->stat;
+       return iter? &iter->stat : NULL;
 }
 
 void regfile_iter_free(struct regfile_iter *iter)
 {
+       if (!iter)
+               return;
        closedir(iter->dir);
        free(iter);
 }