windows: AFSQueryDirectoryQueryDirect no Symlinks
authorJeffrey Altman <jaltman@your-file-system.com>
Tue, 19 Mar 2013 15:48:42 +0000 (11:48 -0400)
committerJeffrey Altman <jaltman@your-file-system.com>
Fri, 22 Mar 2013 14:29:03 +0000 (07:29 -0700)
When evaluating symlinks for directory enumerations, the response
must properly set the FILE_ATTRIBUTE_DIRECTORY flag based upon the
file attributes of the target.  At the present time the target is
not evaluated by the service and AFSQueryDirectoryQueryDirect does
not have the correct context in which to evaluate the target.

Instead of returning an incorrect result to the application, exit
AFSQueryDirectoryQueryDirect() returning STATUS_REPARSE_OBJECT which
is interpreted by AFSQueryDirectory() to perform a full directory
enumeration.

Change-Id: Ic35dcff31f1098b9f40f3a37534b79439e0e3f1f
Reviewed-on: http://gerrit.openafs.org/9633
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Peter Scott <pscott@kerneldrivers.com>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>

src/WINNT/afsrdr/kernel/lib/AFSDirControl.cpp

index f69fcfc..39ddc08 100644 (file)
@@ -440,9 +440,13 @@ AFSQueryDirectory( IN PIRP Irp)
                                                            pCcb,
                                                            Irp);
 
-                SetFlag( pCcb->Flags, CCB_FLAG_DIRECTORY_QUERY_DIRECT_QUERY);
+                if ( ntStatus != STATUS_REPARSE_OBJECT)
+                {
 
-                try_return( ntStatus);
+                    SetFlag( pCcb->Flags, CCB_FLAG_DIRECTORY_QUERY_DIRECT_QUERY);
+
+                    try_return( ntStatus);
+                }
             }
 
             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
@@ -2060,6 +2064,31 @@ AFSProcessDirectoryQueryDirect( IN AFSFcb *Fcb,
             try_return( ntStatus = STATUS_NO_SUCH_FILE);
         }
 
+        if ( pDirEnum->FileType == AFS_FILE_TYPE_SYMLINK &&
+             pIrpSp->Parameters.QueryDirectory.FileInformationClass != FileNamesInformation)
+        {
+
+            //
+            // If the file type is symlink the file attributes of the target object
+            // must be evaluated to determine if the object is a directory or not.
+            // We do not process that here.  Instead, return STATUS_REPARSE_OBJECT and
+            // let AFSQueryDirectory() evaluate everything.
+            //
+
+            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSProcessDirectoryQueryDirect Found Symlink parent %wZ Mask %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
+                          &Ccb->DirectoryCB->NameInformation.FileName,
+                          &Ccb->MaskName,
+                          Fcb->ObjectInformation->FileId.Cell,
+                          Fcb->ObjectInformation->FileId.Volume,
+                          Fcb->ObjectInformation->FileId.Vnode,
+                          Fcb->ObjectInformation->FileId.Unique,
+                          STATUS_REPARSE_OBJECT));
+
+            try_return( ntStatus = STATUS_REPARSE_OBJECT);
+        }
+
         pBuffer = (PUCHAR)AFSLockSystemBuffer( Irp,
                                                pIrpSp->Parameters.QueryDirectory.Length);
 
@@ -2125,8 +2154,10 @@ AFSProcessDirectoryQueryDirect( IN AFSFcb *Fcb,
                 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
         }
 
-        switch( pDirEnum->FileType)
+        if ( pIrpSp->Parameters.QueryDirectory.FileInformationClass != FileNamesInformation)
         {
+            switch( pDirEnum->FileType)
+            {
 
             case AFS_FILE_TYPE_MOUNTPOINT:
             case AFS_FILE_TYPE_DFSLINK:
@@ -2140,14 +2171,11 @@ AFSProcessDirectoryQueryDirect( IN AFSFcb *Fcb,
             case AFS_FILE_TYPE_SYMLINK:
             {
 
-                //
-                // Note: we need to evaluate this entry to determine if the target is a directory or not
-                //
-
-                ulAdditionalAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
+                ASSERT( FALSE);
 
                 break;
             }
+            }
         }
 
         //  Zero the base part of the structure.