summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/dir.c41
1 files changed, 23 insertions, 18 deletions
diff --git a/src/dir.c b/src/dir.c
index b92b7c2..2719c15 100644
--- a/src/dir.c
+++ b/src/dir.c
@@ -4,6 +4,7 @@
#include "dir.h"
#include "bfstd.h"
#include "config.h"
+#include <assert.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@@ -14,22 +15,17 @@
#include <sys/stat.h>
#include <unistd.h>
-#if __has_feature(memory_sanitizer)
-# include <sanitizer/msan_interface.h>
-#endif
-
-#if __linux__
-# include <sys/syscall.h>
-
-/** Directory entry type for bfs_getdents() */
-typedef struct dirent64 sys_dirent;
-#else
-typedef struct dirent sys_dirent;
+#ifndef BFS_GETDENTS
+# define BFS_GETDENTS (__linux__ || __FreeBSD__)
#endif
-#define BFS_GETDENTS (__linux__ || __FreeBSD__)
-
#if BFS_GETDENTS
+# if __has_feature(memory_sanitizer)
+# include <sanitizer/msan_interface.h>
+# endif
+# if __linux__
+# include <sys/syscall.h>
+# endif
/** getdents() syscall wrapper. */
static ssize_t bfs_getdents(int fd, void *buf, size_t size) {
@@ -56,6 +52,13 @@ static ssize_t bfs_getdents(int fd, void *buf, size_t size) {
#endif // BFS_GETDENTS
+#if BFS_GETDENTS && __linux__
+/** Directory entry type for bfs_getdents() */
+typedef struct dirent64 sys_dirent;
+#else
+typedef struct dirent sys_dirent;
+#endif
+
enum bfs_type bfs_mode_to_type(mode_t mode) {
switch (mode & S_IFMT) {
#ifdef S_IFBLK
@@ -112,7 +115,6 @@ struct bfs_dir {
// sys_dirent buf[];
#else
DIR *dir;
- struct dirent *de;
#endif
};
@@ -158,8 +160,6 @@ struct bfs_dir *bfs_opendir(int at_fd, const char *at_path) {
free(dir);
return NULL;
}
-
- dir->de = NULL;
#endif
return dir;
@@ -251,6 +251,7 @@ int bfs_closedir(struct bfs_dir *dir) {
int ret = xclose(dir->fd);
#else
int ret = closedir(dir->dir);
+ assert(ret == 0 || errno != EBADF);
#endif
free(dir);
return ret;
@@ -260,10 +261,14 @@ int bfs_freedir(struct bfs_dir *dir) {
#if BFS_GETDENTS
int ret = dir->fd;
free(dir);
- return ret;
+#elif __FreeBSD__
+ int ret = fdclosedir(dir->dir);
+ free(dir);
#else
int ret = dup_cloexec(dirfd(dir->dir));
+ int error = errno;
bfs_closedir(dir);
- return ret;
+ errno = error;
#endif
+ return ret;
}