dll: fuse: implement new Delete design and POSIX semantics

This commit is contained in:
Bill Zissimopoulos
2021-10-19 17:54:01 +01:00
parent 19823d84de
commit a4d7aee6f5
3 changed files with 72 additions and 43 deletions

View File

@ -34,7 +34,10 @@ VOID fsp_fuse_op_enter_lock(FSP_FILE_SYSTEM *FileSystem,
(FspFsctlTransactCleanupKind == Request->Kind &&
Request->Req.Cleanup.Delete) ||
(FspFsctlTransactSetInformationKind == Request->Kind &&
10/*FileRenameInformation*/ == Request->Req.SetInformation.FileInformationClass) ||
(10/*FileRenameInformation*/ == Request->Req.SetInformation.FileInformationClass ||
65/*FileRenameInformationEx*/ == Request->Req.SetInformation.FileInformationClass ||
(64/*FileDispositionInformationEx*/ == Request->Req.SetInformation.FileInformationClass &&
3/*DELETE|POSIX_SEMANTICS*/ == (3 & Request->Req.SetInformation.Info.DispositionEx.Flags)))) ||
FspFsctlTransactSetVolumeInformationKind == Request->Kind ||
(FspFsctlTransactFlushBuffersKind == Request->Kind &&
0 == Request->Req.FlushBuffers.UserContext &&
@ -48,7 +51,9 @@ VOID fsp_fuse_op_enter_lock(FSP_FILE_SYSTEM *FileSystem,
else
if (FspFsctlTransactCreateKind == Request->Kind ||
(FspFsctlTransactSetInformationKind == Request->Kind &&
13/*FileDispositionInformation*/ == Request->Req.SetInformation.FileInformationClass) ||
(13/*FileDispositionInformation*/ == Request->Req.SetInformation.FileInformationClass ||
(64/*FileDispositionInformationEx*/ == Request->Req.SetInformation.FileInformationClass &&
3/*DELETE|POSIX_SEMANTICS*/ != (3 & Request->Req.SetInformation.Info.DispositionEx.Flags)))) ||
FspFsctlTransactQueryDirectoryKind == Request->Kind ||
FspFsctlTransactQueryVolumeInformationKind == Request->Kind ||
/* FSCTL_GET_REPARSE_POINT may access namespace */
@ -78,7 +83,10 @@ VOID fsp_fuse_op_leave_unlock(FSP_FILE_SYSTEM *FileSystem,
(FspFsctlTransactCleanupKind == Request->Kind &&
Request->Req.Cleanup.Delete) ||
(FspFsctlTransactSetInformationKind == Request->Kind &&
10/*FileRenameInformation*/ == Request->Req.SetInformation.FileInformationClass) ||
(10/*FileRenameInformation*/ == Request->Req.SetInformation.FileInformationClass ||
65/*FileRenameInformationEx*/ == Request->Req.SetInformation.FileInformationClass ||
(64/*FileDispositionInformationEx*/ == Request->Req.SetInformation.FileInformationClass &&
3/*DELETE|POSIX_SEMANTICS*/ == (3 & Request->Req.SetInformation.Info.DispositionEx.Flags)))) ||
FspFsctlTransactSetVolumeInformationKind == Request->Kind ||
(FspFsctlTransactFlushBuffersKind == Request->Kind &&
0 == Request->Req.FlushBuffers.UserContext &&
@ -92,7 +100,9 @@ VOID fsp_fuse_op_leave_unlock(FSP_FILE_SYSTEM *FileSystem,
else
if (FspFsctlTransactCreateKind == Request->Kind ||
(FspFsctlTransactSetInformationKind == Request->Kind &&
13/*FileDispositionInformation*/ == Request->Req.SetInformation.FileInformationClass) ||
(13/*FileDispositionInformation*/ == Request->Req.SetInformation.FileInformationClass ||
(64/*FileDispositionInformationEx*/ == Request->Req.SetInformation.FileInformationClass &&
3/*DELETE|POSIX_SEMANTICS*/ != (3 & Request->Req.SetInformation.Info.DispositionEx.Flags)))) ||
FspFsctlTransactQueryDirectoryKind == Request->Kind ||
FspFsctlTransactQueryVolumeInformationKind == Request->Kind ||
/* FSCTL_GET_REPARSE_POINT may access namespace */
@ -1157,42 +1167,6 @@ static NTSTATUS fsp_fuse_intf_Overwrite(FSP_FILE_SYSTEM *FileSystem,
&Uid, &Gid, &Mode, FileInfo);
}
static VOID fsp_fuse_intf_Cleanup(FSP_FILE_SYSTEM *FileSystem,
PVOID FileDesc, PWSTR FileName, ULONG Flags)
{
struct fuse *f = FileSystem->UserContext;
struct fsp_fuse_file_desc *filedesc = FileDesc;
/*
* In Windows a DeleteFile/RemoveDirectory is the sequence of the following:
* Create(FILE_OPEN)
* SetInformation(Disposition)
* Cleanup
* Close
*
* The FSD maintains a count of how many handles are currently open for a file. When the
* last handle is closed *and* the disposition flag is set the FSD sends us a Cleanup with
* the Delete flag set.
*
* Notice that when we receive a Cleanup with Delete set there can be no open handles other
* than ours. [Even if there is a concurrent Open of this file, the FSD will fail it with
* STATUS_DELETE_PENDING.] This means that we do not need to worry about the hard_remove
* FUSE option and can safely remove the file at this time.
*/
if (Flags & FspCleanupDelete)
if (filedesc->IsDirectory && !filedesc->IsReparsePoint)
{
if (0 != f->ops.rmdir)
f->ops.rmdir(filedesc->PosixPath);
}
else
{
if (0 != f->ops.unlink)
f->ops.unlink(filedesc->PosixPath);
}
}
static VOID fsp_fuse_intf_Close(FSP_FILE_SYSTEM *FileSystem,
PVOID FileDesc)
{
@ -1605,6 +1579,54 @@ static NTSTATUS fsp_fuse_intf_CanDelete(FSP_FILE_SYSTEM *FileSystem,
return STATUS_SUCCESS;
}
static NTSTATUS fsp_fuse_intf_Delete(FSP_FILE_SYSTEM *FileSystem,
PVOID FileDesc, PWSTR FileName, ULONG Flags)
{
switch (Flags)
{
case FILE_DISPOSITION_DO_NOT_DELETE:
return STATUS_SUCCESS;
case FILE_DISPOSITION_DELETE:
return fsp_fuse_intf_CanDelete(FileSystem, FileDesc, FileName);
case FILE_DISPOSITION_DELETE | FILE_DISPOSITION_POSIX_SEMANTICS:
case -1:
{
struct fuse *f = FileSystem->UserContext;
struct fsp_fuse_file_desc *filedesc = FileDesc;
int err;
NTSTATUS Result = STATUS_SUCCESS;
if (filedesc->IsDirectory && !filedesc->IsReparsePoint)
{
if (0 != f->ops.rmdir)
{
err = f->ops.rmdir(filedesc->PosixPath);
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
}
else
Result = STATUS_INVALID_DEVICE_REQUEST;
}
else
{
if (0 != f->ops.unlink)
{
err = f->ops.unlink(filedesc->PosixPath);
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
}
else
Result = STATUS_INVALID_DEVICE_REQUEST;
}
return Result;
}
default:
return STATUS_INVALID_PARAMETER;
}
}
static NTSTATUS fsp_fuse_intf_Rename(FSP_FILE_SYSTEM *FileSystem,
PVOID FileDesc,
PWSTR FileName, PWSTR NewFileName, BOOLEAN ReplaceIfExists)
@ -2424,7 +2446,7 @@ FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
0,
fsp_fuse_intf_Open,
0,
fsp_fuse_intf_Cleanup,
0,
fsp_fuse_intf_Close,
fsp_fuse_intf_Read,
fsp_fuse_intf_Write,
@ -2432,7 +2454,7 @@ FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
fsp_fuse_intf_GetFileInfo,
fsp_fuse_intf_SetBasicInfo,
fsp_fuse_intf_SetFileSize,
fsp_fuse_intf_CanDelete,
0,
fsp_fuse_intf_Rename,
fsp_fuse_intf_GetSecurity,
fsp_fuse_intf_SetSecurity,
@ -2449,6 +2471,7 @@ FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
fsp_fuse_intf_Overwrite,
fsp_fuse_intf_GetEa,
fsp_fuse_intf_SetEa,
fsp_fuse_intf_Delete,
};
/*