win: restore file pos after positional read/write

File read or write from specified position will move file pointer on
Windows but not on POSIX. This makes Windows behave as other
supported platforms.

Ref: https://github.com/nodejs/node/issues/9671

PR-URL: https://github.com/libuv/libuv/pull/1357
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
This commit is contained in:
Bartosz Sosnowski 2017-06-21 12:47:00 +02:00
parent 57f4180cf3
commit 0bd8f5bf36
3 changed files with 66 additions and 0 deletions

View File

@ -556,9 +556,14 @@ void fs__read(uv_fs_t* req) {
DWORD error;
int result;
unsigned int index;
LARGE_INTEGER original_position;
LARGE_INTEGER zero_offset;
int restore_position;
VERIFY_FD(fd, req);
zero_offset.QuadPart = 0;
restore_position = 0;
handle = uv__get_osfhandle(fd);
if (handle == INVALID_HANDLE_VALUE) {
@ -569,6 +574,10 @@ void fs__read(uv_fs_t* req) {
if (offset != -1) {
memset(&overlapped, 0, sizeof overlapped);
overlapped_ptr = &overlapped;
if (SetFilePointerEx(handle, zero_offset, &original_position,
FILE_CURRENT)) {
restore_position = 1;
}
} else {
overlapped_ptr = NULL;
}
@ -593,6 +602,9 @@ void fs__read(uv_fs_t* req) {
++index;
} while (result && index < req->fs.info.nbufs);
if (restore_position)
SetFilePointerEx(handle, original_position, NULL, FILE_BEGIN);
if (result || bytes > 0) {
SET_REQ_RESULT(req, bytes);
} else {
@ -615,9 +627,14 @@ void fs__write(uv_fs_t* req) {
DWORD bytes;
int result;
unsigned int index;
LARGE_INTEGER original_position;
LARGE_INTEGER zero_offset;
int restore_position;
VERIFY_FD(fd, req);
zero_offset.QuadPart = 0;
restore_position = 0;
handle = uv__get_osfhandle(fd);
if (handle == INVALID_HANDLE_VALUE) {
SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
@ -627,6 +644,10 @@ void fs__write(uv_fs_t* req) {
if (offset != -1) {
memset(&overlapped, 0, sizeof overlapped);
overlapped_ptr = &overlapped;
if (SetFilePointerEx(handle, zero_offset, &original_position,
FILE_CURRENT)) {
restore_position = 1;
}
} else {
overlapped_ptr = NULL;
}
@ -651,6 +672,9 @@ void fs__write(uv_fs_t* req) {
++index;
} while (result && index < req->fs.info.nbufs);
if (restore_position)
SetFilePointerEx(handle, original_position, NULL, FILE_BEGIN);
if (result || bytes > 0) {
SET_REQ_RESULT(req, bytes);
} else {

View File

@ -2804,3 +2804,43 @@ TEST_IMPL(get_osfhandle_valid_handle) {
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(fs_file_pos_after_op_with_offset) {
int r;
/* Setup. */
unlink("test_file");
loop = uv_default_loop();
r = uv_fs_open(loop,
&open_req1,
"test_file",
O_RDWR | O_CREAT,
S_IWUSR | S_IRUSR,
NULL);
ASSERT(r > 0);
uv_fs_req_cleanup(&open_req1);
iov = uv_buf_init(test_buf, sizeof(test_buf));
r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, 0, NULL);
ASSERT(r == sizeof(test_buf));
ASSERT(lseek(open_req1.result, 0, SEEK_CUR) == 0);
uv_fs_req_cleanup(&write_req);
iov = uv_buf_init(buf, sizeof(buf));
r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, 0, NULL);
ASSERT(r == sizeof(test_buf));
ASSERT(strcmp(buf, test_buf) == 0);
ASSERT(lseek(open_req1.result, 0, SEEK_CUR) == 0);
uv_fs_req_cleanup(&read_req);
r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
ASSERT(r == 0);
uv_fs_req_cleanup(&close_req);
/* Cleanup */
unlink("test_file");
MAKE_VALGRIND_HAPPY();
return 0;
}

View File

@ -308,6 +308,7 @@ TEST_DECLARE (fs_read_write_null_arguments)
TEST_DECLARE (get_osfhandle_valid_handle)
TEST_DECLARE (fs_write_alotof_bufs)
TEST_DECLARE (fs_write_alotof_bufs_with_offset)
TEST_DECLARE (fs_file_pos_after_op_with_offset)
TEST_DECLARE (threadpool_queue_work_simple)
TEST_DECLARE (threadpool_queue_work_einval)
TEST_DECLARE (threadpool_multiple_event_loops)
@ -793,6 +794,7 @@ TASK_LIST_START
TEST_ENTRY (fs_write_alotof_bufs)
TEST_ENTRY (fs_write_alotof_bufs_with_offset)
TEST_ENTRY (fs_read_write_null_arguments)
TEST_ENTRY (fs_file_pos_after_op_with_offset)
TEST_ENTRY (get_osfhandle_valid_handle)
TEST_ENTRY (threadpool_queue_work_simple)
TEST_ENTRY (threadpool_queue_work_einval)