inc,dll: winfsp: FSP_FILE_SYSTEM_INTERFACE

Consolidate SetFileSize/SetAllocationSize
This commit is contained in:
Bill Zissimopoulos 2016-06-23 14:30:01 -07:00
parent ee5c584614
commit a3cfc84007
4 changed files with 79 additions and 121 deletions

View File

@ -402,41 +402,35 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
UINT64 CreationTime, UINT64 LastAccessTime, UINT64 LastWriteTime, UINT64 CreationTime, UINT64 LastAccessTime, UINT64 LastWriteTime,
FSP_FSCTL_FILE_INFO *FileInfo); 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:
* <ul>
* <li>Allocation size must always be aligned to the allocation unit boundary. The allocation
* unit is the product <code>(UINT64)SectorSize * (UINT64)SectorsPerAllocationUnit</code> from
* the FSP_FSCTL_VOLUME_PARAMS structure. The FSD will always send properly aligned allocation
* sizes when setting the allocation size.</li>
* <li>Allocation size is always greater or equal to the file size.</li>
* <li>A file size of more than the current allocation size will also extend the allocation
* size to the next allocation unit boundary.</li>
* <li>An allocation size of less than the current file size should also truncate the current
* file size.</li>
* </ul>
* *
* @param FileSystem * @param FileSystem
* The file system on which this request is posted. * The file system on which this request is posted.
* @param Request * @param Request
* The request posted by the kernel mode FSD. * The request posted by the kernel mode FSD.
* @param FileNode * @param FileNode
* The file node of the file to set the allocation size for. * The file node of the file to set the file/allocation size for.
* @param AllocationSize * @param NewSize
* Allocation size to apply to the file. Allocation size is always greater than file size. * New file/allocation size to apply to the file.
* An allocation size of less than the current file size should also truncate the current * @param SetAllocationSize
* file size. * 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.
* @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.
* @param FileInfo [out] * @param FileInfo [out]
* Pointer to a structure that will receive the file information on successful return * Pointer to a structure that will receive the file information on successful return
* from this call. This information includes file attributes, file times, etc. * 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, NTSTATUS (*SetFileSize)(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_REQ *Request,
PVOID FileNode, UINT64 FileSize, PVOID FileNode, UINT64 NewSize, BOOLEAN SetAllocationSize,
FSP_FSCTL_FILE_INFO *FileInfo); FSP_FSCTL_FILE_INFO *FileInfo);
/** /**
* Determine whether a file or directory can be deleted. * 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 * not need to perform access checks, but may performs tasks such as check for empty
* directories, etc. * directories, etc.
* *
* This function should <b>NEVER</b> 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 * @param FileSystem
* The file system on which this request is posted. * The file system on which this request is posted.
* @param Request * @param Request
@ -581,7 +581,7 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
* This ensures that this interface will always contain 64 function pointers. * This ensures that this interface will always contain 64 function pointers.
* Please update when changing the interface as it is important for future compatibility. * Please update when changing the interface as it is important for future compatibility.
*/ */
NTSTATUS (*Reserved[44])(); NTSTATUS (*Reserved[45])();
} FSP_FILE_SYSTEM_INTERFACE; } FSP_FILE_SYSTEM_INTERFACE;
#if defined(WINFSP_DLL_INTERNAL) #if defined(WINFSP_DLL_INTERNAL)
/* /*

View File

@ -690,32 +690,17 @@ FSP_API NTSTATUS FspFileSystemOpSetInformation(FSP_FILE_SYSTEM *FileSystem,
&FileInfo); &FileInfo);
break; break;
case 19/*FileAllocationInformation*/: case 19/*FileAllocationInformation*/:
if (0 != FileSystem->Interface->SetAllocationSize) if (0 != FileSystem->Interface->SetFileSize)
Result = FileSystem->Interface->SetAllocationSize(FileSystem, Request,
(PVOID)Request->Req.SetInformation.UserContext,
Request->Req.SetInformation.Info.Allocation.AllocationSize,
&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, Result = FileSystem->Interface->SetFileSize(FileSystem, Request,
(PVOID)Request->Req.SetInformation.UserContext, (PVOID)Request->Req.SetInformation.UserContext,
Request->Req.SetInformation.Info.Allocation.AllocationSize, Request->Req.SetInformation.Info.Allocation.AllocationSize, TRUE,
&FileInfo); &FileInfo);
}
}
break; break;
case 20/*FileEndOfFileInformation*/: case 20/*FileEndOfFileInformation*/:
if (0 != FileSystem->Interface->SetFileSize) if (0 != FileSystem->Interface->SetFileSize)
Result = FileSystem->Interface->SetFileSize(FileSystem, Request, Result = FileSystem->Interface->SetFileSize(FileSystem, Request,
(PVOID)Request->Req.SetInformation.UserContext, (PVOID)Request->Req.SetInformation.UserContext,
Request->Req.SetInformation.Info.EndOfFile.FileSize, Request->Req.SetInformation.Info.EndOfFile.FileSize, FALSE,
&FileInfo); &FileInfo);
break; break;
case 13/*FileDispositionInformation*/: case 13/*FileDispositionInformation*/:

