windows: improve uv_fs_unlink
* It's now more efficient, the file is not opened twice. * It no longer allows deletion of non-symlink directory reparse points.
This commit is contained in:
parent
7edc29a414
commit
7f6b86c687
81
src/win/fs.c
81
src/win/fs.c
@ -338,17 +338,20 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute the length of the target. */
|
/* If needed, compute the length of the target. */
|
||||||
target_len = WideCharToMultiByte(CP_UTF8,
|
if (target_ptr != NULL || target_len_ptr != NULL) {
|
||||||
0,
|
/* Compute the length of the target. */
|
||||||
w_target,
|
target_len = WideCharToMultiByte(CP_UTF8,
|
||||||
w_target_len,
|
0,
|
||||||
NULL,
|
w_target,
|
||||||
0,
|
w_target_len,
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
0,
|
||||||
if (target_len == 0) {
|
NULL,
|
||||||
return -1;
|
NULL);
|
||||||
|
if (target_len == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If requested, allocate memory and convert to UTF8. */
|
/* If requested, allocate memory and convert to UTF8. */
|
||||||
@ -615,14 +618,15 @@ void fs__rmdir(uv_fs_t* req) {
|
|||||||
|
|
||||||
void fs__unlink(uv_fs_t* req) {
|
void fs__unlink(uv_fs_t* req) {
|
||||||
const WCHAR* pathw = req->pathw;
|
const WCHAR* pathw = req->pathw;
|
||||||
int result;
|
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
BY_HANDLE_FILE_INFORMATION info;
|
BY_HANDLE_FILE_INFORMATION info;
|
||||||
int is_dir_symlink;
|
FILE_DISPOSITION_INFORMATION disposition;
|
||||||
|
IO_STATUS_BLOCK iosb;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
handle = CreateFileW(pathw,
|
handle = CreateFileW(pathw,
|
||||||
0,
|
FILE_READ_ATTRIBUTES | DELETE,
|
||||||
0,
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
NULL,
|
NULL,
|
||||||
OPEN_EXISTING,
|
OPEN_EXISTING,
|
||||||
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
|
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
|
||||||
@ -639,19 +643,44 @@ void fs__unlink(uv_fs_t* req) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_dir_symlink = (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||||
(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT);
|
/* Do not allow deletion of directories, unless it is a symlink. When */
|
||||||
|
/* the path refers to a non-symlink directory, report EPERM as mandated */
|
||||||
|
/* by POSIX.1. */
|
||||||
|
|
||||||
|
/* Check if it is a reparse point. If it's not, it's a normal directory. */
|
||||||
|
if (!(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
|
||||||
|
SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED);
|
||||||
|
CloseHandle(handle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read the reparse point and check if it is a valid symlink. */
|
||||||
|
/* If not, don't unlink. */
|
||||||
|
if (fs__readlink_handle(handle, NULL, NULL) < 0) {
|
||||||
|
DWORD error = GetLastError();
|
||||||
|
if (error == ERROR_SYMLINK_NOT_SUPPORTED)
|
||||||
|
error = ERROR_ACCESS_DENIED;
|
||||||
|
SET_REQ_WIN32_ERROR(req, error);
|
||||||
|
CloseHandle(handle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to set the delete flag. */
|
||||||
|
disposition.DeleteFile = TRUE;
|
||||||
|
status = pNtSetInformationFile(handle,
|
||||||
|
&iosb,
|
||||||
|
&disposition,
|
||||||
|
sizeof disposition,
|
||||||
|
FileDispositionInformation);
|
||||||
|
if (NT_SUCCESS(status)) {
|
||||||
|
SET_REQ_SUCCESS(req);
|
||||||
|
} else {
|
||||||
|
SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));
|
||||||
|
}
|
||||||
|
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
|
|
||||||
/* Todo: very inefficient; fix this. */
|
|
||||||
if (is_dir_symlink) {
|
|
||||||
int result = _wrmdir(req->pathw);
|
|
||||||
SET_REQ_RESULT(req, result);
|
|
||||||
} else {
|
|
||||||
result = _wunlink(pathw);
|
|
||||||
SET_REQ_RESULT(req, result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -4132,6 +4132,10 @@ typedef struct _FILE_BASIC_INFORMATION {
|
|||||||
DWORD FileAttributes;
|
DWORD FileAttributes;
|
||||||
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
|
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
|
||||||
|
|
||||||
|
typedef struct _FILE_DISPOSITION_INFORMATION {
|
||||||
|
BOOLEAN DeleteFile;
|
||||||
|
} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION;
|
||||||
|
|
||||||
typedef struct _FILE_MODE_INFORMATION {
|
typedef struct _FILE_MODE_INFORMATION {
|
||||||
ULONG Mode;
|
ULONG Mode;
|
||||||
} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION;
|
} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user