Skip to content

Commit c71d154

Browse files
committed
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: nodejs/node#9671
1 parent 57f4180 commit c71d154

File tree

3 files changed

+66
-0
lines changed

3 files changed

+66
-0
lines changed

src/win/fs.c

+24
Original file line numberDiff line numberDiff line change
@@ -556,9 +556,14 @@ void fs__read(uv_fs_t* req) {
556556
DWORD error;
557557
int result;
558558
unsigned int index;
559+
LARGE_INTEGER original_position;
560+
LARGE_INTEGER zero_offset;
561+
int restore_position;
559562

560563
VERIFY_FD(fd, req);
561564

565+
zero_offset.QuadPart = 0;
566+
restore_position = 0;
562567
handle = uv__get_osfhandle(fd);
563568

564569
if (handle == INVALID_HANDLE_VALUE) {
@@ -569,6 +574,10 @@ void fs__read(uv_fs_t* req) {
569574
if (offset != -1) {
570575
memset(&overlapped, 0, sizeof overlapped);
571576
overlapped_ptr = &overlapped;
577+
if (SetFilePointerEx(handle, zero_offset, &original_position,
578+
FILE_CURRENT)) {
579+
restore_position = 1;
580+
}
572581
} else {
573582
overlapped_ptr = NULL;
574583
}
@@ -593,6 +602,9 @@ void fs__read(uv_fs_t* req) {
593602
++index;
594603
} while (result && index < req->fs.info.nbufs);
595604

605+
if (restore_position)
606+
SetFilePointerEx(handle, original_position, NULL, FILE_BEGIN);
607+
596608
if (result || bytes > 0) {
597609
SET_REQ_RESULT(req, bytes);
598610
} else {
@@ -615,9 +627,14 @@ void fs__write(uv_fs_t* req) {
615627
DWORD bytes;
616628
int result;
617629
unsigned int index;
630+
LARGE_INTEGER original_position;
631+
LARGE_INTEGER zero_offset;
632+
int restore_position;
618633

619634
VERIFY_FD(fd, req);
620635

636+
zero_offset.QuadPart = 0;
637+
restore_position = 0;
621638
handle = uv__get_osfhandle(fd);
622639
if (handle == INVALID_HANDLE_VALUE) {
623640
SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
@@ -627,6 +644,10 @@ void fs__write(uv_fs_t* req) {
627644
if (offset != -1) {
628645
memset(&overlapped, 0, sizeof overlapped);
629646
overlapped_ptr = &overlapped;
647+
if (SetFilePointerEx(handle, zero_offset, &original_position,
648+
FILE_CURRENT)) {
649+
restore_position = 1;
650+
}
630651
} else {
631652
overlapped_ptr = NULL;
632653
}
@@ -651,6 +672,9 @@ void fs__write(uv_fs_t* req) {
651672
++index;
652673
} while (result && index < req->fs.info.nbufs);
653674

675+
if (restore_position)
676+
SetFilePointerEx(handle, original_position, NULL, FILE_BEGIN);
677+
654678
if (result || bytes > 0) {
655679
SET_REQ_RESULT(req, bytes);
656680
} else {

test/test-fs.c

+40
Original file line numberDiff line numberDiff line change
@@ -2804,3 +2804,43 @@ TEST_IMPL(get_osfhandle_valid_handle) {
28042804
MAKE_VALGRIND_HAPPY();
28052805
return 0;
28062806
}
2807+
2808+
TEST_IMPL(fs_file_pos_after_op_with_offset) {
2809+
int r;
2810+
2811+
/* Setup. */
2812+
unlink("test_file");
2813+
loop = uv_default_loop();
2814+
2815+
r = uv_fs_open(loop,
2816+
&open_req1,
2817+
"test_file",
2818+
O_RDWR | O_CREAT,
2819+
S_IWUSR | S_IRUSR,
2820+
NULL);
2821+
ASSERT(r >= 0);
2822+
uv_fs_req_cleanup(&open_req1);
2823+
2824+
iov = uv_buf_init(test_buf, sizeof(test_buf));
2825+
r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, 0, NULL);
2826+
ASSERT(r >= 0);
2827+
ASSERT(lseek(open_req1.result, 0, SEEK_CUR) == 0);
2828+
uv_fs_req_cleanup(&write_req);
2829+
2830+
iov = uv_buf_init(buf, sizeof(buf));
2831+
r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, 0, NULL);
2832+
ASSERT(r >= 0);
2833+
ASSERT(strcmp(buf, test_buf) == 0);
2834+
ASSERT(lseek(open_req1.result, 0, SEEK_CUR) == 0);
2835+
uv_fs_req_cleanup(&read_req);
2836+
2837+
r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
2838+
ASSERT(r == 0);
2839+
uv_fs_req_cleanup(&close_req);
2840+
2841+
/* Cleanup */
2842+
unlink("test_file");
2843+
2844+
MAKE_VALGRIND_HAPPY();
2845+
return 0;
2846+
}

test/test-list.h

+2
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ TEST_DECLARE (fs_read_write_null_arguments)
308308
TEST_DECLARE (get_osfhandle_valid_handle)
309309
TEST_DECLARE (fs_write_alotof_bufs)
310310
TEST_DECLARE (fs_write_alotof_bufs_with_offset)
311+
TEST_DECLARE (fs_file_pos_after_op_with_offset)
311312
TEST_DECLARE (threadpool_queue_work_simple)
312313
TEST_DECLARE (threadpool_queue_work_einval)
313314
TEST_DECLARE (threadpool_multiple_event_loops)
@@ -793,6 +794,7 @@ TASK_LIST_START
793794
TEST_ENTRY (fs_write_alotof_bufs)
794795
TEST_ENTRY (fs_write_alotof_bufs_with_offset)
795796
TEST_ENTRY (fs_read_write_null_arguments)
797+
TEST_ENTRY (fs_file_pos_after_op_with_offset)
796798
TEST_ENTRY (get_osfhandle_valid_handle)
797799
TEST_ENTRY (threadpool_queue_work_simple)
798800
TEST_ENTRY (threadpool_queue_work_einval)

0 commit comments

Comments
 (0)