From a3cfc84007a15609728b8e8c85e0fcdb8a1b4737 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Thu, 23 Jun 2016 14:30:01 -0700 Subject: [PATCH] inc,dll: winfsp: FSP_FILE_SYSTEM_INTERFACE Consolidate SetFileSize/SetAllocationSize --- inc/winfsp/winfsp.h | 62 +++++++++++++++--------------- src/dll/fsop.c | 23 ++--------- src/dll/fuse/fuse_intf.c | 33 ++++------------ tst/memfs/memfs.cpp | 82 ++++++++++++++++++---------------------- 4 files changed, 79 insertions(+), 121 deletions(-) diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h index 6fc4394c..f2dbe968 100644 --- a/inc/winfsp/winfsp.h +++ b/inc/winfsp/winfsp.h @@ -402,41 +402,35 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE UINT64 CreationTime, UINT64 LastAccessTime, UINT64 LastWriteTime, FSP_FSCTL_FILE_INFO *FileInfo); /** - * Set file allocation size. + * Set file/allocation size. + * + * This function is used to change a file's sizes. Windows file systems maintain two kinds + * of sizes: the file size is where the End Of File (EOF) is, and the allocation size is the + * actual size that a file takes up on the "disk". + * + * The rules regarding file/allocation size are: + * * * @param FileSystem * The file system on which this request is posted. * @param Request * The request posted by the kernel mode FSD. * @param FileNode - * The file node of the file to set the allocation size for. - * @param AllocationSize - * Allocation size to apply to the file. Allocation size is always greater than file size. - * An allocation size of less than the current file size should also truncate the current - * file size. - * @param FileInfo [out] - * Pointer to a structure that will receive the file information on successful return - * from this call. This information includes file attributes, file times, etc. - * @return - * STATUS_SUCCESS on error code. - */ - NTSTATUS (*SetAllocationSize)(FSP_FILE_SYSTEM *FileSystem, - FSP_FSCTL_TRANSACT_REQ *Request, - PVOID FileNode, UINT64 AllocationSize, - FSP_FSCTL_FILE_INFO *FileInfo); - /** - * Set file size. - * - * @param FileSystem - * The file system on which this request is posted. - * @param Request - * The request posted by the kernel mode FSD. - * @param FileNode - * The file node of the file to set the size for. - * @param FileSize - * FileSize size to apply to the file. Allocation size is always greater than file size. - * A file size of more than the current allocation size will also extend the allocation - * size to the next allocation unit boundary. + * The file node of the file to set the file/allocation size for. + * @param NewSize + * New file/allocation size to apply to the file. + * @param SetAllocationSize + * If TRUE, then the allocation size is being set. if FALSE, then the file size is being set. * @param FileInfo [out] * Pointer to a structure that will receive the file information on successful return * from this call. This information includes file attributes, file times, etc. @@ -445,7 +439,7 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE */ NTSTATUS (*SetFileSize)(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, - PVOID FileNode, UINT64 FileSize, + PVOID FileNode, UINT64 NewSize, BOOLEAN SetAllocationSize, FSP_FSCTL_FILE_INFO *FileInfo); /** * Determine whether a file or directory can be deleted. @@ -454,6 +448,12 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE * not need to perform access checks, but may performs tasks such as check for empty * directories, etc. * + * This function should NEVER delete the file or directory in question. Deletion should + * happen during Cleanup with Delete==TRUE. + * + * This function gets called when Win32 API's such as DeleteFile or RemoveDirectory are used. + * It does not get called when a file or directory is opened with FILE_DELETE_ON_CLOSE. + * * @param FileSystem * The file system on which this request is posted. * @param Request @@ -581,7 +581,7 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE * This ensures that this interface will always contain 64 function pointers. * Please update when changing the interface as it is important for future compatibility. */ - NTSTATUS (*Reserved[44])(); + NTSTATUS (*Reserved[45])(); } FSP_FILE_SYSTEM_INTERFACE; #if defined(WINFSP_DLL_INTERNAL) /* diff --git a/src/dll/fsop.c b/src/dll/fsop.c index 321fa8a0..ae7ef70b 100644 --- a/src/dll/fsop.c +++ b/src/dll/fsop.c @@ -690,32 +690,17 @@ FSP_API NTSTATUS FspFileSystemOpSetInformation(FSP_FILE_SYSTEM *FileSystem, &FileInfo); break; case 19/*FileAllocationInformation*/: - if (0 != FileSystem->Interface->SetAllocationSize) - Result = FileSystem->Interface->SetAllocationSize(FileSystem, Request, + if (0 != FileSystem->Interface->SetFileSize) + Result = FileSystem->Interface->SetFileSize(FileSystem, Request, (PVOID)Request->Req.SetInformation.UserContext, - Request->Req.SetInformation.Info.Allocation.AllocationSize, + Request->Req.SetInformation.Info.Allocation.AllocationSize, TRUE, &FileInfo); - else - if (0 != FileSystem->Interface->GetFileInfo && - 0 != FileSystem->Interface->SetFileSize) - { - Result = FileSystem->Interface->GetFileInfo(FileSystem, Request, - (PVOID)Request->Req.SetInformation.UserContext, &FileInfo); - if (NT_SUCCESS(Result) && - Request->Req.SetInformation.Info.Allocation.AllocationSize < FileInfo.FileSize) - { - Result = FileSystem->Interface->SetFileSize(FileSystem, Request, - (PVOID)Request->Req.SetInformation.UserContext, - Request->Req.SetInformation.Info.Allocation.AllocationSize, - &FileInfo); - } - } break; case 20/*FileEndOfFileInformation*/: if (0 != FileSystem->Interface->SetFileSize) Result = FileSystem->Interface->SetFileSize(FileSystem, Request, (PVOID)Request->Req.SetInformation.UserContext, - Request->Req.SetInformation.Info.EndOfFile.FileSize, + Request->Req.SetInformation.Info.EndOfFile.FileSize, FALSE, &FileInfo); break; case 13/*FileDispositionInformation*/: diff --git a/src/dll/fuse/fuse_intf.c b/src/dll/fuse/fuse_intf.c index 95a0e315..406792e6 100644 --- a/src/dll/fuse/fuse_intf.c +++ b/src/dll/fuse/fuse_intf.c @@ -935,9 +935,9 @@ static NTSTATUS fsp_fuse_intf_SetBasicInfo(FSP_FILE_SYSTEM *FileSystem, return STATUS_SUCCESS; } -static NTSTATUS fsp_fuse_intf_SetFileSizeCommon(FSP_FILE_SYSTEM *FileSystem, +static NTSTATUS fsp_fuse_intf_SetFileSize(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, - PVOID FileNode, UINT64 NewFileSize, BOOLEAN OnlyIfTruncate, + PVOID FileNode, UINT64 NewSize, BOOLEAN SetAllocationSize, FSP_FSCTL_FILE_INFO *FileInfo) { struct fuse *f = FileSystem->UserContext; @@ -962,21 +962,21 @@ static NTSTATUS fsp_fuse_intf_SetFileSizeCommon(FSP_FILE_SYSTEM *FileSystem, if (!NT_SUCCESS(Result)) return Result; - if (!OnlyIfTruncate || FileInfoBuf.FileSize > NewFileSize) + if (!SetAllocationSize || FileInfoBuf.FileSize > NewSize) { /* - * OnlyIfTruncate explanation: + * "FileInfoBuf.FileSize > NewSize" explanation: * FUSE 2.8 does not support allocation size. However if the new AllocationSize * is less than the current FileSize we must truncate the file. */ if (0 != f->ops.ftruncate) { - err = f->ops.ftruncate(filedesc->PosixPath, NewFileSize, &fi); + err = f->ops.ftruncate(filedesc->PosixPath, NewSize, &fi); Result = fsp_fuse_ntstatus_from_errno(f->env, err); } else { - err = f->ops.truncate(filedesc->PosixPath, NewFileSize); + err = f->ops.truncate(filedesc->PosixPath, NewSize); Result = fsp_fuse_ntstatus_from_errno(f->env, err); } if (!NT_SUCCESS(Result)) @@ -984,7 +984,7 @@ static NTSTATUS fsp_fuse_intf_SetFileSizeCommon(FSP_FILE_SYSTEM *FileSystem, AllocationUnit = (UINT64)f->VolumeParams.SectorSize * (UINT64)f->VolumeParams.SectorsPerAllocationUnit; - FileInfoBuf.FileSize = NewFileSize; + FileInfoBuf.FileSize = NewSize; FileInfoBuf.AllocationSize = (FileInfoBuf.FileSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit; } @@ -994,24 +994,6 @@ static NTSTATUS fsp_fuse_intf_SetFileSizeCommon(FSP_FILE_SYSTEM *FileSystem, return STATUS_SUCCESS; } -static NTSTATUS fsp_fuse_intf_SetAllocationSize(FSP_FILE_SYSTEM *FileSystem, - FSP_FSCTL_TRANSACT_REQ *Request, - PVOID FileNode, UINT64 AllocationSize, - FSP_FSCTL_FILE_INFO *FileInfo) -{ - return fsp_fuse_intf_SetFileSizeCommon(FileSystem, Request, FileNode, AllocationSize, TRUE, - FileInfo); -} - -static NTSTATUS fsp_fuse_intf_SetFileSize(FSP_FILE_SYSTEM *FileSystem, - FSP_FSCTL_TRANSACT_REQ *Request, - PVOID FileNode, UINT64 FileSize, - FSP_FSCTL_FILE_INFO *FileInfo) -{ - return fsp_fuse_intf_SetFileSizeCommon(FileSystem, Request, FileNode, FileSize, FALSE, - FileInfo); -} - static int fsp_fuse_intf_CanDeleteAddDirInfo(void *buf, const char *name, const struct fuse_stat *stbuf, fuse_off_t off) { @@ -1448,7 +1430,6 @@ FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf = fsp_fuse_intf_Flush, fsp_fuse_intf_GetFileInfo, fsp_fuse_intf_SetBasicInfo, - fsp_fuse_intf_SetAllocationSize, fsp_fuse_intf_SetFileSize, fsp_fuse_intf_CanDelete, fsp_fuse_intf_Rename, diff --git a/tst/memfs/memfs.cpp b/tst/memfs/memfs.cpp index 2de91bf7..486f5c4d 100644 --- a/tst/memfs/memfs.cpp +++ b/tst/memfs/memfs.cpp @@ -273,7 +273,7 @@ BOOLEAN MemfsFileNodeMapEnumerateDescendants(MEMFS_FILE_NODE_MAP *FileNodeMap, M static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, - PVOID FileNode0, UINT64 FileSize, + PVOID FileNode0, UINT64 NewSize, BOOLEAN SetAllocationSize, FSP_FSCTL_FILE_INFO *FileInfo); static NTSTATUS GetVolumeInfo(FSP_FILE_SYSTEM *FileSystem, @@ -564,7 +564,7 @@ static NTSTATUS Write(FSP_FILE_SYSTEM *FileSystem, Offset = FileNode->FileInfo.FileSize; EndOffset = Offset + Length; if (EndOffset > FileNode->FileInfo.FileSize) - SetFileSize(FileSystem, Request, FileNode, EndOffset, FileInfo); + SetFileSize(FileSystem, Request, FileNode, EndOffset, FALSE, FileInfo); } memcpy((PUINT8)FileNode->FileData + Offset, Buffer, (size_t)(EndOffset - Offset)); @@ -617,59 +617,52 @@ static NTSTATUS SetBasicInfo(FSP_FILE_SYSTEM *FileSystem, return STATUS_SUCCESS; } -static NTSTATUS SetAllocationSize(FSP_FILE_SYSTEM *FileSystem, +static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, - PVOID FileNode0, UINT64 AllocationSize, + PVOID FileNode0, UINT64 NewSize, BOOLEAN SetAllocationSize, FSP_FSCTL_FILE_INFO *FileInfo) { MEMFS *Memfs = (MEMFS *)FileSystem->UserContext; MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0; - PVOID FileData; - if (FileNode->FileInfo.AllocationSize != AllocationSize) + if (SetAllocationSize) { - if (AllocationSize > Memfs->MaxFileSize) - return STATUS_DISK_FULL; - - FileData = realloc(FileNode->FileData, (size_t)AllocationSize); - if (0 == FileData && 0 != AllocationSize) - return STATUS_INSUFFICIENT_RESOURCES; - - FileNode->FileData = FileData; - - FileNode->FileInfo.AllocationSize = AllocationSize; - if (FileNode->FileInfo.FileSize > AllocationSize) - FileNode->FileInfo.FileSize = AllocationSize; - } - - *FileInfo = FileNode->FileInfo; - - return STATUS_SUCCESS; -} - -static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem, - FSP_FSCTL_TRANSACT_REQ *Request, - PVOID FileNode0, UINT64 FileSize, - FSP_FSCTL_FILE_INFO *FileInfo) -{ - MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0; - - if (FileNode->FileInfo.FileSize != FileSize) - { - if (FileNode->FileInfo.AllocationSize < FileSize) + if (FileNode->FileInfo.AllocationSize != NewSize) { - UINT64 AllocationUnit = MEMFS_SECTOR_SIZE * MEMFS_SECTORS_PER_ALLOCATION_UNIT; - UINT64 AllocationSize = (FileSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit; + if (NewSize > Memfs->MaxFileSize) + return STATUS_DISK_FULL; - NTSTATUS Result = SetAllocationSize(FileSystem, Request, FileNode, AllocationSize, FileInfo); - if (!NT_SUCCESS(Result)) - return Result; + PVOID FileData = realloc(FileNode->FileData, (size_t)NewSize); + if (0 == FileData && 0 != NewSize) + return STATUS_INSUFFICIENT_RESOURCES; + + FileNode->FileData = FileData; + + FileNode->FileInfo.AllocationSize = NewSize; + if (FileNode->FileInfo.FileSize > NewSize) + FileNode->FileInfo.FileSize = NewSize; } + } + else + { + if (FileNode->FileInfo.FileSize != NewSize) + { + if (FileNode->FileInfo.AllocationSize < NewSize) + { + UINT64 AllocationUnit = MEMFS_SECTOR_SIZE * MEMFS_SECTORS_PER_ALLOCATION_UNIT; + UINT64 AllocationSize = (NewSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit; - if (FileNode->FileInfo.FileSize < FileSize) - memset((PUINT8)FileNode->FileData + FileNode->FileInfo.FileSize, 0, - (size_t)(FileSize - FileNode->FileInfo.FileSize)); - FileNode->FileInfo.FileSize = FileSize; + NTSTATUS Result = SetFileSize(FileSystem, Request, FileNode, AllocationSize, TRUE, + FileInfo); + if (!NT_SUCCESS(Result)) + return Result; + } + + if (FileNode->FileInfo.FileSize < NewSize) + memset((PUINT8)FileNode->FileData + FileNode->FileInfo.FileSize, 0, + (size_t)(NewSize - FileNode->FileInfo.FileSize)); + FileNode->FileInfo.FileSize = NewSize; + } } *FileInfo = FileNode->FileInfo; @@ -952,7 +945,6 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface = Flush, GetFileInfo, SetBasicInfo, - SetAllocationSize, SetFileSize, CanDelete, Rename,