diff --git a/tst/passthrough-fuse/.gitignore b/tst/passthrough-fuse/.gitignore new file mode 100644 index 00000000..02b56dcd --- /dev/null +++ b/tst/passthrough-fuse/.gitignore @@ -0,0 +1,6 @@ +build +*.ncb +*.suo +*.vcproj.* +*.vcxproj.user +*.exe diff --git a/tst/passthrough-fuse/Makefile b/tst/passthrough-fuse/Makefile new file mode 100644 index 00000000..41c97570 --- /dev/null +++ b/tst/passthrough-fuse/Makefile @@ -0,0 +1,2 @@ +passthrough-fuse: passthrough-fuse.c + gcc $^ -o $@ -g -Wall `pkg-config fuse --cflags --libs` \ No newline at end of file diff --git a/tst/passthrough-fuse/passthrough-fuse.c b/tst/passthrough-fuse/passthrough-fuse.c new file mode 100644 index 00000000..4d6c53cf --- /dev/null +++ b/tst/passthrough-fuse/passthrough-fuse.c @@ -0,0 +1,275 @@ +/** + * @file passthrough-fuse.c + * + * @copyright 2015-2017 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 +#include +#include +#include + +#include + +#if defined(_WIN64) || defined(_WIN32) +#include "winposix.h" +#else +#include +#include +#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 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) +{ + ptfs_impl_fullpath(path); + + return -1 != lstat(path, 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) +{ + 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) +{ + 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) +{ + ptfs_impl_fullpath(path); + + return -1 != lchown(path, uid, gid) ? 0 : -errno; +} + +static int ptfs_truncate(const char *path, fuse_off_t size) +{ + ptfs_impl_fullpath(path); + + return -1 != truncate(path, size) ? 0 : -errno; +} + +static int ptfs_utime(const char *path, struct fuse_utimbuf *timbuf) +{ + ptfs_impl_fullpath(path); + + return -1 != utime(path, timbuf) ? 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->fh = 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 = (int)fi->fh; + + int by; + return -1 != (by = pread(fd, buf, size, off)) ? by : -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 = (int)fi->fh; + + int by; + return -1 != (by = pwrite(fd, buf, size, off)) ? by : -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 = (int)fi->fh; + + close(fd); + return 0; +} + +static int ptfs_fsync(const char *path, int datasync, struct fuse_file_info *fi) +{ + int fd = (int)fi->fh; + + return -1 != fsync(fd) ? 0 : -errno; +} + +static int ptfs_opendir(const char *path, struct fuse_file_info *fi) +{ + ptfs_impl_fullpath(path); + + DIR *dp; + return 0 != (dp = opendir(path)) ? (fi->fh = (intptr_t)dp, 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) +{ + DIR *dp = (DIR *)fi->fh; + struct dirent *de; + + for (;;) + { + errno = 0; + if (0 == (de = readdir(dp))) + break; + if (0 != filler(buf, de->d_name, 0, 0)) + return -ENOMEM; + } + + return -errno; +} + +static int ptfs_releasedir(const char *path, struct fuse_file_info *fi) +{ + DIR *dp = (DIR *)fi->fh; + + closedir(dp); + return 0; +} + +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 = creat(path, mode)) ? (fi->fh = fd, 0) : -errno; +} + +static int ptfs_ftruncate(const char *path, fuse_off_t off, struct fuse_file_info *fi) +{ + int fd = (int)fi->fh; + + return -1 != ftruncate(fd, off) ? 0 : -errno; +} + +static int ptfs_fgetattr(const char *path, struct fuse_stat *stbuf, struct fuse_file_info *fi) +{ + int fd = (int)fi->fh; + + return -1 != fstat(fd, stbuf) ? 0 : -errno; +} + +static struct fuse_operations ptfs_ops = +{ + ptfs_getattr, + 0, //getdir + 0, //readlink + 0, //mknod + ptfs_mkdir, + ptfs_unlink, + ptfs_rmdir, + 0, //symlink + ptfs_rename, + 0, //link + ptfs_chmod, + ptfs_chown, + ptfs_truncate, + ptfs_utime, + ptfs_open, + ptfs_read, + ptfs_write, + ptfs_statfs, + 0, //flush + ptfs_release, + ptfs_fsync, + 0, //setxattr + 0, //getxattr + 0, //listxattr + 0, //removexattr + ptfs_opendir, + ptfs_readdir, + ptfs_releasedir, + 0, //fsyncdir + 0, //init + 0, //destroy + 0, //access + ptfs_create, + ptfs_ftruncate, + ptfs_fgetattr, +}; + +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 (0 == ptfs.rootdir) + usage(); + + return fuse_main(argc, argv, &ptfs_ops, &ptfs); +} diff --git a/tst/passthrough-fuse/passthrough-fuse.sln b/tst/passthrough-fuse/passthrough-fuse.sln new file mode 100644 index 00000000..148df5cf --- /dev/null +++ b/tst/passthrough-fuse/passthrough-fuse.sln @@ -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-fuse", "passthrough-fuse.vcxproj", "{C753851C-142F-4AAD-B2F7-CBF905C2A600}" +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 + {C753851C-142F-4AAD-B2F7-CBF905C2A600}.Debug|x64.ActiveCfg = Debug|x64 + {C753851C-142F-4AAD-B2F7-CBF905C2A600}.Debug|x64.Build.0 = Debug|x64 + {C753851C-142F-4AAD-B2F7-CBF905C2A600}.Debug|x86.ActiveCfg = Debug|Win32 + {C753851C-142F-4AAD-B2F7-CBF905C2A600}.Debug|x86.Build.0 = Debug|Win32 + {C753851C-142F-4AAD-B2F7-CBF905C2A600}.Release|x64.ActiveCfg = Release|x64 + {C753851C-142F-4AAD-B2F7-CBF905C2A600}.Release|x64.Build.0 = Release|x64 + {C753851C-142F-4AAD-B2F7-CBF905C2A600}.Release|x86.ActiveCfg = Release|Win32 + {C753851C-142F-4AAD-B2F7-CBF905C2A600}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/tst/passthrough-fuse/passthrough-fuse.vcxproj b/tst/passthrough-fuse/passthrough-fuse.vcxproj new file mode 100644 index 00000000..a11bfae4 --- /dev/null +++ b/tst/passthrough-fuse/passthrough-fuse.vcxproj @@ -0,0 +1,190 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {C753851C-142F-4AAD-B2F7-CBF905C2A600} + Win32Proj + passthroughfuse + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)build\$(Configuration)\ + $(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\ + $(ProjectName)-$(PlatformTarget) + + + true + $(SolutionDir)build\$(Configuration)\ + $(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\ + $(ProjectName)-$(PlatformTarget) + + + false + $(SolutionDir)build\$(Configuration)\ + $(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\ + $(ProjectName)-$(PlatformTarget) + + + false + $(SolutionDir)build\$(Configuration)\ + $(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\ + $(ProjectName)-$(PlatformTarget) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(MSBuildProgramFiles32)\WinFsp\inc\fuse + MultiThreaded + 4996 + + + Console + true + $(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies) + winfsp-$(PlatformTarget).dll + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(MSBuildProgramFiles32)\WinFsp\inc\fuse + MultiThreaded + 4996 + + + Console + true + $(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies) + winfsp-$(PlatformTarget).dll + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(MSBuildProgramFiles32)\WinFsp\inc\fuse + MultiThreaded + 4996 + + + Console + true + true + true + $(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies) + winfsp-$(PlatformTarget).dll + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(MSBuildProgramFiles32)\WinFsp\inc\fuse + MultiThreaded + 4996 + + + Console + true + true + true + $(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies) + winfsp-$(PlatformTarget).dll + + + + + + + + + + + + + \ No newline at end of file diff --git a/tst/passthrough-fuse/passthrough-fuse.vcxproj.filters b/tst/passthrough-fuse/passthrough-fuse.vcxproj.filters new file mode 100644 index 00000000..f168939e --- /dev/null +++ b/tst/passthrough-fuse/passthrough-fuse.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source + + + Source + + + + + Source + + + \ No newline at end of file diff --git a/tst/passthrough-fuse/winposix.c b/tst/passthrough-fuse/winposix.c new file mode 100644 index 00000000..4351ab6d --- /dev/null +++ b/tst/passthrough-fuse/winposix.c @@ -0,0 +1,19 @@ +/** + * @file passthrough-fuse.c + * + * @copyright 2015-2017 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 +#include "winposix.h" diff --git a/tst/passthrough-fuse/winposix.h b/tst/passthrough-fuse/winposix.h new file mode 100644 index 00000000..0aaec01d --- /dev/null +++ b/tst/passthrough-fuse/winposix.h @@ -0,0 +1,56 @@ +/** + * @file winposix.h + * + * @copyright 2015-2017 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 PATH_MAX 1024 + +typedef struct _DIR DIR; +struct dirent +{ + char d_name[255]; +}; + +char *realpath(const char *path, char *resolved_path); + +int statvfs(const char *path, struct fuse_statvfs *buf); + +int mkdir(const char *path, fuse_mode_t mode); +int rmdir(const char *path); + +int unlink(const char *path); +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 truncate(const char *path, fuse_off_t size); +int utime(const char *path, const struct fuse_utimbuf *timbuf); + +int creat(const char *path, fuse_mode_t mode); +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); + +DIR *opendir(const char *path); +struct dirent *readdir(DIR *dirp); +int closedir(DIR *dp); + +#endif