Removing indirect refresh calls on directory_entry on posix

removing redundant path instance from windows directory_iterator implementation
This commit is contained in:
Steffen Schuemann 2021-03-01 23:41:27 +01:00
parent b82066f27e
commit 1037c02950

View File

@ -862,12 +862,16 @@ public:
private: private:
friend class directory_iterator; friend class directory_iterator;
#ifdef GHC_WITH_EXCEPTIONS
file_type status_file_type() const;
#endif
file_type status_file_type(std::error_code& ec) const noexcept;
filesystem::path _path; filesystem::path _path;
file_status _status; file_status _status;
file_status _symlink_status; file_status _symlink_status;
uintmax_t _file_size = 0; uintmax_t _file_size = static_cast<uintmax_t>(-1);
#ifndef GHC_OS_WINDOWS #ifndef GHC_OS_WINDOWS
uintmax_t _hard_link_count = 0; uintmax_t _hard_link_count = static_cast<uintmax_t>(-1);
#endif #endif
time_t _last_write_time = 0; time_t _last_write_time = 0;
}; };
@ -5009,9 +5013,9 @@ GHC_INLINE perms file_status::permissions() const noexcept
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
GHC_INLINE directory_entry::directory_entry(const filesystem::path& p) GHC_INLINE directory_entry::directory_entry(const filesystem::path& p)
: _path(p) : _path(p)
, _file_size(0) , _file_size(static_cast<uintmax_t>(-1))
#ifndef GHC_OS_WINDOWS #ifndef GHC_OS_WINDOWS
, _hard_link_count(0) , _hard_link_count(static_cast<uintmax_t>(-1))
#endif #endif
, _last_write_time(0) , _last_write_time(0)
{ {
@ -5021,9 +5025,9 @@ GHC_INLINE directory_entry::directory_entry(const filesystem::path& p)
GHC_INLINE directory_entry::directory_entry(const filesystem::path& p, std::error_code& ec) GHC_INLINE directory_entry::directory_entry(const filesystem::path& p, std::error_code& ec)
: _path(p) : _path(p)
, _file_size(0) , _file_size(static_cast<uintmax_t>(-1))
#ifndef GHC_OS_WINDOWS #ifndef GHC_OS_WINDOWS
, _hard_link_count(0) , _hard_link_count(static_cast<uintmax_t>(-1))
#endif #endif
, _last_write_time(0) , _last_write_time(0)
{ {
@ -5096,117 +5100,140 @@ GHC_INLINE directory_entry::operator const filesystem::path&() const noexcept
return _path; return _path;
} }
#ifdef GHC_WITH_EXCEPTIONS
GHC_INLINE file_type directory_entry::status_file_type() const
{
return _status.type() != file_type::none ? _status.type() : filesystem::status(path()).type();
}
#endif
GHC_INLINE file_type directory_entry::status_file_type(std::error_code& ec) const noexcept
{
if(_status.type() != file_type::none) {
ec.clear();
return _status.type();
}
return filesystem::status(path(), ec).type();
}
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
GHC_INLINE bool directory_entry::exists() const GHC_INLINE bool directory_entry::exists() const
{ {
return filesystem::exists(status()); return status_file_type() != file_type::not_found;
} }
#endif #endif
GHC_INLINE bool directory_entry::exists(std::error_code& ec) const noexcept GHC_INLINE bool directory_entry::exists(std::error_code& ec) const noexcept
{ {
return filesystem::exists(status(ec)); return status_file_type(ec) != file_type::not_found;
} }
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
GHC_INLINE bool directory_entry::is_block_file() const GHC_INLINE bool directory_entry::is_block_file() const
{ {
return filesystem::is_block_file(status()); return status_file_type() == file_type::block;
} }
#endif #endif
GHC_INLINE bool directory_entry::is_block_file(std::error_code& ec) const noexcept GHC_INLINE bool directory_entry::is_block_file(std::error_code& ec) const noexcept
{ {
return filesystem::is_block_file(status(ec)); return status_file_type(ec) == file_type::block;
} }
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
GHC_INLINE bool directory_entry::is_character_file() const GHC_INLINE bool directory_entry::is_character_file() const
{ {
return filesystem::is_character_file(status()); return status_file_type() == file_type::character;
} }
#endif #endif
GHC_INLINE bool directory_entry::is_character_file(std::error_code& ec) const noexcept GHC_INLINE bool directory_entry::is_character_file(std::error_code& ec) const noexcept
{ {
return filesystem::is_character_file(status(ec)); return status_file_type(ec) == file_type::character;
} }
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
GHC_INLINE bool directory_entry::is_directory() const GHC_INLINE bool directory_entry::is_directory() const
{ {
return filesystem::is_directory(status()); return status_file_type() == file_type::directory;
} }
#endif #endif
GHC_INLINE bool directory_entry::is_directory(std::error_code& ec) const noexcept GHC_INLINE bool directory_entry::is_directory(std::error_code& ec) const noexcept
{ {
return filesystem::is_directory(status(ec)); return status_file_type(ec) == file_type::directory;
} }
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
GHC_INLINE bool directory_entry::is_fifo() const GHC_INLINE bool directory_entry::is_fifo() const
{ {
return filesystem::is_fifo(status()); return status_file_type() == file_type::fifo;
} }
#endif #endif
GHC_INLINE bool directory_entry::is_fifo(std::error_code& ec) const noexcept GHC_INLINE bool directory_entry::is_fifo(std::error_code& ec) const noexcept
{ {
return filesystem::is_fifo(status(ec)); return status_file_type(ec) == file_type::fifo;
} }
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
GHC_INLINE bool directory_entry::is_other() const GHC_INLINE bool directory_entry::is_other() const
{ {
return filesystem::is_other(status()); auto ft = status_file_type();
return ft != file_type::none && ft != file_type::not_found && ft != file_type::regular && ft != file_type::directory && !is_symlink();
} }
#endif #endif
GHC_INLINE bool directory_entry::is_other(std::error_code& ec) const noexcept GHC_INLINE bool directory_entry::is_other(std::error_code& ec) const noexcept
{ {
return filesystem::is_other(status(ec)); auto ft = status_file_type(ec);
bool other = ft != file_type::none && ft != file_type::not_found && ft != file_type::regular && ft != file_type::directory && !is_symlink(ec);
return !ec && other;
} }
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
GHC_INLINE bool directory_entry::is_regular_file() const GHC_INLINE bool directory_entry::is_regular_file() const
{ {
return filesystem::is_regular_file(status()); return status_file_type() == file_type::regular;
} }
#endif #endif
GHC_INLINE bool directory_entry::is_regular_file(std::error_code& ec) const noexcept GHC_INLINE bool directory_entry::is_regular_file(std::error_code& ec) const noexcept
{ {
return filesystem::is_regular_file(status(ec)); return status_file_type(ec) == file_type::regular;
} }
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
GHC_INLINE bool directory_entry::is_socket() const GHC_INLINE bool directory_entry::is_socket() const
{ {
return filesystem::is_socket(status()); return status_file_type() == file_type::socket;
} }
#endif #endif
GHC_INLINE bool directory_entry::is_socket(std::error_code& ec) const noexcept GHC_INLINE bool directory_entry::is_socket(std::error_code& ec) const noexcept
{ {
return filesystem::is_socket(status(ec)); return status_file_type(ec) == file_type::socket;
} }
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
GHC_INLINE bool directory_entry::is_symlink() const GHC_INLINE bool directory_entry::is_symlink() const
{ {
return filesystem::is_symlink(symlink_status()); return _symlink_status.type() != file_type::none ? _symlink_status.type() == file_type::symlink : filesystem::is_symlink(symlink_status());
} }
#endif #endif
GHC_INLINE bool directory_entry::is_symlink(std::error_code& ec) const noexcept GHC_INLINE bool directory_entry::is_symlink(std::error_code& ec) const noexcept
{ {
if(_symlink_status.type() != file_type::none) {
ec.clear();
return _symlink_status.type() == file_type::symlink;
}
return filesystem::is_symlink(symlink_status(ec)); return filesystem::is_symlink(symlink_status(ec));
} }
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
GHC_INLINE uintmax_t directory_entry::file_size() const GHC_INLINE uintmax_t directory_entry::file_size() const
{ {
if (_status.type() != file_type::none) { if (_file_size != static_cast<uintmax_t>(-1)) {
return _file_size; return _file_size;
} }
return filesystem::file_size(path()); return filesystem::file_size(path());
@ -5215,7 +5242,7 @@ GHC_INLINE uintmax_t directory_entry::file_size() const
GHC_INLINE uintmax_t directory_entry::file_size(std::error_code& ec) const noexcept GHC_INLINE uintmax_t directory_entry::file_size(std::error_code& ec) const noexcept
{ {
if (_status.type() != file_type::none) { if (_file_size != static_cast<uintmax_t>(-1)) {
ec.clear(); ec.clear();
return _file_size; return _file_size;
} }
@ -5227,7 +5254,7 @@ GHC_INLINE uintmax_t directory_entry::file_size(std::error_code& ec) const noexc
GHC_INLINE uintmax_t directory_entry::hard_link_count() const GHC_INLINE uintmax_t directory_entry::hard_link_count() const
{ {
#ifndef GHC_OS_WINDOWS #ifndef GHC_OS_WINDOWS
if (_status.type() != file_type::none) { if (_hard_link_count != static_cast<uintmax_t>(-1)) {
return _hard_link_count; return _hard_link_count;
} }
#endif #endif
@ -5238,7 +5265,7 @@ GHC_INLINE uintmax_t directory_entry::hard_link_count() const
GHC_INLINE uintmax_t directory_entry::hard_link_count(std::error_code& ec) const noexcept GHC_INLINE uintmax_t directory_entry::hard_link_count(std::error_code& ec) const noexcept
{ {
#ifndef GHC_OS_WINDOWS #ifndef GHC_OS_WINDOWS
if (_status.type() != file_type::none) { if (_hard_link_count != static_cast<uintmax_t>(-1)) {
ec.clear(); ec.clear();
return _hard_link_count; return _hard_link_count;
} }
@ -5250,7 +5277,7 @@ GHC_INLINE uintmax_t directory_entry::hard_link_count(std::error_code& ec) const
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
GHC_INLINE file_time_type directory_entry::last_write_time() const GHC_INLINE file_time_type directory_entry::last_write_time() const
{ {
if (_status.type() != file_type::none) { if (_last_write_time != 0) {
return std::chrono::system_clock::from_time_t(_last_write_time); return std::chrono::system_clock::from_time_t(_last_write_time);
} }
return filesystem::last_write_time(path()); return filesystem::last_write_time(path());
@ -5259,7 +5286,7 @@ GHC_INLINE file_time_type directory_entry::last_write_time() const
GHC_INLINE file_time_type directory_entry::last_write_time(std::error_code& ec) const noexcept GHC_INLINE file_time_type directory_entry::last_write_time(std::error_code& ec) const noexcept
{ {
if (_status.type() != file_type::none) { if (_last_write_time != 0) {
ec.clear(); ec.clear();
return std::chrono::system_clock::from_time_t(_last_write_time); return std::chrono::system_clock::from_time_t(_last_write_time);
} }
@ -5269,7 +5296,7 @@ GHC_INLINE file_time_type directory_entry::last_write_time(std::error_code& ec)
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
GHC_INLINE file_status directory_entry::status() const GHC_INLINE file_status directory_entry::status() const
{ {
if (_status.type() != file_type::none) { if (_status.type() != file_type::none && _status.permissions() != perms::unknown) {
return _status; return _status;
} }
return filesystem::status(path()); return filesystem::status(path());
@ -5278,7 +5305,7 @@ GHC_INLINE file_status directory_entry::status() const
GHC_INLINE file_status directory_entry::status(std::error_code& ec) const noexcept GHC_INLINE file_status directory_entry::status(std::error_code& ec) const noexcept
{ {
if (_status.type() != file_type::none) { if (_status.type() != file_type::none && _status.permissions() != perms::unknown) {
ec.clear(); ec.clear();
return _status; return _status;
} }
@ -5288,7 +5315,7 @@ GHC_INLINE file_status directory_entry::status(std::error_code& ec) const noexce
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
GHC_INLINE file_status directory_entry::symlink_status() const GHC_INLINE file_status directory_entry::symlink_status() const
{ {
if (_symlink_status.type() != file_type::none) { if (_symlink_status.type() != file_type::none && _symlink_status.permissions() != perms::unknown) {
return _symlink_status; return _symlink_status;
} }
return filesystem::symlink_status(path()); return filesystem::symlink_status(path());
@ -5297,7 +5324,7 @@ GHC_INLINE file_status directory_entry::symlink_status() const
GHC_INLINE file_status directory_entry::symlink_status(std::error_code& ec) const noexcept GHC_INLINE file_status directory_entry::symlink_status(std::error_code& ec) const noexcept
{ {
if (_symlink_status.type() != file_type::none) { if (_symlink_status.type() != file_type::none && _symlink_status.permissions() != perms::unknown) {
ec.clear(); ec.clear();
return _symlink_status; return _symlink_status;
} }
@ -5360,7 +5387,7 @@ public:
increment(_ec); increment(_ec);
} }
else { else {
_current = _base / std::wstring(_findData.cFileName); _dir_entry._path = _base / std::wstring(_findData.cFileName);
copyToDirEntry(_ec); copyToDirEntry(_ec);
} }
} }
@ -5386,20 +5413,20 @@ public:
if (_dirHandle != INVALID_HANDLE_VALUE) { if (_dirHandle != INVALID_HANDLE_VALUE) {
do { do {
if (FindNextFileW(_dirHandle, &_findData)) { if (FindNextFileW(_dirHandle, &_findData)) {
_current = _base; _dir_entry._path = _base;
#ifdef GHC_USE_WCHAR_T #ifdef GHC_USE_WCHAR_T
_current.append_name(_findData.cFileName); _dir_entry._path.append_name(_findData.cFileName);
#else #else
#ifdef GHC_RAISE_UNICODE_ERRORS #ifdef GHC_RAISE_UNICODE_ERRORS
try { try {
_current.append_name(detail::toUtf8(_findData.cFileName).c_str()); _dir_entry._path.append_name(detail::toUtf8(_findData.cFileName).c_str());
} }
catch (filesystem_error& fe) { catch (filesystem_error& fe) {
ec = fe.code(); ec = fe.code();
return; return;
} }
#else #else
_current.append_name(detail::toUtf8(_findData.cFileName).c_str()); _dir_entry._path.append_name(detail::toUtf8(_findData.cFileName).c_str());
#endif #endif
#endif #endif
copyToDirEntry(ec); copyToDirEntry(ec);
@ -5411,7 +5438,7 @@ public:
} }
FindClose(_dirHandle); FindClose(_dirHandle);
_dirHandle = INVALID_HANDLE_VALUE; _dirHandle = INVALID_HANDLE_VALUE;
_current = filesystem::path(); _dir_entry._path.clear();
break; break;
} }
} while (std::wstring(_findData.cFileName) == L"." || std::wstring(_findData.cFileName) == L".."); } while (std::wstring(_findData.cFileName) == L"." || std::wstring(_findData.cFileName) == L"..");
@ -5422,12 +5449,11 @@ public:
} }
void copyToDirEntry(std::error_code& ec) void copyToDirEntry(std::error_code& ec)
{ {
_dir_entry._path = _current;
if (_findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { if (_findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
_dir_entry._status = detail::status_ex(_current, ec, &_dir_entry._symlink_status, &_dir_entry._file_size, nullptr, &_dir_entry._last_write_time); _dir_entry._status = detail::status_ex(_dir_entry._path, ec, &_dir_entry._symlink_status, &_dir_entry._file_size, nullptr, &_dir_entry._last_write_time);
} }
else { else {
_dir_entry._status = detail::status_from_INFO(_current, &_findData, ec, &_dir_entry._file_size, &_dir_entry._last_write_time); _dir_entry._status = detail::status_from_INFO(_dir_entry._path, &_findData, ec, &_dir_entry._file_size, &_dir_entry._last_write_time);
_dir_entry._symlink_status = _dir_entry._status; _dir_entry._symlink_status = _dir_entry._status;
} }
if (ec) { if (ec) {
@ -5444,7 +5470,6 @@ public:
directory_options _options; directory_options _options;
WIN32_FIND_DATAW _findData; WIN32_FIND_DATAW _findData;
HANDLE _dirHandle; HANDLE _dirHandle;
path _current;
directory_entry _dir_entry; directory_entry _dir_entry;
std::error_code _ec; std::error_code _ec;
}; };
@ -5489,9 +5514,9 @@ public:
errno = 0; errno = 0;
_entry = ::readdir(_dir); _entry = ::readdir(_dir);
if (_entry) { if (_entry) {
_current = _base; _dir_entry._path = _base;
_current.append_name(_entry->d_name); _dir_entry._path.append_name(_entry->d_name);
_dir_entry.assign(_current, ec); copyToDirEntry();
if (ec && (ec.value() == EACCES || ec.value() == EPERM) && (_options & directory_options::skip_permission_denied) == directory_options::skip_permission_denied) { if (ec && (ec.value() == EACCES || ec.value() == EPERM) && (_options & directory_options::skip_permission_denied) == directory_options::skip_permission_denied) {
ec.clear(); ec.clear();
skip = true; skip = true;
@ -5500,7 +5525,7 @@ public:
else { else {
::closedir(_dir); ::closedir(_dir);
_dir = nullptr; _dir = nullptr;
_current = path(); _dir_entry._path.clear();
if (errno) { if (errno) {
ec = detail::make_system_error(); ec = detail::make_system_error();
} }
@ -5509,9 +5534,32 @@ public:
} while (skip || std::strcmp(_entry->d_name, ".") == 0 || std::strcmp(_entry->d_name, "..") == 0); } while (skip || std::strcmp(_entry->d_name, ".") == 0 || std::strcmp(_entry->d_name, "..") == 0);
} }
} }
void copyToDirEntry()
{
_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;
default: _dir_entry._symlink_status.type(file_type::unknown); break;
}
if (_entry->d_type != DT_LNK) {
_dir_entry._status = _dir_entry._symlink_status;
}
else {
_dir_entry._status.type(file_type::none);
_dir_entry._status.permissions(perms::unknown);
}
_dir_entry._file_size = static_cast<uintmax_t>(-1);
_dir_entry._hard_link_count = static_cast<uintmax_t>(-1);
_dir_entry._last_write_time = 0;
}
path _base; path _base;
directory_options _options; directory_options _options;
path _current;
DIR* _dir; DIR* _dir;
struct ::dirent* _entry; struct ::dirent* _entry;
directory_entry _dir_entry; directory_entry _dir_entry;
@ -5600,7 +5648,7 @@ GHC_INLINE directory_iterator& directory_iterator::operator++()
std::error_code ec; std::error_code ec;
_impl->increment(ec); _impl->increment(ec);
if (ec) { if (ec) {
throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_current, ec); throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_dir_entry._path, ec);
} }
return *this; return *this;
} }
@ -5614,12 +5662,12 @@ GHC_INLINE directory_iterator& directory_iterator::increment(std::error_code& ec
GHC_INLINE bool directory_iterator::operator==(const directory_iterator& rhs) const GHC_INLINE bool directory_iterator::operator==(const directory_iterator& rhs) const
{ {
return _impl->_current == rhs._impl->_current; return _impl->_dir_entry._path == rhs._impl->_dir_entry._path;
} }
GHC_INLINE bool directory_iterator::operator!=(const directory_iterator& rhs) const GHC_INLINE bool directory_iterator::operator!=(const directory_iterator& rhs) const
{ {
return _impl->_current != rhs._impl->_current; return _impl->_dir_entry._path != rhs._impl->_dir_entry._path;
} }
// 30.10.13.2 directory_iterator non-member functions // 30.10.13.2 directory_iterator non-member functions