From 00219f29cfdf176b0899542e181e0380c486ed34 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Thu, 25 Nov 2021 10:35:22 +0000 Subject: [PATCH] sys: POSIX rename improvements --- src/sys/file.c | 2 +- src/sys/fileinfo.c | 6 +++++ tst/winfsp-tests/info-test.c | 51 ++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/sys/file.c b/src/sys/file.c index 078ac24f..b33c6a2a 100644 --- a/src/sys/file.c +++ b/src/sys/file.c @@ -1342,7 +1342,7 @@ NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp * "rename" resource exclusively, which disallows new Opens. */ - if (!PosixRename && !CheckingOldName) + if (!CheckingOldName) { /* replaced file cannot be a directory or mapped as an image */ for ( diff --git a/src/sys/fileinfo.c b/src/sys/fileinfo.c index ffcdfff8..25e0c53b 100644 --- a/src/sys/fileinfo.c +++ b/src/sys/fileinfo.c @@ -1691,6 +1691,12 @@ retry: FspFsvolDeviceFileRenameAcquireExclusive(FsvolDeviceObject); FspFileNodeAcquireExclusive(FileNode, Full); + if (FileNode->PosixDelete) + { + Result = STATUS_ACCESS_DENIED; + goto unlock_exit; + } + if (0 == Request) { if (0 != TargetFileNode) diff --git a/tst/winfsp-tests/info-test.c b/tst/winfsp-tests/info-test.c index 7ee768fe..04c9a690 100644 --- a/tst/winfsp-tests/info-test.c +++ b/tst/winfsp-tests/info-test.c @@ -2049,6 +2049,10 @@ static void rename_ex_dotest(ULONG Flags, PWSTR VolPrefix, PWSTR Prefix, ULONG F ULONG FileNameLength; WCHAR FileName[1]; } FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION; + typedef struct + { + ULONG Flags; + } FILE_DISPOSITION_INFORMATION_EX, *PFILE_DISPOSITION_INFORMATION_EX; HANDLE Handle0, Handle1, Handle2; WCHAR File0Path[MAX_PATH]; @@ -2058,6 +2062,7 @@ static void rename_ex_dotest(ULONG Flags, PWSTR VolPrefix, PWSTR Prefix, ULONG F FILE_RENAME_INFORMATION I; UINT8 B[sizeof(FILE_RENAME_INFORMATION) + MAX_PATH * sizeof(WCHAR)]; } RenameInfo; + FILE_DISPOSITION_INFORMATION_EX DispositionInfo; IO_STATUS_BLOCK IoStatus; StringCbPrintfW(File0Path, sizeof File0Path, L"%s%s\\", @@ -2076,6 +2081,8 @@ static void rename_ex_dotest(ULONG Flags, PWSTR VolPrefix, PWSTR Prefix, ULONG F StringCbPrintfW(File2Path, sizeof File2Path, L"%s%s\\file2", Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); + /* File Test */ + Handle0 = CreateFileW(File0Path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); @@ -2127,6 +2134,16 @@ static void rename_ex_dotest(ULONG Flags, PWSTR VolPrefix, PWSTR Prefix, ULONG F OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); ASSERT(INVALID_HANDLE_VALUE != Handle0); + memset(&RenameInfo.I, 0, sizeof RenameInfo.I); + RenameInfo.I.Flags = 1/*FILE_RENAME_REPLACE_IF_EXISTS*/; + RenameInfo.I.FileNameLength = (ULONG)(wcslen(L"file0") * sizeof(WCHAR)); + memcpy(RenameInfo.I.FileName, L"file0", RenameInfo.I.FileNameLength); + IoStatus.Status = NtSetInformationFile( + Handle2, &IoStatus, + &RenameInfo.I, FIELD_OFFSET(FILE_RENAME_INFORMATION, FileName) + RenameInfo.I.FileNameLength, + 10/*FileRenameInformation*/); + ASSERT(STATUS_ACCESS_DENIED == IoStatus.Status); + memset(&RenameInfo.I, 0, sizeof RenameInfo.I); RenameInfo.I.Flags = 3/*FILE_RENAME_REPLACE_IF_EXISTS|FILE_RENAME_POSIX_SEMANTICS*/; RenameInfo.I.FileNameLength = (ULONG)(wcslen(L"file0") * sizeof(WCHAR)); @@ -2165,6 +2182,40 @@ static void rename_ex_dotest(ULONG Flags, PWSTR VolPrefix, PWSTR Prefix, ULONG F Success = DeleteFileW(File0Path); ASSERT(Success); + + /* Deleted File Test */ + + Handle0 = CreateFileW(File0Path, + GENERIC_READ | GENERIC_WRITE | DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, + CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle0); + + Handle1 = CreateFileW(File0Path, + DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, + OPEN_EXISTING, 0, 0); + ASSERT(INVALID_HANDLE_VALUE != Handle1); + + memset(&DispositionInfo, 0, sizeof DispositionInfo); + DispositionInfo.Flags = 3; /* DELETE | POSIX_SEMANTICS */ + IoStatus.Status = NtSetInformationFile( + Handle1, &IoStatus, + &DispositionInfo, sizeof DispositionInfo, + 64/*FileDispositionInformationEx*/); + ASSERT(0 == IoStatus.Status); + + CloseHandle(Handle1); + + memset(&RenameInfo.I, 0, sizeof RenameInfo.I); + RenameInfo.I.Flags = 2/*FILE_RENAME_POSIX_SEMANTICS*/; + RenameInfo.I.FileNameLength = (ULONG)(wcslen(L"file2") * sizeof(WCHAR)); + memcpy(RenameInfo.I.FileName, L"file2", RenameInfo.I.FileNameLength); + IoStatus.Status = NtSetInformationFile( + Handle0, &IoStatus, + &RenameInfo.I, FIELD_OFFSET(FILE_RENAME_INFORMATION, FileName) + RenameInfo.I.FileNameLength, + 65/*FileRenameInformationEx*/); + ASSERT(STATUS_ACCESS_DENIED == IoStatus.Status); + + CloseHandle(Handle0); } memfs_stop(memfs);