Windows: !overwrite IOMgr populated FileInfo data
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSFileInfo.cpp
index 71b7d00..c0645be 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
- * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2014 Your File System, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -245,17 +245,18 @@ AFSQueryFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
                     try_return( ntStatus);
                 }
 
-                ntStatus = AFSQueryAccess( Irp,
-                                           pFcb,
-                                           &pAllInfo->AccessInformation,
-                                           &lLength);
+               //
+               // We skip setting AccessInformation since this is set by the IO Mgr prior
+               // to sending this request to the file system
+               //
 
-                if( !NT_SUCCESS( ntStatus))
+               if( lLength < sizeof( FILE_ACCESS_INFORMATION))
                 {
-
-                    try_return( ntStatus);
+                   try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
                 }
 
+               lLength -= sizeof( FILE_ACCESS_INFORMATION);
+
                 ntStatus = AFSQueryPositionInfo( Irp,
                                                  pFcb,
                                                  &pAllInfo->PositionInformation,
@@ -267,28 +268,29 @@ AFSQueryFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
                     try_return( ntStatus);
                 }
 
-                ntStatus = AFSQueryMode( Irp,
-                                         pFcb,
-                                         &pAllInfo->ModeInformation,
-                                         &lLength);
+               //
+               // We skip setting ModeInformation and AlignmentInformation since this is set by the IO Mgr prior
+               // to sending this request to the file system
+               //
 
-                if( !NT_SUCCESS( ntStatus))
+               if( lLength < sizeof( FILE_MODE_INFORMATION))
                 {
-
-                    try_return( ntStatus);
+                   try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
                 }
 
-                ntStatus = AFSQueryAlignment( Irp,
-                                              pFcb,
-                                              &pAllInfo->AlignmentInformation,
-                                              &lLength);
+               lLength -= sizeof( FILE_MODE_INFORMATION);
 
-                if( !NT_SUCCESS( ntStatus))
+               if( lLength < sizeof( FILE_ALIGNMENT_INFORMATION))
                 {
-
-                    try_return( ntStatus);
+                   try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
                 }
 
+               lLength -= sizeof( FILE_ALIGNMENT_INFORMATION);
+
+               //
+               // Populate the name information
+               //
+
                 ntStatus = AFSQueryNameInfo( Irp,
                                              pCcb->DirectoryCB,
                                              &pAllInfo->NameInformation,
@@ -592,7 +594,8 @@ AFSSetFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
             try_return( ntStatus);
         }
 
-        if( BooleanFlagOn( pFcb->ObjectInformation->VolumeCB->VolumeInformation.FileSystemAttributes, FILE_READ_ONLY_VOLUME))
+       if( FileInformationClass != FilePositionInformation &&
+           BooleanFlagOn( pFcb->ObjectInformation->VolumeCB->VolumeInformation.FileSystemAttributes, FILE_READ_ONLY_VOLUME))
         {
 
             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
@@ -646,10 +649,9 @@ AFSSetFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
             case FileBasicInformation:
             {
 
-                bUpdateFileInfo = TRUE;
-
                 ntStatus = AFSSetBasicInfo( Irp,
-                                            pCcb->DirectoryCB);
+                                           pCcb->DirectoryCB,
+                                           &bUpdateFileInfo);
 
                 break;
             }
@@ -1126,96 +1128,6 @@ AFSQueryPositionInfo( IN PIRP Irp,
 }
 
 NTSTATUS
