summaryrefslogtreecommitdiff
path: root/libfusepp/fuseAppBase.h
blob: 5c8582c5870a9f4ae8d2e8fd9c131e6b95a11e99 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#ifndef FUSEAPP_H
#define FUSEAPP_H

#define FUSE_USE_VERSION 26
#include <fuse.h>
#include <typeinfo>
#include <exception>
#include <stdio.h>
#include <errno.h>
#include <syslog.h>
#include <visibility.h>
#include <buffer.h>

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 log(int level, const std::string &) const throw() = 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>(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 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 <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 (...) {
						fuseApp->log(LOG_ERR, stringf("Unknown exception calling %s\n", typeid(f).name()));
						return -ENOSYS;
					}
				}
		};

		static FuseAppBase * fuseApp;
};

#endif