Merge branch 'master' into feature-27-mingw-preferred_separator

This commit is contained in:
Steffen Schümann 2019-09-20 13:42:31 +02:00
commit 03b437cefb
2 changed files with 105 additions and 84 deletions

View File

@ -1080,6 +1080,11 @@ enum class portable_error {
is_a_directory, is_a_directory,
}; };
GHC_FS_API std::error_code make_error_code(portable_error err); GHC_FS_API std::error_code make_error_code(portable_error err);
#ifdef GHC_OS_WINDOWS
GHC_FS_API std::error_code make_system_error(DWORD err = 0);
#else
GHC_FS_API std::error_code make_system_error(int err = 0);
#endif
} // namespace detail } // namespace detail
namespace detail { namespace detail {
@ -1130,6 +1135,18 @@ GHC_INLINE std::error_code make_error_code(portable_error err)
return std::error_code(); return std::error_code();
} }
#ifdef GHC_OS_WINDOWS
GHC_INLINE std::error_code make_system_error(DWORD err)
{
return std::error_code(err ? static_cast<int>(err) : static_cast<int>(::GetLastError()), std::system_category());
}
#else
GHC_INLINE std::error_code make_system_error(int err)
{
return std::error_code(err ? err : errno, std::system_category());
}
#endif
#endif // GHC_EXPAND_IMPL #endif // GHC_EXPAND_IMPL
template <typename Enum> template <typename Enum>
@ -1249,7 +1266,7 @@ GHC_INLINE unsigned consumeUtf8Fragment(const unsigned state, const uint8_t frag
0x88888880u, 0x22818108u, 0x88888881u, 0x88888882u, 0x88888884u, 0x88888887u, 0x88888886u, 0x82218108u, 0x82281108u, 0x88888888u, 0x88888883u, 0x88888885u, 0u, 0u, 0u, 0u, 0x88888880u, 0x22818108u, 0x88888881u, 0x88888882u, 0x88888884u, 0x88888887u, 0x88888886u, 0x82218108u, 0x82281108u, 0x88888888u, 0x88888883u, 0x88888885u, 0u, 0u, 0u, 0u,
}; };
uint8_t category = fragment < 128 ? 0 : (utf8_state_info[(fragment >> 3) & 0xf] >> ((fragment & 7) << 2)) & 0xf; uint8_t category = fragment < 128 ? 0 : (utf8_state_info[(fragment >> 3) & 0xf] >> ((fragment & 7) << 2)) & 0xf;
codepoint = (state ? (codepoint << 6) | (fragment & 0x3f) : (0xff >> category) & fragment); codepoint = (state ? (codepoint << 6) | (fragment & 0x3fu) : (0xffu >> category) & fragment);
return state == S_RJCT ? static_cast<unsigned>(S_RJCT) : static_cast<unsigned>((utf8_state_info[category + 16] >> (state << 2)) & 0xf); return state == S_RJCT ? static_cast<unsigned>(S_RJCT) : static_cast<unsigned>((utf8_state_info[category + 16] >> (state << 2)) & 0xf);
} }
@ -1331,7 +1348,7 @@ inline StringType fromUtf8(const std::string& utf8String, const typename StringT
std::uint32_t codepoint = 0; std::uint32_t codepoint = 0;
while (iter < utf8String.end()) { while (iter < utf8String.end()) {
if ((utf8_state = consumeUtf8Fragment(utf8_state, (uint8_t)*iter++, codepoint)) == S_STRT) { if ((utf8_state = consumeUtf8Fragment(utf8_state, (uint8_t)*iter++, codepoint)) == S_STRT) {
result += codepoint; result += static_cast<typename StringType::value_type>(codepoint);
codepoint = 0; codepoint = 0;
} }
else if (utf8_state == S_RJCT) { else if (utf8_state == S_RJCT) {
@ -1394,7 +1411,7 @@ inline std::string toUtf8(const std::basic_string<charT, traits, Alloc>& unicode
{ {
std::string result; std::string result;
for (auto c : unicodeString) { for (auto c : unicodeString) {
appendUTF8(result, c); appendUTF8(result, static_cast<uint32_t>(c));
} }
return result; return result;
} }
@ -1557,7 +1574,7 @@ GHC_INLINE std::string systemErrorText(ErrorNumber code = 0)
{ {
#if defined(GHC_OS_WINDOWS) #if defined(GHC_OS_WINDOWS)
LPVOID msgBuf; LPVOID msgBuf;
DWORD dw = code ? code : ::GetLastError(); DWORD dw = code ? static_cast<DWORD>(code) : ::GetLastError();
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&msgBuf, 0, NULL); FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&msgBuf, 0, NULL);
std::string msg = toUtf8(std::wstring((LPWSTR)msgBuf)); std::string msg = toUtf8(std::wstring((LPWSTR)msgBuf));
LocalFree(msgBuf); LocalFree(msgBuf);
@ -1587,11 +1604,11 @@ GHC_INLINE void create_symlink(const path& target_name, const path& new_symlink,
if (result == ERROR_PRIVILEGE_NOT_HELD && api_call(detail::fromUtf8<std::wstring>(new_symlink.u8string()).c_str(), detail::fromUtf8<std::wstring>(target_name.u8string()).c_str(), to_directory ? 3 : 2) != 0) { if (result == ERROR_PRIVILEGE_NOT_HELD && api_call(detail::fromUtf8<std::wstring>(new_symlink.u8string()).c_str(), detail::fromUtf8<std::wstring>(target_name.u8string()).c_str(), to_directory ? 3 : 2) != 0) {
return; return;
} }
ec = std::error_code(result, std::system_category()); ec = detail::make_system_error(result);
} }
} }
else { else {
ec = std::error_code(ERROR_NOT_SUPPORTED, std::system_category()); ec = detail::make_system_error(ERROR_NOT_SUPPORTED);
} }
} }
@ -1600,25 +1617,25 @@ GHC_INLINE void create_hardlink(const path& target_name, const path& new_hardlin
static CreateHardLinkW_fp api_call = reinterpret_cast<CreateHardLinkW_fp>(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW")); static CreateHardLinkW_fp api_call = reinterpret_cast<CreateHardLinkW_fp>(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW"));
if (api_call) { if (api_call) {
if (api_call(detail::fromUtf8<std::wstring>(new_hardlink.u8string()).c_str(), detail::fromUtf8<std::wstring>(target_name.u8string()).c_str(), NULL) == 0) { if (api_call(detail::fromUtf8<std::wstring>(new_hardlink.u8string()).c_str(), detail::fromUtf8<std::wstring>(target_name.u8string()).c_str(), NULL) == 0) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
} }
} }
else { else {
ec = std::error_code(ERROR_NOT_SUPPORTED, std::system_category()); ec = detail::make_system_error(ERROR_NOT_SUPPORTED);
} }
} }
#else #else
GHC_INLINE void create_symlink(const path& target_name, const path& new_symlink, bool, std::error_code& ec) GHC_INLINE void create_symlink(const path& target_name, const path& new_symlink, bool, std::error_code& ec)
{ {
if (::symlink(target_name.c_str(), new_symlink.c_str()) != 0) { if (::symlink(target_name.c_str(), new_symlink.c_str()) != 0) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
} }
} }
GHC_INLINE void create_hardlink(const path& target_name, const path& new_hardlink, std::error_code& ec) GHC_INLINE void create_hardlink(const path& target_name, const path& new_hardlink, std::error_code& ec)
{ {
if (::link(target_name.c_str(), new_hardlink.c_str()) != 0) { if (::link(target_name.c_str(), new_hardlink.c_str()) != 0) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
} }
} }
#endif #endif
@ -1708,7 +1725,7 @@ GHC_INLINE path resolveSymlink(const path& p, std::error_code& ec)
std::shared_ptr<void> file(CreateFileW(p.wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle); std::shared_ptr<void> file(CreateFileW(p.wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
if (file.get() == INVALID_HANDLE_VALUE) { if (file.get() == INVALID_HANDLE_VALUE) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
return path(); return path();
} }
@ -1730,7 +1747,7 @@ GHC_INLINE path resolveSymlink(const path& p, std::error_code& ec)
} }
} }
else { else {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
} }
return result; return result;
#else #else
@ -1739,11 +1756,11 @@ GHC_INLINE path resolveSymlink(const path& p, std::error_code& ec)
std::vector<char> buffer(bufferSize, (char)0); std::vector<char> buffer(bufferSize, (char)0);
auto rc = ::readlink(p.c_str(), buffer.data(), buffer.size()); auto rc = ::readlink(p.c_str(), buffer.data(), buffer.size());
if (rc < 0) { if (rc < 0) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
return path(); return path();
} }
else if (rc < static_cast<int>(bufferSize)) { else if (rc < static_cast<int>(bufferSize)) {
return path(std::string(buffer.data(), rc)); return path(std::string(buffer.data(), static_cast<std::string::size_type>(rc)));
} }
bufferSize *= 2; bufferSize *= 2;
} }
@ -1757,15 +1774,15 @@ GHC_INLINE time_t timeFromFILETIME(const FILETIME& ft)
ULARGE_INTEGER ull; ULARGE_INTEGER ull;
ull.LowPart = ft.dwLowDateTime; ull.LowPart = ft.dwLowDateTime;
ull.HighPart = ft.dwHighDateTime; ull.HighPart = ft.dwHighDateTime;
return ull.QuadPart / 10000000ULL - 11644473600ULL; return static_cast<time_t>(ull.QuadPart / 10000000ULL - 11644473600ULL);
} }
GHC_INLINE void timeToFILETIME(time_t t, FILETIME& ft) GHC_INLINE void timeToFILETIME(time_t t, FILETIME& ft)
{ {
LONGLONG ll; LONGLONG ll;
ll = Int32x32To64(t, 10000000) + 116444736000000000; ll = Int32x32To64(t, 10000000) + 116444736000000000;
ft.dwLowDateTime = (DWORD)ll; ft.dwLowDateTime = static_cast<DWORD>(ll);
ft.dwHighDateTime = ll >> 32; ft.dwHighDateTime = static_cast<DWORD>(ll >> 32);
} }
template <typename INFO> template <typename INFO>
@ -1829,7 +1846,7 @@ GHC_INLINE file_status symlink_status_ex(const path& p, std::error_code& ec, uin
file_status fs; file_status fs;
WIN32_FILE_ATTRIBUTE_DATA attr; WIN32_FILE_ATTRIBUTE_DATA attr;
if (!GetFileAttributesExW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), GetFileExInfoStandard, &attr)) { if (!GetFileAttributesExW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), GetFileExInfoStandard, &attr)) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
} }
else { else {
ec.clear(); ec.clear();
@ -1856,7 +1873,7 @@ GHC_INLINE file_status symlink_status_ex(const path& p, std::error_code& ec, uin
file_status f_s = detail::file_status_from_st_mode(fs.st_mode); file_status f_s = detail::file_status_from_st_mode(fs.st_mode);
return f_s; return f_s;
} }
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
if (detail::is_not_found_error(ec)) { if (detail::is_not_found_error(ec)) {
return file_status(file_type::not_found, perms::unknown); return file_status(file_type::not_found, perms::unknown);
} }
@ -1869,12 +1886,12 @@ GHC_INLINE file_status status_ex(const path& p, std::error_code& ec, file_status
ec.clear(); ec.clear();
#ifdef GHC_OS_WINDOWS #ifdef GHC_OS_WINDOWS
if (recurse_count > 16) { if (recurse_count > 16) {
ec = std::error_code(0x2A9 /*ERROR_STOPPED_ON_SYMLINK*/, std::system_category()); ec = detail::make_system_error(0x2A9 /*ERROR_STOPPED_ON_SYMLINK*/);
return file_status(file_type::unknown); return file_status(file_type::unknown);
} }
WIN32_FILE_ATTRIBUTE_DATA attr; WIN32_FILE_ATTRIBUTE_DATA attr;
if (!::GetFileAttributesExW(p.wstring().c_str(), GetFileExInfoStandard, &attr)) { if (!::GetFileAttributesExW(p.wstring().c_str(), GetFileExInfoStandard, &attr)) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
} }
else if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { else if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
path target = resolveSymlink(p, ec); path target = resolveSymlink(p, ec);
@ -1914,7 +1931,7 @@ GHC_INLINE file_status status_ex(const path& p, std::error_code& ec, file_status
} }
} }
if (sz) { if (sz) {
*sz = st.st_size; *sz = static_cast<uintmax_t>(st.st_size);
} }
if (nhl) { if (nhl) {
*nhl = st.st_nlink; *nhl = st.st_nlink;
@ -1925,7 +1942,7 @@ GHC_INLINE file_status status_ex(const path& p, std::error_code& ec, file_status
return fs; return fs;
} }
else { else {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
if (detail::is_not_found_error(ec)) { if (detail::is_not_found_error(ec)) {
return file_status(file_type::not_found, perms::unknown); return file_status(file_type::not_found, perms::unknown);
} }
@ -1946,8 +1963,8 @@ GHC_INLINE u8arguments::u8arguments(int& argc, char**& argv)
#ifdef GHC_OS_WINDOWS #ifdef GHC_OS_WINDOWS
LPWSTR* p; LPWSTR* p;
p = ::CommandLineToArgvW(::GetCommandLineW(), &argc); p = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
_args.reserve(argc); _args.reserve(static_cast<size_t>(argc));
_argp.reserve(argc); _argp.reserve(static_cast<size_t>(argc));
for (size_t i = 0; i < static_cast<size_t>(argc); ++i) { for (size_t i = 0; i < static_cast<size_t>(argc); ++i) {
_args.push_back(detail::toUtf8(std::wstring(p[i]))); _args.push_back(detail::toUtf8(std::wstring(p[i])));
_argp.push_back((char*)_args[i].data()); _argp.push_back((char*)_args[i].data());
@ -3024,7 +3041,7 @@ GHC_INLINE path absolute(const path& p, std::error_code& ec)
return result; return result;
} }
} }
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
return path(); return path();
#else #else
path base = current_path(ec); path base = current_path(ec);
@ -3049,7 +3066,7 @@ GHC_INLINE path absolute(const path& p, std::error_code& ec)
} }
} }
} }
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
return path(); return path();
#endif #endif
} }
@ -3261,12 +3278,12 @@ GHC_INLINE bool copy_file(const path& from, const path& to, copy_options options
if ((options & copy_options::update_existing) == copy_options::update_existing) { if ((options & copy_options::update_existing) == copy_options::update_existing) {
auto from_time = last_write_time(from, ec); auto from_time = last_write_time(from, ec);
if (ec) { if (ec) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
return false; return false;
} }
auto to_time = last_write_time(to, ec); auto to_time = last_write_time(to, ec);
if (ec) { if (ec) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
return false; return false;
} }
if (from_time <= to_time) { if (from_time <= to_time) {
@ -3277,7 +3294,7 @@ GHC_INLINE bool copy_file(const path& from, const path& to, copy_options options
} }
#ifdef GHC_OS_WINDOWS #ifdef GHC_OS_WINDOWS
if (!::CopyFileW(detail::fromUtf8<std::wstring>(from.u8string()).c_str(), detail::fromUtf8<std::wstring>(to.u8string()).c_str(), !overwrite)) { if (!::CopyFileW(detail::fromUtf8<std::wstring>(from.u8string()).c_str(), detail::fromUtf8<std::wstring>(to.u8string()).c_str(), !overwrite)) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
return false; return false;
} }
return true; return true;
@ -3285,7 +3302,7 @@ GHC_INLINE bool copy_file(const path& from, const path& to, copy_options options
std::vector<char> buffer(16384, '\0'); std::vector<char> buffer(16384, '\0');
int in = -1, out = -1; int in = -1, out = -1;
if ((in = ::open(from.c_str(), O_RDONLY)) < 0) { if ((in = ::open(from.c_str(), O_RDONLY)) < 0) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
return false; return false;
} }
std::shared_ptr<void> guard_in(nullptr, [in](void*) { ::close(in); }); std::shared_ptr<void> guard_in(nullptr, [in](void*) { ::close(in); });
@ -3294,20 +3311,20 @@ GHC_INLINE bool copy_file(const path& from, const path& to, copy_options options
mode |= O_EXCL; mode |= O_EXCL;
} }
if ((out = ::open(to.c_str(), mode, static_cast<int>(sf.permissions() & perms::all))) < 0) { if ((out = ::open(to.c_str(), mode, static_cast<int>(sf.permissions() & perms::all))) < 0) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
return false; return false;
} }
std::shared_ptr<void> guard_out(nullptr, [out](void*) { ::close(out); }); std::shared_ptr<void> guard_out(nullptr, [out](void*) { ::close(out); });
ssize_t br, bw; ssize_t br, bw;
while ((br = ::read(in, buffer.data(), buffer.size())) > 0) { while ((br = ::read(in, buffer.data(), buffer.size())) > 0) {
int offset = 0; ssize_t offset = 0;
do { do {
if ((bw = ::write(out, buffer.data() + offset, br)) > 0) { if ((bw = ::write(out, buffer.data() + offset, static_cast<size_t>(br))) > 0) {
br -= bw; br -= bw;
offset += bw; offset += bw;
} }
else if (bw < 0) { else if (bw < 0) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
return false; return false;
} }
} while (br); } while (br);
@ -3421,12 +3438,12 @@ GHC_INLINE bool create_directory(const path& p, const path& attributes, std::err
#ifdef GHC_OS_WINDOWS #ifdef GHC_OS_WINDOWS
if (!attributes.empty()) { if (!attributes.empty()) {
if (!::CreateDirectoryExW(detail::fromUtf8<std::wstring>(attributes.u8string()).c_str(), detail::fromUtf8<std::wstring>(p.u8string()).c_str(), NULL)) { if (!::CreateDirectoryExW(detail::fromUtf8<std::wstring>(attributes.u8string()).c_str(), detail::fromUtf8<std::wstring>(p.u8string()).c_str(), NULL)) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
return false; return false;
} }
} }
else if (!::CreateDirectoryW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), NULL)) { else if (!::CreateDirectoryW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), NULL)) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
return false; return false;
} }
#else #else
@ -3434,13 +3451,13 @@ GHC_INLINE bool create_directory(const path& p, const path& attributes, std::err
if (!attributes.empty()) { if (!attributes.empty()) {
struct ::stat fileStat; struct ::stat fileStat;
if (::stat(attributes.c_str(), &fileStat) != 0) { if (::stat(attributes.c_str(), &fileStat) != 0) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
return false; return false;
} }
attribs = fileStat.st_mode; attribs = fileStat.st_mode;
} }
if (::mkdir(p.c_str(), attribs) != 0) { if (::mkdir(p.c_str(), attribs) != 0) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
return false; return false;
} }
#endif #endif
@ -3506,7 +3523,7 @@ GHC_INLINE path current_path(std::error_code& ec)
DWORD pathlen = ::GetCurrentDirectoryW(0, 0); DWORD pathlen = ::GetCurrentDirectoryW(0, 0);
std::unique_ptr<wchar_t[]> buffer(new wchar_t[size_t(pathlen) + 1]); std::unique_ptr<wchar_t[]> buffer(new wchar_t[size_t(pathlen) + 1]);
if (::GetCurrentDirectoryW(pathlen, buffer.get()) == 0) { if (::GetCurrentDirectoryW(pathlen, buffer.get()) == 0) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
return path(); return path();
} }
return path(std::wstring(buffer.get()), path::native_format); return path(std::wstring(buffer.get()), path::native_format);
@ -3514,7 +3531,7 @@ GHC_INLINE path current_path(std::error_code& ec)
size_t pathlen = static_cast<size_t>(std::max(int(::pathconf(".", _PC_PATH_MAX)), int(PATH_MAX))); size_t pathlen = static_cast<size_t>(std::max(int(::pathconf(".", _PC_PATH_MAX)), int(PATH_MAX)));
std::unique_ptr<char[]> buffer(new char[pathlen + 1]); std::unique_ptr<char[]> buffer(new char[pathlen + 1]);
if (::getcwd(buffer.get(), pathlen) == NULL) { if (::getcwd(buffer.get(), pathlen) == NULL) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
return path(); return path();
} }
return path(buffer.get()); return path(buffer.get());
@ -3535,11 +3552,11 @@ GHC_INLINE void current_path(const path& p, std::error_code& ec) noexcept
ec.clear(); ec.clear();
#ifdef GHC_OS_WINDOWS #ifdef GHC_OS_WINDOWS
if (!::SetCurrentDirectoryW(detail::fromUtf8<std::wstring>(p.u8string()).c_str())) { if (!::SetCurrentDirectoryW(detail::fromUtf8<std::wstring>(p.u8string()).c_str())) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
} }
#else #else
if (::chdir(p.string().c_str()) == -1) { if (::chdir(p.string().c_str()) == -1) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
} }
#endif #endif
} }
@ -3582,21 +3599,21 @@ GHC_INLINE bool equivalent(const path& p1, const path& p2, std::error_code& ec)
std::shared_ptr<void> file2(::CreateFileW(p2.wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle); std::shared_ptr<void> file2(::CreateFileW(p2.wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
if (file1.get() == INVALID_HANDLE_VALUE || file2.get() == INVALID_HANDLE_VALUE) { if (file1.get() == INVALID_HANDLE_VALUE || file2.get() == INVALID_HANDLE_VALUE) {
#ifdef LWG_2937_BEHAVIOUR #ifdef LWG_2937_BEHAVIOUR
ec = std::error_code(e1 ? e1 : ::GetLastError(), std::system_category()); ec = detail::make_system_error(e1 ? e1 : ::GetLastError());
#else #else
if (file1 == file2) { if (file1 == file2) {
ec = std::error_code(e1 ? e1 : ::GetLastError(), std::system_category()); ec = detail::make_system_error(e1 ? e1 : ::GetLastError());
} }
#endif #endif
return false; return false;
} }
BY_HANDLE_FILE_INFORMATION inf1, inf2; BY_HANDLE_FILE_INFORMATION inf1, inf2;
if (!::GetFileInformationByHandle(file1.get(), &inf1)) { if (!::GetFileInformationByHandle(file1.get(), &inf1)) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
return false; return false;
} }
if (!::GetFileInformationByHandle(file2.get(), &inf2)) { if (!::GetFileInformationByHandle(file2.get(), &inf2)) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
return false; return false;
} }
return inf1.ftLastWriteTime.dwLowDateTime == inf2.ftLastWriteTime.dwLowDateTime && inf1.ftLastWriteTime.dwHighDateTime == inf2.ftLastWriteTime.dwHighDateTime && inf1.nFileIndexHigh == inf2.nFileIndexHigh && inf1.nFileIndexLow == inf2.nFileIndexLow && return inf1.ftLastWriteTime.dwLowDateTime == inf2.ftLastWriteTime.dwLowDateTime && inf1.ftLastWriteTime.dwHighDateTime == inf2.ftLastWriteTime.dwHighDateTime && inf1.nFileIndexHigh == inf2.nFileIndexHigh && inf1.nFileIndexLow == inf2.nFileIndexLow &&
@ -3608,10 +3625,10 @@ GHC_INLINE bool equivalent(const path& p1, const path& p2, std::error_code& ec)
auto rc2 = ::stat(p2.c_str(), &s2); auto rc2 = ::stat(p2.c_str(), &s2);
if (rc1 || rc2) { if (rc1 || rc2) {
#ifdef LWG_2937_BEHAVIOUR #ifdef LWG_2937_BEHAVIOUR
ec = std::error_code(e1 ? e1 : errno, std::system_category()); ec = detail::make_system_error(e1 ? e1 : errno);
#else #else
if (rc1 && rc2) { if (rc1 && rc2) {
ec = std::error_code(e1 ? e1 : errno, std::system_category()); ec = detail::make_system_error(e1 ? e1 : errno);
} }
#endif #endif
return false; return false;
@ -3636,14 +3653,14 @@ GHC_INLINE uintmax_t file_size(const path& p, std::error_code& ec) noexcept
#ifdef GHC_OS_WINDOWS #ifdef GHC_OS_WINDOWS
WIN32_FILE_ATTRIBUTE_DATA attr; WIN32_FILE_ATTRIBUTE_DATA attr;
if (!GetFileAttributesExW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), GetFileExInfoStandard, &attr)) { if (!GetFileAttributesExW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), GetFileExInfoStandard, &attr)) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
return static_cast<uintmax_t>(-1); return static_cast<uintmax_t>(-1);
} }
return static_cast<uintmax_t>(attr.nFileSizeHigh) << (sizeof(attr.nFileSizeHigh) * 8) | attr.nFileSizeLow; return static_cast<uintmax_t>(attr.nFileSizeHigh) << (sizeof(attr.nFileSizeHigh) * 8) | attr.nFileSizeLow;
#else #else
struct ::stat fileStat; struct ::stat fileStat;
if (::stat(p.c_str(), &fileStat) == -1) { if (::stat(p.c_str(), &fileStat) == -1) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
return static_cast<uintmax_t>(-1); return static_cast<uintmax_t>(-1);
} }
return static_cast<uintmax_t>(fileStat.st_size); return static_cast<uintmax_t>(fileStat.st_size);
@ -3668,11 +3685,11 @@ GHC_INLINE uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcep
std::shared_ptr<void> file(::CreateFileW(p.wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle); std::shared_ptr<void> file(::CreateFileW(p.wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
BY_HANDLE_FILE_INFORMATION inf; BY_HANDLE_FILE_INFORMATION inf;
if (file.get() == INVALID_HANDLE_VALUE) { if (file.get() == INVALID_HANDLE_VALUE) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
} }
else { else {
if (!::GetFileInformationByHandle(file.get(), &inf)) { if (!::GetFileInformationByHandle(file.get(), &inf)) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
} }
else { else {
result = inf.nNumberOfLinks; result = inf.nNumberOfLinks;
@ -3876,10 +3893,10 @@ GHC_INLINE void last_write_time(const path& p, file_time_type new_time, std::err
std::shared_ptr<void> file(::CreateFileW(p.wstring().c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL), ::CloseHandle); std::shared_ptr<void> file(::CreateFileW(p.wstring().c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL), ::CloseHandle);
FILETIME ft; FILETIME ft;
auto tt = std::chrono::duration_cast<std::chrono::microseconds>(d).count() * 10 + 116444736000000000; auto tt = std::chrono::duration_cast<std::chrono::microseconds>(d).count() * 10 + 116444736000000000;
ft.dwLowDateTime = (unsigned long)tt; ft.dwLowDateTime = static_cast<DWORD>(tt);
ft.dwHighDateTime = tt >> 32; ft.dwHighDateTime = static_cast<DWORD>(tt >> 32);
if (!::SetFileTime(file.get(), 0, 0, &ft)) { if (!::SetFileTime(file.get(), 0, 0, &ft)) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
} }
#elif defined(GHC_OS_MACOS) #elif defined(GHC_OS_MACOS)
#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
@ -3895,7 +3912,7 @@ GHC_INLINE void last_write_time(const path& p, file_time_type new_time, std::err
return; return;
} }
} }
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
return; return;
#else #else
struct ::timespec times[2]; struct ::timespec times[2];
@ -3904,7 +3921,7 @@ GHC_INLINE void last_write_time(const path& p, file_time_type new_time, std::err
times[1].tv_sec = std::chrono::duration_cast<std::chrono::seconds>(d).count(); times[1].tv_sec = std::chrono::duration_cast<std::chrono::seconds>(d).count();
times[1].tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(d).count() % 1000000000; times[1].tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(d).count() % 1000000000;
if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) { if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
} }
return; return;
#endif #endif
@ -3916,7 +3933,7 @@ GHC_INLINE void last_write_time(const path& p, file_time_type new_time, std::err
times[1].tv_sec = std::chrono::duration_cast<std::chrono::seconds>(d).count(); times[1].tv_sec = std::chrono::duration_cast<std::chrono::seconds>(d).count();
times[1].tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(d).count() % 1000000000; times[1].tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(d).count() % 1000000000;
if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) { if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
} }
return; return;
#endif #endif
@ -3955,12 +3972,12 @@ GHC_INLINE void permissions(const path& p, perms prms, perm_options opts, std::e
#ifdef __GNUC__ #ifdef __GNUC__
auto oldAttr = GetFileAttributesW(p.wstring().c_str()); auto oldAttr = GetFileAttributesW(p.wstring().c_str());
if (oldAttr != INVALID_FILE_ATTRIBUTES) { if (oldAttr != INVALID_FILE_ATTRIBUTES) {
DWORD newAttr = ((prms & perms::owner_write) == perms::owner_write) ? oldAttr & ~FILE_ATTRIBUTE_READONLY : oldAttr | FILE_ATTRIBUTE_READONLY; DWORD newAttr = ((prms & perms::owner_write) == perms::owner_write) ? oldAttr & ~(static_cast<DWORD>(FILE_ATTRIBUTE_READONLY)) : oldAttr | FILE_ATTRIBUTE_READONLY;
if (oldAttr == newAttr || SetFileAttributesW(p.wstring().c_str(), newAttr)) { if (oldAttr == newAttr || SetFileAttributesW(p.wstring().c_str(), newAttr)) {
return; return;
} }
} }
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
#else #else
int mode = 0; int mode = 0;
if ((prms & perms::owner_read) == perms::owner_read) { if ((prms & perms::owner_read) == perms::owner_read) {
@ -3970,13 +3987,13 @@ GHC_INLINE void permissions(const path& p, perms prms, perm_options opts, std::e
mode |= _S_IWRITE; mode |= _S_IWRITE;
} }
if (::_wchmod(p.wstring().c_str(), mode) != 0) { if (::_wchmod(p.wstring().c_str(), mode) != 0) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
} }
#endif #endif
#else #else
if ((opts & perm_options::nofollow) != perm_options::nofollow) { if ((opts & perm_options::nofollow) != perm_options::nofollow) {
if (::chmod(p.c_str(), static_cast<mode_t>(prms)) != 0) { if (::chmod(p.c_str(), static_cast<mode_t>(prms)) != 0) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
} }
} }
#endif #endif
@ -4054,17 +4071,17 @@ GHC_INLINE bool remove(const path& p, std::error_code& ec) noexcept
if (error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND) { if (error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND) {
return false; return false;
} }
ec = std::error_code(error, std::system_category()); ec = detail::make_system_error(error);
} }
if (!ec) { if (!ec) {
if (attr & FILE_ATTRIBUTE_DIRECTORY) { if (attr & FILE_ATTRIBUTE_DIRECTORY) {
if (!RemoveDirectoryW(np.c_str())) { if (!RemoveDirectoryW(np.c_str())) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
} }
} }
else { else {
if (!DeleteFileW(np.c_str())) { if (!DeleteFileW(np.c_str())) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
} }
} }
} }
@ -4074,7 +4091,7 @@ GHC_INLINE bool remove(const path& p, std::error_code& ec) noexcept
if (error == ENOENT) { if (error == ENOENT) {
return false; return false;
} }
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
} }
#endif #endif
return ec ? false : true; return ec ? false : true;
@ -4146,13 +4163,13 @@ GHC_INLINE void rename(const path& from, const path& to, std::error_code& ec) no
#ifdef GHC_OS_WINDOWS #ifdef GHC_OS_WINDOWS
if (from != to) { if (from != to) {
if (!MoveFileW(detail::fromUtf8<std::wstring>(from.u8string()).c_str(), detail::fromUtf8<std::wstring>(to.u8string()).c_str())) { if (!MoveFileW(detail::fromUtf8<std::wstring>(from.u8string()).c_str(), detail::fromUtf8<std::wstring>(to.u8string()).c_str())) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
} }
} }
#else #else
if (from != to) { if (from != to) {
if (::rename(from.c_str(), to.c_str()) != 0) { if (::rename(from.c_str(), to.c_str()) != 0) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
} }
} }
#endif #endif
@ -4172,17 +4189,21 @@ GHC_INLINE void resize_file(const path& p, uintmax_t size, std::error_code& ec)
ec.clear(); ec.clear();
#ifdef GHC_OS_WINDOWS #ifdef GHC_OS_WINDOWS
LARGE_INTEGER lisize; LARGE_INTEGER lisize;
lisize.QuadPart = size; lisize.QuadPart = static_cast<LONGLONG>(size);
if(lisize.QuadPart < 0) {
ec = detail::make_system_error(ERROR_FILE_TOO_LARGE);
return;
}
std::shared_ptr<void> file(CreateFileW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL), CloseHandle); std::shared_ptr<void> file(CreateFileW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL), CloseHandle);
if (file.get() == INVALID_HANDLE_VALUE) { if (file.get() == INVALID_HANDLE_VALUE) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
} }
else if (SetFilePointerEx(file.get(), lisize, NULL, FILE_BEGIN) == 0 || SetEndOfFile(file.get()) == 0) { else if (SetFilePointerEx(file.get(), lisize, NULL, FILE_BEGIN) == 0 || SetEndOfFile(file.get()) == 0) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
} }
#else #else
if (::truncate(p.c_str(), size) != 0) { if (::truncate(p.c_str(), static_cast<off_t>(size)) != 0) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
} }
#endif #endif
} }
@ -4205,14 +4226,14 @@ GHC_INLINE space_info space(const path& p, std::error_code& ec) noexcept
ULARGE_INTEGER totalNumberOfBytes = {0, 0}; ULARGE_INTEGER totalNumberOfBytes = {0, 0};
ULARGE_INTEGER totalNumberOfFreeBytes = {0, 0}; ULARGE_INTEGER totalNumberOfFreeBytes = {0, 0};
if (!GetDiskFreeSpaceExW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes)) { if (!GetDiskFreeSpaceExW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes)) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
return {static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1)}; return {static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1)};
} }
return {static_cast<uintmax_t>(totalNumberOfBytes.QuadPart), static_cast<uintmax_t>(totalNumberOfFreeBytes.QuadPart), static_cast<uintmax_t>(freeBytesAvailableToCaller.QuadPart)}; return {static_cast<uintmax_t>(totalNumberOfBytes.QuadPart), static_cast<uintmax_t>(totalNumberOfFreeBytes.QuadPart), static_cast<uintmax_t>(freeBytesAvailableToCaller.QuadPart)};
#elif !defined(__ANDROID__) || __ANDROID_API__ >= 19 #elif !defined(__ANDROID__) || __ANDROID_API__ >= 19
struct ::statvfs sfs; struct ::statvfs sfs;
if (::statvfs(p.c_str(), &sfs) != 0) { if (::statvfs(p.c_str(), &sfs) != 0) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
return {static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1)}; return {static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1)};
} }
return {static_cast<uintmax_t>(sfs.f_blocks * sfs.f_frsize), static_cast<uintmax_t>(sfs.f_bfree * sfs.f_frsize), static_cast<uintmax_t>(sfs.f_bavail * sfs.f_frsize)}; return {static_cast<uintmax_t>(sfs.f_blocks * sfs.f_frsize), static_cast<uintmax_t>(sfs.f_bfree * sfs.f_frsize), static_cast<uintmax_t>(sfs.f_bavail * sfs.f_frsize)};
@ -4272,9 +4293,9 @@ GHC_INLINE path temp_directory_path(std::error_code& ec) noexcept
ec.clear(); ec.clear();
#ifdef GHC_OS_WINDOWS #ifdef GHC_OS_WINDOWS
wchar_t buffer[512]; wchar_t buffer[512];
int rc = GetTempPathW(511, buffer); auto rc = GetTempPathW(511, buffer);
if (!rc || rc > 511) { if (!rc || rc > 511) {
ec = std::error_code(::GetLastError(), std::system_category()); ec = detail::make_system_error();
return path(); return path();
} }
return path(std::wstring(buffer)); return path(std::wstring(buffer));
@ -4723,7 +4744,7 @@ public:
auto error = ::GetLastError(); auto error = ::GetLastError();
_base = filesystem::path(); _base = filesystem::path();
if (error != ERROR_ACCESS_DENIED || (options & directory_options::skip_permission_denied) == directory_options::none) { if (error != ERROR_ACCESS_DENIED || (options & directory_options::skip_permission_denied) == directory_options::none) {
_ec = std::error_code(::GetLastError(), std::system_category()); _ec = detail::make_system_error();
} }
} }
} }
@ -4754,7 +4775,7 @@ public:
else { else {
auto err = ::GetLastError(); auto err = ::GetLastError();
if(err != ERROR_NO_MORE_FILES) { if(err != ERROR_NO_MORE_FILES) {
_ec = ec = std::error_code(err, std::system_category()); _ec = ec = detail::make_system_error(err);
} }
FindClose(_dirHandle); FindClose(_dirHandle);
_dirHandle = INVALID_HANDLE_VALUE; _dirHandle = INVALID_HANDLE_VALUE;
@ -4814,7 +4835,7 @@ public:
auto error = errno; auto error = errno;
_base = filesystem::path(); _base = filesystem::path();
if (error != EACCES || (options & directory_options::skip_permission_denied) == directory_options::none) { if (error != EACCES || (options & directory_options::skip_permission_denied) == directory_options::none) {
_ec = std::error_code(errno, std::system_category()); _ec = detail::make_system_error();
} }
} }
else { else {
@ -4845,7 +4866,7 @@ public:
_dir = nullptr; _dir = nullptr;
_current = path(); _current = path();
if (errno) { if (errno) {
ec = std::error_code(errno, std::system_category()); ec = detail::make_system_error();
} }
break; break;
} }

View File

@ -18,8 +18,8 @@ else()
add_executable(filesystem_test filesystem_test.cpp catch.hpp) add_executable(filesystem_test filesystem_test.cpp catch.hpp)
target_link_libraries(filesystem_test ghc_filesystem) target_link_libraries(filesystem_test ghc_filesystem)
target_compile_options(filesystem_test PRIVATE target_compile_options(filesystem_test PRIVATE
$<$<CXX_COMPILER_ID:Clang>:-Wall -Wextra -Wshadow -Werror> $<$<CXX_COMPILER_ID:Clang>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Werror>
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wshadow -Werror> $<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Werror>
$<$<CXX_COMPILER_ID:MSVC>:/WX>) $<$<CXX_COMPILER_ID:MSVC>:/WX>)
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC) if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
target_compile_definitions(filesystem_test PRIVATE _CRT_SECURE_NO_WARNINGS) target_compile_definitions(filesystem_test PRIVATE _CRT_SECURE_NO_WARNINGS)