diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2016-11-14 22:40:40 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2016-11-14 22:40:40 -0500 |
commit | a7e08e893eb796637ca2c53cd32a529f453ace12 (patch) | |
tree | 73f6bdc3e00baab465b5b90e963af94391f6d984 | |
parent | 196cf9f617ca17acec75eafbcd9e5e7989752dcb (diff) |
Check for readdir() errors everywhere.
-rw-r--r-- | bftw.c | 16 | ||||
-rw-r--r-- | eval.c | 20 | ||||
-rw-r--r-- | util.c | 10 | ||||
-rw-r--r-- | util.h | 6 |
4 files changed, 34 insertions, 18 deletions
@@ -22,6 +22,7 @@ #include "bftw.h" #include "dstring.h" +#include "util.h" #include <assert.h> #include <dirent.h> #include <errno.h> @@ -868,19 +869,6 @@ static struct dircache_entry *bftw_add(struct bftw_state *state, const char *nam } /** - * readdir() wrapper that makes error handling cleaner. - */ -static int bftw_readdir(DIR *dir, struct dirent **de) { - errno = 0; - *de = readdir(dir); - if (!*de && errno != 0) { - return -1; - } else { - return 0; - } -} - -/** * Push a new entry onto the queue. */ static int bftw_push(struct bftw_state *state, const char *name) { @@ -1016,7 +1004,7 @@ int bftw(const char *path, bftw_fn *fn, int nopenfd, enum bftw_flags flags, void while (true) { struct dirent *de; - if (bftw_readdir(dir, &de) != 0) { + if (xreaddir(dir, &de) != 0) { goto dir_error; } if (!de) { @@ -498,14 +498,23 @@ bool eval_empty(const struct expr *expr, struct eval_state *state) { ret = true; - struct dirent *de; - while ((de = readdir(dir)) != NULL) { + while (true) { + struct dirent *de; + if (xreaddir(dir, &de) != 0) { + eval_error(state); + goto done_dir; + } + if (!de) { + break; + } + if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0) { ret = false; break; } } + done_dir: closedir(dir); } else { const struct stat *statbuf = fill_statbuf(state); @@ -1038,8 +1047,11 @@ static int infer_fdlimit(const struct cmdline *cmdline) { // Account for 'dir' itself nopen = -1; - struct dirent *de; - while ((de = readdir(dir)) != NULL) { + while (true) { + struct dirent *de; + if (xreaddir(dir, &de) != 0 || !de) { + break; + } if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0) { ++nopen; } @@ -17,6 +17,16 @@ #include <sys/types.h> #include <unistd.h> +int xreaddir(DIR *dir, struct dirent **de) { + errno = 0; + *de = readdir(dir); + if (!*de && errno != 0) { + return -1; + } else { + return 0; + } +} + bool isopen(int fd) { return fcntl(fd, F_GETFD) >= 0 || errno != EBADF; } @@ -12,9 +12,15 @@ #ifndef BFS_UTIL_H #define BFS_UTIL_H +#include <dirent.h> #include <stdbool.h> /** + * readdir() wrapper that makes error handling cleaner. + */ +int xreaddir(DIR *dir, struct dirent **de); + +/** * Check if a file descriptor is open. */ bool isopen(int fd); |