From a4f687c635bbc44b9dcc53e0046df535b37c945c Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Fri, 10 Jun 2016 18:42:18 -0700 Subject: [PATCH] dll: fuseintf: CanDelete implementation --- src/dll/fuse/fuseintf.c | 56 +++++++++++++++++++++++++++++++---------- src/dll/fuse/library.h | 12 +++++++++ 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/src/dll/fuse/fuseintf.c b/src/dll/fuse/fuseintf.c index 84255c9a..d77fcd7b 100644 --- a/src/dll/fuse/fuseintf.c +++ b/src/dll/fuse/fuseintf.c @@ -743,11 +743,52 @@ static NTSTATUS fsp_fuse_intf_SetFileSize(FSP_FILE_SYSTEM *FileSystem, return STATUS_INVALID_DEVICE_REQUEST; } +static int fsp_fuse_intf_CanDeleteAddDirInfo(void *buf, const char *name, + const struct fuse_stat *stbuf, fuse_off_t off) +{ + struct fuse_dirhandle *dh = buf; + + if ('.' == name[0] && '\0' == name[1]) + return 0; + else + if ('.' == name[0] && '.' == name[1] && '\0' == name[2]) + return 0; + else + { + dh->HasChild = TRUE; + return 1; + } +} + +static int fsp_fuse_intf_CanDeleteAddDirInfoOld(fuse_dirh_t dh, const char *name, + int type, fuse_ino_t ino) +{ + return fsp_fuse_intf_CanDeleteAddDirInfo(dh, name, 0, 0) ? -ENOMEM : 0; +} + static NTSTATUS fsp_fuse_intf_CanDelete(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, PVOID FileNode, PWSTR FileName) { - return STATUS_INVALID_DEVICE_REQUEST; + struct fuse *f = FileSystem->UserContext; + struct fsp_fuse_file_desc *filedesc = + (PVOID)(UINT_PTR)Request->Req.SetInformation.UserContext2; + struct fuse_file_info fi; + struct fuse_dirhandle dh; + + if (filedesc->IsDirectory) + { + memset(&dh, 0, sizeof dh); + + if (0 != f->ops.readdir) + f->ops.readdir(filedesc->PosixPath, &dh, fsp_fuse_intf_CanDeleteAddDirInfo, 0, &fi); + else if (0 != f->ops.getdir) + f->ops.getdir(filedesc->PosixPath, &dh, fsp_fuse_intf_CanDeleteAddDirInfoOld); + + return dh.HasChild ? STATUS_DIRECTORY_NOT_EMPTY : STATUS_SUCCESS; + } + + return STATUS_SUCCESS; } static NTSTATUS fsp_fuse_intf_Rename(FSP_FILE_SYSTEM *FileSystem, @@ -853,17 +894,6 @@ exit: return Result; } -struct fuse_dirhandle -{ - FSP_FILE_SYSTEM *FileSystem; - char *PosixPath, *PosixName; - PVOID OriginalBuffer; - ULONG OriginalLength; - PVOID Buffer; - ULONG Length; - ULONG BytesTransferred; -}; - int fsp_fuse_intf_AddDirInfo(void *buf, const char *name, const struct fuse_stat *stbuf, fuse_off_t off) { @@ -1033,7 +1063,7 @@ static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem, fi.flags = filedesc->OpenFlags; fi.fh = filedesc->FileHandle; - err = f->ops.readdir(filedesc->PosixPath, &dh, fsp_fuse_intf_AddDirInfo, 0, &fi); + err = f->ops.readdir(filedesc->PosixPath, &dh, fsp_fuse_intf_AddDirInfo, Offset, &fi); Result = fsp_fuse_ntstatus_from_errno(f->env, err); } else if (0 != f->ops.getdir) diff --git a/src/dll/fuse/library.h b/src/dll/fuse/library.h index aa4dc421..c6aa7206 100644 --- a/src/dll/fuse/library.h +++ b/src/dll/fuse/library.h @@ -55,6 +55,18 @@ struct fsp_fuse_file_desc ULONG DirBufferSize; }; +struct fuse_dirhandle +{ + FSP_FILE_SYSTEM *FileSystem; + char *PosixPath, *PosixName; + PVOID OriginalBuffer; + ULONG OriginalLength; + PVOID Buffer; + ULONG Length; + ULONG BytesTransferred; + BOOLEAN HasChild; +}; + static inline struct fsp_fuse_context_header *fsp_fuse_context_header(VOID) {