From edf05b97f03472def2837ceb2d6bf61a0d0dc248 Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Fri, 16 Mar 2018 22:42:34 +0100 Subject: [PATCH] win, fs: fix uv_fs_unlink for +R -A files uv_fs_unlink would fail for read-only files with Archive attribute cleared. This fixes this issue. PR-URL: https://github.com/libuv/libuv/pull/1774 Reviewed-By: Santiago Gimeno --- src/win/fs.c | 4 +++- test/test-fs.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ test/test-list.h | 6 +++++ 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/win/fs.c b/src/win/fs.c index e454edac9..30b87ac51 100644 --- a/src/win/fs.c +++ b/src/win/fs.c @@ -783,7 +783,9 @@ void fs__unlink(uv_fs_t* req) { /* Remove read-only attribute */ FILE_BASIC_INFORMATION basic = { 0 }; - basic.FileAttributes = info.dwFileAttributes & ~(FILE_ATTRIBUTE_READONLY); + basic.FileAttributes = info.dwFileAttributes + & ~(FILE_ATTRIBUTE_READONLY) + | FILE_ATTRIBUTE_ARCHIVE; status = pNtSetInformationFile(handle, &iosb, diff --git a/test/test-fs.c b/test/test-fs.c index 3318b8664..000a151a6 100644 --- a/test/test-fs.c +++ b/test/test-fs.c @@ -1474,6 +1474,64 @@ TEST_IMPL(fs_unlink_readonly) { return 0; } +#ifdef _WIN32 +TEST_IMPL(fs_unlink_archive_readonly) { + int r; + uv_fs_t req; + uv_file file; + + /* Setup. */ + unlink("test_file"); + + loop = uv_default_loop(); + + r = uv_fs_open(NULL, + &req, + "test_file", + O_RDWR | O_CREAT, + S_IWUSR | S_IRUSR, + NULL); + ASSERT(r >= 0); + ASSERT(req.result >= 0); + file = req.result; + uv_fs_req_cleanup(&req); + + iov = uv_buf_init(test_buf, sizeof(test_buf)); + r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL); + ASSERT(r == sizeof(test_buf)); + ASSERT(req.result == sizeof(test_buf)); + uv_fs_req_cleanup(&req); + + close(file); + + /* Make the file read-only and clear archive flag */ + r = SetFileAttributes("test_file", FILE_ATTRIBUTE_READONLY); + ASSERT(r != 0); + uv_fs_req_cleanup(&req); + + check_permission("test_file", 0400); + + /* Try to unlink the file */ + r = uv_fs_unlink(NULL, &req, "test_file", NULL); + ASSERT(r == 0); + ASSERT(req.result == 0); + uv_fs_req_cleanup(&req); + + /* + * Run the loop just to check we don't have make any extraneous uv_ref() + * calls. This should drop out immediately. + */ + uv_run(loop, UV_RUN_DEFAULT); + + /* Cleanup. */ + uv_fs_chmod(NULL, &req, "test_file", 0600, NULL); + uv_fs_req_cleanup(&req); + unlink("test_file"); + + MAKE_VALGRIND_HAPPY(); + return 0; +} +#endif TEST_IMPL(fs_chown) { int r; diff --git a/test/test-list.h b/test/test-list.h index f7641871a..b89930d70 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -284,6 +284,9 @@ TEST_DECLARE (fs_access) TEST_DECLARE (fs_chmod) TEST_DECLARE (fs_copyfile) TEST_DECLARE (fs_unlink_readonly) +#ifdef _WIN32 +TEST_DECLARE (fs_unlink_archive_readonly) +#endif TEST_DECLARE (fs_chown) TEST_DECLARE (fs_link) TEST_DECLARE (fs_readlink) @@ -815,6 +818,9 @@ TASK_LIST_START TEST_ENTRY (fs_chmod) TEST_ENTRY (fs_copyfile) TEST_ENTRY (fs_unlink_readonly) +#ifdef _WIN32 + TEST_ENTRY (fs_unlink_archive_readonly) +#endif TEST_ENTRY (fs_chown) TEST_ENTRY (fs_utime) TEST_ENTRY (fs_futime)