mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
Merge branch 'pvt-fuse3'
This commit is contained in:
commit
523ccbea02
@ -5,9 +5,11 @@ v1.4B2 (2018.2 B2)::
|
||||
|
||||
Changes since v1.3:
|
||||
|
||||
* New `Control` file system operation allows sending custom control codes to the file system using the Windows `DeviceIoControl` API.
|
||||
* FUSE3 API (version 3.2) is now available. The FUSE2 API (version 2.8) also remains supported.
|
||||
* New `Control` file system operation allows sending custom control codes to the file system using the Windows `DeviceIoControl` API. FUSE `ioctl` is also supported.
|
||||
* `FlushAndPurgeOnCleanup` has now been added to the .NET API. (GitHub PR #176; thanks @FrKaram.)
|
||||
* New sample file system "airfs" contributed by @JohnOberschelp.
|
||||
* New sample file system "airfs" contributed by @JohnOberschelp. Airfs is an in-memory file system like Memfs on which it is based on; it has received substantial improvements in how the file name space is maintained and has been modified to use modern C++ techniques by John.
|
||||
* New sample file system "passthrough-fuse3" passes all operations to an underlying file system. This file system is built using the FUSE3 API. It builds and runs on both Windows and Cygwin.
|
||||
|
||||
|
||||
v1.4B1 (2018.2 B1)::
|
||||
|
@ -281,6 +281,20 @@
|
||||
<File Name="winfsp_fuse.h" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="INCDIR.fuse3" Name="fuse3">
|
||||
<Component Id="C.fuse3.h">
|
||||
<File Id="fuse3.h" Name="fuse.h" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.fuse3_common.h">
|
||||
<File Id="fuse3_common.h" Name="fuse_common.h" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.fuse3_opt.h">
|
||||
<File Id="fuse3_opt.h" Name="fuse_opt.h" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.winfsp_fuse3.h">
|
||||
<File Id="winfsp_fuse3.h" Name="winfsp_fuse.h" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="LIBDIR" FileSource="..\build\$(var.Configuration)">
|
||||
<Component Id="C.winfsp_x64.lib">
|
||||
@ -309,6 +323,26 @@
|
||||
KeyPath="yes" />
|
||||
<Condition>NOT VersionNT64</Condition>
|
||||
</Component>
|
||||
|
||||
<!-- On Win64 copy fuse3-x64.pc -->
|
||||
<Component Id="C.fuse3_x64.pc" Guid="FE59E3BA-E5EA-4822-80B1-19A1DE6B62C7">
|
||||
<File
|
||||
Id="FILE.fuse3_x64.pc"
|
||||
Name="fuse3.pc"
|
||||
Source="..\build\$(var.Configuration)\fuse3-x64.pc"
|
||||
KeyPath="yes" />
|
||||
<Condition>VersionNT64</Condition>
|
||||
</Component>
|
||||
|
||||
<!-- On Win32 copy fuse3-x86.pc -->
|
||||
<Component Id="C.fuse3_x86.pc" Guid="176205D0-07EA-4DFC-947F-18E89ABDAFAB">
|
||||
<File
|
||||
Id="FILE.fuse3_x86.pc"
|
||||
Name="fuse3.pc"
|
||||
Source="..\build\$(var.Configuration)\fuse3-x86.pc"
|
||||
KeyPath="yes" />
|
||||
<Condition>NOT VersionNT64</Condition>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="OPTDIR">
|
||||
<Directory Id="OPTDIR.cygfuse" Name="cygfuse" FileSource="..\..\..\opt\cygfuse\dist">
|
||||
@ -415,6 +449,32 @@
|
||||
<File Name="README.md" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="SMPDIR.passthrough_fuse3" Name="passthrough-fuse3">
|
||||
<Component Id="C.passthrough_fuse3.c">
|
||||
<File Name="passthrough-fuse3.c" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_fuse3.winposix.c">
|
||||
<File Id="F.passthrough_fuse3.winposix.c" Name="winposix.c" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_fuse3.winposix.h">
|
||||
<File Id="F.passthrough_fuse3.winposix.h" Name="winposix.h" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_fuse3.sln">
|
||||
<File Name="passthrough-fuse3.sln" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_fuse3.vcxproj">
|
||||
<File Name="passthrough-fuse3.vcxproj" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_fuse3.vcxproj.filters">
|
||||
<File Name="passthrough-fuse3.vcxproj.filters" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_fuse3.Makefile">
|
||||
<File Id="F.passthrough_fuse3.Makefile" Name="Makefile" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_fuse3.README.md">
|
||||
<File Id="F.passthrough_fuse3.README.md" Name="README.md" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="SMPDIR.passthrough_dotnet" Name="passthrough-dotnet">
|
||||
<Component Id="C.passthrough_dotnet.Program.cs">
|
||||
<File Id="FILE.passthrough_dotnet.Program.cs" Name="Program.cs" KeyPath="yes" />
|
||||
@ -493,12 +553,18 @@
|
||||
<ComponentRef Id="C.fuse_common.h" />
|
||||
<ComponentRef Id="C.fuse_opt.h" />
|
||||
<ComponentRef Id="C.winfsp_fuse.h" />
|
||||
<ComponentRef Id="C.fuse3.h" />
|
||||
<ComponentRef Id="C.fuse3_common.h" />
|
||||
<ComponentRef Id="C.fuse3_opt.h" />
|
||||
<ComponentRef Id="C.winfsp_fuse3.h" />
|
||||
</ComponentGroup>
|
||||
<ComponentGroup Id="C.WinFsp.lib">
|
||||
<ComponentRef Id="C.winfsp_x64.lib" />
|
||||
<ComponentRef Id="C.winfsp_x86.lib" />
|
||||
<ComponentRef Id="C.fuse_x64.pc" />
|
||||
<ComponentRef Id="C.fuse_x86.pc" />
|
||||
<ComponentRef Id="C.fuse3_x64.pc" />
|
||||
<ComponentRef Id="C.fuse3_x86.pc" />
|
||||
</ComponentGroup>
|
||||
<ComponentGroup Id="C.WinFsp.opt.fuse">
|
||||
<ComponentRef Id="C.fuse.tar.xz.x64" />
|
||||
@ -532,6 +598,14 @@
|
||||
<ComponentRef Id="C.passthrough_fuse.vcxproj.filters" />
|
||||
<ComponentRef Id="C.passthrough_fuse.Makefile" />
|
||||
<ComponentRef Id="C.passthrough_fuse.README.md" />
|
||||
<ComponentRef Id="C.passthrough_fuse3.c" />
|
||||
<ComponentRef Id="C.passthrough_fuse3.winposix.c" />
|
||||
<ComponentRef Id="C.passthrough_fuse3.winposix.h" />
|
||||
<ComponentRef Id="C.passthrough_fuse3.sln" />
|
||||
<ComponentRef Id="C.passthrough_fuse3.vcxproj" />
|
||||
<ComponentRef Id="C.passthrough_fuse3.vcxproj.filters" />
|
||||
<ComponentRef Id="C.passthrough_fuse3.Makefile" />
|
||||
<ComponentRef Id="C.passthrough_fuse3.README.md" />
|
||||
</ComponentGroup>
|
||||
<ComponentGroup Id="C.WinFsp.sym">
|
||||
<ComponentRef Id="C.winfsp_x64.sys.pdb" />
|
||||
|
@ -20,6 +20,10 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\inc\fuse3\fuse.h" />
|
||||
<ClInclude Include="..\..\inc\fuse3\fuse_common.h" />
|
||||
<ClInclude Include="..\..\inc\fuse3\fuse_opt.h" />
|
||||
<ClInclude Include="..\..\inc\fuse3\winfsp_fuse.h" />
|
||||
<ClInclude Include="..\..\inc\fuse\fuse.h" />
|
||||
<ClInclude Include="..\..\inc\fuse\fuse_common.h" />
|
||||
<ClInclude Include="..\..\inc\fuse\fuse_opt.h" />
|
||||
@ -28,6 +32,7 @@
|
||||
<ClInclude Include="..\..\inc\winfsp\launch.h" />
|
||||
<ClInclude Include="..\..\inc\winfsp\winfsp.h" />
|
||||
<ClInclude Include="..\..\inc\winfsp\winfsp.hpp" />
|
||||
<ClInclude Include="..\..\src\dll\fuse3\library.h" />
|
||||
<ClInclude Include="..\..\src\dll\fuse\library.h" />
|
||||
<ClInclude Include="..\..\src\dll\library.h" />
|
||||
<ClInclude Include="..\..\src\shared\minimal.h" />
|
||||
@ -35,6 +40,8 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\dll\dirbuf.c" />
|
||||
<ClCompile Include="..\..\src\dll\eventlog.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse3\fuse2to3.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse3\fuse3.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_compat.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_intf.c" />
|
||||
@ -79,6 +86,29 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)fuse-$(PlatformTarget).pc</Outputs>
|
||||
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkObjects>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="..\..\src\dll\fuse3\fuse3.pc.in">
|
||||
<FileType>Document</FileType>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">echo arch=$(PlatformTarget) >$(OutDir)fuse3-$(PlatformTarget).pc
|
||||
copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(PlatformTarget).pc >nul</Command>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo arch=$(PlatformTarget) >$(OutDir)fuse3-$(PlatformTarget).pc
|
||||
copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(PlatformTarget).pc >nul</Command>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">echo arch=$(PlatformTarget) >$(OutDir)fuse3-$(PlatformTarget).pc
|
||||
copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(PlatformTarget).pc >nul</Command>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">echo arch=$(PlatformTarget) >$(OutDir)fuse3-$(PlatformTarget).pc
|
||||
copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(PlatformTarget).pc >nul</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Writing fuse3-$(PlatformTarget).pc</Message>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Writing fuse3-$(PlatformTarget).pc</Message>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Writing fuse3-$(PlatformTarget).pc</Message>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Writing fuse3-$(PlatformTarget).pc</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)fuse3-$(PlatformTarget).pc</Outputs>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)fuse3-$(PlatformTarget).pc</Outputs>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)fuse3-$(PlatformTarget).pc</Outputs>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)fuse3-$(PlatformTarget).pc</Outputs>
|
||||
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
|
||||
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
|
||||
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkObjects>
|
||||
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkObjects>
|
||||
</CustomBuild>
|
||||
<None Include="..\..\src\dll\library.def" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -21,6 +21,12 @@
|
||||
<Filter Include="Source\fuse">
|
||||
<UniqueIdentifier>{518cce17-85cd-489c-b4be-920a84c1d73c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Include\fuse3">
|
||||
<UniqueIdentifier>{12afd2f1-f5ec-4008-b6ef-89cc626019ea}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source\fuse3">
|
||||
<UniqueIdentifier>{96091a7b-3923-4a74-9491-3ee230c688f9}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\inc\winfsp\fsctl.h">
|
||||
@ -56,6 +62,21 @@
|
||||
<ClInclude Include="..\..\inc\winfsp\launch.h">
|
||||
<Filter>Include\winfsp</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\inc\fuse3\fuse.h">
|
||||
<Filter>Include\fuse3</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\inc\fuse3\fuse_common.h">
|
||||
<Filter>Include\fuse3</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\inc\fuse3\fuse_opt.h">
|
||||
<Filter>Include\fuse3</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\inc\fuse3\winfsp_fuse.h">
|
||||
<Filter>Include\fuse3</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\dll\fuse3\library.h">
|
||||
<Filter>Source\fuse3</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\dll\library.c">
|
||||
@ -121,6 +142,12 @@
|
||||
<ClCompile Include="..\..\src\dll\launch.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\dll\fuse3\fuse3.c">
|
||||
<Filter>Source\fuse3</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\dll\fuse3\fuse2to3.c">
|
||||
<Filter>Source\fuse3</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\src\dll\library.def">
|
||||
@ -139,5 +166,8 @@
|
||||
<CustomBuild Include="..\..\src\dll\fuse\fuse.pc.in">
|
||||
<Filter>Source\fuse</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="..\..\src\dll\fuse3\fuse3.pc.in">
|
||||
<Filter>Source\fuse3</Filter>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
</Project>
|
334
inc/fuse3/fuse.h
Normal file
334
inc/fuse3/fuse.h
Normal file
@ -0,0 +1,334 @@
|
||||
/**
|
||||
* @file fuse3/fuse.h
|
||||
* WinFsp FUSE3 compatible API.
|
||||
*
|
||||
* This file is derived from libfuse/include/fuse.h:
|
||||
* FUSE: Filesystem in Userspace
|
||||
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||
*
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#ifndef FUSE_H_
|
||||
#define FUSE_H_
|
||||
|
||||
#include "fuse_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct fuse3;
|
||||
|
||||
enum fuse3_readdir_flags
|
||||
{
|
||||
FUSE_READDIR_PLUS = (1 << 0),
|
||||
};
|
||||
|
||||
enum fuse3_fill_dir_flags
|
||||
{
|
||||
FUSE_FILL_DIR_PLUS = (1 << 1),
|
||||
};
|
||||
|
||||
typedef int (*fuse3_fill_dir_t)(void *buf, const char *name,
|
||||
const struct fuse_stat *stbuf, fuse_off_t off,
|
||||
enum fuse3_fill_dir_flags flags);
|
||||
|
||||
struct fuse3_config
|
||||
{
|
||||
int set_gid;
|
||||
unsigned int gid;
|
||||
int set_uid;
|
||||
unsigned int uid;
|
||||
int set_mode;
|
||||
unsigned int umask;
|
||||
double entry_timeout;
|
||||
double negative_timeout;
|
||||
double attr_timeout;
|
||||
int intr;
|
||||
int intr_signal;
|
||||
int remember;
|
||||
int hard_remove;
|
||||
int use_ino;
|
||||
int readdir_ino;
|
||||
int direct_io;
|
||||
int kernel_cache;
|
||||
int auto_cache;
|
||||
int ac_attr_timeout_set;
|
||||
double ac_attr_timeout;
|
||||
int nullpath_ok;
|
||||
/* private */
|
||||
int show_help;
|
||||
char *modules;
|
||||
int debug;
|
||||
};
|
||||
|
||||
struct fuse3_operations
|
||||
{
|
||||
/* S - supported by WinFsp */
|
||||
/* S */ int (*getattr)(const char *path, struct fuse_stat *stbuf,
|
||||
struct fuse3_file_info *fi);
|
||||
/* S */ int (*readlink)(const char *path, char *buf, size_t size);
|
||||
/* S */ int (*mknod)(const char *path, fuse_mode_t mode, fuse_dev_t dev);
|
||||
/* S */ int (*mkdir)(const char *path, fuse_mode_t mode);
|
||||
/* S */ int (*unlink)(const char *path);
|
||||
/* S */ int (*rmdir)(const char *path);
|
||||
/* S */ int (*symlink)(const char *dstpath, const char *srcpath);
|
||||
/* S */ int (*rename)(const char *oldpath, const char *newpath, unsigned int flags);
|
||||
/* _ */ int (*link)(const char *srcpath, const char *dstpath);
|
||||
/* S */ int (*chmod)(const char *path, fuse_mode_t mode,
|
||||
struct fuse3_file_info *fi);
|
||||
/* S */ int (*chown)(const char *path, fuse_uid_t uid, fuse_gid_t gid,
|
||||
struct fuse3_file_info *fi);
|
||||
/* S */ int (*truncate)(const char *path, fuse_off_t size,
|
||||
struct fuse3_file_info *fi);
|
||||
/* S */ int (*open)(const char *path, struct fuse3_file_info *fi);
|
||||
/* S */ int (*read)(const char *path, char *buf, size_t size, fuse_off_t off,
|
||||
struct fuse3_file_info *fi);
|
||||
/* S */ int (*write)(const char *path, const char *buf, size_t size, fuse_off_t off,
|
||||
struct fuse3_file_info *fi);
|
||||
/* S */ int (*statfs)(const char *path, struct fuse_statvfs *stbuf);
|
||||
/* S */ int (*flush)(const char *path, struct fuse3_file_info *fi);
|
||||
/* S */ int (*release)(const char *path, struct fuse3_file_info *fi);
|
||||
/* S */ int (*fsync)(const char *path, int datasync, struct fuse3_file_info *fi);
|
||||
/* _ */ int (*setxattr)(const char *path, const char *name, const char *value, size_t size,
|
||||
int flags);
|
||||
/* _ */ int (*getxattr)(const char *path, const char *name, char *value, size_t size);
|
||||
/* _ */ int (*listxattr)(const char *path, char *namebuf, size_t size);
|
||||
/* _ */ int (*removexattr)(const char *path, const char *name);
|
||||
/* S */ int (*opendir)(const char *path, struct fuse3_file_info *fi);
|
||||
/* S */ int (*readdir)(const char *path, void *buf, fuse3_fill_dir_t filler, fuse_off_t off,
|
||||
struct fuse3_file_info *fi, enum fuse3_readdir_flags);
|
||||
/* S */ int (*releasedir)(const char *path, struct fuse3_file_info *fi);
|
||||
/* S */ int (*fsyncdir)(const char *path, int datasync, struct fuse3_file_info *fi);
|
||||
/* S */ void *(*init)(struct fuse3_conn_info *conn,
|
||||
struct fuse3_config *conf);
|
||||
/* S */ void (*destroy)(void *data);
|
||||
/* _ */ int (*access)(const char *path, int mask);
|
||||
/* S */ int (*create)(const char *path, fuse_mode_t mode, struct fuse3_file_info *fi);
|
||||
/* _ */ int (*lock)(const char *path,
|
||||
struct fuse3_file_info *fi, int cmd, struct fuse_flock *lock);
|
||||
/* S */ int (*utimens)(const char *path, const struct fuse_timespec tv[2],
|
||||
struct fuse3_file_info *fi);
|
||||
/* _ */ int (*bmap)(const char *path, size_t blocksize, uint64_t *idx);
|
||||
/* S */ int (*ioctl)(const char *path, int cmd, void *arg, struct fuse3_file_info *fi,
|
||||
unsigned int flags, void *data);
|
||||
/* _ */ int (*poll)(const char *path, struct fuse3_file_info *fi,
|
||||
struct fuse3_pollhandle *ph, unsigned *reventsp);
|
||||
/* _ */ int (*write_buf)(const char *path,
|
||||
struct fuse3_bufvec *buf, fuse_off_t off, struct fuse3_file_info *fi);
|
||||
/* _ */ int (*read_buf)(const char *path,
|
||||
struct fuse3_bufvec **bufp, size_t size, fuse_off_t off, struct fuse3_file_info *fi);
|
||||
/* _ */ int (*flock)(const char *path, struct fuse3_file_info *, int op);
|
||||
/* _ */ int (*fallocate)(const char *path, int mode, fuse_off_t off, fuse_off_t len,
|
||||
struct fuse3_file_info *fi);
|
||||
};
|
||||
|
||||
struct fuse3_context
|
||||
{
|
||||
struct fuse3 *fuse;
|
||||
fuse_uid_t uid;
|
||||
fuse_gid_t gid;
|
||||
fuse_pid_t pid;
|
||||
void *private_data;
|
||||
fuse_mode_t umask;
|
||||
};
|
||||
|
||||
#define fuse_main(argc, argv, ops, data)\
|
||||
fuse3_main_real(argc, argv, ops, sizeof *(ops), data)
|
||||
|
||||
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_main_real)(struct fsp_fuse_env *env,
|
||||
int argc, char *argv[],
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data);
|
||||
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_lib_help)(struct fsp_fuse_env *env,
|
||||
struct fuse_args *args);
|
||||
FSP_FUSE_API struct fuse3 *FSP_FUSE_API_NAME(fsp_fuse3_new_30)(struct fsp_fuse_env *env,
|
||||
struct fuse_args *args,
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data);
|
||||
FSP_FUSE_API struct fuse3 *FSP_FUSE_API_NAME(fsp_fuse3_new)(struct fsp_fuse_env *env,
|
||||
struct fuse_args *args,
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data);
|
||||
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_destroy)(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f);
|
||||
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_mount)(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f, const char *mountpoint);
|
||||
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_unmount)(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f);
|
||||
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_loop)(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f);
|
||||
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_loop_mt_31)(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f, int clone_fd);
|
||||
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_loop_mt)(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f, struct fuse3_loop_config *config);
|
||||
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_exit)(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f);
|
||||
FSP_FUSE_API struct fuse3_context *FSP_FUSE_API_NAME(fsp_fuse3_get_context)(struct fsp_fuse_env *env);
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_main_real(int argc, char *argv[],
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_main_real)
|
||||
(fsp_fuse_env(), argc, argv, ops, opsize, data);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
void fuse3_lib_help(struct fuse_args *args),
|
||||
{
|
||||
FSP_FUSE_API_CALL(fsp_fuse3_lib_help)
|
||||
(fsp_fuse_env(), args);
|
||||
})
|
||||
|
||||
#if FUSE_USE_VERSION == 30
|
||||
FSP_FUSE_SYM(
|
||||
struct fuse3 *fuse3_new_30(struct fuse_args *args,
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_new_30)
|
||||
(fsp_fuse_env(), args, ops, opsize, data);
|
||||
})
|
||||
#define fuse_new(args, op, size, data)\
|
||||
fuse3_new_30(args, op, size, data)
|
||||
|
||||
#else
|
||||
FSP_FUSE_SYM(
|
||||
struct fuse3 *fuse3_new(struct fuse_args *args,
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_new)
|
||||
(fsp_fuse_env(), args, ops, opsize, data);
|
||||
})
|
||||
#endif
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
void fuse3_destroy(struct fuse3 *f),
|
||||
{
|
||||
FSP_FUSE_API_CALL(fsp_fuse3_destroy)
|
||||
(fsp_fuse_env(), f);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_mount(struct fuse3 *f, const char *mountpoint),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_mount)
|
||||
(fsp_fuse_env(), f, mountpoint);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
void fuse3_unmount(struct fuse3 *f),
|
||||
{
|
||||
FSP_FUSE_API_CALL(fsp_fuse3_unmount)
|
||||
(fsp_fuse_env(), f);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_loop(struct fuse3 *f),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_loop)
|
||||
(fsp_fuse_env(), f);
|
||||
})
|
||||
|
||||
#if FUSE_USE_VERSION < 32
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_loop_mt_31(struct fuse3 *f, int clone_fd),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_loop_mt_31)
|
||||
(fsp_fuse_env(), f, clone_fd);
|
||||
})
|
||||
#define fuse_loop_mt(f, clone_fd)\
|
||||
fuse3_loop_mt_31(f, clone_fd)
|
||||
|
||||
#else
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_loop_mt(struct fuse3 *f, struct fuse3_loop_config *config),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_loop_mt)
|
||||
(fsp_fuse_env(), f, config);
|
||||
})
|
||||
#endif
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
void fuse3_exit(struct fuse3 *f),
|
||||
{
|
||||
FSP_FUSE_API_CALL(fsp_fuse3_exit)
|
||||
(fsp_fuse_env(), f);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
struct fuse3_context *fuse3_get_context(void),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_get_context)
|
||||
(fsp_fuse_env());
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_getgroups(int size, fuse_gid_t list[]),
|
||||
{
|
||||
(void)size;
|
||||
(void)list;
|
||||
return -ENOSYS;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_interrupted(void),
|
||||
{
|
||||
return 0;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_invalidate_path(struct fuse3 *f, const char *path),
|
||||
{
|
||||
(void)f;
|
||||
(void)path;
|
||||
return -ENOENT;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_notify_poll(struct fuse3_pollhandle *ph),
|
||||
{
|
||||
(void)ph;
|
||||
return 0;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_start_cleanup_thread(struct fuse3 *f),
|
||||
{
|
||||
(void)f;
|
||||
return 0;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
void fuse3_stop_cleanup_thread(struct fuse3 *f),
|
||||
{
|
||||
(void)f;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_clean_cache(struct fuse3 *f),
|
||||
{
|
||||
(void)f;
|
||||
return 600;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
struct fuse3_session *fuse3_get_session(struct fuse3 *f),
|
||||
{
|
||||
return (struct fuse3_session *)f;
|
||||
})
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
232
inc/fuse3/fuse_common.h
Normal file
232
inc/fuse3/fuse_common.h
Normal file
@ -0,0 +1,232 @@
|
||||
/**
|
||||
* @file fuse3/fuse_common.h
|
||||
* WinFsp FUSE3 compatible API.
|
||||
*
|
||||
* This file is derived from libfuse/include/fuse_common.h:
|
||||
* FUSE: Filesystem in Userspace
|
||||
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||
*
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#ifndef FUSE_COMMON_H_
|
||||
#define FUSE_COMMON_H_
|
||||
|
||||
#include "winfsp_fuse.h"
|
||||
#include "fuse_opt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FUSE_MAJOR_VERSION 3
|
||||
#define FUSE_MINOR_VERSION 2
|
||||
#define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min))
|
||||
#define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION)
|
||||
|
||||
#define FUSE_CAP_ASYNC_READ (1 << 0)
|
||||
#define FUSE_CAP_POSIX_LOCKS (1 << 1)
|
||||
#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3)
|
||||
#define FUSE_CAP_EXPORT_SUPPORT (1 << 4)
|
||||
#define FUSE_CAP_DONT_MASK (1 << 6)
|
||||
#define FUSE_CAP_SPLICE_WRITE (1 << 7)
|
||||
#define FUSE_CAP_SPLICE_MOVE (1 << 8)
|
||||
#define FUSE_CAP_SPLICE_READ (1 << 9)
|
||||
#define FUSE_CAP_FLOCK_LOCKS (1 << 10)
|
||||
#define FUSE_CAP_IOCTL_DIR (1 << 11)
|
||||
#define FUSE_CAP_AUTO_INVAL_DATA (1 << 12)
|
||||
#define FUSE_CAP_READDIRPLUS (1 << 13)
|
||||
#define FUSE_CAP_READDIRPLUS_AUTO (1 << 14)
|
||||
#define FUSE_CAP_ASYNC_DIO (1 << 15)
|
||||
#define FUSE_CAP_WRITEBACK_CACHE (1 << 16)
|
||||
#define FUSE_CAP_NO_OPEN_SUPPORT (1 << 17)
|
||||
#define FUSE_CAP_PARALLEL_DIROPS (1 << 18)
|
||||
#define FUSE_CAP_POSIX_ACL (1 << 19)
|
||||
#define FUSE_CAP_HANDLE_KILLPRIV (1 << 20)
|
||||
#define FUSE_CAP_ALLOCATE (1 << 27) /* reserved (OSXFUSE) */
|
||||
#define FUSE_CAP_EXCHANGE_DATA (1 << 28) /* reserved (OSXFUSE) */
|
||||
#define FUSE_CAP_CASE_INSENSITIVE (1 << 29) /* file system is case insensitive */
|
||||
#define FUSE_CAP_VOL_RENAME (1 << 30) /* reserved (OSXFUSE) */
|
||||
#define FUSE_CAP_XTIMES (1 << 31) /* reserved (OSXFUSE) */
|
||||
|
||||
#define FSP_FUSE_CAP_CASE_INSENSITIVE FUSE_CAP_CASE_INSENSITIVE
|
||||
|
||||
#define FUSE_IOCTL_COMPAT (1 << 0)
|
||||
#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
|
||||
#define FUSE_IOCTL_RETRY (1 << 2)
|
||||
#define FUSE_IOCTL_DIR (1 << 4)
|
||||
#define FUSE_IOCTL_MAX_IOV 256
|
||||
|
||||
#define FUSE_BUFVEC_INIT(s) \
|
||||
((struct fuse3_bufvec){ 1, 0, 0, { {s, (enum fuse3_buf_flags)0, 0, -1, 0} } })
|
||||
|
||||
struct fuse3_file_info
|
||||
{
|
||||
int flags;
|
||||
unsigned int writepage:1;
|
||||
unsigned int direct_io:1;
|
||||
unsigned int keep_cache:1;
|
||||
unsigned int flush:1;
|
||||
unsigned int nonseekable:1;
|
||||
unsigned int flock_release:1;
|
||||
unsigned int padding:27;
|
||||
uint64_t fh;
|
||||
uint64_t lock_owner;
|
||||
uint32_t poll_events;
|
||||
};
|
||||
|
||||
struct fuse3_loop_config
|
||||
{
|
||||
int clone_fd;
|
||||
unsigned int max_idle_threads;
|
||||
};
|
||||
|
||||
struct fuse3_conn_info
|
||||
{
|
||||
unsigned proto_major;
|
||||
unsigned proto_minor;
|
||||
unsigned max_write;
|
||||
unsigned max_read;
|
||||
unsigned max_readahead;
|
||||
unsigned capable;
|
||||
unsigned want;
|
||||
unsigned max_background;
|
||||
unsigned congestion_threshold;
|
||||
unsigned time_gran;
|
||||
unsigned reserved[22];
|
||||
};
|
||||
|
||||
enum fuse3_buf_flags
|
||||
{
|
||||
FUSE_BUF_IS_FD = (1 << 1),
|
||||
FUSE_BUF_FD_SEEK = (1 << 2),
|
||||
FUSE_BUF_FD_RETRY = (1 << 3),
|
||||
};
|
||||
|
||||
enum fuse3_buf_copy_flags
|
||||
{
|
||||
FUSE_BUF_NO_SPLICE = (1 << 1),
|
||||
FUSE_BUF_FORCE_SPLICE = (1 << 2),
|
||||
FUSE_BUF_SPLICE_MOVE = (1 << 3),
|
||||
FUSE_BUF_SPLICE_NONBLOCK = (1 << 4),
|
||||
};
|
||||
|
||||
struct fuse3_buf
|
||||
{
|
||||
size_t size;
|
||||
enum fuse3_buf_flags flags;
|
||||
void *mem;
|
||||
int fd;
|
||||
fuse_off_t pos;
|
||||
};
|
||||
|
||||
struct fuse3_bufvec
|
||||
{
|
||||
size_t count;
|
||||
size_t idx;
|
||||
size_t off;
|
||||
struct fuse3_buf buf[1];
|
||||
};
|
||||
|
||||
struct fuse3_session;
|
||||
struct fuse3_pollhandle;
|
||||
struct fuse3_conn_info_opts;
|
||||
|
||||
FSP_FUSE_API struct fuse3_conn_info_opts *FSP_FUSE_API_NAME(fsp_fuse3_parse_conn_info_opts)(
|
||||
struct fsp_fuse_env *env,
|
||||
struct fuse_args *args);
|
||||
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_apply_conn_info_opts)(struct fsp_fuse_env *env,
|
||||
struct fuse3_conn_info_opts *opts, struct fuse3_conn_info *conn);
|
||||
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_version)(struct fsp_fuse_env *env);
|
||||
FSP_FUSE_API const char *FSP_FUSE_API_NAME(fsp_fuse3_pkgversion)(struct fsp_fuse_env *env);
|
||||
FSP_FUSE_API int32_t FSP_FUSE_API_NAME(fsp_fuse_ntstatus_from_errno)(struct fsp_fuse_env *env,
|
||||
int err);
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
struct fuse3_conn_info_opts* fuse3_parse_conn_info_opts(
|
||||
struct fuse_args *args),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_parse_conn_info_opts)
|
||||
(fsp_fuse_env(), args);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
void fuse3_apply_conn_info_opts(
|
||||
struct fuse3_conn_info_opts *opts, struct fuse3_conn_info *conn),
|
||||
{
|
||||
FSP_FUSE_API_CALL(fsp_fuse3_apply_conn_info_opts)
|
||||
(fsp_fuse_env(), opts, conn);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_version(void),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_version)
|
||||
(fsp_fuse_env());
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
const char *fuse3_pkgversion(void),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_pkgversion)
|
||||
(fsp_fuse_env());
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
void fuse3_pollhandle_destroy(struct fuse3_pollhandle *ph),
|
||||
{
|
||||
(void)ph;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
size_t fuse3_buf_size(const struct fuse3_bufvec *bufv),
|
||||
{
|
||||
(void)bufv;
|
||||
return 0;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
ssize_t fuse3_buf_copy(struct fuse3_bufvec *dst, struct fuse3_bufvec *src,
|
||||
enum fuse3_buf_copy_flags flags),
|
||||
{
|
||||
(void)dst;
|
||||
(void)src;
|
||||
(void)flags;
|
||||
return 0;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_daemonize(int foreground),
|
||||
{
|
||||
return fsp_fuse_daemonize(foreground);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_set_signal_handlers(struct fuse3_session *se),
|
||||
{
|
||||
return fsp_fuse_set_signal_handlers(se);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
void fuse3_remove_signal_handlers(struct fuse3_session *se),
|
||||
{
|
||||
(void)se;
|
||||
fsp_fuse_set_signal_handlers(0);
|
||||
})
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
19
inc/fuse3/fuse_opt.h
Normal file
19
inc/fuse3/fuse_opt.h
Normal file
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* @file fuse3/fuse_opt.h
|
||||
* WinFsp FUSE3 compatible API.
|
||||
*
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include "../fuse/fuse_opt.h"
|
78
inc/fuse3/winfsp_fuse.h
Normal file
78
inc/fuse3/winfsp_fuse.h
Normal file
@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @file fuse3/winfsp_fuse.h
|
||||
* WinFsp FUSE3 compatible API.
|
||||
*
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#ifndef FUSE3_WINFSP_FUSE_H_INCLUDED
|
||||
#define FUSE3_WINFSP_FUSE_H_INCLUDED
|
||||
|
||||
#include "../fuse/winfsp_fuse.h"
|
||||
|
||||
#if defined(_WIN64) || defined(_WIN32)
|
||||
typedef intptr_t ssize_t;
|
||||
#endif
|
||||
|
||||
#if !defined(WINFSP_DLL_INTERNAL)
|
||||
#define fuse3 fuse
|
||||
#define fuse3_apply_conn_info_opts fuse_apply_conn_info_opts
|
||||
#define fuse3_buf fuse_buf
|
||||
#define fuse3_buf_copy fuse_buf_copy
|
||||
#define fuse3_buf_copy_flags fuse_buf_copy_flags
|
||||
#define fuse3_buf_flags fuse_buf_flags
|
||||
#define fuse3_buf_size fuse_buf_size
|
||||
#define fuse3_bufvec fuse_bufvec
|
||||
#define fuse3_clean_cache fuse_clean_cache
|
||||
#define fuse3_config fuse_config
|
||||
#define fuse3_conn_info fuse_conn_info
|
||||
#define fuse3_conn_info_opts fuse_conn_info_opts
|
||||
#define fuse3_context fuse_context
|
||||
#define fuse3_daemonize fuse_daemonize
|
||||
#define fuse3_destroy fuse_destroy
|
||||
#define fuse3_exit fuse_exit
|
||||
#define fuse3_file_info fuse_file_info
|
||||
#define fuse3_fill_dir_flags fuse_fill_dir_flags
|
||||
#define fuse3_fill_dir_t fuse_fill_dir_t
|
||||
#define fuse3_get_context fuse_get_context
|
||||
#define fuse3_get_session fuse_get_session
|
||||
#define fuse3_getgroups fuse_getgroups
|
||||
#define fuse3_interrupted fuse_interrupted
|
||||
#define fuse3_invalidate_path fuse_invalidate_path
|
||||
#define fuse3_lib_help fuse_lib_help
|
||||
#define fuse3_loop fuse_loop
|
||||
#define fuse3_loop_config fuse_loop_config
|
||||
#define fuse3_loop_mt fuse_loop_mt
|
||||
#define fuse3_loop_mt_31 fuse_loop_mt_31
|
||||
#define fuse3_main_real fuse_main_real
|
||||
#define fuse3_mount fuse_mount
|
||||
#define fuse3_new fuse_new
|
||||
#define fuse3_new_30 fuse_new_30
|
||||
#define fuse3_notify_poll fuse_notify_poll
|
||||
#define fuse3_operations fuse_operations
|
||||
#define fuse3_parse_conn_info_opts fuse_parse_conn_info_opts
|
||||
#define fuse3_pkgversion fuse_pkgversion
|
||||
#define fuse3_pollhandle fuse_pollhandle
|
||||
#define fuse3_pollhandle_destroy fuse_pollhandle_destroy
|
||||
#define fuse3_readdir_flags fuse_readdir_flags
|
||||
#define fuse3_remove_signal_handlers fuse_remove_signal_handlers
|
||||
#define fuse3_session fuse_session
|
||||
#define fuse3_set_signal_handlers fuse_set_signal_handlers
|
||||
#define fuse3_start_cleanup_thread fuse_start_cleanup_thread
|
||||
#define fuse3_stop_cleanup_thread fuse_stop_cleanup_thread
|
||||
#define fuse3_unmount fuse_unmount
|
||||
#define fuse3_version fuse_version
|
||||
#endif
|
||||
|
||||
#endif
|
@ -27,30 +27,7 @@ struct fuse_chan
|
||||
};
|
||||
|
||||
#define FSP_FUSE_CORE_OPT(n, f, v) { n, offsetof(struct fsp_fuse_core_opt_data, f), v }
|
||||
|
||||
struct fsp_fuse_core_opt_data
|
||||
{
|
||||
struct fsp_fuse_env *env;
|
||||
int help, debug;
|
||||
HANDLE DebugLogHandle;
|
||||
int set_umask, umask,
|
||||
set_create_umask, create_umask,
|
||||
set_uid, uid,
|
||||
set_gid, gid,
|
||||
set_attr_timeout, attr_timeout,
|
||||
rellinks;
|
||||
int set_FileInfoTimeout,
|
||||
set_DirInfoTimeout,
|
||||
set_VolumeInfoTimeout,
|
||||
set_KeepFileCache;
|
||||
unsigned ThreadCount;
|
||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||
UINT16 VolumeLabelLength;
|
||||
WCHAR VolumeLabel[sizeof ((FSP_FSCTL_VOLUME_INFO *)0)->VolumeLabel / sizeof(WCHAR)];
|
||||
};
|
||||
FSP_FSCTL_STATIC_ASSERT(
|
||||
sizeof ((struct fuse *)0)->VolumeLabel == sizeof ((struct fsp_fuse_core_opt_data *)0)->VolumeLabel,
|
||||
"fuse::VolumeLabel and fsp_fuse_core_opt_data::VolumeLabel: sizeof must be same.");
|
||||
#define FSP_FUSE_CORE_OPT_NOHELP_IDX 4
|
||||
|
||||
static struct fuse_opt fsp_fuse_core_opts[] =
|
||||
{
|
||||
@ -122,35 +99,6 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
||||
static INIT_ONCE fsp_fuse_initonce = INIT_ONCE_STATIC_INIT;
|
||||
static DWORD fsp_fuse_tlskey = TLS_OUT_OF_INDEXES;
|
||||
|
||||
struct fsp_fuse_obj_hdr
|
||||
{
|
||||
void (*dtor)(void *);
|
||||
__declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 ObjectBuf[];
|
||||
};
|
||||
|
||||
static inline void *fsp_fuse_obj_alloc(struct fsp_fuse_env *env, size_t size)
|
||||
{
|
||||
struct fsp_fuse_obj_hdr *hdr;
|
||||
|
||||
hdr = env->memalloc(sizeof(struct fsp_fuse_obj_hdr) + size);
|
||||
if (0 == hdr)
|
||||
return 0;
|
||||
|
||||
hdr->dtor = env->memfree;
|
||||
memset(hdr->ObjectBuf, 0, size);
|
||||
return hdr->ObjectBuf;
|
||||
}
|
||||
|
||||
static inline void fsp_fuse_obj_free(void *obj)
|
||||
{
|
||||
if (0 == obj)
|
||||
return;
|
||||
|
||||
struct fsp_fuse_obj_hdr *hdr = (PVOID)((PUINT8)obj - sizeof(struct fsp_fuse_obj_hdr));
|
||||
|
||||
hdr->dtor(hdr);
|
||||
}
|
||||
|
||||
static BOOL WINAPI fsp_fuse_initialize(
|
||||
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||
{
|
||||
@ -383,7 +331,7 @@ static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||
|
||||
/* this should always fail with ENOSYS or EINVAL */
|
||||
err = f->ops.readlink("/", buf, sizeof buf);
|
||||
f->has_symlinks = -ENOSYS != err;
|
||||
f->has_symlinks = -ENOSYS_(f->env) != err;
|
||||
}
|
||||
|
||||
/* the FSD does not currently limit these VolumeParams fields; do so here! */
|
||||
@ -575,6 +523,18 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||
}
|
||||
}
|
||||
|
||||
int fsp_fuse_core_opt_parse(struct fsp_fuse_env *env,
|
||||
struct fuse_args *args, struct fsp_fuse_core_opt_data *opt_data,
|
||||
int help)
|
||||
{
|
||||
if (help)
|
||||
return fsp_fuse_opt_parse(env, args, opt_data,
|
||||
fsp_fuse_core_opts, fsp_fuse_core_opt_proc);
|
||||
else
|
||||
return fsp_fuse_opt_parse(env, args, opt_data,
|
||||
fsp_fuse_core_opts + FSP_FUSE_CORE_OPT_NOHELP_IDX, fsp_fuse_core_opt_proc);
|
||||
}
|
||||
|
||||
FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
struct fuse_chan *ch, struct fuse_args *args,
|
||||
const struct fuse_operations *ops, size_t opsize, void *data)
|
||||
@ -595,7 +555,7 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
opt_data.VolumeParams.FileInfoTimeout = 1000;
|
||||
opt_data.VolumeParams.FlushAndPurgeOnCleanup = TRUE;
|
||||
|
||||
if (-1 == fsp_fuse_opt_parse(env, args, &opt_data, fsp_fuse_core_opts, fsp_fuse_core_opt_proc))
|
||||
if (-1 == fsp_fuse_core_opt_parse(env, args, &opt_data, /*help=*/1))
|
||||
return 0;
|
||||
if (opt_data.help)
|
||||
return 0;
|
||||
@ -788,6 +748,11 @@ FSP_FUSE_API struct fuse_context *fsp_fuse_get_context(struct fsp_fuse_env *env)
|
||||
return context;
|
||||
}
|
||||
|
||||
struct fuse_context *fsp_fuse_get_context_internal(void)
|
||||
{
|
||||
return TlsGetValue(fsp_fuse_tlskey);
|
||||
}
|
||||
|
||||
FSP_FUSE_API int32_t fsp_fuse_ntstatus_from_errno(struct fsp_fuse_env *env,
|
||||
int err)
|
||||
{
|
||||
|
@ -266,7 +266,7 @@ loopend:;
|
||||
if (0 != f->ops.getattr)
|
||||
err = f->ops.getattr(PosixHiddenPath, (void *)&stbuf);
|
||||
else
|
||||
err = -ENOSYS;
|
||||
err = -ENOSYS_(f->env);
|
||||
} while (0 == err && 0 < --maxtries);
|
||||
|
||||
if (0 == err)
|
||||
@ -308,7 +308,7 @@ static BOOLEAN fsp_fuse_intf_CheckSymlinkDirectory(FSP_FILE_SYSTEM *FileSystem,
|
||||
if (0 != f->ops.getattr)
|
||||
err = f->ops.getattr(PosixDotPath, (void *)&stbuf);
|
||||
else
|
||||
err = -ENOSYS;
|
||||
err = -ENOSYS_(f->env);
|
||||
|
||||
MemFree(PosixDotPath);
|
||||
|
||||
@ -1427,7 +1427,8 @@ static NTSTATUS fsp_fuse_intf_SetFileSize(FSP_FILE_SYSTEM *FileSystem,
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static int fsp_fuse_intf_CanDeleteAddDirInfo(void *buf, const char *name,
|
||||
/* !static: used by fuse2to3 */
|
||||
int fsp_fuse_intf_CanDeleteAddDirInfo(void *buf, const char *name,
|
||||
const struct fuse_stat *stbuf, fuse_off_t off)
|
||||
{
|
||||
struct fuse_dirhandle *dh = buf;
|
||||
@ -1617,7 +1618,8 @@ exit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
static int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
|
||||
/* !static: used by fuse2to3 */
|
||||
int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
|
||||
const struct fuse_stat *stbuf, fuse_off_t off)
|
||||
{
|
||||
struct fuse_dirhandle *dh = buf;
|
||||
|
@ -25,12 +25,14 @@
|
||||
#define FSP_FUSE_LIBRARY_NAME LIBRARY_NAME "-FUSE"
|
||||
|
||||
#define FSP_FUSE_HDR_FROM_CONTEXT(c) \
|
||||
(struct fsp_fuse_context_header *)((PUINT8)(c) - sizeof(struct fsp_fuse_context_header))
|
||||
((struct fsp_fuse_context_header *)((PUINT8)(c) - sizeof(struct fsp_fuse_context_header)))
|
||||
#define FSP_FUSE_CONTEXT_FROM_HDR(h) \
|
||||
(struct fuse_context *)((PUINT8)(h) + sizeof(struct fsp_fuse_context_header))
|
||||
((struct fuse_context *)((PUINT8)(h) + sizeof(struct fsp_fuse_context_header)))
|
||||
|
||||
#define FSP_FUSE_HAS_SYMLINKS(f) ((f)->has_symlinks)
|
||||
|
||||
#define ENOSYS_(env) ('C' == (env)->environment ? 88 : 40)
|
||||
|
||||
struct fuse
|
||||
{
|
||||
struct fsp_fuse_env *env;
|
||||
@ -54,6 +56,7 @@ struct fuse
|
||||
FSP_FILE_SYSTEM *FileSystem;
|
||||
FSP_SERVICE *Service; /* weak */
|
||||
volatile int exited;
|
||||
struct fuse3 *fuse3;
|
||||
};
|
||||
|
||||
struct fsp_fuse_context_header
|
||||
@ -87,6 +90,11 @@ NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem,
|
||||
NTSTATUS fsp_fuse_op_leave(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||
|
||||
int fsp_fuse_intf_CanDeleteAddDirInfo(void *buf, const char *name,
|
||||
const struct fuse_stat *stbuf, fuse_off_t off);
|
||||
int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
|
||||
const struct fuse_stat *stbuf, fuse_off_t off);
|
||||
|
||||
extern FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf;
|
||||
|
||||
NTSTATUS fsp_fuse_get_token_uidgid(
|
||||
@ -102,4 +110,65 @@ NTSTATUS fsp_fuse_get_token_uidgid(
|
||||
#define NFS_SPECFILE_LNK 0x00000000014b4e4c
|
||||
#define NFS_SPECFILE_SOCK 0x000000004B434F53
|
||||
|
||||
/* FUSE obj alloc/free */
|
||||
|
||||
struct fsp_fuse_obj_hdr
|
||||
{
|
||||
void (*dtor)(void *);
|
||||
__declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 ObjectBuf[];
|
||||
};
|
||||
|
||||
static inline void *fsp_fuse_obj_alloc(struct fsp_fuse_env *env, size_t size)
|
||||
{
|
||||
struct fsp_fuse_obj_hdr *hdr;
|
||||
|
||||
hdr = env->memalloc(sizeof(struct fsp_fuse_obj_hdr) + size);
|
||||
if (0 == hdr)
|
||||
return 0;
|
||||
|
||||
hdr->dtor = env->memfree;
|
||||
memset(hdr->ObjectBuf, 0, size);
|
||||
return hdr->ObjectBuf;
|
||||
}
|
||||
|
||||
static inline void fsp_fuse_obj_free(void *obj)
|
||||
{
|
||||
if (0 == obj)
|
||||
return;
|
||||
|
||||
struct fsp_fuse_obj_hdr *hdr = (PVOID)((PUINT8)obj - sizeof(struct fsp_fuse_obj_hdr));
|
||||
|
||||
hdr->dtor(hdr);
|
||||
}
|
||||
|
||||
struct fuse_context *fsp_fuse_get_context_internal(void);
|
||||
|
||||
struct fsp_fuse_core_opt_data
|
||||
{
|
||||
struct fsp_fuse_env *env;
|
||||
int help, debug;
|
||||
HANDLE DebugLogHandle;
|
||||
int set_umask, umask,
|
||||
set_create_umask, create_umask,
|
||||
set_uid, uid,
|
||||
set_gid, gid,
|
||||
set_attr_timeout, attr_timeout,
|
||||
rellinks;
|
||||
int set_FileInfoTimeout,
|
||||
set_DirInfoTimeout,
|
||||
set_VolumeInfoTimeout,
|
||||
set_KeepFileCache;
|
||||
unsigned ThreadCount;
|
||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||
UINT16 VolumeLabelLength;
|
||||
WCHAR VolumeLabel[sizeof ((FSP_FSCTL_VOLUME_INFO *)0)->VolumeLabel / sizeof(WCHAR)];
|
||||
};
|
||||
FSP_FSCTL_STATIC_ASSERT(
|
||||
sizeof ((struct fuse *)0)->VolumeLabel == sizeof ((struct fsp_fuse_core_opt_data *)0)->VolumeLabel,
|
||||
"fuse::VolumeLabel and fsp_fuse_core_opt_data::VolumeLabel: sizeof must be same.");
|
||||
|
||||
int fsp_fuse_core_opt_parse(struct fsp_fuse_env *env,
|
||||
struct fuse_args *args, struct fsp_fuse_core_opt_data *opt_data,
|
||||
int help);
|
||||
|
||||
#endif
|
||||
|
656
src/dll/fuse3/fuse2to3.c
Normal file
656
src/dll/fuse3/fuse2to3.c
Normal file
@ -0,0 +1,656 @@
|
||||
/**
|
||||
* @file dll/fuse3/fuse2to3.c
|
||||
*
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <dll/fuse3/library.h>
|
||||
|
||||
static inline struct fuse3 *fuse2to3_getfuse3(void)
|
||||
{
|
||||
return fsp_fuse_get_context_internal()->fuse->fuse3;
|
||||
}
|
||||
|
||||
static inline void fuse2to3_fi2from3(struct fuse_file_info *fi, struct fuse3_file_info *fi3)
|
||||
{
|
||||
memset(fi, 0, sizeof *fi);
|
||||
fi->flags = fi3->flags;
|
||||
fi->writepage = fi3->writepage;
|
||||
fi->direct_io = fi3->direct_io;
|
||||
fi->keep_cache = fi3->keep_cache;
|
||||
fi->flush = fi3->flush;
|
||||
fi->nonseekable = fi3->nonseekable;
|
||||
fi->fh = fi3->fh;
|
||||
fi->lock_owner = fi3->lock_owner;
|
||||
}
|
||||
|
||||
static inline void fuse2to3_fi3from2(struct fuse3_file_info *fi3, struct fuse_file_info *fi)
|
||||
{
|
||||
memset(fi3, 0, sizeof *fi3);
|
||||
fi3->flags = fi->flags;
|
||||
fi3->writepage = fi->writepage;
|
||||
fi3->direct_io = fi->direct_io;
|
||||
fi3->keep_cache = fi->keep_cache;
|
||||
fi3->flush = fi->flush;
|
||||
fi3->nonseekable = fi->nonseekable;
|
||||
fi3->fh = fi->fh;
|
||||
fi3->lock_owner = fi->lock_owner;
|
||||
}
|
||||
|
||||
static inline void fuse2to3_conn3from2(struct fuse3_conn_info *conn3, struct fuse_conn_info *conn)
|
||||
{
|
||||
memset(conn3, 0, sizeof *conn3);
|
||||
conn3->proto_major = 7; /* pretend that we are FUSE kernel protocol 7.26 */
|
||||
conn3->proto_minor = 26; /* which was current at the time of FUSE 3.2 */
|
||||
conn3->max_write = conn->max_write;
|
||||
conn3->max_read = conn->max_write;
|
||||
conn3->max_readahead = conn->max_readahead;
|
||||
conn3->capable = (conn->capable & ~FSP_FUSE_CAP_READDIR_PLUS) | FUSE_CAP_READDIRPLUS;
|
||||
conn3->want = conn->want;
|
||||
}
|
||||
|
||||
static int fuse2to3_getattr(const char *path, struct fuse_stat *stbuf)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.getattr(path, stbuf, 0);
|
||||
}
|
||||
|
||||
static int fuse2to3_readlink(const char *path, char *buf, size_t size)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.readlink(path, buf, size);
|
||||
}
|
||||
|
||||
static int fuse2to3_mknod(const char *path, fuse_mode_t mode, fuse_dev_t dev)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.mknod(path, mode, dev);
|
||||
}
|
||||
|
||||
static int fuse2to3_mkdir(const char *path, fuse_mode_t mode)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.mkdir(path, mode);
|
||||
}
|
||||
|
||||
static int fuse2to3_unlink(const char *path)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.unlink(path);
|
||||
}
|
||||
|
||||
static int fuse2to3_rmdir(const char *path)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.rmdir(path);
|
||||
}
|
||||
|
||||
static int fuse2to3_symlink(const char *dstpath, const char *srcpath)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.symlink(dstpath, srcpath);
|
||||
}
|
||||
|
||||
static int fuse2to3_rename(const char *oldpath, const char *newpath)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.rename(oldpath, newpath, 0);
|
||||
}
|
||||
|
||||
static int fuse2to3_link(const char *srcpath, const char *dstpath)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.link(srcpath, dstpath);
|
||||
}
|
||||
|
||||
static int fuse2to3_chmod(const char *path, fuse_mode_t mode)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.chmod(path, mode, 0);
|
||||
}
|
||||
|
||||
static int fuse2to3_chown(const char *path, fuse_uid_t uid, fuse_gid_t gid)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.chown(path, uid, gid, 0);
|
||||
}
|
||||
|
||||
static int fuse2to3_truncate(const char *path, fuse_off_t size)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.truncate(path, size, 0);
|
||||
}
|
||||
|
||||
static int fuse2to3_open(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.open(path, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_read(const char *path, char *buf, size_t size, fuse_off_t off,
|
||||
struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.read(path, buf, size, off, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_write(const char *path, const char *buf, size_t size, fuse_off_t off,
|
||||
struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.write(path, buf, size, off, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_statfs(const char *path, struct fuse_statvfs *stbuf)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.statfs(path, stbuf);
|
||||
}
|
||||
|
||||
static int fuse2to3_flush(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.flush(path, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_release(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.release(path, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_fsync(const char *path, int datasync, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.fsync(path, datasync, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_setxattr(const char *path, const char *name, const char *value, size_t size,
|
||||
int flags)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.setxattr(path, name, value, size, flags);
|
||||
}
|
||||
|
||||
static int fuse2to3_getxattr(const char *path, const char *name, char *value, size_t size)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.getxattr(path, name, value, size);
|
||||
}
|
||||
|
||||
static int fuse2to3_listxattr(const char *path, char *namebuf, size_t size)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.listxattr(path, namebuf, size);
|
||||
}
|
||||
|
||||
static int fuse2to3_removexattr(const char *path, const char *name)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.removexattr(path, name);
|
||||
}
|
||||
|
||||
static int fuse2to3_opendir(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.opendir(path, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_candel_filldir(void *buf, const char *name,
|
||||
const struct fuse_stat *stbuf, fuse_off_t off,
|
||||
enum fuse3_fill_dir_flags flags)
|
||||
{
|
||||
return fsp_fuse_intf_CanDeleteAddDirInfo(buf, name, 0, off);
|
||||
}
|
||||
|
||||
static int fuse2to3_filldir(void *buf, const char *name,
|
||||
const struct fuse_stat *stbuf, fuse_off_t off,
|
||||
enum fuse3_fill_dir_flags flags)
|
||||
{
|
||||
return 0 != (flags & FUSE_FILL_DIR_PLUS) ?
|
||||
fsp_fuse_intf_AddDirInfo(buf, name, stbuf, off) :
|
||||
fsp_fuse_intf_AddDirInfo(buf, name, 0, off);
|
||||
}
|
||||
|
||||
static int fuse2to3_readdir(const char *path, void *buf, fuse_fill_dir_t filler, fuse_off_t off,
|
||||
struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse_dirhandle *dh = buf;
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res;
|
||||
if (fsp_fuse_intf_CanDeleteAddDirInfo == filler)
|
||||
res = f3->ops.readdir(path, buf, &fuse2to3_candel_filldir, off, &fi3, 0);
|
||||
else if (fsp_fuse_intf_AddDirInfo == filler)
|
||||
res = f3->ops.readdir(path, buf, &fuse2to3_filldir, off, &fi3,
|
||||
dh->ReaddirPlus ? FUSE_READDIR_PLUS : 0);
|
||||
else
|
||||
{
|
||||
FspDebugLog("fuse2to3_readdir = -ENOSYS (internal error: unknown filler)\n");
|
||||
res = -ENOSYS_(f3->fuse->env);
|
||||
}
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_releasedir(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.releasedir(path, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_fsyncdir(const char *path, int datasync, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.fsyncdir(path, datasync, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void *fuse2to3_init(struct fuse_conn_info *conn)
|
||||
{
|
||||
struct fuse_context *context = fsp_fuse_get_context_internal();
|
||||
struct fuse *f = context->fuse;
|
||||
struct fuse3 *f3 = f->fuse3;
|
||||
|
||||
struct fuse3_conn_info conn3;
|
||||
fuse2to3_conn3from2(&conn3, conn);
|
||||
|
||||
struct fuse3_config conf3;
|
||||
memset(&conf3, 0, sizeof conf3);
|
||||
conf3.set_gid = f->set_gid;
|
||||
conf3.gid = f->gid;
|
||||
conf3.set_uid = f->set_uid;
|
||||
conf3.uid = f->uid;
|
||||
conf3.set_mode = f->set_umask;
|
||||
conf3.umask = f->umask;
|
||||
#if 0
|
||||
/*
|
||||
* Cannot set timeouts because of lack of floating point support.
|
||||
*
|
||||
* FUSE uses the `double` type for timeouts. This DLL does not use the standard library
|
||||
* for a variety of reasons. This means that we cannot easily perform the computations
|
||||
* below.
|
||||
*
|
||||
* If this becomes important (double) floating point values could perhaps be calculated
|
||||
* using bit tricks. See below:
|
||||
* - http://locklessinc.com/articles/i2f/
|
||||
* - https://stackoverflow.com/a/20308114
|
||||
*/
|
||||
conf3.entry_timeout = f->VolumeParams.DirInfoTimeoutValid ?
|
||||
f->VolumeParams.DirInfoTimeout / 1000 : f->VolumeParams.FileInfoTimeout / 1000;
|
||||
conf3.negative_timeout = 0;
|
||||
conf3.attr_timeout = f->VolumeParams.FileInfoTimeout / 1000;
|
||||
conf3.ac_attr_timeout = conf3.attr_timeout;
|
||||
#endif
|
||||
|
||||
void *res = f3->ops.init(&conn3, &conf3);
|
||||
|
||||
conn->max_write = conn3.max_write;
|
||||
conn->max_readahead = conn3.max_readahead;
|
||||
conn->want = 0 != (conn3.want & FUSE_CAP_READDIRPLUS) ? FSP_FUSE_CAP_READDIR_PLUS : 0;
|
||||
conn->want |= conn3.want & ~FUSE_CAP_READDIRPLUS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void fuse2to3_destroy(void *data)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
f3->ops.destroy(data);
|
||||
}
|
||||
|
||||
static int fuse2to3_access(const char *path, int mask)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.access(path, mask);
|
||||
}
|
||||
|
||||
static int fuse2to3_create(const char *path, fuse_mode_t mode, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.create(path, mode, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_ftruncate(const char *path, fuse_off_t off, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.truncate(path, off, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_fgetattr(const char *path, struct fuse_stat *stbuf, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.getattr(path, stbuf, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_lock(const char *path,
|
||||
struct fuse_file_info *fi, int cmd, struct fuse_flock *lock)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.lock(path, &fi3, cmd, lock);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_utimens(const char *path, const struct fuse_timespec tv[2])
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.utimens(path, tv, 0);
|
||||
}
|
||||
|
||||
static int fuse2to3_bmap(const char *path, size_t blocksize, uint64_t *idx)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.bmap(path, blocksize, idx);
|
||||
}
|
||||
|
||||
static int fuse2to3_ioctl(const char *path, int cmd, void *arg, struct fuse_file_info *fi,
|
||||
unsigned int flags, void *data)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.ioctl(path, cmd, arg, &fi3, flags, data);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_poll(const char *path, struct fuse_file_info *fi,
|
||||
struct fuse_pollhandle *ph, unsigned *reventsp)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.poll(path, &fi3, (struct fuse3_pollhandle *)ph, reventsp);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_write_buf(const char *path,
|
||||
struct fuse_bufvec *buf, fuse_off_t off, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.write_buf(path,
|
||||
(struct fuse3_bufvec *)buf, /* revisit if we implement bufvec's */
|
||||
off, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_read_buf(const char *path,
|
||||
struct fuse_bufvec **bufp, size_t size, fuse_off_t off, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.read_buf(path,
|
||||
(struct fuse3_bufvec **)bufp, /* revisit if we implement bufvec's */
|
||||
size, off, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_flock(const char *path, struct fuse_file_info *fi, int op)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.flock(path, &fi3, op);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_fallocate(const char *path, int mode, fuse_off_t off, fuse_off_t len,
|
||||
struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.fallocate(path, mode, off, len, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fsp_fuse3_copy_args(struct fsp_fuse_env *env,
|
||||
const struct fuse_args *args,
|
||||
struct fuse_args *outargs)
|
||||
{
|
||||
outargs->argc = 0;
|
||||
outargs->argv = 0;
|
||||
outargs->allocated = 0;
|
||||
|
||||
for (int argi = 0; args->argc > argi; argi++)
|
||||
if (-1 == fsp_fuse_opt_add_arg(env, outargs, args->argv[argi]))
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
fsp_fuse_opt_free_args(env, outargs);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct fuse3 *fsp_fuse3_new_common(struct fsp_fuse_env *env,
|
||||
struct fuse_args *args,
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data,
|
||||
int help)
|
||||
{
|
||||
/* preflight args */
|
||||
struct fsp_fuse_core_opt_data opt_data;
|
||||
struct fuse_args pfargs;
|
||||
memset(&opt_data, 0, sizeof opt_data);
|
||||
if (-1 == fsp_fuse3_copy_args(env, args, &pfargs))
|
||||
return 0;
|
||||
int optres = fsp_fuse_core_opt_parse(env, &pfargs, &opt_data, /*help=*/1);
|
||||
fsp_fuse_opt_free_args(env, &pfargs);
|
||||
if (-1 == optres)
|
||||
return 0;
|
||||
if (opt_data.help)
|
||||
return 0;
|
||||
|
||||
struct fuse3 *f3 = 0;
|
||||
|
||||
if (opsize > sizeof(struct fuse3_operations))
|
||||
opsize = sizeof(struct fuse3_operations);
|
||||
|
||||
f3 = fsp_fuse_obj_alloc(env, sizeof *f3);
|
||||
if (0 == f3)
|
||||
goto fail;
|
||||
|
||||
if (-1 == fsp_fuse3_copy_args(env, args, &f3->args))
|
||||
goto fail;
|
||||
memcpy(&f3->ops, ops, opsize);
|
||||
f3->data = data;
|
||||
|
||||
return f3;
|
||||
|
||||
fail:
|
||||
if (0 != f3)
|
||||
fsp_fuse3_destroy(env, f3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FSP_FUSE_API struct fuse3 *fsp_fuse3_new_30(struct fsp_fuse_env *env,
|
||||
struct fuse_args *args,
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data)
|
||||
{
|
||||
return fsp_fuse3_new_common(env, args, ops, opsize, data, /*help=*/1);
|
||||
}
|
||||
|
||||
FSP_FUSE_API struct fuse3 *fsp_fuse3_new(struct fsp_fuse_env *env,
|
||||
struct fuse_args *args,
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data)
|
||||
{
|
||||
return fsp_fuse3_new_common(env, args, ops, opsize, data, /*help=*/0);
|
||||
}
|
||||
|
||||
FSP_FUSE_API void fsp_fuse3_destroy(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f3)
|
||||
{
|
||||
if (0 != f3->fuse)
|
||||
fsp_fuse_destroy(env, f3->fuse);
|
||||
|
||||
fsp_fuse_opt_free_args(env, &f3->args);
|
||||
|
||||
fsp_fuse_obj_free(f3);
|
||||
}
|
||||
|
||||
FSP_FUSE_API int fsp_fuse3_mount(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f3, const char *mountpoint)
|
||||
{
|
||||
struct fuse_chan *ch = 0;
|
||||
struct fuse *f = 0;
|
||||
struct fuse_operations fuse2to3_ops =
|
||||
{
|
||||
.getattr = 0 != f3->ops.getattr ? fuse2to3_getattr : 0,
|
||||
.readlink = 0 != f3->ops.readlink ? fuse2to3_readlink : 0,
|
||||
.mknod = 0 != f3->ops.mknod ? fuse2to3_mknod : 0,
|
||||
.mkdir = 0 != f3->ops.mkdir ? fuse2to3_mkdir : 0,
|
||||
.unlink = 0 != f3->ops.unlink ? fuse2to3_unlink : 0,
|
||||
.rmdir = 0 != f3->ops.rmdir ? fuse2to3_rmdir : 0,
|
||||
.symlink = 0 != f3->ops.symlink ? fuse2to3_symlink : 0,
|
||||
.rename = 0 != f3->ops.rename ? fuse2to3_rename : 0,
|
||||
.link = 0 != f3->ops.link ? fuse2to3_link : 0,
|
||||
.chmod = 0 != f3->ops.chmod ? fuse2to3_chmod : 0,
|
||||
.chown = 0 != f3->ops.chown ? fuse2to3_chown : 0,
|
||||
.truncate = 0 != f3->ops.truncate ? fuse2to3_truncate : 0,
|
||||
.open = 0 != f3->ops.open ? fuse2to3_open : 0,
|
||||
.read = 0 != f3->ops.read ? fuse2to3_read : 0,
|
||||
.write = 0 != f3->ops.write ? fuse2to3_write : 0,
|
||||
.statfs = 0 != f3->ops.statfs ? fuse2to3_statfs : 0,
|
||||
.flush = 0 != f3->ops.flush ? fuse2to3_flush : 0,
|
||||
.release = 0 != f3->ops.release ? fuse2to3_release : 0,
|
||||
.fsync = 0 != f3->ops.fsync ? fuse2to3_fsync : 0,
|
||||
.setxattr = 0 != f3->ops.setxattr ? fuse2to3_setxattr : 0,
|
||||
.getxattr = 0 != f3->ops.getxattr ? fuse2to3_getxattr : 0,
|
||||
.listxattr = 0 != f3->ops.listxattr ? fuse2to3_listxattr : 0,
|
||||
.removexattr = 0 != f3->ops.removexattr ? fuse2to3_removexattr : 0,
|
||||
.opendir = 0 != f3->ops.opendir ? fuse2to3_opendir : 0,
|
||||
.readdir = 0 != f3->ops.readdir ? fuse2to3_readdir : 0,
|
||||
.releasedir = 0 != f3->ops.releasedir ? fuse2to3_releasedir : 0,
|
||||
.fsyncdir = 0 != f3->ops.fsyncdir ? fuse2to3_fsyncdir : 0,
|
||||
.init = 0 != f3->ops.init ? fuse2to3_init : 0,
|
||||
.destroy = 0 != f3->ops.destroy ? fuse2to3_destroy : 0,
|
||||
.access = 0 != f3->ops.access ? fuse2to3_access : 0,
|
||||
.create = 0 != f3->ops.create ? fuse2to3_create : 0,
|
||||
.ftruncate = 0 != f3->ops.truncate ? fuse2to3_ftruncate : 0,
|
||||
.fgetattr = 0 != f3->ops.getattr ? fuse2to3_fgetattr : 0,
|
||||
.lock = 0 != f3->ops.lock ? fuse2to3_lock : 0,
|
||||
.utimens = 0 != f3->ops.utimens ? fuse2to3_utimens : 0,
|
||||
.bmap = 0 != f3->ops.bmap ? fuse2to3_bmap : 0,
|
||||
.ioctl = 0 != f3->ops.ioctl ? fuse2to3_ioctl : 0,
|
||||
.poll = 0 != f3->ops.poll ? fuse2to3_poll : 0,
|
||||
.write_buf = 0 != f3->ops.write_buf ? fuse2to3_write_buf : 0,
|
||||
.read_buf = 0 != f3->ops.read_buf ? fuse2to3_read_buf : 0,
|
||||
.flock = 0 != f3->ops.flock ? fuse2to3_flock : 0,
|
||||
.fallocate = 0 != f3->ops.fallocate ? fuse2to3_fallocate : 0,
|
||||
};
|
||||
|
||||
ch = fsp_fuse_mount(env, mountpoint, &f3->args);
|
||||
if (0 == ch)
|
||||
goto fail;
|
||||
|
||||
f = fsp_fuse_new(env, ch, &f3->args, &fuse2to3_ops, sizeof fuse2to3_ops, f3->data);
|
||||
if (0 == f)
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* Free the fuse_chan which is no longer needed. Note that this behavior is WinFsp-FUSE
|
||||
* specific, because WinFsp-FUSE only allocates/frees fuse_chan memory during fuse_mount/
|
||||
* fuse_unmount and does not perform any actual mounting/unmounting. This would not work
|
||||
* on a different FUSE implementation.
|
||||
*
|
||||
* (Store mountpoint and ch inside struct fuse3 so that they can be freed during fuse_destroy
|
||||
* in that case.)
|
||||
*/
|
||||
fsp_fuse_unmount(env, mountpoint, ch);
|
||||
|
||||
/* Free the args which are no longer needed. */
|
||||
fsp_fuse_opt_free_args(env, &f3->args);
|
||||
|
||||
f->fuse3 = f3;
|
||||
f3->fuse = f;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (0 != f)
|
||||
fsp_fuse_destroy(env, f);
|
||||
|
||||
if (0 != ch)
|
||||
fsp_fuse_unmount(env, mountpoint, ch);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
FSP_FUSE_API void fsp_fuse3_unmount(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f3)
|
||||
{
|
||||
fsp_fuse_destroy(env, f3->fuse);
|
||||
f3->fuse = 0;
|
||||
}
|
152
src/dll/fuse3/fuse3.c
Normal file
152
src/dll/fuse3/fuse3.c
Normal file
@ -0,0 +1,152 @@
|
||||
/**
|
||||
* @file dll/fuse3/fuse3.c
|
||||
*
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <dll/fuse3/library.h>
|
||||
|
||||
FSP_FUSE_API int fsp_fuse3_main_real(struct fsp_fuse_env *env,
|
||||
int argc, char *argv[],
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data)
|
||||
{
|
||||
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
|
||||
char *mountpoint = 0;
|
||||
int multithreaded = 0;
|
||||
int foreground = 0;
|
||||
struct fuse3 *f3 = 0;
|
||||
int mounted = 0;
|
||||
int signal_handlers = 0;
|
||||
int result;
|
||||
|
||||
result = fsp_fuse_parse_cmdline(env, &args, &mountpoint, &multithreaded, &foreground);
|
||||
if (-1 == result)
|
||||
goto exit;
|
||||
|
||||
f3 = fsp_fuse3_new_30(env, &args, ops, opsize, data);
|
||||
if (0 == f3)
|
||||
{
|
||||
result = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
result = fsp_fuse3_mount(env, f3, mountpoint);
|
||||
if (-1 == result)
|
||||
goto exit;
|
||||
mounted = 1;
|
||||
|
||||
result = env->daemonize(foreground);
|
||||
if (-1 == result)
|
||||
goto exit;
|
||||
|
||||
result = env->set_signal_handlers(f3);
|
||||
if (-1 == result)
|
||||
goto exit;
|
||||
signal_handlers = 1;
|
||||
|
||||
result = multithreaded ? fsp_fuse3_loop_mt(env, f3, 0) : fsp_fuse3_loop(env, f3);
|
||||
|
||||
exit:
|
||||
if (signal_handlers)
|
||||
env->set_signal_handlers(0);
|
||||
|
||||
if (mounted)
|
||||
fsp_fuse3_unmount(env, f3);
|
||||
|
||||
if (0 != f3)
|
||||
fsp_fuse3_destroy(env, f3);
|
||||
|
||||
env->memfree(mountpoint);
|
||||
|
||||
fsp_fuse_opt_free_args(env, &args);
|
||||
|
||||
/* main() style return: 0 success, 1 error */
|
||||
return !!result;
|
||||
}
|
||||
|
||||
FSP_FUSE_API void fsp_fuse3_lib_help(struct fsp_fuse_env *env,
|
||||
struct fuse_args *args)
|
||||
{
|
||||
char *helpargv[] =
|
||||
{
|
||||
"UNKNOWN",
|
||||
"-h",
|
||||
0
|
||||
};
|
||||
struct fuse_args helpargs = FUSE_ARGS_INIT(2, helpargv);
|
||||
struct fsp_fuse_core_opt_data opt_data;
|
||||
|
||||
memset(&opt_data, 0, sizeof opt_data);
|
||||
fsp_fuse_core_opt_parse(env, &helpargs, &opt_data, /*help=*/1);
|
||||
}
|
||||
|
||||
FSP_FUSE_API int fsp_fuse3_loop(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f3)
|
||||
{
|
||||
return 0 == fsp_fuse_loop(env, f3->fuse) ? 0 : -EINVAL/* same on MSVC and Cygwin */;
|
||||
}
|
||||
|
||||
FSP_FUSE_API int fsp_fuse3_loop_mt_31(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f3, int clone_fd)
|
||||
{
|
||||
return 0 == fsp_fuse_loop_mt(env, f3->fuse) ? 0 : -EINVAL/* same on MSVC and Cygwin */;
|
||||
}
|
||||
|
||||
FSP_FUSE_API int fsp_fuse3_loop_mt(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f3, struct fuse3_loop_config *config)
|
||||
{
|
||||
return 0 == fsp_fuse_loop_mt(env, f3->fuse) ? 0 : -EINVAL/* same on MSVC and Cygwin */;
|
||||
}
|
||||
|
||||
FSP_FUSE_API void fsp_fuse3_exit(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f3)
|
||||
{
|
||||
fsp_fuse_exit(env, f3->fuse);
|
||||
}
|
||||
|
||||
FSP_FUSE_API struct fuse3_context *fsp_fuse3_get_context(struct fsp_fuse_env *env)
|
||||
{
|
||||
FSP_FSCTL_STATIC_ASSERT(
|
||||
sizeof(struct fuse_context) == sizeof(struct fuse3_context),
|
||||
"incompatible structs fuse_context and fuse3_context");
|
||||
FSP_FSCTL_STATIC_ASSERT(FIELD_OFFSET(
|
||||
struct fuse_context, private_data) == FIELD_OFFSET(struct fuse3_context, private_data),
|
||||
"incompatible structs fuse_context and fuse3_context");
|
||||
return (struct fuse3_context *)fsp_fuse_get_context(env);
|
||||
}
|
||||
|
||||
FSP_FUSE_API struct fuse3_conn_info_opts *fsp_fuse3_parse_conn_info_opts(
|
||||
struct fsp_fuse_env *env,
|
||||
struct fuse_args *args)
|
||||
{
|
||||
static int dummy;
|
||||
return (struct fuse3_conn_info_opts *)&dummy;
|
||||
}
|
||||
|
||||
FSP_FUSE_API void fsp_fuse3_apply_conn_info_opts(struct fsp_fuse_env *env,
|
||||
struct fuse3_conn_info_opts *opts, struct fuse3_conn_info *conn)
|
||||
{
|
||||
}
|
||||
|
||||
FSP_FUSE_API int fsp_fuse3_version(struct fsp_fuse_env *env)
|
||||
{
|
||||
return FUSE_VERSION;
|
||||
}
|
||||
|
||||
FSP_FUSE_API const char *fsp_fuse3_pkgversion(struct fsp_fuse_env *env)
|
||||
{
|
||||
#define STR(x) #x
|
||||
return STR(FUSE_MAJOR_VERSION) "." STR(FUSE_MINOR_VERSION);
|
||||
#undef STR
|
||||
}
|
10
src/dll/fuse3/fuse3.pc.in
Normal file
10
src/dll/fuse3/fuse3.pc.in
Normal file
@ -0,0 +1,10 @@
|
||||
prefix=${pcfiledir}/..
|
||||
incdir=${prefix}/inc/fuse3
|
||||
implib=${prefix}/bin/winfsp-${arch}.dll
|
||||
|
||||
Name: fuse3
|
||||
Description: WinFsp FUSE3 compatible API
|
||||
Version: 3.2
|
||||
URL: http://www.secfs.net/winfsp/
|
||||
Libs: "${implib}"
|
||||
Cflags: -I"${incdir}"
|
37
src/dll/fuse3/library.h
Normal file
37
src/dll/fuse3/library.h
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @file dll/fuse3/library.h
|
||||
*
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#ifndef WINFSP_DLL_FUSE3_LIBRARY_H_INCLUDED
|
||||
#define WINFSP_DLL_FUSE3_LIBRARY_H_INCLUDED
|
||||
|
||||
#include <dll/fuse/library.h>
|
||||
#undef FUSE_H_
|
||||
#undef FUSE_COMMON_H_
|
||||
#undef FUSE_MAJOR_VERSION
|
||||
#undef FUSE_MINOR_VERSION
|
||||
#undef fuse_main
|
||||
#include <fuse3/fuse.h>
|
||||
|
||||
struct fuse3
|
||||
{
|
||||
struct fuse_args args;
|
||||
struct fuse3_operations ops;
|
||||
void *data;
|
||||
struct fuse *fuse;
|
||||
};
|
||||
|
||||
#endif
|
@ -83,6 +83,10 @@ set opt_tests=^
|
||||
sample-fsx-passthrough-fuse-x64 ^
|
||||
sample-passthrough-fuse-x86 ^
|
||||
sample-fsx-passthrough-fuse-x86 ^
|
||||
sample-passthrough-fuse3-x64 ^
|
||||
sample-fsx-passthrough-fuse3-x64 ^
|
||||
sample-passthrough-fuse3-x86 ^
|
||||
sample-fsx-passthrough-fuse3-x86 ^
|
||||
sample-passthrough-dotnet ^
|
||||
compat-v1.2-memfs-x64 ^
|
||||
compat-v1.2-memfs-x86 ^
|
||||
@ -707,6 +711,28 @@ call :__run_sample_fsx_fuse_test passthrough-fuse x86 passthrough-fuse-x86 fsx
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:sample-passthrough-fuse3-x64
|
||||
call :__run_sample_fuse_test passthrough-fuse3 x64 passthrough-fuse3-x64 winfsp-tests-x64 ^
|
||||
"-create_fileattr_test -setfileinfo_test"
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:sample-passthrough-fuse3-x86
|
||||
call :__run_sample_fuse_test passthrough-fuse3 x86 passthrough-fuse3-x86 winfsp-tests-x86 ^
|
||||
"-create_fileattr_test -setfileinfo_test"
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:sample-fsx-passthrough-fuse3-x64
|
||||
call :__run_sample_fsx_fuse_test passthrough-fuse3 x64 passthrough-fuse3-x64 fsx
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:sample-fsx-passthrough-fuse3-x86
|
||||
call :__run_sample_fsx_fuse_test passthrough-fuse3 x86 passthrough-fuse3-x86 fsx
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:__run_sample_disk_test
|
||||
set RunSampleTestExit=0
|
||||
call %ProjRoot%\tools\build-sample %Configuration% %2 %1 "%TMP%\%1"
|
||||
@ -783,11 +809,16 @@ net use | findstr L:
|
||||
pushd >nul
|
||||
cd L: >nul 2>nul || (echo Unable to find drive L: >&2 & goto fail)
|
||||
L:
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^
|
||||
--external --resilient --case-insensitive-cmp --share-prefix="\%1\%TMP::=$%\%1\test" ^
|
||||
-create_allocation_test -create_notraverse_test -create_backup_test -create_restore_test -create_namelen_test ^
|
||||
-getfileinfo_name_test -delete_access_test -delete_mmap_test -rename_flipflop_test -rename_mmap_test -setsecurity_test -querydir_namelen_test -exec_rename_dir_test ^
|
||||
-reparse* -stream*
|
||||
if X%5==XNOEXCL (
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^
|
||||
--external --resilient
|
||||
) else (
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^
|
||||
--external --resilient --case-insensitive-cmp --share-prefix="\%1\%TMP::=$%\%1\test" ^
|
||||
-create_allocation_test -create_notraverse_test -create_backup_test -create_restore_test -create_namelen_test ^
|
||||
-getfileinfo_name_test -delete_access_test -delete_mmap_test -rename_flipflop_test -rename_mmap_test -setsecurity_test -querydir_namelen_test -exec_rename_dir_test ^
|
||||
-reparse* -stream* %~5
|
||||
)
|
||||
if !ERRORLEVEL! neq 0 set RunSampleTestExit=1
|
||||
popd
|
||||
echo net use L: /delete
|
||||
|
7
tst/passthrough-fuse3/.gitignore
vendored
Normal file
7
tst/passthrough-fuse3/.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
build
|
||||
*.ncb
|
||||
*.suo
|
||||
*.vcproj.*
|
||||
*.vcxproj.user
|
||||
*.exe
|
||||
*.install
|
18
tst/passthrough-fuse3/Makefile
Normal file
18
tst/passthrough-fuse3/Makefile
Normal file
@ -0,0 +1,18 @@
|
||||
usage:
|
||||
@echo "make cygfuse3|winfsp-fuse3" 1>&2
|
||||
@echo "" 1>&2
|
||||
@echo " cygfuse3 Link with CYGFUSE3" 1>&2
|
||||
@echo " winfsp-fuse3 Link with WinFsp-FUSE3" 1>&2
|
||||
@exit 2
|
||||
|
||||
cygfuse3: passthrough-cygfuse3
|
||||
|
||||
winfsp-fuse3: passthrough-winfsp-fuse3
|
||||
|
||||
passthrough-cygfuse3: passthrough-fuse3.c
|
||||
gcc $^ -o $@ -g -Wall `pkg-config fuse3 --cflags --libs`
|
||||
|
||||
passthrough-winfsp-fuse3: export PKG_CONFIG_PATH=$(PWD)/winfsp.install/lib
|
||||
passthrough-winfsp-fuse3: passthrough-fuse3.c
|
||||
ln -nsf "`regtool --wow32 get '/HKLM/Software/WinFsp/InstallDir' | cygpath -au -f -`" winfsp.install
|
||||
gcc $^ -o $@ -g -Wall `pkg-config fuse3 --cflags --libs`
|
7
tst/passthrough-fuse3/README.md
Normal file
7
tst/passthrough-fuse3/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
`Passthrough-fuse3` is a simple FUSE3 file system that passes all file system operations to an underlying file system.
|
||||
|
||||
It can be built with the following tools:
|
||||
|
||||
- Using Visual Studio (`winfsp.sln`).
|
||||
- Using Cygwin GCC and linking directly with the WinFsp DLL (`make winfsp-fuse3`).
|
||||
- Using Cygwin GCC and linking to CYGFUSE3 (`make cygfuse3`).
|
331
tst/passthrough-fuse3/passthrough-fuse3.c
Normal file
331
tst/passthrough-fuse3/passthrough-fuse3.c
Normal file
@ -0,0 +1,331 @@
|
||||
/**
|
||||
* @file passthrough-fuse.c
|
||||
*
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <fuse.h>
|
||||
|
||||
#if defined(_WIN64) || defined(_WIN32)
|
||||
#include "winposix.h"
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define FSNAME "passthrough"
|
||||
#define PROGNAME "passthrough-fuse"
|
||||
|
||||
#define concat_path(ptfs, fn, fp) (sizeof fp > (unsigned)snprintf(fp, sizeof fp, "%s%s", ptfs->rootdir, fn))
|
||||
|
||||
#define fi_dirbit (0x8000000000000000ULL)
|
||||
#define fi_fh(fi, MASK) ((fi)->fh & (MASK))
|
||||
#define fi_setfh(fi, FH, MASK) ((fi)->fh = (intptr_t)(FH) | (MASK))
|
||||
#define fi_fd(fi) (fi_fh(fi, fi_dirbit) ? \
|
||||
dirfd((DIR *)(intptr_t)fi_fh(fi, ~fi_dirbit)) : (int)fi_fh(fi, ~fi_dirbit))
|
||||
#define fi_dirp(fi) ((DIR *)(intptr_t)fi_fh(fi, ~fi_dirbit))
|
||||
#define fi_setfd(fi, fd) (fi_setfh(fi, fd, 0))
|
||||
#define fi_setdirp(fi, dirp) (fi_setfh(fi, dirp, fi_dirbit))
|
||||
|
||||
#define ptfs_impl_fullpath(n) \
|
||||
char full ## n[PATH_MAX]; \
|
||||
if (!concat_path(((PTFS *)fuse_get_context()->private_data), n, full ## n))\
|
||||
return -ENAMETOOLONG; \
|
||||
n = full ## n
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *rootdir;
|
||||
} PTFS;
|
||||
|
||||
static int ptfs_getattr(const char *path, struct fuse_stat *stbuf, struct fuse_file_info *fi)
|
||||
{
|
||||
if (0 == fi)
|
||||
{
|
||||
ptfs_impl_fullpath(path);
|
||||
|
||||
return -1 != lstat(path, stbuf) ? 0 : -errno;
|
||||
}
|
||||
else
|
||||
{
|
||||
int fd = fi_fd(fi);
|
||||
|
||||
return -1 != fstat(fd, stbuf) ? 0 : -errno;
|
||||
}
|
||||
}
|
||||
|
||||
static int ptfs_mkdir(const char *path, fuse_mode_t mode)
|
||||
{
|
||||
ptfs_impl_fullpath(path);
|
||||
|
||||
return -1 != mkdir(path, mode) ? 0 : -errno;
|
||||
}
|
||||
|
||||
static int ptfs_unlink(const char *path)
|
||||
{
|
||||
ptfs_impl_fullpath(path);
|
||||
|
||||
return -1 != unlink(path) ? 0 : -errno;
|
||||
}
|
||||
|
||||
static int ptfs_rmdir(const char *path)
|
||||
{
|
||||
ptfs_impl_fullpath(path);
|
||||
|
||||
return -1 != rmdir(path) ? 0 : -errno;
|
||||
}
|
||||
|
||||
static int ptfs_rename(const char *oldpath, const char *newpath, unsigned int flags)
|
||||
{
|
||||
ptfs_impl_fullpath(newpath);
|
||||
ptfs_impl_fullpath(oldpath);
|
||||
|
||||
return -1 != rename(oldpath, newpath) ? 0 : -errno;
|
||||
}
|
||||
|
||||
static int ptfs_chmod(const char *path, fuse_mode_t mode, struct fuse_file_info *fi)
|
||||
{
|
||||
ptfs_impl_fullpath(path);
|
||||
|
||||
return -1 != chmod(path, mode) ? 0 : -errno;
|
||||
}
|
||||
|
||||
static int ptfs_chown(const char *path, fuse_uid_t uid, fuse_gid_t gid, struct fuse_file_info *fi)
|
||||
{
|
||||
ptfs_impl_fullpath(path);
|
||||
|
||||
return -1 != lchown(path, uid, gid) ? 0 : -errno;
|
||||
}
|
||||
|
||||
static int ptfs_truncate(const char *path, fuse_off_t size, struct fuse_file_info *fi)
|
||||
{
|
||||
if (0 == fi)
|
||||
{
|
||||
ptfs_impl_fullpath(path);
|
||||
|
||||
return -1 != truncate(path, size) ? 0 : -errno;
|
||||
}
|
||||
else
|
||||
{
|
||||
int fd = fi_fd(fi);
|
||||
|
||||
return -1 != ftruncate(fd, size) ? 0 : -errno;
|
||||
}
|
||||
}
|
||||
|
||||
static int ptfs_open(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
ptfs_impl_fullpath(path);
|
||||
|
||||
int fd;
|
||||
return -1 != (fd = open(path, fi->flags)) ? (fi_setfd(fi, fd), 0) : -errno;
|
||||
}
|
||||
|
||||
static int ptfs_read(const char *path, char *buf, size_t size, fuse_off_t off,
|
||||
struct fuse_file_info *fi)
|
||||
{
|
||||
int fd = fi_fd(fi);
|
||||
|
||||
int nb;
|
||||
return -1 != (nb = pread(fd, buf, size, off)) ? nb : -errno;
|
||||
}
|
||||
|
||||
static int ptfs_write(const char *path, const char *buf, size_t size, fuse_off_t off,
|
||||
struct fuse_file_info *fi)
|
||||
{
|
||||
int fd = fi_fd(fi);
|
||||
|
||||
int nb;
|
||||
return -1 != (nb = pwrite(fd, buf, size, off)) ? nb : -errno;
|
||||
}
|
||||
|
||||
static int ptfs_statfs(const char *path, struct fuse_statvfs *stbuf)
|
||||
{
|
||||
ptfs_impl_fullpath(path);
|
||||
|
||||
return -1 != statvfs(path, stbuf) ? 0 : -errno;
|
||||
}
|
||||
|
||||
static int ptfs_release(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
int fd = fi_fd(fi);
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ptfs_fsync(const char *path, int datasync, struct fuse_file_info *fi)
|
||||
{
|
||||
int fd = fi_fd(fi);
|
||||
|
||||
return -1 != fsync(fd) ? 0 : -errno;
|
||||
}
|
||||
|
||||
static int ptfs_opendir(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
ptfs_impl_fullpath(path);
|
||||
|
||||
DIR *dirp;
|
||||
return 0 != (dirp = opendir(path)) ? (fi_setdirp(fi, dirp), 0) : -errno;
|
||||
}
|
||||
|
||||
static int ptfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, fuse_off_t off,
|
||||
struct fuse_file_info *fi, enum fuse_readdir_flags flags)
|
||||
{
|
||||
DIR *dirp = fi_dirp(fi);
|
||||
struct dirent *de;
|
||||
|
||||
rewinddir(dirp);
|
||||
for (;;)
|
||||
{
|
||||
errno = 0;
|
||||
if (0 == (de = readdir(dirp)))
|
||||
break;
|
||||
#if defined(_WIN64) || defined(_WIN32)
|
||||
if (0 != filler(buf, de->d_name, &de->d_stat, 0, FUSE_FILL_DIR_PLUS))
|
||||
#else
|
||||
if (0 != filler(buf, de->d_name, 0, 0, 0))
|
||||
#endif
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
static int ptfs_releasedir(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
DIR *dirp = fi_dirp(fi);
|
||||
|
||||
return -1 != closedir(dirp) ? 0 : -errno;
|
||||
}
|
||||
|
||||
static void *ptfs_init(struct fuse_conn_info *conn, struct fuse_config *conf)
|
||||
{
|
||||
conn->want |= (conn->capable & FUSE_CAP_READDIRPLUS);
|
||||
|
||||
#if defined(FSP_FUSE_CAP_CASE_INSENSITIVE)
|
||||
conn->want |= (conn->capable & FSP_FUSE_CAP_CASE_INSENSITIVE);
|
||||
#endif
|
||||
|
||||
return fuse_get_context()->private_data;
|
||||
}
|
||||
|
||||
static int ptfs_create(const char *path, fuse_mode_t mode, struct fuse_file_info *fi)
|
||||
{
|
||||
ptfs_impl_fullpath(path);
|
||||
|
||||
int fd;
|
||||
return -1 != (fd = open(path, fi->flags, mode)) ? (fi_setfd(fi, fd), 0) : -errno;
|
||||
}
|
||||
|
||||
static int ptfs_utimens(const char *path, const struct fuse_timespec tv[2], struct fuse_file_info *fi)
|
||||
{
|
||||
ptfs_impl_fullpath(path);
|
||||
|
||||
return -1 != utimensat(AT_FDCWD, path, tv, AT_SYMLINK_NOFOLLOW) ? 0 : -errno;
|
||||
}
|
||||
|
||||
static struct fuse_operations ptfs_ops =
|
||||
{
|
||||
.getattr = ptfs_getattr,
|
||||
.mkdir = ptfs_mkdir,
|
||||
.unlink = ptfs_unlink,
|
||||
.rmdir = ptfs_rmdir,
|
||||
.rename = ptfs_rename,
|
||||
.chmod = ptfs_chmod,
|
||||
.chown = ptfs_chown,
|
||||
.truncate = ptfs_truncate,
|
||||
.open = ptfs_open,
|
||||
.read = ptfs_read,
|
||||
.write = ptfs_write,
|
||||
.statfs = ptfs_statfs,
|
||||
.release = ptfs_release,
|
||||
.fsync = ptfs_fsync,
|
||||
.opendir = ptfs_opendir,
|
||||
.readdir = ptfs_readdir,
|
||||
.releasedir = ptfs_releasedir,
|
||||
.init = ptfs_init,
|
||||
.create = ptfs_create,
|
||||
.utimens = ptfs_utimens,
|
||||
};
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage: " PROGNAME " [FUSE options] rootdir mountpoint\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
PTFS ptfs = { 0 };
|
||||
|
||||
if (3 <= argc && '-' != argv[argc - 2][0] && '-' != argv[argc - 1][0])
|
||||
{
|
||||
ptfs.rootdir = realpath(argv[argc - 2], 0); /* memory freed at process end */
|
||||
argv[argc - 2] = argv[argc - 1];
|
||||
argc--;
|
||||
}
|
||||
|
||||
#if defined(_WIN64) || defined(_WIN32)
|
||||
/*
|
||||
* When building for Windows (rather than Cygwin or POSIX OS)
|
||||
* allow the path to be specified using the --VolumePrefix
|
||||
* switch using the syntax \\passthrough-fuse\C$\Path. This
|
||||
* allows us to run the file system under the WinFsp.Launcher
|
||||
* and start it using commands like:
|
||||
*
|
||||
* net use z: \\passthrough-fuse\C$\Path
|
||||
*/
|
||||
if (0 == ptfs.rootdir)
|
||||
for (int argi = 1; argc > argi; argi++)
|
||||
{
|
||||
int strncmp(const char *a, const char *b, size_t length);
|
||||
char *strchr(const char *s, int c);
|
||||
char *p = 0;
|
||||
|
||||
if (0 == strncmp("--UNC=", argv[argi], sizeof "--UNC=" - 1))
|
||||
p = argv[argi] + sizeof "--UNC=" - 1;
|
||||
else if (0 == strncmp("--VolumePrefix=", argv[argi], sizeof "--VolumePrefix=" - 1))
|
||||
p = argv[argi] + sizeof "--VolumePrefix=" - 1;
|
||||
|
||||
if (0 != p && '\\' != p[1])
|
||||
{
|
||||
p = strchr(p + 1, '\\');
|
||||
if (0 != p &&
|
||||
(
|
||||
('A' <= p[1] && p[1] <= 'Z') ||
|
||||
('a' <= p[1] && p[1] <= 'z')
|
||||
) &&
|
||||
'$' == p[2])
|
||||
{
|
||||
p[2] = ':';
|
||||
ptfs.rootdir = realpath(p + 1, 0); /* memory freed at process end */
|
||||
p[2] = '$';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (0 == ptfs.rootdir)
|
||||
usage();
|
||||
|
||||
return fuse_main(argc, argv, &ptfs_ops, &ptfs);
|
||||
}
|
28
tst/passthrough-fuse3/passthrough-fuse3.sln
Normal file
28
tst/passthrough-fuse3/passthrough-fuse3.sln
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "passthrough-fuse3", "passthrough-fuse3.vcxproj", "{5E99498C-D30C-48EF-A04A-7977C0305FAC}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{5E99498C-D30C-48EF-A04A-7977C0305FAC}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{5E99498C-D30C-48EF-A04A-7977C0305FAC}.Debug|x64.Build.0 = Debug|x64
|
||||
{5E99498C-D30C-48EF-A04A-7977C0305FAC}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{5E99498C-D30C-48EF-A04A-7977C0305FAC}.Debug|x86.Build.0 = Debug|Win32
|
||||
{5E99498C-D30C-48EF-A04A-7977C0305FAC}.Release|x64.ActiveCfg = Release|x64
|
||||
{5E99498C-D30C-48EF-A04A-7977C0305FAC}.Release|x64.Build.0 = Release|x64
|
||||
{5E99498C-D30C-48EF-A04A-7977C0305FAC}.Release|x86.ActiveCfg = Release|Win32
|
||||
{5E99498C-D30C-48EF-A04A-7977C0305FAC}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
190
tst/passthrough-fuse3/passthrough-fuse3.vcxproj
Normal file
190
tst/passthrough-fuse3/passthrough-fuse3.vcxproj
Normal file
@ -0,0 +1,190 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{5E99498C-D30C-48EF-A04A-7977C0305FAC}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>passthroughfuse3</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc\fuse3;$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc\fuse3;$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc\fuse3;$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc\fuse3;$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="passthrough-fuse3.c" />
|
||||
<ClCompile Include="winposix.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="winposix.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
21
tst/passthrough-fuse3/passthrough-fuse3.vcxproj.filters
Normal file
21
tst/passthrough-fuse3/passthrough-fuse3.vcxproj.filters
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source">
|
||||
<UniqueIdentifier>{bfbcc136-ea14-4445-8f9b-1fa7f8aedc71}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="passthrough-fuse3.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="winposix.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="winposix.h">
|
||||
<Filter>Source</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
634
tst/passthrough-fuse3/winposix.c
Normal file
634
tst/passthrough-fuse3/winposix.c
Normal file
@ -0,0 +1,634 @@
|
||||
/**
|
||||
* @file winposix.c
|
||||
*
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is a very simple Windows POSIX layer. It handles all the POSIX
|
||||
* file API's required to implement passthrough-fuse in POSIX, however
|
||||
* the API handling is rather unsophisticated.
|
||||
*
|
||||
* Ways to improve it: use the FspPosix* API's to properly handle
|
||||
* file names and security.
|
||||
*/
|
||||
|
||||
#include <winfsp/winfsp.h>
|
||||
#include <fcntl.h>
|
||||
#include <fuse.h>
|
||||
#include "winposix.h"
|
||||
|
||||
struct _DIR
|
||||
{
|
||||
HANDLE h, fh;
|
||||
struct dirent de;
|
||||
char path[];
|
||||
};
|
||||
|
||||
#if defined(FSP_FUSE_USE_STAT_EX)
|
||||
static inline uint32_t MapFileAttributesToFlags(UINT32 FileAttributes)
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
|
||||
if (FileAttributes & FILE_ATTRIBUTE_READONLY)
|
||||
flags |= FSP_FUSE_UF_READONLY;
|
||||
if (FileAttributes & FILE_ATTRIBUTE_HIDDEN)
|
||||
flags |= FSP_FUSE_UF_HIDDEN;
|
||||
if (FileAttributes & FILE_ATTRIBUTE_SYSTEM)
|
||||
flags |= FSP_FUSE_UF_SYSTEM;
|
||||
if (FileAttributes & FILE_ATTRIBUTE_ARCHIVE)
|
||||
flags |= FSP_FUSE_UF_ARCHIVE;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static inline UINT32 MapFlagsToFileAttributes(uint32_t flags)
|
||||
{
|
||||
UINT32 FileAttributes = 0;
|
||||
|
||||
if (flags & FSP_FUSE_UF_READONLY)
|
||||
FileAttributes |= FILE_ATTRIBUTE_READONLY;
|
||||
if (flags & FSP_FUSE_UF_HIDDEN)
|
||||
FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
|
||||
if (flags & FSP_FUSE_UF_SYSTEM)
|
||||
FileAttributes |= FILE_ATTRIBUTE_SYSTEM;
|
||||
if (flags & FSP_FUSE_UF_ARCHIVE)
|
||||
FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
|
||||
|
||||
return FileAttributes;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int maperror(int winerrno);
|
||||
|
||||
static inline void *error0(void)
|
||||
{
|
||||
errno = maperror(GetLastError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int error(void)
|
||||
{
|
||||
errno = maperror(GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *realpath(const char *path, char *resolved)
|
||||
{
|
||||
char *result;
|
||||
|
||||
if (0 == resolved)
|
||||
{
|
||||
result = malloc(PATH_MAX); /* sets errno */
|
||||
if (0 == result)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
result = resolved;
|
||||
|
||||
int err = 0;
|
||||
DWORD len = GetFullPathNameA(path, PATH_MAX, result, 0);
|
||||
if (0 == len)
|
||||
err = GetLastError();
|
||||
else if (PATH_MAX < len)
|
||||
err = ERROR_INVALID_PARAMETER;
|
||||
|
||||
if (0 == err)
|
||||
{
|
||||
HANDLE h = CreateFileA(result,
|
||||
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
0,
|
||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||
if (INVALID_HANDLE_VALUE != h)
|
||||
CloseHandle(h);
|
||||
else
|
||||
err = GetLastError();
|
||||
}
|
||||
|
||||
if (0 != err)
|
||||
{
|
||||
if (result != resolved)
|
||||
free(result);
|
||||
|
||||
errno = maperror(err);
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int statvfs(const char *path, struct fuse_statvfs *stbuf)
|
||||
{
|
||||
char root[PATH_MAX];
|
||||
DWORD
|
||||
VolumeSerialNumber,
|
||||
MaxComponentLength,
|
||||
SectorsPerCluster,
|
||||
BytesPerSector,
|
||||
NumberOfFreeClusters,
|
||||
TotalNumberOfClusters;
|
||||
|
||||
if (!GetVolumePathNameA(path, root, PATH_MAX) ||
|
||||
!GetVolumeInformationA(root, 0, 0, &VolumeSerialNumber, &MaxComponentLength, 0, 0, 0) ||
|
||||
!GetDiskFreeSpaceA(root, &SectorsPerCluster, &BytesPerSector,
|
||||
&NumberOfFreeClusters, &TotalNumberOfClusters))
|
||||
{
|
||||
return error();
|
||||
}
|
||||
|
||||
memset(stbuf, 0, sizeof *stbuf);
|
||||
stbuf->f_bsize = SectorsPerCluster * BytesPerSector;
|
||||
stbuf->f_frsize = SectorsPerCluster * BytesPerSector;
|
||||
stbuf->f_blocks = TotalNumberOfClusters;
|
||||
stbuf->f_bfree = NumberOfFreeClusters;
|
||||
stbuf->f_bavail = TotalNumberOfClusters;
|
||||
stbuf->f_fsid = VolumeSerialNumber;
|
||||
stbuf->f_namemax = MaxComponentLength;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int open(const char *path, int oflag, ...)
|
||||
{
|
||||
static DWORD da[] = { GENERIC_READ, GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE, 0 };
|
||||
static DWORD cd[] = { OPEN_EXISTING, OPEN_ALWAYS, TRUNCATE_EXISTING, CREATE_ALWAYS };
|
||||
DWORD DesiredAccess = 0 == (oflag & _O_APPEND) ?
|
||||
da[oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)] :
|
||||
(da[oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)] & ~FILE_WRITE_DATA) | FILE_APPEND_DATA;
|
||||
DWORD CreationDisposition = (_O_CREAT | _O_EXCL) == (oflag & (_O_CREAT | _O_EXCL)) ?
|
||||
CREATE_NEW :
|
||||
cd[(oflag & (_O_CREAT | _O_TRUNC)) >> 8];
|
||||
|
||||
HANDLE h = CreateFileA(path,
|
||||
DesiredAccess, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
0/* default security */,
|
||||
CreationDisposition, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||
|
||||
if (INVALID_HANDLE_VALUE == h)
|
||||
return error();
|
||||
|
||||
return (int)(intptr_t)h;
|
||||
}
|
||||
|
||||
int fstat(int fd, struct fuse_stat *stbuf)
|
||||
{
|
||||
HANDLE h = (HANDLE)(intptr_t)fd;
|
||||
BY_HANDLE_FILE_INFORMATION FileInfo;
|
||||
|
||||
if (!GetFileInformationByHandle(h, &FileInfo))
|
||||
return error();
|
||||
|
||||
memset(stbuf, 0, sizeof *stbuf);
|
||||
stbuf->st_mode = 0777 |
|
||||
((FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 0040000/* S_IFDIR */ : 0);
|
||||
stbuf->st_nlink = 1;
|
||||
stbuf->st_size = ((UINT64)FileInfo.nFileSizeHigh << 32) | ((UINT64)FileInfo.nFileSizeLow);
|
||||
FspPosixFileTimeToUnixTime(*(PUINT64)&FileInfo.ftCreationTime, (void *)&stbuf->st_birthtim);
|
||||
FspPosixFileTimeToUnixTime(*(PUINT64)&FileInfo.ftLastAccessTime, (void *)&stbuf->st_atim);
|
||||
FspPosixFileTimeToUnixTime(*(PUINT64)&FileInfo.ftLastWriteTime, (void *)&stbuf->st_mtim);
|
||||
FspPosixFileTimeToUnixTime(*(PUINT64)&FileInfo.ftLastWriteTime, (void *)&stbuf->st_ctim);
|
||||
#if defined(FSP_FUSE_USE_STAT_EX)
|
||||
stbuf->st_flags = MapFileAttributesToFlags(FileInfo.dwFileAttributes);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ftruncate(int fd, fuse_off_t size)
|
||||
{
|
||||
HANDLE h = (HANDLE)(intptr_t)fd;
|
||||
FILE_END_OF_FILE_INFO EndOfFileInfo;
|
||||
|
||||
EndOfFileInfo.EndOfFile.QuadPart = size;
|
||||
|
||||
if (!SetFileInformationByHandle(h, FileEndOfFileInfo, &EndOfFileInfo, sizeof EndOfFileInfo))
|
||||
return error();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pread(int fd, void *buf, size_t nbyte, fuse_off_t offset)
|
||||
{
|
||||
HANDLE h = (HANDLE)(intptr_t)fd;
|
||||
OVERLAPPED Overlapped = { 0 };
|
||||
DWORD BytesTransferred;
|
||||
|
||||
Overlapped.Offset = (DWORD)offset;
|
||||
Overlapped.OffsetHigh = (DWORD)(offset >> 32);
|
||||
|
||||
if (!ReadFile(h, buf, (DWORD)nbyte, &BytesTransferred, &Overlapped))
|
||||
{
|
||||
if (ERROR_HANDLE_EOF == GetLastError())
|
||||
return 0;
|
||||
return error();
|
||||
}
|
||||
|
||||
return BytesTransferred;
|
||||
}
|
||||
|
||||
int pwrite(int fd, const void *buf, size_t nbyte, fuse_off_t offset)
|
||||
{
|
||||
HANDLE h = (HANDLE)(intptr_t)fd;
|
||||
OVERLAPPED Overlapped = { 0 };
|
||||
DWORD BytesTransferred;
|
||||
|
||||
Overlapped.Offset = (DWORD)offset;
|
||||
Overlapped.OffsetHigh = (DWORD)(offset >> 32);
|
||||
|
||||
if (!WriteFile(h, buf, (DWORD)nbyte, &BytesTransferred, &Overlapped))
|
||||
return error();
|
||||
|
||||
return BytesTransferred;
|
||||
}
|
||||
|
||||
int fsync(int fd)
|
||||
{
|
||||
HANDLE h = (HANDLE)(intptr_t)fd;
|
||||
|
||||
if (!FlushFileBuffers(h))
|
||||
return error();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int close(int fd)
|
||||
{
|
||||
HANDLE h = (HANDLE)(intptr_t)fd;
|
||||
|
||||
if (!CloseHandle(h))
|
||||
return error();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lstat(const char *path, struct fuse_stat *stbuf)
|
||||
{
|
||||
HANDLE h = CreateFileA(path,
|
||||
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
0,
|
||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||
if (INVALID_HANDLE_VALUE == h)
|
||||
return error();
|
||||
|
||||
int res = fstat((int)(intptr_t)h, stbuf);
|
||||
|
||||
CloseHandle(h);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int chmod(const char *path, fuse_mode_t mode)
|
||||
{
|
||||
/* we do not support file security */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lchown(const char *path, fuse_uid_t uid, fuse_gid_t gid)
|
||||
{
|
||||
/* we do not support file security */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lchflags(const char *path, uint32_t flags)
|
||||
{
|
||||
#if defined(FSP_FUSE_USE_STAT_EX)
|
||||
UINT32 FileAttributes = MapFlagsToFileAttributes(flags);
|
||||
|
||||
if (0 == FileAttributes)
|
||||
FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||
|
||||
if (!SetFileAttributesA(path, FileAttributes))
|
||||
return error();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int truncate(const char *path, fuse_off_t size)
|
||||
{
|
||||
HANDLE h = CreateFileA(path,
|
||||
FILE_WRITE_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
0,
|
||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||
if (INVALID_HANDLE_VALUE == h)
|
||||
return error();
|
||||
|
||||
int res = ftruncate((int)(intptr_t)h, size);
|
||||
|
||||
CloseHandle(h);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int utime(const char *path, const struct fuse_utimbuf *timbuf)
|
||||
{
|
||||
if (0 == timbuf)
|
||||
return utimensat(AT_FDCWD, path, 0, AT_SYMLINK_NOFOLLOW);
|
||||
else
|
||||
{
|
||||
struct fuse_timespec times[2];
|
||||
times[0].tv_sec = timbuf->actime;
|
||||
times[0].tv_nsec = 0;
|
||||
times[1].tv_sec = timbuf->modtime;
|
||||
times[1].tv_nsec = 0;
|
||||
return utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW);
|
||||
}
|
||||
}
|
||||
|
||||
int utimensat(int dirfd, const char *path, const struct fuse_timespec times[2], int flag)
|
||||
{
|
||||
/* ignore dirfd and assume that it is always AT_FDCWD */
|
||||
/* ignore flag and assume that it is always AT_SYMLINK_NOFOLLOW */
|
||||
|
||||
HANDLE h = CreateFileA(path,
|
||||
FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
0,
|
||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||
if (INVALID_HANDLE_VALUE == h)
|
||||
return error();
|
||||
|
||||
UINT64 LastAccessTime, LastWriteTime;
|
||||
if (0 == times)
|
||||
{
|
||||
FILETIME FileTime;
|
||||
GetSystemTimeAsFileTime(&FileTime);
|
||||
LastAccessTime = LastWriteTime = *(PUINT64)&FileTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
FspPosixUnixTimeToFileTime((void *)×[0], &LastAccessTime);
|
||||
FspPosixUnixTimeToFileTime((void *)×[1], &LastWriteTime);
|
||||
}
|
||||
|
||||
int res = SetFileTime(h,
|
||||
0, (PFILETIME)&LastAccessTime, (PFILETIME)&LastWriteTime) ? 0 : error();
|
||||
|
||||
CloseHandle(h);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int setcrtime(const char *path, const struct fuse_timespec *tv)
|
||||
{
|
||||
HANDLE h = CreateFileA(path,
|
||||
FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
0,
|
||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||
if (INVALID_HANDLE_VALUE == h)
|
||||
return error();
|
||||
|
||||
UINT64 CreationTime;
|
||||
FspPosixUnixTimeToFileTime((void *)tv, &CreationTime);
|
||||
|
||||
int res = SetFileTime(h,
|
||||
(PFILETIME)&CreationTime, 0, 0) ? 0 : error();
|
||||
|
||||
CloseHandle(h);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unlink(const char *path)
|
||||
{
|
||||
if (!DeleteFileA(path))
|
||||
return error();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rename(const char *oldpath, const char *newpath)
|
||||
{
|
||||
if (!MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
|
||||
return error();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mkdir(const char *path, fuse_mode_t mode)
|
||||
{
|
||||
if (!CreateDirectoryA(path, 0/* default security */))
|
||||
return error();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rmdir(const char *path)
|
||||
{
|
||||
if (!RemoveDirectoryA(path))
|
||||
return error();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DIR *opendir(const char *path)
|
||||
{
|
||||
HANDLE h = CreateFileA(path,
|
||||
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
0,
|
||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||
if (INVALID_HANDLE_VALUE == h)
|
||||
return error0();
|
||||
|
||||
size_t pathlen = strlen(path);
|
||||
if (0 < pathlen && '/' == path[pathlen - 1])
|
||||
pathlen--;
|
||||
|
||||
DIR *dirp = malloc(sizeof *dirp + pathlen + 3); /* sets errno */
|
||||
if (0 == dirp)
|
||||
{
|
||||
CloseHandle(h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(dirp, 0, sizeof *dirp);
|
||||
dirp->h = h;
|
||||
dirp->fh = INVALID_HANDLE_VALUE;
|
||||
memcpy(dirp->path, path, pathlen);
|
||||
dirp->path[pathlen + 0] = '/';
|
||||
dirp->path[pathlen + 1] = '*';
|
||||
dirp->path[pathlen + 2] = '\0';
|
||||
|
||||
return dirp;
|
||||
}
|
||||
|
||||
int dirfd(DIR *dirp)
|
||||
{
|
||||
return (int)(intptr_t)dirp->h;
|
||||
}
|
||||
|
||||
void rewinddir(DIR *dirp)
|
||||
{
|
||||
if (INVALID_HANDLE_VALUE != dirp->fh)
|
||||
{
|
||||
FindClose(dirp->fh);
|
||||
dirp->fh = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
struct dirent *readdir(DIR *dirp)
|
||||
{
|
||||
WIN32_FIND_DATAA FindData;
|
||||
struct fuse_stat *stbuf = &dirp->de.d_stat;
|
||||
|
||||
if (INVALID_HANDLE_VALUE == dirp->fh)
|
||||
{
|
||||
dirp->fh = FindFirstFileA(dirp->path, &FindData);
|
||||
if (INVALID_HANDLE_VALUE == dirp->fh)
|
||||
return error0();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!FindNextFileA(dirp->fh, &FindData))
|
||||
{
|
||||
if (ERROR_NO_MORE_FILES == GetLastError())
|
||||
return 0;
|
||||
return error0();
|
||||
}
|
||||
}
|
||||
|
||||
memset(stbuf, 0, sizeof *stbuf);
|
||||
stbuf->st_mode = 0777 |
|
||||
((FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 0040000/* S_IFDIR */ : 0);
|
||||
stbuf->st_nlink = 1;
|
||||
stbuf->st_size = ((UINT64)FindData.nFileSizeHigh << 32) | ((UINT64)FindData.nFileSizeLow);
|
||||
FspPosixFileTimeToUnixTime(*(PUINT64)&FindData.ftCreationTime, (void *)&stbuf->st_birthtim);
|
||||
FspPosixFileTimeToUnixTime(*(PUINT64)&FindData.ftLastAccessTime, (void *)&stbuf->st_atim);
|
||||
FspPosixFileTimeToUnixTime(*(PUINT64)&FindData.ftLastWriteTime, (void *)&stbuf->st_mtim);
|
||||
FspPosixFileTimeToUnixTime(*(PUINT64)&FindData.ftLastWriteTime, (void *)&stbuf->st_ctim);
|
||||
#if defined(FSP_FUSE_USE_STAT_EX)
|
||||
stbuf->st_flags = MapFileAttributesToFlags(FindData.dwFileAttributes);
|
||||
#endif
|
||||
|
||||
strcpy(dirp->de.d_name, FindData.cFileName);
|
||||
|
||||
return &dirp->de;
|
||||
}
|
||||
|
||||
int closedir(DIR *dirp)
|
||||
{
|
||||
if (INVALID_HANDLE_VALUE != dirp->fh)
|
||||
FindClose(dirp->fh);
|
||||
|
||||
CloseHandle(dirp->h);
|
||||
free(dirp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int maperror(int winerrno)
|
||||
{
|
||||
switch (winerrno)
|
||||
{
|
||||
case ERROR_INVALID_FUNCTION:
|
||||
return EINVAL;
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
return ENOENT;
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
return ENOENT;
|
||||
case ERROR_TOO_MANY_OPEN_FILES:
|
||||
return EMFILE;
|
||||
case ERROR_ACCESS_DENIED:
|
||||
return EACCES;
|
||||
case ERROR_INVALID_HANDLE:
|
||||
return EBADF;
|
||||
case ERROR_ARENA_TRASHED:
|
||||
return ENOMEM;
|
||||
case ERROR_NOT_ENOUGH_MEMORY:
|
||||
return ENOMEM;
|
||||
case ERROR_INVALID_BLOCK:
|
||||
return ENOMEM;
|
||||
case ERROR_BAD_ENVIRONMENT:
|
||||
return E2BIG;
|
||||
case ERROR_BAD_FORMAT:
|
||||
return ENOEXEC;
|
||||
case ERROR_INVALID_ACCESS:
|
||||
return EINVAL;
|
||||
case ERROR_INVALID_DATA:
|
||||
return EINVAL;
|
||||
case ERROR_INVALID_DRIVE:
|
||||
return ENOENT;
|
||||
case ERROR_CURRENT_DIRECTORY:
|
||||
return EACCES;
|
||||
case ERROR_NOT_SAME_DEVICE:
|
||||
return EXDEV;
|
||||
case ERROR_NO_MORE_FILES:
|
||||
return ENOENT;
|
||||
case ERROR_LOCK_VIOLATION:
|
||||
return EACCES;
|
||||
case ERROR_BAD_NETPATH:
|
||||
return ENOENT;
|
||||
case ERROR_NETWORK_ACCESS_DENIED:
|
||||
return EACCES;
|
||||
case ERROR_BAD_NET_NAME:
|
||||
return ENOENT;
|
||||
case ERROR_FILE_EXISTS:
|
||||
return EEXIST;
|
||||
case ERROR_CANNOT_MAKE:
|
||||
return EACCES;
|
||||
case ERROR_FAIL_I24:
|
||||
return EACCES;
|
||||
case ERROR_INVALID_PARAMETER:
|
||||
return EINVAL;
|
||||
case ERROR_NO_PROC_SLOTS:
|
||||
return EAGAIN;
|
||||
case ERROR_DRIVE_LOCKED:
|
||||
return EACCES;
|
||||
case ERROR_BROKEN_PIPE:
|
||||
return EPIPE;
|
||||
case ERROR_DISK_FULL:
|
||||
return ENOSPC;
|
||||
case ERROR_INVALID_TARGET_HANDLE:
|
||||
return EBADF;
|
||||
case ERROR_WAIT_NO_CHILDREN:
|
||||
return ECHILD;
|
||||
case ERROR_CHILD_NOT_COMPLETE:
|
||||
return ECHILD;
|
||||
case ERROR_DIRECT_ACCESS_HANDLE:
|
||||
return EBADF;
|
||||
case ERROR_NEGATIVE_SEEK:
|
||||
return EINVAL;
|
||||
case ERROR_SEEK_ON_DEVICE:
|
||||
return EACCES;
|
||||
case ERROR_DIR_NOT_EMPTY:
|
||||
return ENOTEMPTY;
|
||||
case ERROR_NOT_LOCKED:
|
||||
return EACCES;
|
||||
case ERROR_BAD_PATHNAME:
|
||||
return ENOENT;
|
||||
case ERROR_MAX_THRDS_REACHED:
|
||||
return EAGAIN;
|
||||
case ERROR_LOCK_FAILED:
|
||||
return EACCES;
|
||||
case ERROR_ALREADY_EXISTS:
|
||||
return EEXIST;
|
||||
case ERROR_FILENAME_EXCED_RANGE:
|
||||
return ENOENT;
|
||||
case ERROR_NESTING_NOT_ALLOWED:
|
||||
return EAGAIN;
|
||||
case ERROR_NOT_ENOUGH_QUOTA:
|
||||
return ENOMEM;
|
||||
default:
|
||||
if (ERROR_WRITE_PROTECT <= winerrno && winerrno <= ERROR_SHARING_BUFFER_EXCEEDED)
|
||||
return EACCES;
|
||||
else if (ERROR_INVALID_STARTING_CODESEG <= winerrno && winerrno <= ERROR_INFLOOP_IN_RELOC_CHAIN)
|
||||
return ENOEXEC;
|
||||
else
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
long WinFspLoad(void)
|
||||
{
|
||||
return FspLoad(0);
|
||||
}
|
77
tst/passthrough-fuse3/winposix.h
Normal file
77
tst/passthrough-fuse3/winposix.h
Normal file
@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @file winposix.h
|
||||
*
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#ifndef WINPOSIX_H_INCLUDED
|
||||
#define WINPOSIX_H_INCLUDED
|
||||
|
||||
#define O_RDONLY _O_RDONLY
|
||||
#define O_WRONLY _O_WRONLY
|
||||
#define O_RDWR _O_RDWR
|
||||
#define O_APPEND _O_APPEND
|
||||
#define O_CREAT _O_CREAT
|
||||
#define O_EXCL _O_EXCL
|
||||
#define O_TRUNC _O_TRUNC
|
||||
|
||||
#define PATH_MAX 1024
|
||||
#define AT_FDCWD -2
|
||||
#define AT_SYMLINK_NOFOLLOW 2
|
||||
|
||||
typedef struct _DIR DIR;
|
||||
struct dirent
|
||||
{
|
||||
struct fuse_stat d_stat;
|
||||
char d_name[255];
|
||||
};
|
||||
|
||||
char *realpath(const char *path, char *resolved);
|
||||
|
||||
int statvfs(const char *path, struct fuse_statvfs *stbuf);
|
||||
|
||||
int open(const char *path, int oflag, ...);
|
||||
int fstat(int fd, struct fuse_stat *stbuf);
|
||||
int ftruncate(int fd, fuse_off_t size);
|
||||
int pread(int fd, void *buf, size_t nbyte, fuse_off_t offset);
|
||||
int pwrite(int fd, const void *buf, size_t nbyte, fuse_off_t offset);
|
||||
int fsync(int fd);
|
||||
int close(int fd);
|
||||
|
||||
int lstat(const char *path, struct fuse_stat *stbuf);
|
||||
int chmod(const char *path, fuse_mode_t mode);
|
||||
int lchown(const char *path, fuse_uid_t uid, fuse_gid_t gid);
|
||||
int lchflags(const char *path, uint32_t flags);
|
||||
int truncate(const char *path, fuse_off_t size);
|
||||
int utime(const char *path, const struct fuse_utimbuf *timbuf);
|
||||
int utimensat(int dirfd, const char *path, const struct fuse_timespec times[2], int flag);
|
||||
int setcrtime(const char *path, const struct fuse_timespec *tv);
|
||||
int unlink(const char *path);
|
||||
int rename(const char *oldpath, const char *newpath);
|
||||
|
||||
int mkdir(const char *path, fuse_mode_t mode);
|
||||
int rmdir(const char *path);
|
||||
|
||||
DIR *opendir(const char *path);
|
||||
int dirfd(DIR *dirp);
|
||||
void rewinddir(DIR *dirp);
|
||||
struct dirent *readdir(DIR *dirp);
|
||||
int closedir(DIR *dirp);
|
||||
|
||||
long WinFspLoad(void);
|
||||
#undef fuse_main
|
||||
#define fuse_main(argc, argv, ops, data)\
|
||||
(WinFspLoad(), fuse_main_real(argc, argv, ops, sizeof *(ops), data))
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user