merge revision(s) 40887,40888,40894,40896: [Backport #8431]

* win32/win32.c (setup_overlapped, finish_overlapped): extract from
	  rb_w32_read() and rb_w32_write().

	* win32/win32.c (setup_overlapped): check the error code in addition
	  to the result of SetFilePointer() to determine if an error occurred,
	  because INVALID_SET_FILE_POINTER is a valid value.
	  [ruby-core:55098] [Bug #8431]


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_0_0@41056 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nagachika 2013-06-03 15:49:06 +00:00
parent e6ae0db36e
commit e377d3bb75
4 changed files with 84 additions and 57 deletions

View file

@ -5867,6 +5867,49 @@ rb_w32_close(int fd)
return 0;
}
static int
setup_overlapped(OVERLAPPED *ol, int fd)
{
memset(ol, 0, sizeof(*ol));
if (!(_osfile(fd) & (FDEV | FPIPE))) {
LONG high = 0;
DWORD method = _osfile(fd) & FAPPEND ? FILE_END : FILE_CURRENT;
DWORD low = SetFilePointer((HANDLE)_osfhnd(fd), 0, &high, method);
#ifndef INVALID_SET_FILE_POINTER
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
#endif
if (low == INVALID_SET_FILE_POINTER) {
DWORD err = GetLastError();
if (err != NO_ERROR) {
errno = map_errno(err);
return -1;
}
}
ol->Offset = low;
ol->OffsetHigh = high;
}
ol->hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
if (!ol->hEvent) {
errno = map_errno(GetLastError());
return -1;
}
return 0;
}
static void
finish_overlapped(OVERLAPPED *ol, int fd, DWORD size)
{
CloseHandle(ol->hEvent);
if (!(_osfile(fd) & (FDEV | FPIPE))) {
LONG high = ol->OffsetHigh;
DWORD low = ol->Offset + size;
if (low < ol->Offset)
++high;
SetFilePointer((HANDLE)_osfhnd(fd), low, &high, FILE_BEGIN);
}
}
#undef read
/* License: Ruby's */
ssize_t
@ -5927,25 +5970,7 @@ rb_w32_read(int fd, void *buf, size_t size)
/* if have cancel_io, use Overlapped I/O */
if (cancel_io) {
memset(&ol, 0, sizeof(ol));
if (!(_osfile(fd) & (FDEV | FPIPE))) {
LONG high = 0;
DWORD low = SetFilePointer((HANDLE)_osfhnd(fd), 0, &high,
FILE_CURRENT);
#ifndef INVALID_SET_FILE_POINTER
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
#endif
if (low == INVALID_SET_FILE_POINTER) {
errno = map_errno(GetLastError());
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
return -1;
}
ol.Offset = low;
ol.OffsetHigh = high;
}
ol.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
if (!ol.hEvent) {
errno = map_errno(GetLastError());
if (setup_overlapped(&ol, fd)) {
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
return -1;
}
@ -6003,15 +6028,7 @@ rb_w32_read(int fd, void *buf, size_t size)
}
if (pol) {
CloseHandle(ol.hEvent);
if (!(_osfile(fd) & (FDEV | FPIPE))) {
LONG high = ol.OffsetHigh;
DWORD low = ol.Offset + read;
if (low < ol.Offset)
++high;
SetFilePointer((HANDLE)_osfhnd(fd), low, &high, FILE_BEGIN);
}
finish_overlapped(&ol, fd, read);
}
ret += read;
@ -6071,25 +6088,7 @@ rb_w32_write(int fd, const void *buf, size_t size)
/* if have cancel_io, use Overlapped I/O */
if (cancel_io) {
memset(&ol, 0, sizeof(ol));
if (!(_osfile(fd) & (FDEV | FPIPE))) {
LONG high = 0;
DWORD method = _osfile(fd) & FAPPEND ? FILE_END : FILE_CURRENT;
DWORD low = SetFilePointer((HANDLE)_osfhnd(fd), 0, &high, method);
#ifndef INVALID_SET_FILE_POINTER
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
#endif
if (low == INVALID_SET_FILE_POINTER) {
errno = map_errno(GetLastError());
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
return -1;
}
ol.Offset = low;
ol.OffsetHigh = high;
}
ol.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
if (!ol.hEvent) {
errno = map_errno(GetLastError());
if (setup_overlapped(&ol, fd)) {
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
return -1;
}
@ -6135,15 +6134,7 @@ rb_w32_write(int fd, const void *buf, size_t size)
}
if (pol) {
CloseHandle(ol.hEvent);
if (!(_osfile(fd) & (FDEV | FPIPE))) {
LONG high = ol.OffsetHigh;
DWORD low = ol.Offset + written;
if (low < ol.Offset)
++high;
SetFilePointer((HANDLE)_osfhnd(fd), low, &high, FILE_BEGIN);
}
finish_overlapped(&ol, fd, written);
}
ret += written;