From ff08d63a82d4778fb45d196cd9ff8273d5f39e58 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Tue, 13 Dec 2016 14:37:44 -0800 Subject: [PATCH] sys,dll: Overwrite: named streams are now removed as per NTFS --- src/dll/fsop.c | 2 ++ src/dll/fuse/fuse_intf.c | 2 ++ src/sys/create.c | 2 ++ src/sys/driver.h | 1 + src/sys/file.c | 41 ++++++++++++++++++++++++++++++++++++++++ tst/memfs/memfs.cpp | 12 ++++++++++++ 6 files changed, 60 insertions(+) diff --git a/src/dll/fsop.c b/src/dll/fsop.c index b47924e3..5ff6ad0d 100644 --- a/src/dll/fsop.c +++ b/src/dll/fsop.c @@ -48,6 +48,7 @@ FSP_API NTSTATUS FspFileSystemOpEnter(FSP_FILE_SYSTEM *FileSystem, case FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE: if ((FspFsctlTransactCreateKind == Request->Kind && FILE_OPEN != ((Request->Req.Create.CreateOptions >> 24) & 0xff)) || + FspFsctlTransactOverwriteKind == Request->Kind || (FspFsctlTransactCleanupKind == Request->Kind && Request->Req.Cleanup.Delete) || (FspFsctlTransactSetInformationKind == Request->Kind && @@ -86,6 +87,7 @@ FSP_API NTSTATUS FspFileSystemOpLeave(FSP_FILE_SYSTEM *FileSystem, case FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE: if ((FspFsctlTransactCreateKind == Request->Kind && FILE_OPEN != ((Request->Req.Create.CreateOptions >> 24) & 0xff)) || + FspFsctlTransactOverwriteKind == Request->Kind || (FspFsctlTransactCleanupKind == Request->Kind && Request->Req.Cleanup.Delete) || (FspFsctlTransactSetInformationKind == Request->Kind && diff --git a/src/dll/fuse/fuse_intf.c b/src/dll/fuse/fuse_intf.c index edeafbf9..deb0f41d 100644 --- a/src/dll/fuse/fuse_intf.c +++ b/src/dll/fuse/fuse_intf.c @@ -26,6 +26,7 @@ VOID fsp_fuse_op_enter_lock(FSP_FILE_SYSTEM *FileSystem, case FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE: if ((FspFsctlTransactCreateKind == Request->Kind && FILE_OPEN != ((Request->Req.Create.CreateOptions >> 24) & 0xff)) || + FspFsctlTransactOverwriteKind == Request->Kind || (FspFsctlTransactCleanupKind == Request->Kind && Request->Req.Cleanup.Delete) || (FspFsctlTransactSetInformationKind == Request->Kind && @@ -69,6 +70,7 @@ VOID fsp_fuse_op_leave_unlock(FSP_FILE_SYSTEM *FileSystem, case FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE: if ((FspFsctlTransactCreateKind == Request->Kind && FILE_OPEN != ((Request->Req.Create.CreateOptions >> 24) & 0xff)) || + FspFsctlTransactOverwriteKind == Request->Kind || (FspFsctlTransactCleanupKind == Request->Kind && Request->Req.Cleanup.Delete) || (FspFsctlTransactSetInformationKind == Request->Kind && diff --git a/src/sys/create.c b/src/sys/create.c index 41f5b63a..08f2e077 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -996,6 +996,8 @@ NTSTATUS FspFsvolCreateComplete( } /* file was successfully overwritten/superseded */ + if (0 == FileNode->MainFileNode) + FspFileNodeOverwriteStreams(FileNode); FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.Overwrite.FileInfo); FspFileNodeNotifyChange(FileNode, FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE, diff --git a/src/sys/driver.h b/src/sys/driver.h index 75098c4b..fce15d4e 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -1264,6 +1264,7 @@ VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, BOOLEAN HandleCleanup); /* TRUE to decrement handle count */ NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode, UINT64 FlushOffset64, ULONG FlushLength, BOOLEAN FlushAndPurge); +VOID FspFileNodeOverwriteStreams(FSP_FILE_NODE *FileNode); NTSTATUS FspFileNodeCheckBatchOplocksOnAllStreams( PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp, diff --git a/src/sys/file.c b/src/sys/file.c index 12ee5429..f2055a84 100644 --- a/src/sys/file.c +++ b/src/sys/file.c @@ -42,6 +42,7 @@ VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, BOOLEAN HandleCleanup); /* TRUE to decrement handle count */ NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode, UINT64 FlushOffset64, ULONG FlushLength, BOOLEAN FlushAndPurge); +VOID FspFileNodeOverwriteStreams(FSP_FILE_NODE *FileNode); NTSTATUS FspFileNodeCheckBatchOplocksOnAllStreams( PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp, @@ -113,6 +114,7 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp); #pragma alloc_text(PAGE, FspFileNodeCleanupComplete) #pragma alloc_text(PAGE, FspFileNodeClose) #pragma alloc_text(PAGE, FspFileNodeFlushAndPurgeCache) +#pragma alloc_text(PAGE, FspFileNodeOverwriteStreams) #pragma alloc_text(PAGE, FspFileNodeCheckBatchOplocksOnAllStreams) #pragma alloc_text(PAGE, FspFileNodeRenameCheck) #pragma alloc_text(PAGE, FspFileNodeRename) @@ -911,6 +913,45 @@ NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode, FspFree(DescendantFileNodes); \ ((VOID)0) +VOID FspFileNodeOverwriteStreams(FSP_FILE_NODE *FileNode) +{ + /* + * Called during Create processing. The device rename resource has been acquired shared. + * No concurrent renames are allowed. + */ + + PAGED_CODE(); + + ASSERT(0 == FileNode->MainFileNode); + + PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject; + USHORT FileNameLength = FileNode->FileName.Length; + + FspFsvolDeviceLockContextTable(FsvolDeviceObject); + + GATHER_DESCENDANTS(&FileNode->FileName, FALSE, + if (DescendantFileNode->FileName.Length > FileNameLength && + L'\\' == DescendantFileNode->FileName.Buffer[FileNameLength / sizeof(WCHAR)]) + break; + if (FileNode == DescendantFileNode || 0 >= DescendantFileNode->HandleCount) + continue; + ); + + /* mark any open named streams as DeletePending */ + for ( + DescendantFileNodeIndex = 0; + DescendantFileNodeCount > DescendantFileNodeIndex; + DescendantFileNodeIndex++) + { + DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex]; + DescendantFileNode->DeletePending = TRUE; + } + + FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); + + SCATTER_DESCENDANTS(FALSE); +} + NTSTATUS FspFileNodeCheckBatchOplocksOnAllStreams( PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp, diff --git a/tst/memfs/memfs.cpp b/tst/memfs/memfs.cpp index 38824f97..89d901e0 100644 --- a/tst/memfs/memfs.cpp +++ b/tst/memfs/memfs.cpp @@ -925,6 +925,18 @@ static NTSTATUS Overwrite(FSP_FILE_SYSTEM *FileSystem, MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0; NTSTATUS Result; +#if defined(MEMFS_NAMED_STREAMS) + MEMFS_FILE_NODE_MAP_ENUM_CONTEXT Context = { FALSE }; + ULONG Index; + + MemfsFileNodeMapEnumerateNamedStreams(Memfs->FileNodeMap, FileNode, + MemfsFileNodeMapEnumerateFn, &Context); + for (Index = 0; Context.Count > Index; Index++) + if (1 >= Context.FileNodes[Index]->RefCount) + MemfsFileNodeMapRemove(Memfs->FileNodeMap, Context.FileNodes[Index]); + MemfsFileNodeMapEnumerateFree(&Context); +#endif + Result = SetFileSize(FileSystem, FileNode, AllocationSize, TRUE, FileInfo); if (!NT_SUCCESS(Result)) return Result;