10#include "fuse_config.h"
11#include "cuse_lowlevel.h"
12#include "fuse_kernel.h"
24 struct cuse_lowlevel_ops clop;
29 unsigned dev_info_len;
33static struct cuse_lowlevel_ops *req_clop(
fuse_req_t req)
35 return &req->se->cuse_data->clop;
42 req_clop(req)->open(req, fi);
49 req_clop(req)->read(req, size, off, fi);
56 req_clop(req)->write(req, buf, size, off, fi);
63 req_clop(req)->flush(req, fi);
70 req_clop(req)->release(req, fi);
77 req_clop(req)->fsync(req, datasync, fi);
82 const void *in_buf,
size_t in_bufsz,
size_t out_bufsz)
85 req_clop(req)->ioctl(req, cmd, arg, fi, flags, in_buf, in_bufsz,
93 req_clop(req)->poll(req, fi, ph);
96static size_t cuse_pack_info(
int argc,
const char **argv,
char *buf)
101 for (i = 0; i < argc; i++) {
104 len = strlen(argv[i]) + 1;
107 memcpy(buf, argv[i], len);
115static struct cuse_data *cuse_prep_data(
const struct cuse_info *ci,
116 const struct cuse_lowlevel_ops *clop)
118 struct cuse_data *cd;
121 dev_info_len = cuse_pack_info(ci->dev_info_argc, ci->dev_info_argv,
124 if (dev_info_len > CUSE_INIT_INFO_MAX) {
125 fuse_log(FUSE_LOG_ERR,
"cuse: dev_info (%zu) too large, limit=%u\n",
126 dev_info_len, CUSE_INIT_INFO_MAX);
130 cd = calloc(1,
sizeof(*cd) + dev_info_len);
132 fuse_log(FUSE_LOG_ERR,
"cuse: failed to allocate cuse_data\n");
136 memcpy(&cd->clop, clop,
sizeof(cd->clop));
137 cd->max_read = 131072;
138 cd->dev_major = ci->dev_major;
139 cd->dev_minor = ci->dev_minor;
140 cd->dev_info_len = dev_info_len;
141 cd->flags = ci->flags;
142 cuse_pack_info(ci->dev_info_argc, ci->dev_info_argv, cd->dev_info);
147struct fuse_session *cuse_lowlevel_new(
struct fuse_args *args,
148 const struct cuse_info *ci,
149 const struct cuse_lowlevel_ops *clop,
153 struct cuse_data *cd;
154 struct fuse_session *se;
156 cd = cuse_prep_data(ci, clop);
160 memset(&lop, 0,
sizeof(lop));
161 lop.init = clop->init;
162 lop.destroy = clop->destroy;
163 lop.open = clop->open ? cuse_fll_open : NULL;
164 lop.read = clop->read ? cuse_fll_read : NULL;
165 lop.write = clop->write ? cuse_fll_write : NULL;
166 lop.flush = clop->flush ? cuse_fll_flush : NULL;
167 lop.release = clop->release ? cuse_fll_release : NULL;
168 lop.fsync = clop->fsync ? cuse_fll_fsync : NULL;
169 lop.ioctl = clop->ioctl ? cuse_fll_ioctl : NULL;
170 lop.poll = clop->poll ? cuse_fll_poll : NULL;
172 se = fuse_session_new(args, &lop,
sizeof(lop), userdata);
182static int cuse_reply_init(
fuse_req_t req,
struct cuse_init_out *arg,
183 char *dev_info,
unsigned dev_info_len)
187 iov[1].iov_base = arg;
188 iov[1].iov_len =
sizeof(
struct cuse_init_out);
189 iov[2].iov_base = dev_info;
190 iov[2].iov_len = dev_info_len;
192 return fuse_send_reply_iov_nofree(req, 0, iov, 3);
196 const void *op_in,
const void *req_payload)
198 const struct fuse_init_in *arg = op_in;
200 struct cuse_init_out outarg;
201 struct fuse_session *se = req->se;
202 struct cuse_data *cd = se->cuse_data;
203 size_t bufsize = se->bufsize;
204 struct cuse_lowlevel_ops *clop = req_clop(req);
208 fuse_log(FUSE_LOG_DEBUG,
"CUSE_INIT: %u.%u\n", arg->major, arg->minor);
209 fuse_log(FUSE_LOG_DEBUG,
"flags=0x%08x\n", arg->flags);
211 se->conn.proto_major = arg->major;
212 se->conn.proto_minor = arg->minor;
215 se->conn.capable_ext = 0;
216 se->conn.want_ext = 0;
218 if (arg->major < 7) {
219 fuse_log(FUSE_LOG_ERR,
"cuse: unsupported protocol version: %u.%u\n",
220 arg->major, arg->minor);
225 if (bufsize < FUSE_MIN_READ_BUFFER) {
226 fuse_log(FUSE_LOG_ERR,
"cuse: warning: buffer size too small: %zu\n",
228 bufsize = FUSE_MIN_READ_BUFFER;
232 if (bufsize < se->conn.max_write)
233 se->conn.max_write = bufsize;
237 se->op.init(se->userdata, &se->conn);
239 memset(&outarg, 0,
sizeof(outarg));
240 outarg.major = FUSE_KERNEL_VERSION;
241 outarg.minor = FUSE_KERNEL_MINOR_VERSION;
242 outarg.flags = cd->flags;
243 outarg.max_read = cd->max_read;
244 outarg.max_write = se->conn.max_write;
245 outarg.dev_major = cd->dev_major;
246 outarg.dev_minor = cd->dev_minor;
249 fuse_log(FUSE_LOG_DEBUG,
" CUSE_INIT: %u.%u\n",
250 outarg.major, outarg.minor);
251 fuse_log(FUSE_LOG_DEBUG,
" flags=0x%08x\n", outarg.flags);
252 fuse_log(FUSE_LOG_DEBUG,
" max_read=0x%08x\n", outarg.max_read);
253 fuse_log(FUSE_LOG_DEBUG,
" max_write=0x%08x\n", outarg.max_write);
254 fuse_log(FUSE_LOG_DEBUG,
" dev_major=%u\n", outarg.dev_major);
255 fuse_log(FUSE_LOG_DEBUG,
" dev_minor=%u\n", outarg.dev_minor);
256 fuse_log(FUSE_LOG_DEBUG,
" dev_info: %.*s\n", cd->dev_info_len,
260 cuse_reply_init(req, &outarg, cd->dev_info, cd->dev_info_len);
263 clop->init_done(se->userdata);
270 _cuse_lowlevel_init(req, nodeid, inarg, NULL);
273struct fuse_session *cuse_lowlevel_setup(
int argc,
char *argv[],
274 const struct cuse_info *ci,
275 const struct cuse_lowlevel_ops *clop,
276 int *multithreaded,
void *userdata)
278 const char *devname =
"/dev/cuse";
279 static const struct fuse_opt kill_subtype_opts[] = {
284 struct fuse_session *se;
289 if (fuse_parse_cmdline(&args, &opts) == -1)
291 *multithreaded = !opts.singlethread;
303 fd = open(
"/dev/null", O_RDWR);
306 }
while (fd >= 0 && fd <= 2);
308 se = cuse_lowlevel_new(&args, ci, clop, userdata);
312 fd = open(devname, O_RDWR);
314 if (errno == ENODEV || errno == ENOENT)
315 fuse_log(FUSE_LOG_ERR,
"cuse: device not found, try 'modprobe cuse' first\n");
317 fuse_log(FUSE_LOG_ERR,
"cuse: failed to open %s: %s\n",
318 devname, strerror(errno));
339 free(opts.mountpoint);
344void cuse_lowlevel_teardown(
struct fuse_session *se)
350int cuse_lowlevel_main(
int argc,
char *argv[],
const struct cuse_info *ci,
351 const struct cuse_lowlevel_ops *clop,
void *userdata)
353 struct fuse_session *se;
357 se = cuse_lowlevel_setup(argc, argv, ci, clop, &multithreaded,
364 res = fuse_session_loop_mt(se, config);
365 fuse_loop_cfg_destroy(config);
370 cuse_lowlevel_teardown(se);
int fuse_set_signal_handlers(struct fuse_session *se)
void fuse_remove_signal_handlers(struct fuse_session *se)
int fuse_daemonize(int foreground)
void fuse_log(enum fuse_log_level level, const char *fmt,...)
void fuse_session_destroy(struct fuse_session *se)
int fuse_reply_err(fuse_req_t req, int err)
struct fuse_req * fuse_req_t
int fuse_session_loop(struct fuse_session *se)
void fuse_opt_free_args(struct fuse_args *args)
#define FUSE_OPT_KEY(templ, key)
int fuse_opt_parse(struct fuse_args *args, void *data, const struct fuse_opt opts[], fuse_opt_proc_t proc)
#define FUSE_OPT_KEY_DISCARD
#define FUSE_ARGS_INIT(argc, argv)