From dd59f6f6114a436ae86b70cd0837e97eea18dde8 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Mon, 1 Oct 2012 11:04:23 -0400 Subject: [PATCH] Windows: Dir Enum behavior for Symlinks / MPs Comparisons of the behavior of cmd.exe, powershell.exe, and tcc.exe with regards to directory enumeration show that when Symlink file information is returned that the "reparse point" data should be reported along with whether or not the target is a directory. For mount points, the reparse point file information should always be returned and the type should always be directory. The target timestamps, file sizes, etc. should never be returned. Change-Id: I0f899229061a282d0d218155407ffc4ab62ad377 Reviewed-on: http://gerrit.openafs.org/8170 Tested-by: BuildBot Reviewed-by: Jeffrey Altman Tested-by: Jeffrey Altman --- src/WINNT/afsrdr/kernel/lib/AFSDirControl.cpp | 135 ++++++++++-------- 1 file changed, 79 insertions(+), 56 deletions(-) diff --git a/src/WINNT/afsrdr/kernel/lib/AFSDirControl.cpp b/src/WINNT/afsrdr/kernel/lib/AFSDirControl.cpp index c32caf947..9a1946883 100644 --- a/src/WINNT/afsrdr/kernel/lib/AFSDirControl.cpp +++ b/src/WINNT/afsrdr/kernel/lib/AFSDirControl.cpp @@ -146,7 +146,6 @@ AFSQueryDirectory( IN PIRP Irp) BOOLEAN bReleaseFcb = FALSE; ULONG ulTargetFileType = AFS_FILE_TYPE_UNKNOWN; AFSFileInfoCB stFileInfo; - BOOLEAN bUseFileInfo = TRUE; AFSObjectInfoCB *pObjectInfo = NULL; ULONG ulAdditionalAttributes = 0; LONG lCount; @@ -617,6 +616,8 @@ AFSQueryDirectory( IN PIRP Irp) ULONG ulBytesRemainingInBuffer; int rc; + ulAdditionalAttributes = 0; + // // If the user had requested only a single match and we have // returned that, then we stop at this point. @@ -747,36 +748,6 @@ AFSQueryDirectory( IN PIRP Irp) pObjectInfo = pDirEntry->ObjectInformation; - bUseFileInfo = FALSE; - - ulAdditionalAttributes = 0; - - if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK) - { - - // - // Go grab the file information for this entry - // No worries on failures since we will just display - // pseudo information - // - - RtlZeroMemory( &stFileInfo, - sizeof( AFSFileInfoCB)); - - if( NT_SUCCESS( AFSRetrieveFileAttributes( pCcb->DirectoryCB, - pDirEntry, - &pCcb->FullFileName, - pCcb->NameArray, - &pCcb->AuthGroup, - &stFileInfo))) - { - - ulAdditionalAttributes = FILE_ATTRIBUTE_REPARSE_POINT; - - bUseFileInfo = TRUE; - } - } - // Here are the rules concerning filling up the buffer: // // 1. The Io system guarantees that there will always be @@ -809,6 +780,74 @@ AFSQueryDirectory( IN PIRP Irp) try_return( ntStatus = STATUS_SUCCESS); } + + // + // For Symlinks and Mount Points the reparse point attribute + // must be associated with the directory entry. In addition, + // for Symlinks it must be determined if the target object is + // a directory or not. If so, the directory attribute must be + // specified. Mount points always refer to directories and + // must have the directory attribute set. + // + + switch( pObjectInfo->FileType) + { + + case AFS_FILE_TYPE_MOUNTPOINT: + case AFS_FILE_TYPE_DFSLINK: + { + + ulAdditionalAttributes = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT; + + break; + } + + case AFS_FILE_TYPE_SYMLINK: + { + + // + // Go grab the file information for this entry + // No worries on failures since we will just display + // pseudo information + // + + RtlZeroMemory( &stFileInfo, + sizeof( AFSFileInfoCB)); + + if( NT_SUCCESS( AFSRetrieveFileAttributes( pCcb->DirectoryCB, + pDirEntry, + &pCcb->FullFileName, + pCcb->NameArray, + &pCcb->AuthGroup, + &stFileInfo))) + { + + if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + + ulAdditionalAttributes = FILE_ATTRIBUTE_DIRECTORY; + } + } + + ulAdditionalAttributes |= FILE_ATTRIBUTE_REPARSE_POINT; + + break; + } + } + + // + // Check if the name begins with a . and we are hiding them + // + + if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) && + pDirEntry->NameInformation.FileName.Buffer[ 0] == L'.' && + BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES)) + { + + ulAdditionalAttributes |= FILE_ATTRIBUTE_HIDDEN; + } + + AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSQueryDirectory Insert into parent %wZ Entry %wZ\n", @@ -847,20 +886,7 @@ AFSQueryDirectory( IN PIRP Irp) { pDirInfo = (PFILE_DIRECTORY_INFORMATION)&pBuffer[ ulNextEntry]; - if( bUseFileInfo) - { - - pDirInfo->CreationTime = stFileInfo.CreationTime; - pDirInfo->LastWriteTime = stFileInfo.LastWriteTime; - pDirInfo->LastAccessTime = stFileInfo.LastAccessTime; - pDirInfo->ChangeTime = stFileInfo.ChangeTime; - - pDirInfo->EndOfFile = stFileInfo.EndOfFile; - pDirInfo->AllocationSize = stFileInfo.AllocationSize; - - pDirInfo->FileAttributes = stFileInfo.FileAttributes | ulAdditionalAttributes; - } - else if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE)) + if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE)) { pDirInfo->CreationTime = pFcb->ObjectInformation->CreationTime; @@ -891,19 +917,16 @@ AFSQueryDirectory( IN PIRP Irp) pDirInfo->EndOfFile = pObjectInfo->EndOfFile; pDirInfo->AllocationSize = pObjectInfo->AllocationSize; - pDirInfo->FileAttributes = pObjectInfo->FileAttributes | ulAdditionalAttributes; - } - - // - // Check if the name begins with a . and we are hiding them - // + if ( ulAdditionalAttributes && pObjectInfo->FileAttributes == FILE_ATTRIBUTE_NORMAL) + { - if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) && - pDirEntry->NameInformation.FileName.Buffer[ 0] == L'.' && - BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES)) - { + pDirInfo->FileAttributes = ulAdditionalAttributes; + } + else + { - pDirInfo->FileAttributes |= FILE_ATTRIBUTE_HIDDEN; + pDirInfo->FileAttributes = pObjectInfo->FileAttributes | ulAdditionalAttributes; + } } pDirInfo->FileIndex = pDirEntry->FileIndex; -- 2.39.5