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;
 
   33 static 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);
 
   96 static 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);
 
  115 static 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);
 
  147 struct 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;
 
  182 static 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);
 
  197         struct fuse_init_in *arg = (
struct fuse_init_in *) inarg;
 
  198         struct cuse_init_out outarg;
 
  199         struct fuse_session *se = req->se;
 
  200         struct cuse_data *cd = se->cuse_data;
 
  201         size_t bufsize = se->bufsize;
 
  202         struct cuse_lowlevel_ops *clop = req_clop(req);
 
  206                 fuse_log(FUSE_LOG_DEBUG, 
"CUSE_INIT: %u.%u\n", arg->major, arg->minor);
 
  207                 fuse_log(FUSE_LOG_DEBUG, 
"flags=0x%08x\n", arg->flags);
 
  209         se->conn.proto_major = arg->major;
 
  210         se->conn.proto_minor = arg->minor;
 
  211         se->conn.capable = 0;
 
  214         if (arg->major < 7) {
 
  215                 fuse_log(FUSE_LOG_ERR, 
"cuse: unsupported protocol version: %u.%u\n",
 
  216                         arg->major, arg->minor);
 
  221         if (bufsize < FUSE_MIN_READ_BUFFER) {
 
  222                 fuse_log(FUSE_LOG_ERR, 
"cuse: warning: buffer size too small: %zu\n",
 
  224                 bufsize = FUSE_MIN_READ_BUFFER;
 
  228         if (bufsize < se->conn.max_write)
 
  229                 se->conn.max_write = bufsize;
 
  233                 se->op.init(se->userdata, &se->conn);
 
  235         memset(&outarg, 0, 
sizeof(outarg));
 
  236         outarg.major = FUSE_KERNEL_VERSION;
 
  237         outarg.minor = FUSE_KERNEL_MINOR_VERSION;
 
  238         outarg.flags = cd->flags;
 
  239         outarg.max_read = cd->max_read;
 
  240         outarg.max_write = se->conn.max_write;
 
  241         outarg.dev_major = cd->dev_major;
 
  242         outarg.dev_minor = cd->dev_minor;
 
  245                 fuse_log(FUSE_LOG_DEBUG, 
"   CUSE_INIT: %u.%u\n",
 
  246                         outarg.major, outarg.minor);
 
  247                 fuse_log(FUSE_LOG_DEBUG, 
"   flags=0x%08x\n", outarg.flags);
 
  248                 fuse_log(FUSE_LOG_DEBUG, 
"   max_read=0x%08x\n", outarg.max_read);
 
  249                 fuse_log(FUSE_LOG_DEBUG, 
"   max_write=0x%08x\n", outarg.max_write);
 
  250                 fuse_log(FUSE_LOG_DEBUG, 
"   dev_major=%u\n", outarg.dev_major);
 
  251                 fuse_log(FUSE_LOG_DEBUG, 
"   dev_minor=%u\n", outarg.dev_minor);
 
  252                 fuse_log(FUSE_LOG_DEBUG, 
"   dev_info: %.*s\n", cd->dev_info_len,
 
  256         cuse_reply_init(req, &outarg, cd->dev_info, cd->dev_info_len);
 
  259                 clop->init_done(se->userdata);
 
  264 struct fuse_session *cuse_lowlevel_setup(
int argc, 
char *argv[],
 
  265                                          const struct cuse_info *ci,
 
  266                                          const struct cuse_lowlevel_ops *clop,
 
  267                                          int *multithreaded, 
void *userdata)
 
  269         const char *devname = 
"/dev/cuse";
 
  270         static const struct fuse_opt kill_subtype_opts[] = {
 
  275         struct fuse_session *se;
 
  280         if (fuse_parse_cmdline(&args, &opts) == -1)
 
  282         *multithreaded = !opts.singlethread;
 
  294                 fd = open(
"/dev/null", O_RDWR);
 
  297         } 
while (fd >= 0 && fd <= 2);
 
  299         se = cuse_lowlevel_new(&args, ci, clop, userdata);
 
  303         fd = open(devname, O_RDWR);
 
  305                 if (errno == ENODEV || errno == ENOENT)
 
  306                         fuse_log(FUSE_LOG_ERR, 
"cuse: device not found, try 'modprobe cuse' first\n");
 
  308                         fuse_log(FUSE_LOG_ERR, 
"cuse: failed to open %s: %s\n",
 
  309                                 devname, strerror(errno));
 
  330         free(opts.mountpoint);
 
  335 void cuse_lowlevel_teardown(
struct fuse_session *se)
 
  341 int cuse_lowlevel_main(
int argc, 
char *argv[], 
const struct cuse_info *ci,
 
  342                        const struct cuse_lowlevel_ops *clop, 
void *userdata)
 
  344         struct fuse_session *se;
 
  348         se = cuse_lowlevel_setup(argc, argv, ci, clop, &multithreaded,
 
  355                 res = fuse_session_loop_mt(se, config);
 
  361         cuse_lowlevel_teardown(se);
 
int fuse_set_signal_handlers(struct fuse_session *se)
struct fuse_loop_config * fuse_loop_cfg_create(void)
void fuse_loop_cfg_destroy(struct fuse_loop_config *config)
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)
struct fuse_session * fuse_session_new(struct fuse_args *args, const struct fuse_lowlevel_ops *op, size_t op_size, void *userdata)
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)