mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 16:33:02 -05:00
sys,dll: Cleanup/TruncateOnClose overhaul
This commit is contained in:
parent
8d6314e2db
commit
c897ddd864
@ -146,7 +146,7 @@ typedef struct
|
||||
UINT32 ExtendedAttributes:1; /* unimplemented; set to 0 */
|
||||
UINT32 ReadOnlyVolume:1;
|
||||
/* kernel-mode flags */
|
||||
UINT32 PostCleanupOnDeleteOnly:1; /* post Cleanup when deleting a file only */
|
||||
UINT32 PostCleanupWhenModifiedOnly:1; /* post Cleanup when a file was modified/deleted */
|
||||
UINT32 KmReservedFlags:5;
|
||||
/* user-mode flags */
|
||||
UINT32 UmFileContextIsUserContext2:1; /* user mode: FileContext parameter is UserContext2 */
|
||||
@ -248,6 +248,11 @@ typedef struct
|
||||
UINT64 UserContext;
|
||||
UINT64 UserContext2;
|
||||
UINT32 Delete:1; /* file must be deleted */
|
||||
UINT32 SetAllocationSize:1;
|
||||
UINT32 SetArchiveBit:1;
|
||||
UINT32 SetLastAccessTime:1;
|
||||
UINT32 SetLastWriteTime:1;
|
||||
UINT32 SetChangeTime:1;
|
||||
} Cleanup;
|
||||
struct
|
||||
{
|
||||
|
@ -122,6 +122,15 @@ typedef enum
|
||||
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE = 0,
|
||||
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_COARSE,
|
||||
} FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY;
|
||||
enum
|
||||
{
|
||||
FspCleanupDelete = 0x01,
|
||||
FspCleanupSetAllocationSize = 0x02,
|
||||
FspCleanupSetArchiveBit = 0x10,
|
||||
FspCleanupSetLastAccessTime = 0x20,
|
||||
FspCleanupSetLastWriteTime = 0x40,
|
||||
FspCleanupSetChangeTime = 0x80,
|
||||
};
|
||||
/**
|
||||
* @class FSP_FILE_SYSTEM
|
||||
* File system interface.
|
||||
@ -332,8 +341,8 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
||||
* deleted during Cleanup.
|
||||
*
|
||||
* As an optimization a file system may specify the FSP_FSCTL_VOLUME_PARAMS ::
|
||||
* PostCleanupOnDeleteOnly flag. In this case the FSD will only post Cleanup requests when a
|
||||
* file is being deleted.
|
||||
* PostCleanupWhenModifiedOnly flag. In this case the FSD will only post Cleanup requests when
|
||||
* the file was modified/deleted.
|
||||
*
|
||||
* @param FileSystem
|
||||
* The file system on which this request is posted.
|
||||
@ -341,16 +350,17 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
||||
* The file context of the file or directory to cleanup.
|
||||
* @param FileName
|
||||
* The name of the file or directory to cleanup. Sent only when a Delete is requested.
|
||||
* @param Delete
|
||||
* Determines whether to delete the file. Note that there is no way to report failure of
|
||||
* this operation. Also note that when this parameter is TRUE this is the last outstanding
|
||||
* cleanup for this particular file node.
|
||||
* @param Flags
|
||||
* These flags determine whether the file was modified and whether to delete the file.
|
||||
* Note that there is no way to report failure of this operation. Also note that when
|
||||
* this parameter has the FspCleanupDelete bit set, this is the last outstanding cleanup
|
||||
* for this particular file node.
|
||||
* @see
|
||||
* Close
|
||||
* CanDelete
|
||||
*/
|
||||
VOID (*Cleanup)(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileContext, PWSTR FileName, BOOLEAN Delete);
|
||||
PVOID FileContext, PWSTR FileName, ULONG Flags);
|
||||
/**
|
||||
* Close a file.
|
||||
*
|
||||
|
@ -875,7 +875,12 @@ FSP_API NTSTATUS FspFileSystemOpCleanup(FSP_FILE_SYSTEM *FileSystem,
|
||||
FileSystem->Interface->Cleanup(FileSystem,
|
||||
(PVOID)ValOfFileContext(Request->Req.Cleanup),
|
||||
0 != Request->FileName.Size ? (PWSTR)Request->Buffer : 0,
|
||||
0 != Request->Req.Cleanup.Delete);
|
||||
(0 != Request->Req.Cleanup.Delete ? FspCleanupDelete : 0) |
|
||||
(0 != Request->Req.Cleanup.SetAllocationSize ? FspCleanupSetAllocationSize : 0) |
|
||||
(0 != Request->Req.Cleanup.SetArchiveBit ? FspCleanupSetArchiveBit : 0) |
|
||||
(0 != Request->Req.Cleanup.SetLastAccessTime ? FspCleanupSetLastAccessTime : 0) |
|
||||
(0 != Request->Req.Cleanup.SetLastWriteTime ? FspCleanupSetLastWriteTime : 0) |
|
||||
(0 != Request->Req.Cleanup.SetChangeTime ? FspCleanupSetChangeTime : 0));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -523,7 +523,7 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
opt_data.VolumeParams.ReparsePointsAccessCheck = FALSE;
|
||||
opt_data.VolumeParams.NamedStreams = FALSE;
|
||||
opt_data.VolumeParams.ReadOnlyVolume = !!opt_data.ReadOnlyVolume;
|
||||
opt_data.VolumeParams.PostCleanupOnDeleteOnly = TRUE;
|
||||
opt_data.VolumeParams.PostCleanupWhenModifiedOnly = TRUE;
|
||||
opt_data.VolumeParams.UmFileContextIsUserContext2 = TRUE;
|
||||
if (L'\0' == opt_data.VolumeParams.FileSystemName[0])
|
||||
memcpy(opt_data.VolumeParams.FileSystemName, L"FUSE", 5 * sizeof(WCHAR));
|
||||
|
@ -1050,7 +1050,7 @@ static NTSTATUS fsp_fuse_intf_Overwrite(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
|
||||
static VOID fsp_fuse_intf_Cleanup(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode, PWSTR FileName, BOOLEAN Delete)
|
||||
PVOID FileNode, PWSTR FileName, ULONG Flags)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
@ -1072,7 +1072,7 @@ static VOID fsp_fuse_intf_Cleanup(FSP_FILE_SYSTEM *FileSystem,
|
||||
* FUSE option and can safely remove the file at this time.
|
||||
*/
|
||||
|
||||
if (Delete)
|
||||
if (Flags & FspCleanupDelete)
|
||||
if (filedesc->IsDirectory && !filedesc->IsReparsePoint)
|
||||
{
|
||||
if (0 != f->ops.rmdir)
|
||||
|
@ -77,13 +77,17 @@ static NTSTATUS FspFsvolCleanup(
|
||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||
BOOLEAN DeletePending;
|
||||
ULONG CleanupFlags;
|
||||
BOOLEAN DeletePending, SetAllocationSize, FileModified;
|
||||
|
||||
ASSERT(FileNode == FileDesc->FileNode);
|
||||
|
||||
FspFileNodeAcquireExclusive(FileNode, Main);
|
||||
|
||||
FspFileNodeCleanup(FileNode, FileObject, &DeletePending);
|
||||
FspFileNodeCleanup(FileNode, FileObject, &CleanupFlags);
|
||||
DeletePending = CleanupFlags & 1;
|
||||
SetAllocationSize = !!(CleanupFlags & 2);
|
||||
FileModified = BooleanFlagOn(FileObject->Flags, FO_FILE_MODIFIED);
|
||||
|
||||
/* if this is a directory inform the FSRTL Notify mechanism */
|
||||
if (FileNode->IsDirectory)
|
||||
@ -106,13 +110,23 @@ static NTSTATUS FspFsvolCleanup(
|
||||
Request->Req.Cleanup.UserContext = FileNode->UserContext;
|
||||
Request->Req.Cleanup.UserContext2 = FileDesc->UserContext2;
|
||||
Request->Req.Cleanup.Delete = DeletePending;
|
||||
Request->Req.Cleanup.SetAllocationSize = SetAllocationSize;
|
||||
Request->Req.Cleanup.SetArchiveBit = FileModified;
|
||||
Request->Req.Cleanup.SetLastAccessTime = !FileDesc->DidSetLastAccessTime;
|
||||
Request->Req.Cleanup.SetLastWriteTime = FileModified && !FileDesc->DidSetLastWriteTime;
|
||||
Request->Req.Cleanup.SetChangeTime = FileModified;
|
||||
|
||||
FspFileNodeAcquireExclusive(FileNode, Pgio);
|
||||
|
||||
FspFileNodeSetOwner(FileNode, Full, Request);
|
||||
FspIopRequestContext(Request, RequestIrp) = Irp;
|
||||
|
||||
if (DeletePending || !FsvolDeviceExtension->VolumeParams.PostCleanupOnDeleteOnly)
|
||||
if (Request->Req.Cleanup.Delete ||
|
||||
Request->Req.Cleanup.SetAllocationSize ||
|
||||
Request->Req.Cleanup.SetArchiveBit ||
|
||||
Request->Req.Cleanup.SetLastWriteTime ||
|
||||
Request->Req.Cleanup.SetChangeTime ||
|
||||
!FsvolDeviceExtension->VolumeParams.PostCleanupWhenModifiedOnly)
|
||||
/*
|
||||
* Note that it is still possible for this request to not be delivered,
|
||||
* if the volume device Ioq is stopped. But such failures are benign
|
||||
|
@ -1025,6 +1025,10 @@ NTSTATUS FspFsvolCreateComplete(
|
||||
if (0 == FileNode->MainFileNode)
|
||||
FspFileNodeOverwriteStreams(FileNode);
|
||||
FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.Overwrite.FileInfo);
|
||||
|
||||
if (0 != Response->Rsp.Overwrite.FileInfo.AllocationSize)
|
||||
FileNode->TruncateOnClose = TRUE;
|
||||
|
||||
FspFileNodeNotifyChange(FileNode,
|
||||
FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE,
|
||||
FILE_ACTION_MODIFIED);
|
||||
@ -1115,9 +1119,14 @@ static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Re
|
||||
}
|
||||
|
||||
if (FILE_CREATED == Response->IoStatus.Information)
|
||||
{
|
||||
if (0 != Response->Rsp.Create.Opened.FileInfo.AllocationSize)
|
||||
FileNode->TruncateOnClose = TRUE;
|
||||
|
||||
FspFileNodeNotifyChange(FileNode,
|
||||
FileNode->IsDirectory ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME,
|
||||
FILE_ACTION_ADDED);
|
||||
}
|
||||
|
||||
FspFileNodeRelease(FileNode, Main);
|
||||
|
||||
|
@ -1200,6 +1200,7 @@ typedef struct
|
||||
BOOLEAN CaseSensitive;
|
||||
BOOLEAN HasTraversePrivilege;
|
||||
BOOLEAN DeleteOnClose;
|
||||
BOOLEAN DidSetLastAccessTime, DidSetLastWriteTime;
|
||||
BOOLEAN DirectoryHasSuchFile;
|
||||
UNICODE_STRING DirectoryPattern;
|
||||
UINT64 DirectoryOffset;
|
||||
@ -1259,8 +1260,7 @@ VOID FspFileNodeReleaseForeign(FSP_FILE_NODE *FileNode)
|
||||
NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
UINT32 GrantedAccess, UINT32 ShareAccess,
|
||||
FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason);
|
||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
PBOOLEAN PDeletePending);
|
||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags);
|
||||
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
|
||||
PFILE_OBJECT FileObject, /* non-0 to remove share access */
|
||||
|
@ -34,8 +34,7 @@ VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner)
|
||||
NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
UINT32 GrantedAccess, UINT32 ShareAccess,
|
||||
FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason);
|
||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
PBOOLEAN PDeletePending);
|
||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags);
|
||||
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
|
||||
PFILE_OBJECT FileObject, /* non-0 to remove share access */
|
||||
@ -635,8 +634,7 @@ exit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
PBOOLEAN PDeletePending)
|
||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags)
|
||||
{
|
||||
/*
|
||||
* Determine whether a FileNode should be deleted. Note that when FileNode->DeletePending
|
||||
@ -650,7 +648,7 @@ VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
|
||||
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
|
||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||
BOOLEAN DeletePending, SingleHandle;
|
||||
BOOLEAN DeletePending, SetAllocationSize, SingleHandle;
|
||||
|
||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||
|
||||
@ -659,12 +657,13 @@ VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
DeletePending = 0 != FileNode->DeletePending;
|
||||
MemoryBarrier();
|
||||
|
||||
SetAllocationSize = !DeletePending && FileNode->TruncateOnClose;
|
||||
|
||||
SingleHandle = 1 == FileNode->HandleCount;
|
||||
|
||||
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
||||
|
||||
if (0 != PDeletePending)
|
||||
*PDeletePending = SingleHandle && DeletePending;
|
||||
*PCleanupFlags = SingleHandle ? DeletePending | (SetAllocationSize << 1) : 0;
|
||||
}
|
||||
|
||||
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject)
|
||||
@ -684,7 +683,7 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
||||
PAGED_CODE();
|
||||
|
||||
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
|
||||
LARGE_INTEGER TruncateSize = { 0 }, *PTruncateSize = 0;
|
||||
LARGE_INTEGER TruncateSize, *PTruncateSize = 0;
|
||||
BOOLEAN DeletePending;
|
||||
BOOLEAN DeletedFromContextTable = FALSE;
|
||||
|
||||
@ -715,23 +714,34 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
||||
|
||||
if (DeletePending)
|
||||
{
|
||||
PTruncateSize = &TruncateSize;
|
||||
|
||||
FspFsvolDeviceDeleteContextByName(FsvolDeviceObject, &FileNode->FileName,
|
||||
&DeletedFromContextTable);
|
||||
ASSERT(DeletedFromContextTable);
|
||||
|
||||
FileNode->OpenCount = 0;
|
||||
FileNode->Header.FileSize.QuadPart = 0;
|
||||
}
|
||||
else if (FileNode->TruncateOnClose && FlagOn(FileObject->Flags, FO_CACHE_SUPPORTED))
|
||||
|
||||
if (DeletePending || FileNode->TruncateOnClose)
|
||||
{
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||
FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
UINT64 AllocationUnit =
|
||||
FsvolDeviceExtension->VolumeParams.SectorSize *
|
||||
FsvolDeviceExtension->VolumeParams.SectorsPerAllocationUnit;
|
||||
|
||||
/*
|
||||
* Even when the FileInfo is expired, this is the best guess for a file size
|
||||
* without asking the user-mode file system.
|
||||
*/
|
||||
TruncateSize = FileNode->Header.FileSize;
|
||||
PTruncateSize = &TruncateSize;
|
||||
|
||||
FileNode->Header.AllocationSize.QuadPart = (TruncateSize.QuadPart + AllocationUnit - 1)
|
||||
/ AllocationUnit * AllocationUnit;
|
||||
}
|
||||
|
||||
FileNode->TruncateOnClose = FALSE;
|
||||
}
|
||||
|
||||
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
||||
|
@ -956,8 +956,11 @@ static NTSTATUS FspFsvolSetBasicInformation(PFILE_OBJECT FileObject,
|
||||
else
|
||||
{
|
||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||
ULONG NotifyFilter = 0;
|
||||
|
||||
ASSERT(FileNode == FileDesc->FileNode);
|
||||
|
||||
if (!FileNode->IsDirectory)
|
||||
{
|
||||
/* properly set temporary bit for lazy writer */
|
||||
@ -975,9 +978,15 @@ static NTSTATUS FspFsvolSetBasicInformation(PFILE_OBJECT FileObject,
|
||||
if (0 != Request->Req.SetInformation.Info.Basic.CreationTime)
|
||||
NotifyFilter |= FILE_NOTIFY_CHANGE_CREATION;
|
||||
if (0 != Request->Req.SetInformation.Info.Basic.LastAccessTime)
|
||||
{
|
||||
FileDesc->DidSetLastAccessTime = TRUE;
|
||||
NotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
|
||||
}
|
||||
if (0 != Request->Req.SetInformation.Info.Basic.LastWriteTime)
|
||||
{
|
||||
FileDesc->DidSetLastWriteTime = TRUE;
|
||||
NotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||
}
|
||||
FspFileNodeNotifyChange(FileNode, NotifyFilter, FILE_ACTION_MODIFIED);
|
||||
}
|
||||
|
||||
|
@ -195,6 +195,7 @@ static NTSTATUS FspFsvolWriteCached(
|
||||
{
|
||||
ASSERT(CanWait);
|
||||
|
||||
/* send EndOfFileInformation IRP; this will also set TruncateOnClose, etc. */
|
||||
EndOfFileInformation.EndOfFile.QuadPart = WriteEndOffset;
|
||||
Result = FspSendSetInformationIrp(FsvolDeviceObject/* bypass filters */, FileObject,
|
||||
FileEndOfFileInformation, &EndOfFileInformation, sizeof EndOfFileInformation);
|
||||
@ -471,11 +472,14 @@ NTSTATUS FspFsvolWriteComplete(
|
||||
/* update file info */
|
||||
FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.Write.FileInfo);
|
||||
|
||||
if (OriginalFileSize != Response->Rsp.Write.FileInfo.FileSize)
|
||||
if (!PagingIo && OriginalFileSize != Response->Rsp.Write.FileInfo.FileSize)
|
||||
{
|
||||
FileNode->TruncateOnClose = TRUE;
|
||||
FspFileNodeNotifyChange(FileNode, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED);
|
||||
}
|
||||
|
||||
/* update the current file offset if synchronous I/O (and not paging I/O) */
|
||||
if (SynchronousIo && !PagingIo)
|
||||
if (!PagingIo && SynchronousIo)
|
||||
FileObject->CurrentByteOffset.QuadPart = WriteToEndOfFile ?
|
||||
Response->Rsp.Write.FileInfo.FileSize :
|
||||
WriteOffset.QuadPart + Response->IoStatus.Information;
|
||||
|
@ -627,9 +627,8 @@ static NTSTATUS GetReparsePointByName(
|
||||
PWSTR FileName, BOOLEAN IsDirectory, PVOID Buffer, PSIZE_T PSize);
|
||||
#endif
|
||||
|
||||
static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode0, UINT64 NewSize, BOOLEAN SetAllocationSize,
|
||||
FSP_FSCTL_FILE_INFO *FileInfo);
|
||||
static NTSTATUS SetFileSizeInternal(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode0, UINT64 NewSize, BOOLEAN SetAllocationSize);
|
||||
|
||||
static NTSTATUS GetVolumeInfo(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_VOLUME_INFO *VolumeInfo)
|
||||
@ -888,21 +887,6 @@ static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem,
|
||||
return Result;
|
||||
}
|
||||
|
||||
/*
|
||||
* NTFS and FastFat do this at Cleanup time, but we are going to cheat.
|
||||
*
|
||||
* To properly implement this we should maintain some state of whether
|
||||
* we modified the file or not. Alternatively we could have the driver
|
||||
* report to us at Cleanup time whether the file was modified. [The
|
||||
* FSD does maintain the FO_FILE_MODIFIED bit, but does not send it
|
||||
* to us.]
|
||||
*
|
||||
* TBD.
|
||||
*/
|
||||
if (0 == (FileNode->FileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||
(GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
|
||||
FileNode->FileInfo.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
|
||||
|
||||
MemfsFileNodeReference(FileNode);
|
||||
*PFileNode = FileNode;
|
||||
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
||||
@ -944,7 +928,7 @@ static NTSTATUS Overwrite(FSP_FILE_SYSTEM *FileSystem,
|
||||
MemfsFileNodeMapEnumerateFree(&Context);
|
||||
#endif
|
||||
|
||||
Result = SetFileSize(FileSystem, FileNode, AllocationSize, TRUE, FileInfo);
|
||||
Result = SetFileSizeInternal(FileSystem, FileNode, AllocationSize, TRUE);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
@ -954,8 +938,9 @@ static NTSTATUS Overwrite(FSP_FILE_SYSTEM *FileSystem,
|
||||
FileNode->FileInfo.FileAttributes |= FileAttributes | FILE_ATTRIBUTE_ARCHIVE;
|
||||
|
||||
FileNode->FileInfo.FileSize = 0;
|
||||
FileNode->FileInfo.LastAccessTime =
|
||||
FileNode->FileInfo.LastWriteTime =
|
||||
FileNode->FileInfo.LastAccessTime = MemfsGetSystemTime();
|
||||
FileNode->FileInfo.ChangeTime = MemfsGetSystemTime();
|
||||
|
||||
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
||||
|
||||
@ -963,14 +948,41 @@ static NTSTATUS Overwrite(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
|
||||
static VOID Cleanup(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode0, PWSTR FileName, BOOLEAN Delete)
|
||||
PVOID FileNode0, PWSTR FileName, ULONG Flags)
|
||||
{
|
||||
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
||||
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
||||
|
||||
assert(Delete); /* the new FSP_FSCTL_VOLUME_PARAMS::PostCleanupOnDeleteOnly ensures this */
|
||||
assert(0 != Flags); /* FSP_FSCTL_VOLUME_PARAMS::PostCleanupWhenModifiedOnly ensures this */
|
||||
|
||||
if (Delete && !MemfsFileNodeMapHasChild(Memfs->FileNodeMap, FileNode))
|
||||
if (Flags & FspCleanupSetArchiveBit)
|
||||
{
|
||||
if (0 == (FileNode->FileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||
FileNode->FileInfo.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
|
||||
}
|
||||
|
||||
if (Flags & (FspCleanupSetLastAccessTime | FspCleanupSetLastWriteTime | FspCleanupSetChangeTime))
|
||||
{
|
||||
UINT64 SystemTime = MemfsGetSystemTime();
|
||||
|
||||
if (Flags & FspCleanupSetLastAccessTime)
|
||||
FileNode->FileInfo.LastAccessTime = SystemTime;
|
||||
if (Flags & FspCleanupSetLastWriteTime)
|
||||
FileNode->FileInfo.LastWriteTime = SystemTime;
|
||||
if (Flags & FspCleanupSetChangeTime)
|
||||
FileNode->FileInfo.ChangeTime = SystemTime;
|
||||
}
|
||||
|
||||
if (Flags & FspCleanupSetAllocationSize)
|
||||
{
|
||||
UINT64 AllocationUnit = MEMFS_SECTOR_SIZE * MEMFS_SECTORS_PER_ALLOCATION_UNIT;
|
||||
UINT64 AllocationSize = (FileNode->FileInfo.FileSize + AllocationUnit - 1) /
|
||||
AllocationUnit * AllocationUnit;
|
||||
|
||||
SetFileSizeInternal(FileSystem, FileNode, AllocationSize, TRUE);
|
||||
}
|
||||
|
||||
if ((Flags & FspCleanupDelete) && !MemfsFileNodeMapHasChild(Memfs->FileNodeMap, FileNode))
|
||||
{
|
||||
#if defined(MEMFS_NAMED_STREAMS)
|
||||
MEMFS_FILE_NODE_MAP_ENUM_CONTEXT Context = { FALSE };
|
||||
@ -1062,7 +1074,7 @@ static NTSTATUS Write(FSP_FILE_SYSTEM *FileSystem,
|
||||
EndOffset = Offset + Length;
|
||||
if (EndOffset > FileNode->FileInfo.FileSize)
|
||||
{
|
||||
Result = SetFileSize(FileSystem, FileNode, EndOffset, FALSE, FileInfo);
|
||||
Result = SetFileSizeInternal(FileSystem, FileNode, EndOffset, FALSE);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
}
|
||||
@ -1077,9 +1089,19 @@ static NTSTATUS Write(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
|
||||
NTSTATUS Flush(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode)
|
||||
PVOID FileNode0)
|
||||
{
|
||||
/* nothing to do, since we do not cache anything */
|
||||
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
||||
|
||||
/* nothing to flush, since we do not cache anything */
|
||||
|
||||
if (0 != FileNode)
|
||||
{
|
||||
FileNode->FileInfo.LastAccessTime =
|
||||
FileNode->FileInfo.LastWriteTime =
|
||||
FileNode->FileInfo.ChangeTime = MemfsGetSystemTime();
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1120,9 +1142,8 @@ static NTSTATUS SetBasicInfo(FSP_FILE_SYSTEM *FileSystem,
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode0, UINT64 NewSize, BOOLEAN SetAllocationSize,
|
||||
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
static NTSTATUS SetFileSizeInternal(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode0, UINT64 NewSize, BOOLEAN SetAllocationSize)
|
||||
{
|
||||
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
||||
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
||||
@ -1154,8 +1175,7 @@ static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem,
|
||||
UINT64 AllocationUnit = MEMFS_SECTOR_SIZE * MEMFS_SECTORS_PER_ALLOCATION_UNIT;
|
||||
UINT64 AllocationSize = (NewSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit;
|
||||
|
||||
NTSTATUS Result = SetFileSize(FileSystem, FileNode, AllocationSize, TRUE,
|
||||
FileInfo);
|
||||
NTSTATUS Result = SetFileSizeInternal(FileSystem, FileNode, AllocationSize, TRUE);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
}
|
||||
@ -1167,6 +1187,24 @@ static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode0, UINT64 NewSize, BOOLEAN SetAllocationSize,
|
||||
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
{
|
||||
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
||||
NTSTATUS Result;
|
||||
|
||||
Result = SetFileSizeInternal(FileSystem, FileNode0, NewSize, SetAllocationSize);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
FileNode->FileInfo.LastAccessTime =
|
||||
FileNode->FileInfo.LastWriteTime =
|
||||
FileNode->FileInfo.ChangeTime = MemfsGetSystemTime();
|
||||
|
||||
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
@ -1319,6 +1357,8 @@ static NTSTATUS SetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
||||
FileNode->FileSecuritySize = FileSecuritySize;
|
||||
FileNode->FileSecurity = FileSecurity;
|
||||
|
||||
FileNode->FileInfo.ChangeTime = MemfsGetSystemTime();
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1523,6 +1563,8 @@ static NTSTATUS SetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
||||
FileNode->ReparseData = ReparseData;
|
||||
memcpy(FileNode->ReparseData, Buffer, Size);
|
||||
|
||||
FileNode->FileInfo.ChangeTime = MemfsGetSystemTime();
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1556,6 +1598,8 @@ static NTSTATUS DeleteReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
||||
FileNode->ReparseDataSize = 0;
|
||||
FileNode->ReparseData = 0;
|
||||
|
||||
FileNode->FileInfo.ChangeTime = MemfsGetSystemTime();
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
@ -1737,7 +1781,7 @@ NTSTATUS MemfsCreateFunnel(
|
||||
#if defined(MEMFS_NAMED_STREAMS)
|
||||
VolumeParams.NamedStreams = 1;
|
||||
#endif
|
||||
VolumeParams.PostCleanupOnDeleteOnly = 1;
|
||||
VolumeParams.PostCleanupWhenModifiedOnly = 1;
|
||||
if (0 != VolumePrefix)
|
||||
wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix);
|
||||
wcscpy_s(VolumeParams.FileSystemName, sizeof VolumeParams.FileSystemName / sizeof(WCHAR),
|
||||
|
@ -288,9 +288,9 @@ void create_related_test(void)
|
||||
create_related_dotest(MemfsNet, L"\\\\memfs\\share");
|
||||
}
|
||||
|
||||
void create_allocation_dotest(ULONG Flags, PWSTR Prefix)
|
||||
void create_allocation_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout)
|
||||
{
|
||||
void *memfs = memfs_start(Flags);
|
||||
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
||||
|
||||
HANDLE DirHandle, FileHandle, FileHandle2;
|
||||
NTSTATUS Result;
|
||||
@ -346,10 +346,27 @@ void create_allocation_dotest(ULONG Flags, PWSTR Prefix)
|
||||
ASSERT(Success);
|
||||
ASSERT(65536 == StandardInfo.AllocationSize.QuadPart);
|
||||
|
||||
CloseHandle(FileHandle2);
|
||||
|
||||
AllocationSize.QuadPart = 0;
|
||||
UnicodePath.Length = (USHORT)wcslen(UnicodePathBuf) * sizeof(WCHAR);
|
||||
UnicodePath.MaximumLength = sizeof UnicodePathBuf;
|
||||
UnicodePath.Buffer = UnicodePathBuf;
|
||||
InitializeObjectAttributes(&Obja, &UnicodePath, 0, DirHandle, 0);
|
||||
Result = NtCreateFile(&FileHandle2,
|
||||
FILE_READ_ATTRIBUTES, &Obja, &Iosb,
|
||||
&AllocationSize, FILE_ATTRIBUTE_NORMAL,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
FILE_OPEN, 0, 0, 0);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
|
||||
Success = GetFileInformationByHandleEx(FileHandle2, FileStandardInfo, &StandardInfo, sizeof StandardInfo);
|
||||
ASSERT(Success);
|
||||
ASSERT(65536 == StandardInfo.AllocationSize.QuadPart);
|
||||
|
||||
CloseHandle(FileHandle2);
|
||||
CloseHandle(FileHandle);
|
||||
|
||||
#if 0
|
||||
AllocationSize.QuadPart = 0;
|
||||
UnicodePath.Length = (USHORT)wcslen(UnicodePathBuf) * sizeof(WCHAR);
|
||||
UnicodePath.MaximumLength = sizeof UnicodePathBuf;
|
||||
@ -366,7 +383,6 @@ void create_allocation_dotest(ULONG Flags, PWSTR Prefix)
|
||||
ASSERT(0 == StandardInfo.AllocationSize.QuadPart);
|
||||
|
||||
CloseHandle(FileHandle);
|
||||
#endif
|
||||
|
||||
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir1\\file2",
|
||||
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||
@ -388,12 +404,20 @@ void create_allocation_test(void)
|
||||
{
|
||||
WCHAR DirBuf[MAX_PATH];
|
||||
GetTestDirectory(DirBuf);
|
||||
create_allocation_dotest(-1, DirBuf);
|
||||
create_allocation_dotest(-1, DirBuf, 0);
|
||||
}
|
||||
if (WinFspDiskTests)
|
||||
create_allocation_dotest(MemfsDisk, 0);
|
||||
{
|
||||
create_allocation_dotest(MemfsDisk, 0, 0);
|
||||
create_allocation_dotest(MemfsDisk, 0, 1000);
|
||||
create_allocation_dotest(MemfsDisk, 0, INFINITE);
|
||||
}
|
||||
if (WinFspNetTests)
|
||||
create_allocation_dotest(MemfsNet, L"\\\\memfs\\share");
|
||||
{
|
||||
create_allocation_dotest(MemfsNet, L"\\\\memfs\\share", 0);
|
||||
create_allocation_dotest(MemfsNet, L"\\\\memfs\\share", 1000);
|
||||
create_allocation_dotest(MemfsNet, L"\\\\memfs\\share", INFINITE);
|
||||
}
|
||||
}
|
||||
|
||||
void create_sd_dotest(ULONG Flags, PWSTR Prefix)
|
||||
|
Loading…
x
Reference in New Issue
Block a user