#ifndef FUSEAPP_H #define FUSEAPP_H #define FUSE_USE_VERSION 26 #include #include #include #include #include #include #include #include class DLL_PUBLIC 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 void beforeOperation(); void log(int level, const char * message) const throw(); void logf(int level, const char * fmt, ...) const throw() __attribute__ ((__format__ (__printf__, 3, 4))); virtual void vlogf(int level, const char * fmt, va_list) const throw() __attribute__ ((__format__ (__printf__, 3, 0))) = 0; 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) template static int run(int argc, char ** argv, FuseApp * fa) { auto args = fa->runint(argc, argv); struct fuse_operations operations = { GetHelper(getattr), GetHelper(readlink), NULL, // getdir deprecated GetHelper(mknod), GetHelper(mkdir), GetHelper(unlink), GetHelper(rmdir), GetHelper(symlink), GetHelper(rename), GetHelper(link), GetHelper(chmod), GetHelper(chown), GetHelper(truncate), NULL, // utime deprecated GetHelper(open), GetHelper(read), GetHelper(write), GetHelper(statfs), GetHelper(flush), GetHelper(release), GetHelper(fsync), GetHelper(setxattr), GetHelper(getxattr), GetHelper(listxattr), GetHelper(removexattr), GetHelper(opendir), GetHelper(readdir), GetHelper(releasedir), GetHelper(fsyncdir), fuseInit, fuseDestroy, GetHelper(access), GetHelper(create), GetHelper(ftruncate), GetHelper(fgetattr), #if (FUSE_MINOR_VERSION >= 6) GetHelper(lock), GetHelper(utimens), 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 GetHelper(ioctl), GetHelper(poll), #if (FUSE_MINOR_VERSION >= 9) GetHelper(write_buf), GetHelper(read_buf), GetHelper(flock), 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 static typename std::enable_if::value, int(*)(Args...)>::type getHelper(int(FuseAppBase::*)(Args...)) { return &helper; } template static typename std::enable_if::value, int(*)(Args...)>::type getHelper(int(FuseAppBase::*)(Args...)) { return nullptr; } template static int helper(Args ... a) { for (int t = 0; ; ++t) { try { fuseApp->beforeOperation(); return (fuseApp->*f)(a...); } catch (const std::exception & ex) { if (t < 10) { if (int rtn = fuseApp->onError(ex)) { return rtn; } } else { fuseApp->logf(LOG_ERR, "Retries expired with %s calling %s", ex.what(), typeid(f).name()); return -EIO; } } catch (...) { fuseApp->logf(LOG_ERR, "Unknown exception calling %s", typeid(f).name()); return -EIO; } } } template static int internalHelper(Args ... a) { return (fuseApp->*f)(a...); } static FuseAppBase * fuseApp; }; #endif