#ifndef FUSEAPP_H #define FUSEAPP_H #define FUSE_USE_VERSION 26 #include #include #include #include #include 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; virtual int main(int &, char **, const struct fuse_operations *) = 0; #define GetHelper(func) getHelper<&FuseAppBase::func>(typeid(&FuseAppBase::func) != typeid(&FuseApp::func)) template static int run(int & argc, char** & argv, FuseApp * fa) { auto args = fa->runint(argc, argv); struct fuse_operations operations = { fuseCall::GetHelper(getattr), fuseCall::GetHelper(readlink), NULL, // getdir deprecated fuseCall::GetHelper(mknod), fuseCall::GetHelper(mkdir), fuseCall::GetHelper(unlink), fuseCall::GetHelper(rmdir), fuseCall::GetHelper(symlink), fuseCall::GetHelper(rename), fuseCall::GetHelper(link), fuseCall::GetHelper(chmod), fuseCall::GetHelper(chown), fuseCall::GetHelper(truncate), NULL, // utime deprecated fuseCall::GetHelper(open), fuseCall::GetHelper(read), fuseCall::GetHelper(write), fuseCall::GetHelper(statfs), fuseCall::GetHelper(flush), fuseCall::GetHelper(release), fuseCall::GetHelper(fsync), fuseCall::GetHelper(setxattr), fuseCall::GetHelper(getxattr), fuseCall::GetHelper(listxattr), fuseCall::GetHelper(removexattr), fuseCall::GetHelper(opendir), fuseCall::GetHelper(readdir), fuseCall::GetHelper(releasedir), fuseCall::GetHelper(fsyncdir), fuseInit, fuseDestroy, fuseCall::GetHelper(access), fuseCall::GetHelper(create), fuseCall::GetHelper(ftruncate), fuseCall::GetHelper(fgetattr), #if (FUSE_MINOR_VERSION >= 6) fuseCall::GetHelper(lock), fuseCall::GetHelper(utimens), fuseCall::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::GetHelper(ioctl), fuseCall::GetHelper(poll), #if (FUSE_MINOR_VERSION >= 9) fuseCall::GetHelper(write_buf), fuseCall::GetHelper(read_buf), fuseCall::GetHelper(flock), fuseCall::GetHelper(fallocate), #endif #endif #endif }; return fa->main(args.argc, args.argv, &operations); } struct fuse_args runint(int &, char ** &); private: static void * fuseInit(struct fuse_conn_info *conn); static void fuseDestroy(void *); template class fuseCall { public: typedef int (*WrapperFunc)(Args...); template static WrapperFunc getHelper(bool implemented) { auto func = &helper; return implemented ? func : NULL; } template 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(a...); } catch (...) { fprintf(stderr, "Unknown exception calling %s\n", typeid(f).name()); return -ENOSYS; } } }; static FuseAppBase * fuseApp; }; #endif