From 52dd6f747835bcf9bffdc39e49dd1d6c09b7c004 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Tue, 26 Oct 2021 13:21:57 +0100 Subject: [PATCH] dll: fuse: FSP_FUSE_CAP_DELETE_ACCESS --- inc/fuse/fuse.h | 2 +- inc/fuse/fuse_common.h | 4 ++ src/dll/fuse/fuse_intf.c | 85 ++++++++++++++++++++++++++-------------- src/dll/fuse/fuse_loop.c | 1 + 4 files changed, 62 insertions(+), 30 deletions(-) diff --git a/inc/fuse/fuse.h b/inc/fuse/fuse.h index d1f90e5e..4d5af860 100644 --- a/inc/fuse/fuse.h +++ b/inc/fuse/fuse.h @@ -79,7 +79,7 @@ struct fuse_operations /* S */ int (*fsyncdir)(const char *path, int datasync, struct fuse_file_info *fi); /* S */ void *(*init)(struct fuse_conn_info *conn); /* S */ void (*destroy)(void *data); - /* _ */ int (*access)(const char *path, int mask); + /* S */ int (*access)(const char *path, int mask); /* S */ int (*create)(const char *path, fuse_mode_t mode, struct fuse_file_info *fi); /* S */ int (*ftruncate)(const char *path, fuse_off_t off, struct fuse_file_info *fi); /* S */ int (*fgetattr)(const char *path, struct fuse_stat *stbuf, struct fuse_file_info *fi); diff --git a/inc/fuse/fuse_common.h b/inc/fuse/fuse_common.h index cf35fc2a..5e7cd432 100644 --- a/inc/fuse/fuse_common.h +++ b/inc/fuse/fuse_common.h @@ -54,6 +54,7 @@ extern "C" { #define FSP_FUSE_CAP_READDIR_PLUS (1 << 21) /* file system supports enhanced readdir */ #define FSP_FUSE_CAP_READ_ONLY (1 << 22) /* file system is marked read-only */ #define FSP_FUSE_CAP_STAT_EX (1 << 23) /* file system supports fuse_stat_ex */ +#define FSP_FUSE_CAP_DELETE_ACCESS (1 << 24) /* file system supports access with DELETE_OK */ #define FSP_FUSE_CAP_CASE_INSENSITIVE FUSE_CAP_CASE_INSENSITIVE #define FUSE_IOCTL_COMPAT (1 << 0) @@ -79,6 +80,9 @@ extern "C" { #define UF_ARCHIVE FSP_FUSE_UF_ARCHIVE #endif +/* delete access */ +#define FSP_FUSE_DELETE_OK 0x40000000 + /* notify extension */ #define FSP_FUSE_NOTIFY_MKDIR 0x0001 #define FSP_FUSE_NOTIFY_RMDIR 0x0002 diff --git a/src/dll/fuse/fuse_intf.c b/src/dll/fuse/fuse_intf.c index 46a9e8b2..2bcee172 100644 --- a/src/dll/fuse/fuse_intf.c +++ b/src/dll/fuse/fuse_intf.c @@ -991,6 +991,19 @@ static NTSTATUS fsp_fuse_intf_Open(FSP_FILE_SYSTEM *FileSystem, int err; NTSTATUS Result; + if (0 != (CreateOptions & FILE_DELETE_ON_CLOSE) && + 0 != (f->conn_want & FSP_FUSE_CAP_DELETE_ACCESS) && 0 != f->ops.access) + { + err = f->ops.access(contexthdr->PosixPath, FSP_FUSE_DELETE_OK); + Result = fsp_fuse_ntstatus_from_errno(f->env, err); + if (!NT_SUCCESS(Result) && STATUS_INVALID_DEVICE_REQUEST != Result) + { + if (STATUS_ACCESS_DENIED == Result) + Result = STATUS_CANNOT_DELETE; + goto exit; + } + } + Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, contexthdr->PosixPath, 0, &Uid, &Gid, &Mode, &FileInfoBuf); if (!NT_SUCCESS(Result)) @@ -1583,49 +1596,63 @@ static NTSTATUS fsp_fuse_intf_CanDelete(FSP_FILE_SYSTEM *FileSystem, static NTSTATUS fsp_fuse_intf_Delete(FSP_FILE_SYSTEM *FileSystem, PVOID FileDesc, PWSTR FileName, ULONG Flags) { + struct fuse *f = FileSystem->UserContext; + struct fsp_fuse_file_desc *filedesc = FileDesc; + int err; + NTSTATUS Result; + switch (Flags) { case FILE_DISPOSITION_DO_NOT_DELETE: return STATUS_SUCCESS; case FILE_DISPOSITION_DELETE: - return fsp_fuse_intf_CanDelete(FileSystem, FileDesc, FileName); + Result = STATUS_SUCCESS; + if (0 != (f->conn_want & FSP_FUSE_CAP_DELETE_ACCESS) && 0 != f->ops.access) + { + err = f->ops.access(filedesc->PosixPath, FSP_FUSE_DELETE_OK); + Result = fsp_fuse_ntstatus_from_errno(f->env, err); + if (STATUS_INVALID_DEVICE_REQUEST == Result) + Result = STATUS_SUCCESS; + } + + if (NT_SUCCESS(Result)) + Result = fsp_fuse_intf_CanDelete(FileSystem, FileDesc, FileName); + + /* when doing unlink/rmdir convert EPERM/EACCES to STATUS_CANNOT_DELETE */ + if (STATUS_ACCESS_DENIED == Result) + Result = STATUS_CANNOT_DELETE; + + return Result; case FILE_DISPOSITION_DELETE | FILE_DISPOSITION_POSIX_SEMANTICS: case -1: + if (filedesc->IsDirectory && !filedesc->IsReparsePoint) { - 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) { - 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; + err = f->ops.rmdir(filedesc->PosixPath); + Result = fsp_fuse_ntstatus_from_errno(f->env, err); } 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; - } - - /* when doing unlink/rmdir convert EPERM/EACCES to STATUS_CANNOT_DELETE */ - if (STATUS_ACCESS_DENIED == Result) - Result = STATUS_CANNOT_DELETE; - - return Result; + 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; + } + + /* when doing unlink/rmdir convert EPERM/EACCES to STATUS_CANNOT_DELETE */ + if (STATUS_ACCESS_DENIED == Result) + Result = STATUS_CANNOT_DELETE; + + return Result; default: return STATUS_INVALID_PARAMETER; diff --git a/src/dll/fuse/fuse_loop.c b/src/dll/fuse/fuse_loop.c index eca0c3d1..5e234a57 100644 --- a/src/dll/fuse/fuse_loop.c +++ b/src/dll/fuse/fuse_loop.c @@ -88,6 +88,7 @@ static NTSTATUS fsp_fuse_loop_start(struct fuse *f) FSP_FUSE_CAP_READDIR_PLUS | FSP_FUSE_CAP_READ_ONLY | FSP_FUSE_CAP_STAT_EX | + FSP_FUSE_CAP_DELETE_ACCESS | FSP_FUSE_CAP_CASE_INSENSITIVE; if (0 != f->ops.init) {