#ifndef FUSEAPP_H #define FUSEAPP_H #define FUSE_USE_VERSION 26 #include <fuse.h> #include <typeinfo> #include <exception> #include <stdio.h> #include <errno.h> class FuseAppBase { public: FuseAppBase(); virtual ~FuseAppBase() = 0; virtual void * init (struct fuse_conn_info * info); virtual int opt_parse(void *, const char * arg, int key, struct fuse_args *); virtual int access(const char *, int); virtual int chmod(const char *, mode_t); virtual int chown(const char *, uid_t, gid_t); virtual int create(const char *, mode_t, struct fuse_file_info *); virtual int fgetattr(const char *, struct stat *, struct fuse_file_info *); virtual int flush(const char *, struct fuse_file_info *); virtual int fsync(const char *, int, struct fuse_file_info *); virtual int fsyncdir(const char *, int, struct fuse_file_info *); virtual int ftruncate(const char *, off_t, struct fuse_file_info *); virtual int getattr(const char *, struct stat *); virtual int getxattr(const char *, const char *, char *, size_t); virtual int link(const char *, const char *); virtual int listxattr(const char *, char *, size_t); virtual int mkdir(const char *, mode_t); virtual int mknod(const char *, mode_t, dev_t); virtual int open(const char *, struct fuse_file_info *); virtual int opendir(const char *, struct fuse_file_info *); virtual int read(const char *, char *, size_t, off_t, struct fuse_file_info *); virtual int readdir(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *); virtual int readlink(const char *, char *, size_t); virtual int release(const char *, struct fuse_file_info *); virtual int releasedir(const char *, struct fuse_file_info *); virtual int removexattr(const char *, const char *); virtual int rename(const char *, const char *); virtual int rmdir(const char *); virtual int setxattr(const char *, const char *, const char *, size_t, int); virtual int statfs(const char *, struct statvfs *); virtual int symlink(const char *, const char *); virtual int truncate(const char *, off_t); virtual int unlink(const char *); virtual int write(const char *, const char *, size_t, off_t, struct fuse_file_info *); virtual int lock(const char *, struct fuse_file_info *, int cmd, struct flock *); virtual int utimens(const char *, const struct timespec tv[2]); virtual int bmap(const char *, size_t blocksize, uint64_t *idx); virtual int ioctl(const char *, int cmd, void *arg, struct fuse_file_info *, unsigned int flags, void * data); virtual int poll(const char *, struct fuse_file_info *, struct fuse_pollhandle *, unsigned *); virtual int write_buf(const char *, struct fuse_bufvec *buf, off_t off, struct fuse_file_info *); virtual int read_buf(const char *, struct fuse_bufvec **bufp, size_t size, off_t off, struct fuse_file_info *); virtual int flock(const char *, struct fuse_file_info *, int op); virtual int fallocate(const char *, int, off_t, off_t, struct fuse_file_info *); virtual int onError(const std::exception & err) throw(); virtual int fuse_opt_parse(struct fuse_args *args, void *data, const struct fuse_opt opts[], fuse_opt_proc_t proc) = 0; #define GetHelper(func) getHelper<&FuseAppBase::func>(typeid(&FuseAppBase::func) != typeid(&FuseApp::func)) template <typename FuseApp> static int run(int & argc, char** & argv, FuseApp * fa) { auto args = fa->runint(argc, argv); struct fuse_operations operations = { fuseCall<const char *, struct stat *>::GetHelper(getattr), fuseCall<const char *, char *, size_t>::GetHelper(readlink), NULL, // getdir deprecated fuseCall<const char *, mode_t, dev_t>::GetHelper(mknod), fuseCall<const char *, mode_t>::GetHelper(mkdir), fuseCall<const char *>::GetHelper(unlink), fuseCall<const char *>::GetHelper(rmdir), fuseCall<const char *, const char *>::GetHelper(symlink), fuseCall<const char *, const char *>::GetHelper(rename), fuseCall<const char *, const char *>::GetHelper(link), fuseCall<const char *, mode_t>::GetHelper(chmod), fuseCall<const char *, uid_t, gid_t>::GetHelper(chown), fuseCall<const char *, off_t>::GetHelper(truncate), NULL, // utime deprecated fuseCall<const char *, struct fuse_file_info *>::GetHelper(open), fuseCall<const char *, char *, size_t, off_t, struct fuse_file_info *>::GetHelper(read), fuseCall<const char *, const char *, size_t, off_t, struct fuse_file_info *>::GetHelper(write), fuseCall<const char *, struct statvfs *>::GetHelper(statfs), fuseCall<const char *, struct fuse_file_info *>::GetHelper(flush), fuseCall<const char *, struct fuse_file_info *>::GetHelper(release), fuseCall<const char *, int, struct fuse_file_info *>::GetHelper(fsync), fuseCall<const char *, const char *, const char *, size_t, int>::GetHelper(setxattr), fuseCall<const char *, const char *, char *, size_t>::GetHelper(getxattr), fuseCall<const char *, char *, size_t>::GetHelper(listxattr), fuseCall<const char *, const char *>::GetHelper(removexattr), fuseCall<const char *, struct fuse_file_info *>::GetHelper(opendir), fuseCall<const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *>::GetHelper(readdir), fuseCall<const char *, struct fuse_file_info *>::GetHelper(releasedir), fuseCall<const char *, int, struct fuse_file_info *>::GetHelper(fsyncdir), fuseInit, fuseDestroy, fuseCall<const char *, int>::GetHelper(access), fuseCall<const char *, mode_t, struct fuse_file_info *>::GetHelper(create), fuseCall<const char *, off_t, struct fuse_file_info *>::GetHelper(ftruncate), fuseCall<const char *, struct stat *, struct fuse_file_info *>::GetHelper(fgetattr), #if (FUSE_MINOR_VERSION >= 6) fuseCall<const char *, struct fuse_file_info *, int, struct flock *>::GetHelper(lock), fuseCall<const char *, const struct timespec [2]>::GetHelper(utimens), fuseCall<const char *, size_t, uint64_t *>::GetHelper(bmap), #if (FUSE_MINOR_VERSION >= 8) 0, // flag_nullpath_ok #if (FUSE_MINOR_VERSION >= 9) 0, // flag_nopath 0, // flag_utime_omit_ok #endif 0, // flag_reserved fuseCall<const char *, int, void *, struct fuse_file_info *, unsigned int, void *>::GetHelper(ioctl), fuseCall<const char *, struct fuse_file_info *, struct fuse_pollhandle *, unsigned *>::GetHelper(poll), #if (FUSE_MINOR_VERSION >= 9) fuseCall<const char *, struct fuse_bufvec *, off_t, struct fuse_file_info *>::GetHelper(write_buf), fuseCall<const char *, struct fuse_bufvec **, size_t, off_t, struct fuse_file_info *>::GetHelper(read_buf), fuseCall<const char *, struct fuse_file_info *, int>::GetHelper(flock), fuseCall<const char *, int, off_t, off_t, struct fuse_file_info *>::GetHelper(fallocate), #endif #endif #endif }; return fuse_main(args.argc, args.argv, &operations, fa); } struct fuse_args runint(int &, char ** &); private: static void * fuseInit(struct fuse_conn_info *conn); static void fuseDestroy(void *); template <typename... Args> class fuseCall { public: typedef int (*WrapperFunc)(Args...); template <int (FuseAppBase::*b)(Args...)> static WrapperFunc getHelper(bool implemented) { auto func = &helper<b>; return implemented ? func : NULL; } template <int (FuseAppBase::*f)(Args...)> static int helper(Args ... a) { try { return (fuseApp->*f)(a...); } catch (const std::exception & ex) { if (int rtn = fuseApp->onError(ex)) { return rtn; } return helper<f>(a...); } catch (...) { fprintf(stderr, "Unknown exception calling %s\n", typeid(f).name()); return -ENOSYS; } } }; static FuseAppBase * fuseApp; }; #endif