diff --git a/posix.cc b/posix.cc index f5060616..0efb5aff 100644 --- a/posix.cc +++ b/posix.cc @@ -140,13 +140,19 @@ void fmt::File::close() { fmt::LongLong fmt::File::size() const { #ifdef _WIN32 - LARGE_INTEGER filesize = {}; + // Use GetFileSize instead of GetFileSizeEx for the case when _WIN32_WINNT + // is less than 0x0500 as is the case with some default MinGW builds. + // Both functions support large file sizes. + DWORD size_upper = 0; HANDLE handle = reinterpret_cast(_get_osfhandle(fd_)); - if (!FMT_SYSTEM(GetFileSizeEx(handle, &filesize))) - throw WindowsError(GetLastError(), "cannot get file size"); - FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(filesize.QuadPart), - "return type of File::size is not large enough"); - return filesize.QuadPart; + DWORD size_lower = FMT_SYSTEM(GetFileSize(handle, &size_upper)); + if (size_lower == INVALID_FILE_SIZE) { + DWORD error = GetLastError(); + if (error != NO_ERROR) + throw WindowsError(GetLastError(), "cannot get file size"); + } + fmt::ULongLong size = size_upper; + return (size << sizeof(DWORD) * CHAR_BIT) | size_lower; #else typedef struct stat Stat; Stat file_stat = Stat(); diff --git a/test/posix-test.cc b/test/posix-test.cc index c9529688..61d95c85 100644 --- a/test/posix-test.cc +++ b/test/posix-test.cc @@ -105,15 +105,17 @@ errno_t test::sopen_s( static LONGLONG max_file_size() { return std::numeric_limits::max(); } -BOOL test::GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize) { +DWORD test::GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh) { if (fstat_sim == ERROR) { SetLastError(ERROR_ACCESS_DENIED); return FALSE; } - BOOL result = ::GetFileSizeEx(hFile, lpFileSize); - if (fstat_sim == MAX_SIZE) - lpFileSize->QuadPart = max_file_size(); - return result; + if (fstat_sim == MAX_SIZE) { + DWORD max = std::numeric_limits::max(); + *lpFileSizeHig = max >> 1; + return max; + } + return ::GetFileSize(hFile, lpFileSizeHigh); } #endif diff --git a/test/posix-test.h b/test/posix-test.h index a43ce1ef..17bf0c97 100644 --- a/test/posix-test.h +++ b/test/posix-test.h @@ -51,7 +51,7 @@ typedef unsigned size_t; typedef int ssize_t; errno_t sopen_s( int* pfh, const char *filename, int oflag, int shflag, int pmode); -BOOL GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize); +DWORD GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh); #endif int close(int fildes);