From: naruse@... Date: 2015-05-23T15:23:47+00:00 Subject: [ruby-dev:48989] [Ruby trunk - Bug #11172] [Assigned] Windowsでmode: ab+の時に開いたファイルの内容が読めない Issue #11172 has been reported by Yui NARUSE. ---------------------------------------- Bug #11172: Windowsでmode: ab+の時に開いたファイルの内容が読めない https://bugs.ruby-lang.org/issues/11172 * Author: Yui NARUSE * Status: Assigned * Priority: Normal * Assignee: Usaku NAKAMURA * ruby -v: * Backport: 2.0.0: REQUIRED, 2.1: REQUIRED, 2.2: REQUIRED ---------------------------------------- Windowsでopen("hoge.txt", "ab+")すると、開いたファイルの既存の内容が読めません。 File::APPEND|File::CREAT|File::RDWR|File::BINARYでも同様です。 Unixでは読める上に、a+の時、つまり_openを使う場合も読めるので、意図しない挙動でしょう。 diff --git a/win32/win32.c b/win32/win32.c index 55e0d2e..57d9df4 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -6476,12 +6476,16 @@ rb_w32_close(int fd) } static int -setup_overlapped(OVERLAPPED *ol, int fd) +setup_overlapped(OVERLAPPED *ol, int fd, int iswrite) { memset(ol, 0, sizeof(*ol)); if (!(_osfile(fd) & (FDEV | FPIPE))) { LONG high = 0; - DWORD method = _osfile(fd) & FAPPEND ? FILE_END : FILE_CURRENT; + /* On mode:a, it can write only FILE_END. + * On mode:a+, though it can write only FILE_END, + * it can read from everywhere. + */ + DWORD method = ((_osfile(fd) & FAPPEND) && iswrite) ? 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) @@ -6578,7 +6582,7 @@ rb_w32_read(int fd, void *buf, size_t size) /* if have cancel_io, use Overlapped I/O */ if (cancel_io) { - if (setup_overlapped(&ol, fd)) { + if (setup_overlapped(&ol, fd, FALSE)) { rb_acrt_lowio_unlock_fh(fd); return -1; } @@ -6708,7 +6712,7 @@ rb_w32_write(int fd, const void *buf, size_t size) /* if have cancel_io, use Overlapped I/O */ if (cancel_io) { - if (setup_overlapped(&ol, fd)) { + if (setup_overlapped(&ol, fd, TRUE)) { rb_acrt_lowio_unlock_fh(fd); return -1; } -- https://bugs.ruby-lang.org/