From fbcefe6339da3ad72686d8274b7a1bd57fad8959 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Mon, 7 May 2018 14:05:18 -0700 Subject: [PATCH] dll: fuse: ioctl --- inc/fuse/fuse.h | 2 +- inc/fuse/winfsp_fuse.h | 11 +++++++++++ src/dll/fuse/fuse_intf.c | 42 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/inc/fuse/fuse.h b/inc/fuse/fuse.h index 1b01eadf..dd0c2c03 100644 --- a/inc/fuse/fuse.h +++ b/inc/fuse/fuse.h @@ -87,7 +87,7 @@ struct fuse_operations /* _ */ unsigned int flag_nopath:1; /* _ */ unsigned int flag_utime_omit_ok:1; /* _ */ unsigned int flag_reserved:29; - /* _ */ int (*ioctl)(const char *path, int cmd, void *arg, struct fuse_file_info *fi, + /* S */ int (*ioctl)(const char *path, int cmd, void *arg, struct fuse_file_info *fi, unsigned int flags, void *data); /* _ */ int (*poll)(const char *path, struct fuse_file_info *fi, struct fuse_pollhandle *ph, unsigned *reventsp); diff --git a/inc/fuse/winfsp_fuse.h b/inc/fuse/winfsp_fuse.h index 7f1b3ecf..38a8e244 100644 --- a/inc/fuse/winfsp_fuse.h +++ b/inc/fuse/winfsp_fuse.h @@ -53,6 +53,17 @@ extern "C" { #endif #endif +#define FSP_FUSE_DEVICE_TYPE (0x8000 | 'W' | 'F' * 0x100) /* DeviceIoControl -> ioctl */ +#define FSP_FUSE_CTLCODE_FROM_IOCTL(cmd)\ + (FSP_FUSE_DEVICE_TYPE << 16) | (((c) & 0x0fff) << 2) +#define FSP_FUSE_IOCTL(cmd, isiz, osiz) \ + ( \ + (((osiz) != 0) << 31) | \ + (((isiz) != 0) << 30) | \ + (((isiz) | (osiz)) << 16) | \ + (cmd) \ + ) + /* * FUSE uses a number of types (notably: struct stat) that are OS specific. * Furthermore there are sometimes multiple definitions of the same type even diff --git a/src/dll/fuse/fuse_intf.c b/src/dll/fuse/fuse_intf.c index f764a449..3363a771 100644 --- a/src/dll/fuse/fuse_intf.c +++ b/src/dll/fuse/fuse_intf.c @@ -2125,6 +2125,47 @@ static NTSTATUS fsp_fuse_intf_DeleteReparsePoint(FSP_FILE_SYSTEM *FileSystem, return STATUS_ACCESS_DENIED; } +static NTSTATUS fsp_fuse_intf_Control(FSP_FILE_SYSTEM *FileSystem, + PVOID FileNode, UINT32 ControlCode, + PVOID InputBuffer, ULONG InputBufferLength, + PVOID OutputBuffer, ULONG OutputBufferLength, PULONG PBytesTransferred) +{ + struct fuse *f = FileSystem->UserContext; + struct fsp_fuse_file_desc *filedesc = FileNode; + struct fuse_file_info fi; + int cmd; + int err; + + if (0 == f->ops.ioctl) + return STATUS_INVALID_DEVICE_REQUEST; + + if (FSP_FUSE_DEVICE_TYPE != DEVICE_TYPE_FROM_CTL_CODE(ControlCode)) + return STATUS_INVALID_DEVICE_REQUEST; + + if (0 != InputBufferLength && 0 != OutputBufferLength && + InputBufferLength != OutputBufferLength) + return STATUS_INVALID_DEVICE_REQUEST; + + memset(&fi, 0, sizeof fi); + fi.flags = filedesc->OpenFlags; + fi.fh = filedesc->FileHandle; + + /* construct a Linux compatible ioctl code */ + cmd = FSP_FUSE_IOCTL((ControlCode >> 2) & 0xfff, InputBufferLength, OutputBufferLength); + + if (0 == OutputBufferLength) + err = f->ops.ioctl(filedesc->PosixPath, cmd, 0, &fi, 0, InputBuffer); + else + { + if (0 != InputBufferLength) + // OutputBuffer points to Response->Buffer which is FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX long + memcpy(OutputBuffer, InputBuffer, InputBufferLength); + err = f->ops.ioctl(filedesc->PosixPath, cmd, 0, &fi, 0, OutputBuffer); + } + + return fsp_fuse_ntstatus_from_errno(f->env, err); +} + FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf = { fsp_fuse_intf_GetVolumeInfo, @@ -2152,6 +2193,7 @@ FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf = fsp_fuse_intf_DeleteReparsePoint, 0, fsp_fuse_intf_GetDirInfoByName, + fsp_fuse_intf_Control, }; /*