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@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