From c4b507e9d807773152b87dede59a73b7685566bb Mon Sep 17 00:00:00 2001 From: Steffen Schuemann Date: Sat, 2 Apr 2022 11:40:50 +0200 Subject: [PATCH] refs #142, autodetect dirent::d_type and add GHC_OS_SOLARIS detection Took 3 hours 8 minutes --- include/ghc/filesystem.hpp | 84 ++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/include/ghc/filesystem.hpp b/include/ghc/filesystem.hpp index a319def..8a1cf41 100644 --- a/include/ghc/filesystem.hpp +++ b/include/ghc/filesystem.hpp @@ -67,6 +67,8 @@ #define GHC_OS_WIN32 #elif defined(__CYGWIN__) #define GHC_OS_CYGWIN +#elif defined(__sun) && defined(__SVR4) +#define GHC_OS_SOLARIS #elif defined(__svr4__) #define GHC_OS_SYS5R4 #elif defined(BSD) @@ -76,7 +78,6 @@ #include #elif defined(__QNX__) #define GHC_OS_QNX -#define GHC_NO_DIRENT_D_TYPE #else #error "Operating system currently not supported!" #endif @@ -1298,6 +1299,49 @@ GHC_FS_API std::error_code make_error_code(portable_error err); GHC_FS_API std::error_code make_system_error(uint32_t err = 0); #else GHC_FS_API std::error_code make_system_error(int err = 0); + +template +struct has_d_type : std::false_type{}; + +template +struct has_d_type : std::true_type {}; + +template +GHC_INLINE file_type file_type_from_dirent_impl(const T&, std::false_type) +{ + return file_type::unknown; +} + +template +GHC_INLINE file_type file_type_from_dirent_impl(const T& t, std::true_type) +{ + switch (t.d_type) { + case DT_BLK: + return file_type::block; + case DT_CHR: + return file_type::character; + case DT_DIR: + return file_type::directory; + case DT_FIFO: + return file_type::fifo; + case DT_LNK: + return file_type::symlink; + case DT_REG: + return file_type::regular; + case DT_SOCK: + return file_type::socket; + case DT_UNKNOWN: + return file_type::none; + default: + return file_type::unknown; + } +} + +template +GHC_INLINE file_type file_type_from_dirent(const T& t) +{ + return file_type_from_dirent_impl(t, has_d_type{}); +} #endif } // namespace detail @@ -5658,48 +5702,16 @@ public: void copyToDirEntry() { -#ifdef GHC_NO_DIRENT_D_TYPE - _dir_entry._symlink_status = file_status(); - _dir_entry._status = file_status(); -#else _dir_entry._symlink_status.permissions(perms::unknown); - switch (_entry->d_type) { - case DT_BLK: - _dir_entry._symlink_status.type(file_type::block); - break; - case DT_CHR: - _dir_entry._symlink_status.type(file_type::character); - break; - case DT_DIR: - _dir_entry._symlink_status.type(file_type::directory); - break; - case DT_FIFO: - _dir_entry._symlink_status.type(file_type::fifo); - break; - case DT_LNK: - _dir_entry._symlink_status.type(file_type::symlink); - break; - case DT_REG: - _dir_entry._symlink_status.type(file_type::regular); - break; - case DT_SOCK: - _dir_entry._symlink_status.type(file_type::socket); - break; - case DT_UNKNOWN: - _dir_entry._symlink_status.type(file_type::none); - break; - default: - _dir_entry._symlink_status.type(file_type::unknown); - break; - } - if (_entry->d_type != DT_LNK) { + auto ft = detail::file_type_from_dirent(*_entry); + _dir_entry._symlink_status.type(ft); + if (ft != file_type::symlink) { _dir_entry._status = _dir_entry._symlink_status; } else { _dir_entry._status.type(file_type::none); _dir_entry._status.permissions(perms::unknown); } -#endif _dir_entry._file_size = static_cast(-1); _dir_entry._hard_link_count = static_cast(-1); _dir_entry._last_write_time = 0;