View File

@ -935,9 +935,9 @@ static NTSTATUS fsp_fuse_intf_SetBasicInfo(FSP_FILE_SYSTEM *FileSystem,
return STATUS_SUCCESS; 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, FSP_FSCTL_TRANSACT_REQ *Request,
PVOID FileNode, UINT64 NewFileSize, BOOLEAN OnlyIfTruncate, PVOID FileNode, UINT64 NewSize, BOOLEAN SetAllocationSize,
FSP_FSCTL_FILE_INFO *FileInfo) FSP_FSCTL_FILE_INFO *FileInfo)
{ {
struct fuse *f = FileSystem->UserContext; struct fuse *f = FileSystem->UserContext;
@ -962,21 +962,21 @@ static NTSTATUS fsp_fuse_intf_SetFileSizeCommon(FSP_FILE_SYSTEM *FileSystem,
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
return 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 * FUSE 2.8 does not support allocation size. However if the new AllocationSize
* is less than the current FileSize we must truncate the file. * is less than the current FileSize we must truncate the file.
*/ */
if (0 != f->ops.ftruncate) 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); Result = fsp_fuse_ntstatus_from_errno(f->env, err);
} }
else else
{ {
err = f->ops.truncate(filedesc->PosixPath, NewFileSize); err = f->ops.truncate(filedesc->PosixPath, NewSize);
Result = fsp_fuse_ntstatus_from_errno(f->env, err); Result = fsp_fuse_ntstatus_from_errno(f->env, err);
} }
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
@ -984,7 +984,7 @@ static NTSTATUS fsp_fuse_intf_SetFileSizeCommon(FSP_FILE_SYSTEM *FileSystem,
AllocationUnit = (UINT64)f->VolumeParams.SectorSize * AllocationUnit = (UINT64)f->VolumeParams.SectorSize *
(UINT64)f->VolumeParams.SectorsPerAllocationUnit; (UINT64)f->VolumeParams.SectorsPerAllocationUnit;
FileInfoBuf.FileSize = NewFileSize; FileInfoBuf.FileSize = NewSize;
FileInfoBuf.AllocationSize = FileInfoBuf.AllocationSize =
(FileInfoBuf.FileSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit; (FileInfoBuf.FileSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit;
} }
@ -994,24 +994,6 @@ static NTSTATUS fsp_fuse_intf_SetFileSizeCommon(FSP_FILE_SYSTEM *FileSystem,
return STATUS_SUCCESS; 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, static int fsp_fuse_intf_CanDeleteAddDirInfo(void *buf, const char *name,
const struct fuse_stat *stbuf, fuse_off_t off) 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_Flush,
fsp_fuse_intf_GetFileInfo, fsp_fuse_intf_GetFileInfo,
fsp_fuse_intf_SetBasicInfo, fsp_fuse_intf_SetBasicInfo,
fsp_fuse_intf_SetAllocationSize,
fsp_fuse_intf_SetFileSize, fsp_fuse_intf_SetFileSize,
fsp_fuse_intf_CanDelete, fsp_fuse_intf_CanDelete,
fsp_fuse_intf_Rename, fsp_fuse_intf_Rename,

View File

@ -273,7 +273,7 @@ BOOLEAN MemfsFileNodeMapEnumerateDescendants(MEMFS_FILE_NODE_MAP *FileNodeMap, M
static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem, static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_REQ *Request,
PVOID FileNode0, UINT64 FileSize, PVOID FileNode0, UINT64 NewSize, BOOLEAN SetAllocationSize,
FSP_FSCTL_FILE_INFO *FileInfo); FSP_FSCTL_FILE_INFO *FileInfo);
static NTSTATUS GetVolumeInfo(FSP_FILE_SYSTEM *FileSystem, static NTSTATUS GetVolumeInfo(FSP_FILE_SYSTEM *FileSystem,
@ -564,7 +564,7 @@ static NTSTATUS Write(FSP_FILE_SYSTEM *FileSystem,
Offset = FileNode->FileInfo.FileSize; Offset = FileNode->FileInfo.FileSize;
EndOffset = Offset + Length; EndOffset = Offset + Length;
if (EndOffset > FileNode->FileInfo.FileSize) 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)); memcpy((PUINT8)FileNode->FileData + Offset, Buffer, (size_t)(EndOffset - Offset));
@ -617,59 +617,52 @@ static NTSTATUS SetBasicInfo(FSP_FILE_SYSTEM *FileSystem,
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
static NTSTATUS SetAllocationSize(FSP_FILE_SYSTEM *FileSystem, static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_REQ *Request,
PVOID FileNode0, UINT64 AllocationSize, PVOID FileNode0, UINT64 NewSize, BOOLEAN SetAllocationSize,
FSP_FSCTL_FILE_INFO *FileInfo) FSP_FSCTL_FILE_INFO *FileInfo)
{ {
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext; MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0; MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
PVOID FileData;
if (FileNode->FileInfo.AllocationSize != AllocationSize) if (SetAllocationSize)
{ {
if (AllocationSize > Memfs->MaxFileSize) if (FileNode->FileInfo.AllocationSize != NewSize)
{
if (NewSize > Memfs->MaxFileSize)
return STATUS_DISK_FULL; return STATUS_DISK_FULL;
FileData = realloc(FileNode->FileData, (size_t)AllocationSize); PVOID FileData = realloc(FileNode->FileData, (size_t)NewSize);
if (0 == FileData && 0 != AllocationSize) if (0 == FileData && 0 != NewSize)
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
FileNode->FileData = FileData; FileNode->FileData = FileData;
FileNode->FileInfo.AllocationSize = AllocationSize; FileNode->FileInfo.AllocationSize = NewSize;
if (FileNode->FileInfo.FileSize > AllocationSize) if (FileNode->FileInfo.FileSize > NewSize)
FileNode->FileInfo.FileSize = AllocationSize; FileNode->FileInfo.FileSize = NewSize;
} }
*FileInfo = FileNode->FileInfo;
return STATUS_SUCCESS;
} }
else
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 != NewSize)
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 AllocationUnit = MEMFS_SECTOR_SIZE * MEMFS_SECTORS_PER_ALLOCATION_UNIT;
UINT64 AllocationSize = (FileSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit; UINT64 AllocationSize = (NewSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit;
NTSTATUS Result = SetAllocationSize(FileSystem, Request, FileNode, AllocationSize, FileInfo); NTSTATUS Result = SetFileSize(FileSystem, Request, FileNode, AllocationSize, TRUE,
FileInfo);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
return Result; return Result;
} }
if (FileNode->FileInfo.FileSize < FileSize) if (FileNode->FileInfo.FileSize < NewSize)
memset((PUINT8)FileNode->FileData + FileNode->FileInfo.FileSize, 0, memset((PUINT8)FileNode->FileData + FileNode->FileInfo.FileSize, 0,
(size_t)(FileSize - FileNode->FileInfo.FileSize)); (size_t)(NewSize - FileNode->FileInfo.FileSize));
FileNode->FileInfo.FileSize = FileSize; FileNode->FileInfo.FileSize = NewSize;
}
} }
*FileInfo = FileNode->FileInfo; *FileInfo = FileNode->FileInfo;
@ -952,7 +945,6 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
Flush, Flush,
GetFileInfo, GetFileInfo,
SetBasicInfo, SetBasicInfo,
SetAllocationSize,
SetFileSize, SetFileSize,
CanDelete, CanDelete,
Rename, Rename,