No need to fstatat() when .d_type is reliable. However, as it is not
portable, I've done this as a separate patch.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
configure.ac | 1 +
plugins/file/file.c | 21 ++++++++++++++-------
2 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/configure.ac b/configure.ac
index 28f4a3cd..8074a470 100644
--- a/configure.ac
+++ b/configure.ac
@@ -323,6 +323,7 @@ AC_CHECK_FUNCS([\
pipe2 \
ppoll \
posix_fadvise])
+AC_CHECK_MEMBERS([struct dirent.d_type], [], [], [[#include <dirent.h>]])
dnl Check whether printf("%m") works
AC_CACHE_CHECK([whether the printf family supports %m],
diff --git a/plugins/file/file.c b/plugins/file/file.c
index 4afcad11..445d5686 100644
--- a/plugins/file/file.c
+++ b/plugins/file/file.c
@@ -184,13 +184,20 @@ static int file_list_exports (int readonly, int default_only,
}
errno = 0;
while ((entry = readdir (dir)) != NULL) {
- /* TODO: Optimize with d_type and/or statx when present? */
- if (fstatat (fd, entry->d_name, &sb, 0) == 0 &&
- (S_ISREG (sb.st_mode) || S_ISBLK (sb.st_mode))) {
- if (nbdkit_add_export (exports, entry->d_name, NULL) == -1) {
- close (fd);
- return -1;
- }
+ int r = -1;
+#if HAVE_STRUCT_DIRENT_D_TYPE
+ if (entry->d_type == DT_BLK || entry->d_type == DT_REG)
+ r = 1;
+ else if (entry->d_type != DT_LNK && entry->d_type != DT_UNKNOWN)
+ r = 0;
+#endif
+ /* TODO: when chasing symlinks, is statx any nicer than fstatat? */
+ if (r < 0 && fstatat (fd, entry->d_name, &sb, 0) == 0 &&
+ (S_ISREG (sb.st_mode) || S_ISBLK (sb.st_mode)))
+ r = 1;
+ if (r == 1 && nbdkit_add_export (exports, entry->d_name, NULL) == -1) {
+ close (fd);
+ return -1;
}
errno = 0;
}
--
2.28.0