Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 2 additions & 69 deletions drivers/filesystems/udfs/fileinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1865,61 +1865,6 @@ UDFPrepareForRenameMoveLink(
return STATUS_SUCCESS;
} // end UDFPrepareForRenameMoveLink()

/*
Check if a directory subtree has any open handles (FcbCleanup != 0).
Iterative depth-first walk via ChildLcbQueue — no recursion, kernel-safe.
Returns TRUE if subtree is clean (no open handles), FALSE otherwise.
*/
BOOLEAN
UDFCheckDirOpenHandles(
IN PFCB DirectoryFcb
)
{
PFCB CheckFcb = DirectoryFcb;
PLIST_ENTRY CheckLink = CheckFcb->ChildLcbQueue.Flink;

while (CheckFcb != NULL) {

// Process all children at current level
while (CheckLink != &CheckFcb->ChildLcbQueue) {
PLCB ChildLcb = CONTAINING_RECORD(CheckLink, LCB, ParentFcbLinks);
PFCB ChildFcb = ChildLcb->ChildFcb;
CheckLink = CheckLink->Flink;

if (!ChildFcb) continue;

if (ChildFcb->FcbCleanup != 0) {
return FALSE;
}

// If child is a directory with children, descend into it
if ((ChildFcb->FcbState & UDF_FCB_DIRECTORY) &&
!IsListEmpty(&ChildFcb->ChildLcbQueue)) {
CheckFcb = ChildFcb;
CheckLink = CheckFcb->ChildLcbQueue.Flink;
}
}

// Back to root — done
if (CheckFcb == DirectoryFcb) break;

// Ascend: find our LCB in parent, advance to next sibling
PLIST_ENTRY ParentLink;
for (ParentLink = CheckFcb->ParentLcbQueue.Flink;
ParentLink != &CheckFcb->ParentLcbQueue;
ParentLink = ParentLink->Flink) {
PLCB ParentLcb = CONTAINING_RECORD(ParentLink, LCB, ChildFcbLinks);
if (ParentLcb->ParentFcb) {
CheckFcb = ParentLcb->ParentFcb;
CheckLink = ParentLcb->ParentFcbLinks.Flink;
break;
}
}
}

return TRUE;
}

/*
Rename or move file
*/
Expand Down Expand Up @@ -2109,25 +2054,13 @@ UDFSetRenameInfo(
}
}

// check if the source file is in use
if (Fcb->FcbCleanup > 1) {

try_return (RC = STATUS_ACCESS_DENIED);
}

ASSERT(Fcb->FcbCleanup);
ASSERT(!Fcb->IrpContextLite);

if (Fcb->IrpContextLite) {
try_return (RC = STATUS_ACCESS_DENIED);
}

// For directories: check that no descendant has open handles.
if ((Fcb->FcbState & UDF_FCB_DIRECTORY) &&
!UDFCheckDirOpenHandles(Fcb)) {
try_return (RC = STATUS_ACCESS_DENIED);
}

// Check if renaming to stream name - only allowed for streams
if (!TargetFileObject && NewName.Length >= sizeof(WCHAR) && NewName.Buffer[0] == L':') {

Expand All @@ -2141,8 +2074,8 @@ UDFSetRenameInfo(
// checks DirNdx->FileInfo != NULL for each child — blocks if any
// child has a cached FileInfo structure, even with FcbCleanup=0
// (no user handles). This is too strict for rename/move where file
// data stays intact. The subtree is already validated above via
// UDFCheckDirOpenHandles which checks FcbCleanup (user handles).
// data stays intact: UDF files are addressed by physical ICB location,
// so moving a directory does not invalidate open handles to files inside.
{

// Note: With LCB model, FcbReference may not always be >= RefCount
Expand Down
5 changes: 0 additions & 5 deletions drivers/filesystems/udfs/protos.h
Original file line number Diff line number Diff line change
Expand Up @@ -445,11 +445,6 @@ UDFSetEndOfFileInfo(
IN PFILE_END_OF_FILE_INFORMATION PtrBuffer
);

BOOLEAN
UDFCheckDirOpenHandles(
IN PFCB DirectoryFcb
);

NTSTATUS
UDFSetRenameInfo(
IN PIRP_CONTEXT IrpContext,
Expand Down