-AFSQueryAccess( IN PIRP Irp,
-                IN AFSFcb *Fcb,
-                IN OUT PFILE_ACCESS_INFORMATION Buffer,
-                IN OUT PLONG Length)
-{
-
-    UNREFERENCED_PARAMETER(Irp);
-    UNREFERENCED_PARAMETER(Fcb);
-    NTSTATUS ntStatus = STATUS_SUCCESS;
-
-    if( *Length >= sizeof( FILE_ACCESS_INFORMATION))
-    {
-
-        RtlZeroMemory( Buffer,
-                       *Length);
-
-        Buffer->AccessFlags = 0;
-
-        *Length -= sizeof( FILE_ACCESS_INFORMATION);
-    }
-    else
-    {
-
-        ntStatus = STATUS_BUFFER_TOO_SMALL;
-    }
-
-    return ntStatus;
-}
-
-NTSTATUS
-AFSQueryMode( IN PIRP Irp,
-              IN AFSFcb *Fcb,
-              IN OUT PFILE_MODE_INFORMATION Buffer,
-              IN OUT PLONG Length)
-{
-
-    UNREFERENCED_PARAMETER(Irp);
-    UNREFERENCED_PARAMETER(Fcb);
-    NTSTATUS ntStatus = STATUS_SUCCESS;
-
-    if( *Length >= sizeof( FILE_MODE_INFORMATION))
-    {
-
-        RtlZeroMemory( Buffer,
-                       *Length);
-
-        Buffer->Mode = 0;
-
-        *Length -= sizeof( FILE_MODE_INFORMATION);
-    }
-    else
-    {
-
-        ntStatus = STATUS_BUFFER_TOO_SMALL;
-    }
-
-    return ntStatus;
-}
-
-NTSTATUS
-AFSQueryAlignment( IN PIRP Irp,
-                   IN AFSFcb *Fcb,
-                   IN OUT PFILE_ALIGNMENT_INFORMATION Buffer,
-                   IN OUT PLONG Length)
-{
-
-    UNREFERENCED_PARAMETER(Irp);
-    UNREFERENCED_PARAMETER(Fcb);
-    NTSTATUS ntStatus = STATUS_SUCCESS;
-
-    if( *Length >= sizeof( FILE_ALIGNMENT_INFORMATION))
-    {
-
-        RtlZeroMemory( Buffer,
-                       *Length);
-
-        Buffer->AlignmentRequirement = 1;
-
-        *Length -= sizeof( FILE_ALIGNMENT_INFORMATION);
-    }
-    else
-    {
-
-        ntStatus = STATUS_BUFFER_TOO_SMALL;
-    }
-
-    return ntStatus;
-}
-
-NTSTATUS
 AFSQueryNameInfo( IN PIRP Irp,
                   IN AFSDirectoryCB *DirectoryCB,
                   IN OUT PFILE_NAME_INFORMATION Buffer,
@@ -1911,7 +1823,8 @@ AFSQueryPhysicalNameInfo( IN PIRP Irp,
 
 NTSTATUS
 AFSSetBasicInfo( IN PIRP Irp,
-                 IN AFSDirectoryCB *DirectoryCB)
+                IN AFSDirectoryCB *DirectoryCB,
+                OUT BOOLEAN *bUpdateFileInfo)
 {
     NTSTATUS ntStatus = STATUS_SUCCESS;
     PFILE_BASIC_INFORMATION pBuffer;
@@ -1931,26 +1844,92 @@ AFSSetBasicInfo( IN PIRP Irp,
         if( pBuffer->FileAttributes != (ULONGLONG)0)
         {
 
-            if( DirectoryCB->ObjectInformation->Fcb->Header.NodeTypeCode == AFS_FILE_FCB &&
-                BooleanFlagOn( pBuffer->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
-            {
+           //
+           // Make sure that the reparse point attribute is not modified.
+           // Fail if the RP attribute is requested but it is not
+           // already a RP.  Otherwise, ignore it.
+           //
 
-                try_return( ntStatus = STATUS_INVALID_PARAMETER);
-            }
+           if ( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
+                                FILE_ATTRIBUTE_REPARSE_POINT) &&
+                BooleanFlagOn( pBuffer->FileAttributes,
+                               FILE_ATTRIBUTE_REPARSE_POINT))
+           {
 
-            if( DirectoryCB->ObjectInformation->Fcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
-            {
+               try_return( ntStatus = STATUS_INVALID_PARAMETER);
+           }
 
-                pBuffer->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
-            }
+           //
+           // Make sure that the directory attribute is not modified.
+           // Fail if the D attribute is requested but it is not
+           // already a directory.  Otherwise, ignore it.
+           //
+
+           if ( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
+                                FILE_ATTRIBUTE_DIRECTORY) &&
+                BooleanFlagOn( pBuffer->FileAttributes,
+                               FILE_ATTRIBUTE_DIRECTORY))
+           {
+
+               try_return( ntStatus = STATUS_INVALID_PARAMETER);
+           }
 
-            pCcb->FileUnwindInfo.FileAttributes = DirectoryCB->ObjectInformation->FileAttributes;
+           //
+           // Save the original value
+           //
 
-            DirectoryCB->ObjectInformation->FileAttributes = pBuffer->FileAttributes;
+           pCcb->FileUnwindInfo.FileAttributes = DirectoryCB->ObjectInformation->FileAttributes;
 
-            ulNotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
+           if( BooleanFlagOn( pBuffer->FileAttributes, FILE_ATTRIBUTE_READONLY))
+           {
+
+               //
+               // Set the readonly flag.
+               //
+
+               if ( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
+                                    FILE_ATTRIBUTE_READONLY))
+               {
+
+                   if ( DirectoryCB->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
+                   {
+
+                       DirectoryCB->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_READONLY;
+                   }
+                   else
+                   {
+
+                       DirectoryCB->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_READONLY;
+                   }
+
+                   ulNotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
+
+                   SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
+               }
+           }
+           else
+           {
+               //
+               // Reset the readonly flag.
+               //
 
-            SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
+               if ( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
+                                   FILE_ATTRIBUTE_READONLY))
+               {
+
+                   DirectoryCB->ObjectInformation->FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
+
+                   if ( DirectoryCB->ObjectInformation->FileAttributes == 0)
+                   {
+
+                       DirectoryCB->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL;
+                   }
+
+                   ulNotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
+
+                   SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
+               }
+           }
         }
 
         pCcb->FileUnwindInfo.CreationTime.QuadPart = (ULONGLONG)-1;
@@ -1996,6 +1975,12 @@ AFSSetBasicInfo( IN PIRP Irp,
             ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
 
             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME);
+
+           SetFlag( pCcb->Flags, CCB_FLAG_LAST_WRITE_TIME_SET);
+
+       } else if ( pBuffer->LastWriteTime.QuadPart == (ULONGLONG)-1) {
+
+           SetFlag( pCcb->Flags, CCB_FLAG_LAST_WRITE_TIME_SET);
         }
 
         pCcb->FileUnwindInfo.ChangeTime.QuadPart = (ULONGLONG)-1;
@@ -2016,6 +2001,8 @@ AFSSetBasicInfo( IN PIRP Irp,
         if( ulNotifyFilter > 0)
         {
 
+           *bUpdateFileInfo = TRUE;
+
             if( BooleanFlagOn( DirectoryCB->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
             {
 
@@ -3835,6 +3822,11 @@ AFSSetAllocationInfo( IN PIRP Irp,
             CcSetFileSizes( pFileObject,
                             (PCC_FILE_SIZES)&pFcb->Header.AllocationSize);
         }
+
+       //
+       // Mark the file as modified so as to reflect the change into the last write on close.
+       //
+       SetFlag( pFileObject->Flags, FO_FILE_MODIFIED);
     }
     else
     {
@@ -4069,6 +4061,11 @@ AFSSetEndOfFileInfo( IN PIRP Irp,
                 AFSTrimExtents( pFcb,
                                 &pFcb->Header.FileSize);
             }
+
+           //
+           // Mark the file as modified so as to reflect the change into the last write on close.
+           //
+           SetFlag( pFileObject->Flags, FO_FILE_MODIFIED);
         }
         else
         {