diff options
author | Juhani Rankimies <[email protected]> | 2010-09-30 21:08:54 +0300 |
---|---|---|
committer | Juhani Rankimies <[email protected]> | 2010-09-30 21:08:54 +0300 |
commit | 6aae43917d587be7f631673d1e1963fbb2ba15e1 (patch) | |
tree | 9ac81e95ca64357e609832bf519667aafe02b3b9 /erts | |
parent | 8e9a96141120b43b4edf05705a2a261916a902a5 (diff) | |
download | otp-6aae43917d587be7f631673d1e1963fbb2ba15e1.tar.gz otp-6aae43917d587be7f631673d1e1963fbb2ba15e1.tar.bz2 otp-6aae43917d587be7f631673d1e1963fbb2ba15e1.zip |
Fix appending to large files (>4GB) on Windows
Append mode doesn't work for files larger that 4GB on Windows.
Caused by incorrect usage of SetFilePointer in win_efile.c.
Fix uses OVERLAPPED structure to specify write position (EOF).
http://msdn.microsoft.com/en-us/library/aa365747.aspx
Opening file in append mode was also considered, but rejected, because
it might cause backwards incompatibility by limiting applicable
operations on the descriptor.
SetFilePointerEx was not used because it would caused more system calls
than using OVERLAPPED structure.
Diffstat (limited to 'erts')
-rw-r--r-- | erts/emulator/drivers/win32/win_efile.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/erts/emulator/drivers/win32/win_efile.c b/erts/emulator/drivers/win32/win_efile.c index 04bd1139f5..cb186e9fab 100644 --- a/erts/emulator/drivers/win32/win_efile.c +++ b/erts/emulator/drivers/win32/win_efile.c @@ -1082,12 +1082,17 @@ char* buf; /* Buffer to write. */ size_t count; /* Number of bytes to write. */ { DWORD written; /* Bytes written in last operation. */ + OVERLAPPED overlapped; + OVERLAPPED* pOverlapped = NULL; if (flags & EFILE_MODE_APPEND) { - (void) SetFilePointer((HANDLE) fd, 0, NULL, FILE_END); + memset(&overlapped, 0, sizeof(overlapped)); + overlapped.Offset = 0xffffffff; + overlapped.OffsetHigh = 0xffffffff; + pOverlapped = &overlapped; } while (count > 0) { - if (!WriteFile((HANDLE) fd, buf, count, &written, NULL)) + if (!WriteFile((HANDLE) fd, buf, count, &written, pOverlapped)) return set_error(errInfo); buf += written; count -= written; @@ -1107,11 +1112,16 @@ efile_writev(Efile_error* errInfo, /* Where to return error codes */ size_t size) /* Number of bytes to write */ { int cnt; /* Buffers so far written */ + OVERLAPPED overlapped; + OVERLAPPED* pOverlapped = NULL; ASSERT(iovcnt >= 0); if (flags & EFILE_MODE_APPEND) { - (void) SetFilePointer((HANDLE) fd, 0, NULL, FILE_END); + memset(&overlapped, 0, sizeof(overlapped)); + overlapped.Offset = 0xffffffff; + overlapped.OffsetHigh = 0xffffffff; + pOverlapped = &overlapped; } for (cnt = 0; cnt < iovcnt; cnt++) { if (iov[cnt].iov_base && iov[cnt].iov_len > 0) { @@ -1123,7 +1133,7 @@ efile_writev(Efile_error* errInfo, /* Where to return error codes */ iov[cnt].iov_base + p, iov[cnt].iov_len - p, &w, - NULL)) + pOverlapped)) return set_error(errInfo); } } |