mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-23 00:43:00 -05:00
dll: fuse: implement new Delete design and POSIX semantics
This commit is contained in:
parent
19823d84de
commit
a4d7aee6f5
@ -96,6 +96,7 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
|||||||
FSP_FUSE_CORE_OPT("VolumeInfoTimeout=", set_VolumeInfoTimeout, 1),
|
FSP_FUSE_CORE_OPT("VolumeInfoTimeout=", set_VolumeInfoTimeout, 1),
|
||||||
FSP_FUSE_CORE_OPT("VolumeInfoTimeout=%d", VolumeParams.VolumeInfoTimeout, 0),
|
FSP_FUSE_CORE_OPT("VolumeInfoTimeout=%d", VolumeParams.VolumeInfoTimeout, 0),
|
||||||
FSP_FUSE_CORE_OPT("KeepFileCache=", set_KeepFileCache, 1),
|
FSP_FUSE_CORE_OPT("KeepFileCache=", set_KeepFileCache, 1),
|
||||||
|
FSP_FUSE_CORE_OPT("LegacyUnlinkRename=", set_LegacyUnlinkRename, 1),
|
||||||
FSP_FUSE_CORE_OPT("ThreadCount=%u", ThreadCount, 0),
|
FSP_FUSE_CORE_OPT("ThreadCount=%u", ThreadCount, 0),
|
||||||
FUSE_OPT_KEY("UNC=", 'U'),
|
FUSE_OPT_KEY("UNC=", 'U'),
|
||||||
FUSE_OPT_KEY("--UNC=", 'U'),
|
FUSE_OPT_KEY("--UNC=", 'U'),
|
||||||
@ -421,6 +422,7 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
|||||||
" -o EaTimeout=N extended attribute timeout (millis)\n"
|
" -o EaTimeout=N extended attribute timeout (millis)\n"
|
||||||
" -o VolumeInfoTimeout=N volume info timeout (millis)\n"
|
" -o VolumeInfoTimeout=N volume info timeout (millis)\n"
|
||||||
" -o KeepFileCache do not discard cache when files are closed\n"
|
" -o KeepFileCache do not discard cache when files are closed\n"
|
||||||
|
" -o LegacyUnlinkRename do not support new POSIX unlink/rename\n"
|
||||||
" -o ThreadCount number of file system dispatcher threads\n"
|
" -o ThreadCount number of file system dispatcher threads\n"
|
||||||
);
|
);
|
||||||
opt_data->help = 1;
|
opt_data->help = 1;
|
||||||
@ -563,6 +565,7 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
|||||||
opt_data.VolumeParams.Version = sizeof(FSP_FSCTL_VOLUME_PARAMS);
|
opt_data.VolumeParams.Version = sizeof(FSP_FSCTL_VOLUME_PARAMS);
|
||||||
opt_data.VolumeParams.FileInfoTimeout = 1000;
|
opt_data.VolumeParams.FileInfoTimeout = 1000;
|
||||||
opt_data.VolumeParams.FlushAndPurgeOnCleanup = TRUE;
|
opt_data.VolumeParams.FlushAndPurgeOnCleanup = TRUE;
|
||||||
|
opt_data.VolumeParams.SupportsPosixUnlinkRename = TRUE;
|
||||||
|
|
||||||
if (-1 == fsp_fuse_core_opt_parse(env, args, &opt_data, /*help=*/1))
|
if (-1 == fsp_fuse_core_opt_parse(env, args, &opt_data, /*help=*/1))
|
||||||
{
|
{
|
||||||
@ -623,6 +626,8 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
|||||||
opt_data.VolumeParams.VolumeInfoTimeoutValid = 1;
|
opt_data.VolumeParams.VolumeInfoTimeoutValid = 1;
|
||||||
if (opt_data.set_KeepFileCache)
|
if (opt_data.set_KeepFileCache)
|
||||||
opt_data.VolumeParams.FlushAndPurgeOnCleanup = FALSE;
|
opt_data.VolumeParams.FlushAndPurgeOnCleanup = FALSE;
|
||||||
|
if (opt_data.set_LegacyUnlinkRename)
|
||||||
|
opt_data.VolumeParams.SupportsPosixUnlinkRename = FALSE;
|
||||||
opt_data.VolumeParams.CaseSensitiveSearch = TRUE;
|
opt_data.VolumeParams.CaseSensitiveSearch = TRUE;
|
||||||
opt_data.VolumeParams.CasePreservedNames = TRUE;
|
opt_data.VolumeParams.CasePreservedNames = TRUE;
|
||||||
opt_data.VolumeParams.PersistentAcls = TRUE;
|
opt_data.VolumeParams.PersistentAcls = TRUE;
|
||||||
|
@ -34,7 +34,10 @@ VOID fsp_fuse_op_enter_lock(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
(FspFsctlTransactCleanupKind == Request->Kind &&
|
(FspFsctlTransactCleanupKind == Request->Kind &&
|
||||||
Request->Req.Cleanup.Delete) ||
|
Request->Req.Cleanup.Delete) ||
|
||||||
(FspFsctlTransactSetInformationKind == Request->Kind &&
|
(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 ||
|
FspFsctlTransactSetVolumeInformationKind == Request->Kind ||
|
||||||
(FspFsctlTransactFlushBuffersKind == Request->Kind &&
|
(FspFsctlTransactFlushBuffersKind == Request->Kind &&
|
||||||
0 == Request->Req.FlushBuffers.UserContext &&
|
0 == Request->Req.FlushBuffers.UserContext &&
|
||||||
@ -48,7 +51,9 @@ VOID fsp_fuse_op_enter_lock(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
else
|
else
|
||||||
if (FspFsctlTransactCreateKind == Request->Kind ||
|
if (FspFsctlTransactCreateKind == Request->Kind ||
|
||||||
(FspFsctlTransactSetInformationKind == 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 ||
|
FspFsctlTransactQueryDirectoryKind == Request->Kind ||
|
||||||
FspFsctlTransactQueryVolumeInformationKind == Request->Kind ||
|
FspFsctlTransactQueryVolumeInformationKind == Request->Kind ||
|
||||||
/* FSCTL_GET_REPARSE_POINT may access namespace */
|
/* FSCTL_GET_REPARSE_POINT may access namespace */
|
||||||
@ -78,7 +83,10 @@ VOID fsp_fuse_op_leave_unlock(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
(FspFsctlTransactCleanupKind == Request->Kind &&
|
(FspFsctlTransactCleanupKind == Request->Kind &&
|
||||||
Request->Req.Cleanup.Delete) ||
|
Request->Req.Cleanup.Delete) ||
|
||||||
(FspFsctlTransactSetInformationKind == Request->Kind &&
|
(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 ||
|
FspFsctlTransactSetVolumeInformationKind == Request->Kind ||
|
||||||
(FspFsctlTransactFlushBuffersKind == Request->Kind &&
|
(FspFsctlTransactFlushBuffersKind == Request->Kind &&
|
||||||
0 == Request->Req.FlushBuffers.UserContext &&
|
0 == Request->Req.FlushBuffers.UserContext &&
|
||||||
@ -92,7 +100,9 @@ VOID fsp_fuse_op_leave_unlock(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
else
|
else
|
||||||
if (FspFsctlTransactCreateKind == Request->Kind ||
|
if (FspFsctlTransactCreateKind == Request->Kind ||
|
||||||
(FspFsctlTransactSetInformationKind == 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 ||
|
FspFsctlTransactQueryDirectoryKind == Request->Kind ||
|
||||||
FspFsctlTransactQueryVolumeInformationKind == Request->Kind ||
|
FspFsctlTransactQueryVolumeInformationKind == Request->Kind ||
|
||||||
/* FSCTL_GET_REPARSE_POINT may access namespace */
|
/* 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);
|
&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,
|
static VOID fsp_fuse_intf_Close(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileDesc)
|
PVOID FileDesc)
|
||||||
{
|
{
|
||||||
@ -1605,6 +1579,54 @@ static NTSTATUS fsp_fuse_intf_CanDelete(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return STATUS_SUCCESS;
|
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,
|
static NTSTATUS fsp_fuse_intf_Rename(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileDesc,
|
PVOID FileDesc,
|
||||||
PWSTR FileName, PWSTR NewFileName, BOOLEAN ReplaceIfExists)
|
PWSTR FileName, PWSTR NewFileName, BOOLEAN ReplaceIfExists)
|
||||||
@ -2424,7 +2446,7 @@ FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
|
|||||||
0,
|
0,
|
||||||
fsp_fuse_intf_Open,
|
fsp_fuse_intf_Open,
|
||||||
0,
|
0,
|
||||||
fsp_fuse_intf_Cleanup,
|
0,
|
||||||
fsp_fuse_intf_Close,
|
fsp_fuse_intf_Close,
|
||||||
fsp_fuse_intf_Read,
|
fsp_fuse_intf_Read,
|
||||||
fsp_fuse_intf_Write,
|
fsp_fuse_intf_Write,
|
||||||
@ -2432,7 +2454,7 @@ FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
|
|||||||
fsp_fuse_intf_GetFileInfo,
|
fsp_fuse_intf_GetFileInfo,
|
||||||
fsp_fuse_intf_SetBasicInfo,
|
fsp_fuse_intf_SetBasicInfo,
|
||||||
fsp_fuse_intf_SetFileSize,
|
fsp_fuse_intf_SetFileSize,
|
||||||
fsp_fuse_intf_CanDelete,
|
0,
|
||||||
fsp_fuse_intf_Rename,
|
fsp_fuse_intf_Rename,
|
||||||
fsp_fuse_intf_GetSecurity,
|
fsp_fuse_intf_GetSecurity,
|
||||||
fsp_fuse_intf_SetSecurity,
|
fsp_fuse_intf_SetSecurity,
|
||||||
@ -2449,6 +2471,7 @@ FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
|
|||||||
fsp_fuse_intf_Overwrite,
|
fsp_fuse_intf_Overwrite,
|
||||||
fsp_fuse_intf_GetEa,
|
fsp_fuse_intf_GetEa,
|
||||||
fsp_fuse_intf_SetEa,
|
fsp_fuse_intf_SetEa,
|
||||||
|
fsp_fuse_intf_Delete,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -153,7 +153,8 @@ struct fsp_fuse_core_opt_data
|
|||||||
set_DirInfoTimeout,
|
set_DirInfoTimeout,
|
||||||
set_EaTimeout,
|
set_EaTimeout,
|
||||||
set_VolumeInfoTimeout,
|
set_VolumeInfoTimeout,
|
||||||
set_KeepFileCache;
|
set_KeepFileCache,
|
||||||
|
set_LegacyUnlinkRename;
|
||||||
unsigned ThreadCount;
|
unsigned ThreadCount;
|
||||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||||
UINT16 VolumeLabelLength;
|
UINT16 VolumeLabelLength;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user