windows: fix fs_write with nbufs > 1 and offset

When multiple bufs are specified, overlapped needs to be advanced
manually between each write.  Without this, each buf will be written
to the same position (if offset is specified.)

ReadFile() automatically advances, but WriteFile() does not.
This commit is contained in:
Unknown W. Brackets 2014-10-19 20:48:51 -07:00 committed by Saúl Ibarra Corretgé
parent 59658a8de7
commit 6760d51b52
3 changed files with 72 additions and 5 deletions

View File

@ -613,11 +613,6 @@ void fs__write(uv_fs_t* req) {
if (offset != -1) {
memset(&overlapped, 0, sizeof overlapped);
offset_.QuadPart = offset;
overlapped.Offset = offset_.LowPart;
overlapped.OffsetHigh = offset_.HighPart;
overlapped_ptr = &overlapped;
} else {
overlapped_ptr = NULL;
@ -627,6 +622,14 @@ void fs__write(uv_fs_t* req) {
bytes = 0;
do {
DWORD incremental_bytes;
/* WriteFile() does not advance overlapped as ReadFile() does. */
if (offset != -1) {
offset_.QuadPart = offset + bytes;
overlapped.Offset = offset_.LowPart;
overlapped.OffsetHigh = offset_.HighPart;
}
result = WriteFile(handle,
req->bufs[index].base,
req->bufs[index].len,

View File

@ -110,6 +110,7 @@ static uv_fs_t futime_req;
static char buf[32];
static char test_buf[] = "test-buffer\n";
static char test_buf2[] = "second-buffer\n";
static uv_buf_t iov;
static void check_permission(const char* filename, unsigned int mode) {
@ -2164,3 +2165,64 @@ TEST_IMPL(fs_read_file_eof) {
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(fs_write_multiple_bufs) {
uv_buf_t iovs[2];
int r;
/* Setup. */
unlink("test_file");
loop = uv_default_loop();
r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT,
S_IWUSR | S_IRUSR, NULL);
ASSERT(r >= 0);
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
iovs[0] = uv_buf_init(test_buf, sizeof(test_buf));
iovs[1] = uv_buf_init(test_buf2, sizeof(test_buf2));
r = uv_fs_write(loop, &write_req, open_req1.result, iovs, 2, 0, NULL);
ASSERT(r >= 0);
ASSERT(write_req.result >= 0);
uv_fs_req_cleanup(&write_req);
r = uv_fs_close(loop, &close_req, open_req1.result, NULL);
ASSERT(r == 0);
ASSERT(close_req.result == 0);
uv_fs_req_cleanup(&close_req);
r = uv_fs_open(loop, &open_req1, "test_file", O_RDONLY, 0, NULL);
ASSERT(r >= 0);
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
memset(buf, 0, sizeof(buf));
iov = uv_buf_init(buf, sizeof(buf));
r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, NULL);
ASSERT(r >= 0);
ASSERT(read_req.result >= 0);
ASSERT(memcmp(buf, test_buf, sizeof(test_buf)) == 0);
ASSERT(strcmp(buf + sizeof(test_buf), test_buf2) == 0);
uv_fs_req_cleanup(&read_req);
iov = uv_buf_init(buf, sizeof(buf));
r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1,
read_req.result, NULL);
ASSERT(r == 0);
ASSERT(read_req.result == 0);
uv_fs_req_cleanup(&read_req);
r = uv_fs_close(loop, &close_req, open_req1.result, NULL);
ASSERT(r == 0);
ASSERT(close_req.result == 0);
uv_fs_req_cleanup(&close_req);
/* Cleanup */
unlink("test_file");
MAKE_VALGRIND_HAPPY();
return 0;
}

View File

@ -246,6 +246,7 @@ TEST_DECLARE (fs_scandir_empty_dir)
TEST_DECLARE (fs_scandir_file)
TEST_DECLARE (fs_open_dir)
TEST_DECLARE (fs_rename_to_existing_file)
TEST_DECLARE (fs_write_multiple_bufs)
TEST_DECLARE (threadpool_queue_work_simple)
TEST_DECLARE (threadpool_queue_work_einval)
TEST_DECLARE (threadpool_multiple_event_loops)
@ -619,6 +620,7 @@ TASK_LIST_START
TEST_ENTRY (fs_scandir_file)
TEST_ENTRY (fs_open_dir)
TEST_ENTRY (fs_rename_to_existing_file)
TEST_ENTRY (fs_write_multiple_bufs)
TEST_ENTRY (threadpool_queue_work_simple)
TEST_ENTRY (threadpool_queue_work_einval)
TEST_ENTRY (threadpool_multiple_event_loops)