diff --git a/inc/fuse/winfsp_fuse.h b/inc/fuse/winfsp_fuse.h index f2b69646..c00addb9 100644 --- a/inc/fuse/winfsp_fuse.h +++ b/inc/fuse/winfsp_fuse.h @@ -60,8 +60,8 @@ typedef int64_t fuse_off_t; typedef uint64_t fuse_fsblkcnt_t; typedef uint64_t fuse_fsfilcnt_t; -typedef int32_t fuse_blksize_t; -typedef int32_t fuse_blkcnt_t; +typedef int64_t fuse_blksize_t; +typedef int64_t fuse_blkcnt_t; struct fuse_timespec { @@ -89,17 +89,17 @@ struct fuse_stat struct fuse_statvfs { - unsigned int f_bsize; - unsigned int f_frsize; + uint64_t f_bsize; + uint64_t f_frsize; fuse_fsblkcnt_t f_blocks; fuse_fsblkcnt_t f_bfree; fuse_fsblkcnt_t f_bavail; fuse_fsfilcnt_t f_files; fuse_fsfilcnt_t f_ffree; fuse_fsfilcnt_t f_favail; - unsigned int f_fsid; - unsigned int f_flag; - unsigned int f_namemax; + uint64_t f_fsid; + uint64_t f_flag; + uint64_t f_namemax; }; #if defined(WINFSP_DLL_INTERNAL) diff --git a/src/dll/fuse/fuse.c b/src/dll/fuse/fuse.c index e0af7fa4..3415db37 100644 --- a/src/dll/fuse/fuse.c +++ b/src/dll/fuse/fuse.c @@ -16,7 +16,6 @@ */ #include -#include #define FSP_FUSE_CORE_OPT(n, f, v) { n, offsetof(struct fsp_fuse_core_opt_data, f), v } @@ -104,10 +103,9 @@ struct fuse { FSP_FILE_SYSTEM *FileSystem; FSP_SERVICE *Service; - const struct fuse_operations *Ops; - size_t OpSize; - void *Data; - int Environment; + struct fuse_operations ops; + void *data; + int environment; CRITICAL_SECTION Lock; }; @@ -286,10 +284,13 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env, fsp_fuse_op_get_security_by_name, }; struct fsp_fuse_core_opt_data opt_data; + struct fuse_conn_info conn; + struct fuse_context *context; struct fuse *f = 0; PWSTR ServiceName = FspDiagIdent(); PWSTR ErrorMessage = L"."; NTSTATUS Result; + BOOLEAN FsInit = FALSE; memset(&opt_data, 0, sizeof opt_data); opt_data.env = env; @@ -318,6 +319,47 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env, opt_data.VolumeParams.NamedStreams = !!opt_data.NamedStreams; opt_data.VolumeParams.ReadOnlyVolume = !!opt_data.ReadOnlyVolume; + context = fsp_fuse_get_context(env); + if (0 == context) + goto fail; + context->private_data = data; + + memset(&conn, 0, sizeof conn); + conn.proto_major = 7; /* pretend that we are FUSE kernel protocol 7.12 */ + conn.proto_minor = 12; /* which was current at the time of FUSE 2.8 */ + conn.async_read = 1; + conn.max_write = UINT_MAX; + conn.capable = + FUSE_CAP_ASYNC_READ | + //FUSE_CAP_POSIX_LOCKS | /* WinFsp handles locking in the FSD currently */ + //FUSE_CAP_ATOMIC_O_TRUNC | /* due to Windows/WinFsp design, no support */ + //FUSE_CAP_EXPORT_SUPPORT | /* not needed in Windows/WinFsp */ + FUSE_CAP_BIG_WRITES | + FUSE_CAP_DONT_MASK; + if (0 != ops->init) + context->private_data = ops->init(&conn); + FsInit = TRUE; + if (0 != ops->statfs) + { + union + { + struct cyg_statvfs cygbuf; + struct fuse_statvfs fspbuf; + } buf; + struct fuse_statvfs fspbuf; + int err; + + err = ops->statfs("/", (void *)&buf); + if (0 != err) + goto fail; + fsp_fuse_op_get_statvfs_buf(env->environment, &buf, &fspbuf); + + opt_data.VolumeParams.SectorSize = (UINT16)f_bsize; + opt_data.VolumeParams.MaxComponentLength = (UINT16)f_namemax; + } + + /* !!!: the FSD does not currently limit the VolumeParams fields! */ + f = MemAlloc(sizeof *f); if (0 == f) goto fail; @@ -381,13 +423,13 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env, } } - f->Ops = ops; - f->OpSize = opsize; - f->Data = data; - f->Environment = env->environment; - + memcpy(&f->ops, ops, opsize); + f->data = context->private_data; + f->environment = env->environment; InitializeCriticalSection(&f->Lock); + context->fuse = f; + return f; fail: @@ -404,6 +446,12 @@ fail: MemFree(f); } + if (FsInit) + { + if (0 != ops->destroy) + ops->destroy(context->private_data); + } + return 0; } diff --git a/src/dll/fuse/fuse_main.c b/src/dll/fuse/fuse_main.c index 80e240de..a53ae446 100644 --- a/src/dll/fuse/fuse_main.c +++ b/src/dll/fuse/fuse_main.c @@ -16,7 +16,6 @@ */ #include -#include #define FSP_FUSE_MAIN_OPT(n, f, v) { n, offsetof(struct fsp_fuse_main_opt_data, f), v } diff --git a/src/dll/fuse/fuse_opt.c b/src/dll/fuse/fuse_opt.c index 427d584e..1e01f63f 100644 --- a/src/dll/fuse/fuse_opt.c +++ b/src/dll/fuse/fuse_opt.c @@ -16,8 +16,6 @@ */ #include -#include -#include /* * Define the following symbol to support escaped commas (',') during fuse_opt_parse. diff --git a/src/dll/fuse/library.h b/src/dll/fuse/library.h index bbab7ba3..87c425f3 100644 --- a/src/dll/fuse/library.h +++ b/src/dll/fuse/library.h @@ -19,6 +19,135 @@ #define WINFSP_DLL_FUSE_LIBRARY_H_INCLUDED #include +#include +#include + +#if defined(_WIN64) +struct cyg_timespec +{ + int64_t tv_sec; + int64_t tv_nsec; +}; +#else +struct cyg_timespec +{ + int32_t tv_sec; + int32_t tv_nsec; +}; +#endif + +struct cyg_stat +{ + uint32_t st_dev; + uint64_t st_ino; + uint32_t st_mode; + uint16_t st_nlink; + uint32_t st_uid; + uint32_t st_gid; + uint32_t st_rdev; + int64_t st_size; + struct cyg_timespec st_atim; + struct cyg_timespec st_mtim; + struct cyg_timespec st_ctim; + int32_t st_blksize; + int64_t st_blocks; + struct cyg_timespec st_birthtim; +}; + +#if defined(_WIN64) +struct cyg_statvfs +{ + uint64_t f_bsize; + uint64_t f_frsize; + uint64_t f_blocks; + uint64_t f_bfree; + uint64_t f_bavail; + uint64_t f_files; + uint64_t f_ffree; + uint64_t f_favail; + uint64_t f_fsid; + uint64_t f_flag; + uint64_t f_namemax; +}; +#else +struct cyg_statvfs +{ + uint32_t f_bsize; + uint32_t f_frsize; + uint32_t f_blocks; + uint32_t f_bfree; + uint32_t f_bavail; + uint32_t f_files; + uint32_t f_ffree; + uint32_t f_favail; + uint32_t f_fsid; + uint32_t f_flag; + uint32_t f_namemax; +}; +#endif + +static inline void fsp_fuse_op_get_stat_buf( + int environment, + const void *buf, struct fuse_stat *fspbuf) +{ + switch (environment) + { + case 'C': + { + const struct cyg_stat *cygbuf = buf; + fspbuf->st_dev = cygbuf->st_dev; + fspbuf->st_ino = cygbuf->st_ino; + fspbuf->st_mode = cygbuf->st_mode; + fspbuf->st_nlink = cygbuf->st_nlink; + fspbuf->st_uid = cygbuf->st_uid; + fspbuf->st_gid = cygbuf->st_gid; + fspbuf->st_rdev = cygbuf->st_rdev; + fspbuf->st_size = cygbuf->st_size; + fspbuf->st_atim.tv_sec = cygbuf->st_atim.tv_sec; + fspbuf->st_atim.tv_nsec = (int)cygbuf->st_atim.tv_nsec; + fspbuf->st_mtim.tv_sec = cygbuf->st_mtim.tv_sec; + fspbuf->st_mtim.tv_nsec = (int)cygbuf->st_mtim.tv_nsec; + fspbuf->st_ctim.tv_sec = cygbuf->st_ctim.tv_sec; + fspbuf->st_ctim.tv_nsec = (int)cygbuf->st_ctim.tv_nsec; + fspbuf->st_blksize = cygbuf->st_blksize; + fspbuf->st_blocks = cygbuf->st_blocks; + fspbuf->st_birthtim.tv_sec = cygbuf->st_birthtim.tv_sec; + fspbuf->st_birthtim.tv_nsec = (int)cygbuf->st_birthtim.tv_nsec; + } + break; + default: + memcpy(fspbuf, buf, sizeof *fspbuf); + break; + } +} + +static inline void fsp_fuse_op_get_statvfs_buf( + int environment, + const void *buf, struct fuse_statvfs *fspbuf) +{ + switch (environment) + { + case 'C': + { + const struct cyg_statvfs *cygbuf = buf; + fspbuf->f_bsize = cygbuf->f_bsize; + fspbuf->f_frsize = cygbuf->f_frsize; + fspbuf->f_blocks = cygbuf->f_blocks; + fspbuf->f_bfree = cygbuf->f_bfree; + fspbuf->f_bavail = cygbuf->f_bavail; + fspbuf->f_files = cygbuf->f_files; + fspbuf->f_ffree = cygbuf->f_ffree; + fspbuf->f_favail = cygbuf->f_favail; + fspbuf->f_fsid = cygbuf->f_fsid; + fspbuf->f_flag = cygbuf->f_flag; + fspbuf->f_namemax = cygbuf->f_namemax; + } + break; + default: + memcpy(fspbuf, buf, sizeof *fspbuf); + break; + } +} NTSTATUS fsp_fuse_op_get_security_by_name(FSP_FILE_SYSTEM *FileSystem, PWSTR FileName, PUINT32 PFileAttributes,