diff --git a/src/file.cpp b/src/file.cpp index 8099643fe..e3d14e1d6 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -202,28 +202,42 @@ namespace { } int ret = 0; + int num_waits = num_bufs; for (int i = 0; i < num_bufs; ++i) { DWORD num_read; - if (ReadFile(fd, bufs[i].iov_base, DWORD(bufs[i].iov_len), &num_read, &ol[i]) == FALSE - && GetLastError() != ERROR_IO_PENDING -#ifdef ERROR_CANT_WAIT - && GetLastError() != ERROR_CANT_WAIT -#endif - ) + if (ReadFile(fd, bufs[i].iov_base, DWORD(bufs[i].iov_len), &num_read, &ol[i]) == FALSE) { - ret = -1; - goto done; + DWORD const last_error = GetLastError(); + if (last_error == ERROR_HANDLE_EOF) + { + num_waits = i; + break; + } + else if (last_error != ERROR_IO_PENDING +#ifdef ERROR_CANT_WAIT + && last_error != ERROR_CANT_WAIT +#endif + ) + { + ret = -1; + goto done; + } } } - if (wait_for_multiple_objects(int(h.size()), h.data()) == WAIT_FAILED) + if (num_waits == 0) + { + goto done; + } + + if (wait_for_multiple_objects(num_waits, h.data()) == WAIT_FAILED) { ret = -1; goto done; } - for (auto& o : ol) + for (auto& o : libtorrent::span(ol).first(num_waits)) { if (WaitForSingleObject(o.hEvent, INFINITE) == WAIT_FAILED) { @@ -233,11 +247,15 @@ namespace { DWORD num_read; if (GetOverlappedResult(fd, &o, &num_read, FALSE) == FALSE) { + DWORD const last_error = GetLastError(); + if (last_error != ERROR_HANDLE_EOF) + { #ifdef ERROR_CANT_WAIT - TORRENT_ASSERT(GetLastError() != ERROR_CANT_WAIT); + TORRENT_ASSERT(last_error != ERROR_CANT_WAIT); #endif - ret = -1; - break; + ret = -1; + break; + } } ret += num_read; } diff --git a/test/test_file.cpp b/test/test_file.cpp index fa61fbb82..f10ad7a79 100644 --- a/test/test_file.cpp +++ b/test/test_file.cpp @@ -287,25 +287,48 @@ TORRENT_TEST(file) { error_code ec; file f; - TEST_CHECK(f.open("test_file", open_mode::read_write, ec)); + std::string test_file_name = "test_file"; + TEST_CHECK(f.open(test_file_name, open_mode::read_write, ec)); if (ec) std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str()); TEST_EQUAL(ec, error_code()); if (ec) std::printf("%s\n", ec.message().c_str()); char test[] = "test"; - iovec_t b = {test, 4}; - TEST_EQUAL(f.writev(0, b, ec), 4); + size_t const test_word_size = sizeof(test) - 1; + iovec_t b = {test, test_word_size}; + TEST_EQUAL(f.writev(0, b, ec), test_word_size); if (ec) std::printf("writev failed: [%s] %s\n", ec.category().name(), ec.message().c_str()); TEST_CHECK(!ec); - char test_buf[5] = {0}; - b = { test_buf, 4 }; - TEST_EQUAL(f.readv(0, b, ec), 4); + char test_buf[test_word_size + 1] = {0}; + b = { test_buf, test_word_size }; + TEST_EQUAL(f.readv(0, b, ec), test_word_size); if (ec) std::printf("readv failed: [%s] %s\n", ec.category().name(), ec.message().c_str()); TEST_EQUAL(ec, error_code()); TEST_CHECK(test_buf == "test"_sv); f.close(); + + TEST_CHECK(f.open(test_file_name, open_mode::read_only, ec)); + if (ec) + std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str()); + TEST_EQUAL(ec, error_code()); + if (ec) std::printf("%s\n", ec.message().c_str()); + + char test_buf2[test_word_size + 1] = {0}; + std::memset(test_buf, 0, sizeof(test_buf)); + iovec_t two_buffers[2] { + {test_buf, test_word_size}, + {test_buf2, test_word_size} + }; + + TEST_EQUAL(f.readv(0, two_buffers, ec), test_word_size); + if (ec) + std::printf("readv failed: [%s] %s\n", ec.category().name(), ec.message().c_str()); + TEST_EQUAL(ec, error_code()); + TEST_CHECK(test_buf == "test"_sv); + f.close(); + } TORRENT_TEST(hard_link)