win: map UV_FS_O_EXLOCK to a share mode of 0

This is necessary to enable writing past the MBR of a raw block device.

Fixes: https://github.com/libuv/libuv/issues/1605
PR-URL: https://github.com/libuv/libuv/pull/1613
Reviewed-By: Bartosz Sosnowski <bartosz@janeasystems.com>
This commit is contained in:
Joran Dirk Greef 2017-11-01 13:18:39 +02:00 committed by Bartosz Sosnowski
parent 7ef23d9e85
commit 1c4de1916e
5 changed files with 78 additions and 6 deletions

View File

@ -409,7 +409,9 @@ File open constants
Atomically obtain an exclusive lock.
.. note::
`UV_FS_O_EXLOCK` is only supported on macOS.
`UV_FS_O_EXLOCK` is only supported on macOS and Windows.
.. versionchanged:: 1.17.0 support is added for Windows.
.. c:macro:: UV_FS_O_NOATIME

View File

@ -664,13 +664,13 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
#define UV_FS_O_WRONLY _O_WRONLY
/* fs open() flags supported on other platforms (or mapped on this platform): */
#define UV_FS_O_DIRECT 0x2000000 /* FILE_FLAG_NO_BUFFERING */
#define UV_FS_O_DIRECT 0x02000000 /* FILE_FLAG_NO_BUFFERING */
#define UV_FS_O_DIRECTORY 0
#define UV_FS_O_DSYNC 0x4000000 /* FILE_FLAG_WRITE_THROUGH */
#define UV_FS_O_EXLOCK 0
#define UV_FS_O_DSYNC 0x04000000 /* FILE_FLAG_WRITE_THROUGH */
#define UV_FS_O_EXLOCK 0x10000000 /* EXCLUSIVE SHARING MODE */
#define UV_FS_O_NOATIME 0
#define UV_FS_O_NOCTTY 0
#define UV_FS_O_NOFOLLOW 0
#define UV_FS_O_NONBLOCK 0
#define UV_FS_O_SYMLINK 0
#define UV_FS_O_SYNC 0x8000000 /* FILE_FLAG_WRITE_THROUGH */
#define UV_FS_O_SYNC 0x08000000 /* FILE_FLAG_WRITE_THROUGH */

View File

@ -439,8 +439,15 @@ void fs__open(uv_fs_t* req) {
* does. We indiscriminately use all the sharing modes, to match
* UNIX semantics. In particular, this ensures that the file can
* be deleted even whilst it's open, fixing issue #1449.
* We still support exclusive sharing mode, since it is necessary
* for opening raw block devices, otherwise Windows will prevent
* any attempt to write past the master boot record.
*/
share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
if (flags & UV_FS_O_EXLOCK) {
share = 0;
} else {
share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
}
switch (flags & (UV_FS_O_CREAT | UV_FS_O_EXCL | UV_FS_O_TRUNC)) {
case 0:

View File

@ -3061,3 +3061,60 @@ TEST_IMPL(fs_null_req) {
return 0;
}
#ifdef _WIN32
TEST_IMPL(fs_exclusive_sharing_mode) {
int r;
/* Setup. */
unlink("test_file");
ASSERT(UV_FS_O_EXLOCK > 0);
r = uv_fs_open(NULL,
&open_req1,
"test_file",
O_RDWR | O_CREAT | UV_FS_O_EXLOCK,
S_IWUSR | S_IRUSR,
NULL);
ASSERT(r >= 0);
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
r = uv_fs_open(NULL,
&open_req2,
"test_file",
O_RDONLY | UV_FS_O_EXLOCK,
S_IWUSR | S_IRUSR,
NULL);
ASSERT(r < 0);
ASSERT(open_req2.result < 0);
uv_fs_req_cleanup(&open_req2);
r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
ASSERT(r == 0);
ASSERT(close_req.result == 0);
uv_fs_req_cleanup(&close_req);
r = uv_fs_open(NULL,
&open_req2,
"test_file",
O_RDONLY | UV_FS_O_EXLOCK,
S_IWUSR | S_IRUSR,
NULL);
ASSERT(r >= 0);
ASSERT(open_req2.result >= 0);
uv_fs_req_cleanup(&open_req2);
r = uv_fs_close(NULL, &close_req, open_req2.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;
}
#endif

View File

@ -321,6 +321,9 @@ 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 (fs_null_req)
#ifdef _WIN32
TEST_DECLARE (fs_exclusive_sharing_mode)
#endif
TEST_DECLARE (threadpool_queue_work_simple)
TEST_DECLARE (threadpool_queue_work_einval)
TEST_DECLARE (threadpool_multiple_event_loops)
@ -832,6 +835,9 @@ TASK_LIST_START
TEST_ENTRY (fs_read_write_null_arguments)
TEST_ENTRY (fs_file_pos_after_op_with_offset)
TEST_ENTRY (fs_null_req)
#ifdef _WIN32
TEST_ENTRY (fs_exclusive_sharing_mode)
#endif
TEST_ENTRY (get_osfhandle_valid_handle)
TEST_ENTRY (threadpool_queue_work_simple)
TEST_ENTRY (threadpool_queue_work_einval)