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:
parent
59658a8de7
commit
6760d51b52
13
src/win/fs.c
13
src/win/fs.c
@ -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,
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user