diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | config.h.in | 2 | ||||
-rw-r--r-- | src/client/rspamc.c | 44 |
3 files changed, 40 insertions, 8 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3163e6a94..882d46a8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -965,6 +965,8 @@ CHECK_SYMBOL_EXISTS(O_ASYNC "sys/types.h;sys/fcntl.h" HAVE_OASYNC) CHECK_SYMBOL_EXISTS(O_NOFOLLOW "sys/types.h;sys/fcntl.h" HAVE_ONOFOLLOW) LIST(APPEND CMAKE_REQUIRED_INCLUDES "${LIBSSL_INCLUDE}") CHECK_SYMBOL_EXISTS(SSL_set_tlsext_host_name "openssl/ssl.h" HAVE_SSL_TLSEXT_HOSTNAME) +CHECK_SYMBOL_EXISTS(dirfd "sys/types.h;unistd.h;dirent.h" HAVE_DIRFD) +CHECK_SYMBOL_EXISTS(fpathconf "sys/types.h;unistd.h" HAVE_FPATHCONF) IF(ENABLE_PCRE2 MATCHES "ON") IF(HAVE_PCRE_JIT) diff --git a/config.h.in b/config.h.in index 90edc1132..bb063b0f0 100644 --- a/config.h.in +++ b/config.h.in @@ -21,6 +21,7 @@ #cmakedefine HAVE_CPUID_H 1 #cmakedefine HAVE_CTYPE_H 1 #cmakedefine HAVE_DIRENT_H 1 +#cmakedefine HAVE_DIRFD 1 #cmakedefine HAVE_ENDIAN_H 1 #cmakedefine HAVE_EXP2L 1 #cmakedefine HAVE_EXPL 1 @@ -31,6 +32,7 @@ #cmakedefine HAVE_FDATASYNC 1 #cmakedefine HAVE_FETCH_H 1 #cmakedefine HAVE_FLOCK 1 +#cmakedefine HAVE_FPATHCONF 1 #cmakedefine HAVE_GETPAGESIZE 1 #cmakedefine HAVE_GET_CPUID 1 #cmakedefine HAVE_GLOB_H 1 diff --git a/src/client/rspamc.c b/src/client/rspamc.c index 400c4c59b..c7068ae8d 100644 --- a/src/client/rspamc.c +++ b/src/client/rspamc.c @@ -1411,6 +1411,39 @@ rspamc_process_input (struct event_base *ev_base, struct rspamc_command *cmd, g_free (hostbuf); } +static gsize +rspamd_dirent_size (DIR * dirp) +{ + goffset name_max; + gsize name_end; + +#if defined(HAVE_FPATHCONF) && defined(HAVE_DIRFD) \ + && defined(_PC_NAME_MAX) + name_max = fpathconf (dirfd (dirp), _PC_NAME_MAX); + + +# if defined(NAME_MAX) + if (name_max == -1) { + name_max = (NAME_MAX > 255) ? NAME_MAX : 255; + } +# else + if (name_max == -1) { + return (size_t)(-1); + } +# endif +#else +# if defined(NAME_MAX) + name_max = (NAME_MAX > 255) ? NAME_MAX : 255; +# else +# error "buffer size for readdir_r cannot be determined" +# endif +#endif + + name_end = G_STRUCT_OFFSET (struct dirent, d_name) + name_max + 1; + + return (name_end > sizeof (struct dirent) ? name_end : sizeof(struct dirent)); +} + static void rspamc_process_dir (struct event_base *ev_base, struct rspamc_command *cmd, const gchar *name, GQueue *attrs) @@ -1422,19 +1455,14 @@ rspamc_process_dir (struct event_base *ev_base, struct rspamc_command *cmd, FILE *in; struct stat st; gboolean is_reg, is_dir; - gsize name_max, len; + gsize len; d = opendir (name); if (d != NULL) { /* Portably allocate struct direntry */ - name_max = pathconf (name, _PC_NAME_MAX); - - if (name_max == -1) { - name_max = PATH_MAX; - } - - len = G_STRUCT_OFFSET (struct dirent, d_name) + name_max + 1; + len = rspamd_dirent_size (d); + g_assert (len != (gsize)-1); entry = g_malloc0 (len); while (readdir_r (d, entry, pentry) == 0) { |