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:
+ *
+ * - Allocation size must always be aligned to the allocation unit boundary. The allocation
+ * unit is the product
(UINT64)SectorSize * (UINT64)SectorsPerAllocationUnit
from
+ * the FSP_FSCTL_VOLUME_PARAMS structure. The FSD will always send properly aligned allocation
+ * sizes when setting the allocation size.
+ * - Allocation size is always greater or equal to the file size.
+ * - A file size of more than the current allocation size will also extend the allocation
+ * size to the next allocation unit boundary.
+ * - An allocation size of less than the current file size should also truncate the current
+ * 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 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,