aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuhani Rankimies <[email protected]>2010-09-30 21:08:54 +0300
committerJuhani Rankimies <[email protected]>2010-09-30 21:08:54 +0300
commit6aae43917d587be7f631673d1e1963fbb2ba15e1 (patch)
tree9ac81e95ca64357e609832bf519667aafe02b3b9
parent8e9a96141120b43b4edf05705a2a261916a902a5 (diff)
downloadotp-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.
-rw-r--r--erts/emulator/drivers/win32/win_efile.c18
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);
}
}