Skip to content

Commit

Permalink
Fix reading of size >4GiB on Windows.
Browse files Browse the repository at this point in the history
ReadFile take a 32bits size. So we cannot blindly pass a 64bits size.
Read by batch of 4MiB.
  • Loading branch information
mgautierfr committed Jun 10, 2024
1 parent 8dd2df3 commit 13f77c2
Showing 1 changed file with 25 additions and 4 deletions.
29 changes: 25 additions & 4 deletions src/fs_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,22 +73,43 @@ zsize_t FD::readAt(char* dest, zsize_t size, offset_t offset) const
EnterCriticalSection(&mp_impl->m_criticalSection);
LARGE_INTEGER off;
off.QuadPart = offset.v;
std::string errorMsg;
auto size_to_read = size.v;
size_type full_size_read = 0;

if (!SetFilePointerEx(mp_impl->m_handle, off, NULL, FILE_BEGIN)) {
errorMsg = "Seek fail";
goto err;
}

DWORD size_read;
if (!ReadFile(mp_impl->m_handle, dest, size.v, &size_read, NULL)) {
goto err;
while (size_to_read > 0) {
// Read by batch < 4GiB
// Lets use a batch of 4MiB
auto batch_to_read = std::min(size_to_read, (size_type)4*1024*1024);
if (!ReadFile(mp_impl->m_handle, dest, batch_to_read, &size_read, NULL)) {
errorMsg = "Read fail";
goto err;
}

if (size_read == 0) {
errorMsg = "Cannot read past the end of the file";
goto err;
}

size_to_read -= size_read;
full_size_read += size_read;
dest += size_read;
}
if (size_read != size.v) {
if (full_size_read != size.v) {
errorMsg = "Wrong read size";
goto err;
}
LeaveCriticalSection(&mp_impl->m_criticalSection);
return size;
err:
LeaveCriticalSection(&mp_impl->m_criticalSection);
throw std::runtime_error("Cannot read");
throw std::runtime_error(errorMsg);
}

bool FD::seek(offset_t offset)
Expand Down

0 comments on commit 13f77c2

Please sign in to comment.