mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-31 12:08:41 -05:00 
			
		
		
		
	dll: fuse: implement new Delete design and POSIX semantics
This commit is contained in:
		| @@ -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=%d", VolumeParams.VolumeInfoTimeout, 0), | ||||
|     FSP_FUSE_CORE_OPT("KeepFileCache=", set_KeepFileCache, 1), | ||||
|     FSP_FUSE_CORE_OPT("LegacyUnlinkRename=", set_LegacyUnlinkRename, 1), | ||||
|     FSP_FUSE_CORE_OPT("ThreadCount=%u", ThreadCount, 0), | ||||
|     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 VolumeInfoTimeout=N     volume info timeout (millis)\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" | ||||
|             ); | ||||
|         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.FileInfoTimeout = 1000; | ||||
|     opt_data.VolumeParams.FlushAndPurgeOnCleanup = TRUE; | ||||
|     opt_data.VolumeParams.SupportsPosixUnlinkRename = TRUE; | ||||
|  | ||||
|     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; | ||||
|     if (opt_data.set_KeepFileCache) | ||||
|         opt_data.VolumeParams.FlushAndPurgeOnCleanup = FALSE; | ||||
|     if (opt_data.set_LegacyUnlinkRename) | ||||
|         opt_data.VolumeParams.SupportsPosixUnlinkRename = FALSE; | ||||
|     opt_data.VolumeParams.CaseSensitiveSearch = TRUE; | ||||
|     opt_data.VolumeParams.CasePreservedNames = TRUE; | ||||
|     opt_data.VolumeParams.PersistentAcls = TRUE; | ||||
|   | ||||
| @@ -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, | ||||
| }; | ||||
|  | ||||
| /* | ||||
|   | ||||
| @@ -153,7 +153,8 @@ struct fsp_fuse_core_opt_data | ||||
|         set_DirInfoTimeout, | ||||
|         set_EaTimeout, | ||||
|         set_VolumeInfoTimeout, | ||||
|         set_KeepFileCache; | ||||
|         set_KeepFileCache, | ||||
|         set_LegacyUnlinkRename; | ||||
|     unsigned ThreadCount; | ||||
|     FSP_FSCTL_VOLUME_PARAMS VolumeParams; | ||||
|     UINT16 VolumeLabelLength; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user