#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(); #define IFIMPL(func) typeid(&FuseAppBase::func) == typeid(&FuseApp::func) ? NULL : template static int run(int & argc, char** & argv, FuseApp * fa) { auto args = runint(argc, argv, fa); struct fuse_operations operations = { IFIMPL(getattr) fuseCall::helper<&FuseAppBase::getattr>, IFIMPL(readlink) fuseCall::helper<&FuseAppBase::readlink>, NULL, // getdir deprecated IFIMPL(mknod) fuseCall::helper<&FuseAppBase::mknod>, IFIMPL(mkdir) fuseCall::helper<&FuseAppBase::mkdir>, IFIMPL(unlink) fuseCall::helper<&FuseAppBase::unlink>, IFIMPL(rmdir) fuseCall::helper<&FuseAppBase::rmdir>, IFIMPL(symlink) fuseCall::helper<&FuseAppBase::symlink>, IFIMPL(rename) fuseCall::helper<&FuseAppBase::rename>, IFIMPL(link) fuseCall::helper<&FuseAppBase::link>, IFIMPL(chmod) fuseCall::helper<&FuseAppBase::chmod>, IFIMPL(chown) fuseCall::helper<&FuseAppBase::chown>, IFIMPL(truncate) fuseCall::helper<&FuseAppBase::truncate>, NULL, // utime deprecated IFIMPL(open) fuseCall::helper<&FuseAppBase::open>, IFIMPL(read) fuseCall::helper<&FuseAppBase::read>, IFIMPL(write) fuseCall::helper<&FuseAppBase::write>, IFIMPL(statfs) fuseCall::helper<&FuseAppBase::statfs>, IFIMPL(flush) fuseCall::helper<&FuseAppBase::flush>, IFIMPL(release) fuseCall::helper<&FuseAppBase::release>, IFIMPL(fsync) fuseCall::helper<&FuseAppBase::fsync>, IFIMPL(setxattr) fuseCall::helper<&FuseAppBase::setxattr>, IFIMPL(getxattr) fuseCall::helper<&FuseAppBase::getxattr>, IFIMPL(listxattr) fuseCall::helper<&FuseAppBase::listxattr>, IFIMPL(removexattr) fuseCall::helper<&FuseAppBase::removexattr>, IFIMPL(opendir) fuseCall::helper<&FuseAppBase::opendir>, IFIMPL(readdir) fuseCall::helper<&FuseAppBase::readdir>, IFIMPL(releasedir) fuseCall::helper<&FuseAppBase::releasedir>, IFIMPL(fsyncdir) fuseCall::helper<&FuseAppBase::fsyncdir>, fuseInit, fuseDestroy, IFIMPL(access) fuseCall::helper<&FuseAppBase::access>, IFIMPL(create) fuseCall::helper<&FuseAppBase::create>, IFIMPL(fgetattr) fuseCall::helper<&FuseAppBase::ftruncate>, IFIMPL(fgetattr) fuseCall::helper<&FuseAppBase::fgetattr>, #if (FUSE_MINOR_VERSION >= 6) IFIMPL(lock) fuseCall::helper<&FuseAppBase::lock>, IFIMPL(utimens) fuseCall::helper<&FuseAppBase::utimens>, IFIMPL(bmap) fuseCall::helper<&FuseAppBase::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 IFIMPL(ioctl) fuseCall::helper<&FuseAppBase::ioctl>, IFIMPL(poll) fuseCall::helper<&FuseAppBase::poll>, #if (FUSE_MINOR_VERSION >= 9) IFIMPL(write_buf) fuseCall::helper<&FuseAppBase::write_buf>, IFIMPL(read_buf) fuseCall::helper<&FuseAppBase::read_buf>, IFIMPL(flock) fuseCall::helper<&FuseAppBase::flock>, IFIMPL(fallocate) fuseCall::helper<&FuseAppBase::fallocate>, #endif #endif #endif }; return fuse_main(args.argc, args.argv, &operations, fa); } private: static struct fuse_args runint(int &, char ** &, FuseAppBase *); static void * fuseInit(struct fuse_conn_info *conn); static void fuseDestroy(void *); template class fuseCall { public: 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