34#define FUSE_USE_VERSION 31 
   36#include <cuse_lowlevel.h> 
   47static void *cusexmp_buf;
 
   48static size_t cusexmp_size;
 
   50static const char *usage =
 
   51"usage: cusexmp [options]\n" 
   54"    --help|-h             print this help message\n" 
   55"    --maj=MAJ|-M MAJ      device major number\n" 
   56"    --min=MIN|-m MIN      device minor number\n" 
   57"    --name=NAME|-n NAME   device name (mandatory)\n" 
   58"    -d   -o debug         enable debug output (implies -f)\n" 
   59"    -f                    foreground operation\n" 
   60"    -s                    disable multi-threaded operation\n" 
   63static int cusexmp_resize(
size_t new_size)
 
   67        if (new_size == cusexmp_size)
 
   70        new_buf = realloc(cusexmp_buf, new_size);
 
   71        if (!new_buf && new_size)
 
   74        if (new_size > cusexmp_size)
 
   75                memset(new_buf + cusexmp_size, 0, new_size - cusexmp_size);
 
   77        cusexmp_buf = new_buf;
 
   78        cusexmp_size = new_size;
 
   83static int cusexmp_expand(
size_t new_size)
 
   85        if (new_size > cusexmp_size)
 
   86                return cusexmp_resize(new_size);
 
   95static void cusexmp_read(
fuse_req_t req, 
size_t size, off_t off,
 
  100        if (off >= cusexmp_size)
 
  102        if (size > cusexmp_size - off)
 
  103                size = cusexmp_size - off;
 
  108static void cusexmp_write(
fuse_req_t req, 
const char *buf, 
size_t size,
 
  113        if (cusexmp_expand(off + size)) {
 
  118        memcpy(cusexmp_buf + off, buf, size);
 
  122static void fioc_do_rw(
fuse_req_t req, 
void *addr, 
const void *in_buf,
 
  123                       size_t in_bufsz, 
size_t out_bufsz, 
int is_read)
 
  125        const struct fioc_rw_arg *arg;
 
  126        struct iovec in_iov[2], out_iov[3], iov[3];
 
  130        in_iov[0].iov_base = addr;
 
  131        in_iov[0].iov_len = 
sizeof(*arg);
 
  137        in_buf += 
sizeof(*arg);
 
  138        in_bufsz -= 
sizeof(*arg);
 
  141        out_iov[0].iov_base =
 
  142                addr + offsetof(
struct fioc_rw_arg, prev_size);
 
  143        out_iov[0].iov_len = 
sizeof(arg->prev_size);
 
  145        out_iov[1].iov_base =
 
  146                addr + offsetof(
struct fioc_rw_arg, new_size);
 
  147        out_iov[1].iov_len = 
sizeof(arg->new_size);
 
  151                out_iov[2].iov_base = arg->buf;
 
  152                out_iov[2].iov_len = arg->size;
 
  158                in_iov[1].iov_base = arg->buf;
 
  159                in_iov[1].iov_len = arg->size;
 
  160                if (arg->size && !in_bufsz) {
 
  167        cur_size = cusexmp_size;
 
  168        iov[0].iov_base = &cur_size;
 
  169        iov[0].iov_len = 
sizeof(cur_size);
 
  171        iov[1].iov_base = &cusexmp_size;
 
  172        iov[1].iov_len = 
sizeof(cusexmp_size);
 
  175                size_t off = arg->offset;
 
  176                size_t size = arg->size;
 
  178                if (off >= cusexmp_size)
 
  180                if (size > cusexmp_size - off)
 
  181                        size = cusexmp_size - off;
 
  183                iov[2].iov_base = cusexmp_buf + off;
 
  184                iov[2].iov_len = size;
 
  187                if (cusexmp_expand(arg->offset + in_bufsz)) {
 
  192                memcpy(cusexmp_buf + arg->offset, in_buf, in_bufsz);
 
  197static void cusexmp_ioctl(
fuse_req_t req, 
int cmd, 
void *arg,
 
  199                          const void *in_buf, 
size_t in_bufsz, 
size_t out_bufsz)
 
  213                        struct iovec iov = { arg, 
sizeof(size_t) };
 
  218                                         sizeof(cusexmp_size));
 
  223                        struct iovec iov = { arg, 
sizeof(size_t) };
 
  227                        cusexmp_resize(*(
size_t *)in_buf);
 
  236                fioc_do_rw(req, arg, in_buf, in_bufsz, out_bufsz, is_read);
 
  244struct cusexmp_param {
 
  251#define CUSEXMP_OPT(t, p) { t, offsetof(struct cusexmp_param, p), 1 } 
  253static const struct fuse_opt cusexmp_opts[] = {
 
  254        CUSEXMP_OPT(
"-M %u",            major),
 
  255        CUSEXMP_OPT(
"--maj=%u",         major),
 
  256        CUSEXMP_OPT(
"-m %u",            minor),
 
  257        CUSEXMP_OPT(
"--min=%u",         minor),
 
  258        CUSEXMP_OPT(
"-n %s",            dev_name),
 
  259        CUSEXMP_OPT(
"--name=%s",        dev_name),
 
  265static int cusexmp_process_arg(
void *data, 
const char *arg, 
int key,
 
  268        struct cusexmp_param *param = data;
 
  276                fprintf(stderr, 
"%s", usage);
 
  283static const struct cuse_lowlevel_ops cusexmp_clop = {
 
  284        .open           = cusexmp_open,
 
  285        .read           = cusexmp_read,
 
  286        .write          = cusexmp_write,
 
  287        .ioctl          = cusexmp_ioctl,
 
  290int main(
int argc, 
char **argv)
 
  293        struct cusexmp_param param = { 0, 0, NULL, 0 };
 
  294        char dev_name[128] = 
"DEVNAME=";
 
  295        const char *dev_info_argv[] = { dev_name };
 
  299        if (
fuse_opt_parse(&args, ¶m, cusexmp_opts, cusexmp_process_arg)) {
 
  300                printf(
"failed to parse option\n");
 
  301                free(param.dev_name);
 
  305        if (!param.is_help) {
 
  306                if (!param.dev_name) {
 
  307                        fprintf(stderr, 
"Error: device name missing\n");
 
  310                strncat(dev_name, param.dev_name, 
sizeof(dev_name) - 
sizeof(
"DEVNAME="));
 
  311                free(param.dev_name);
 
  314        memset(&ci, 0, 
sizeof(ci));
 
  315        ci.dev_major = param.major;
 
  316        ci.dev_minor = param.minor;
 
  317        ci.dev_info_argc = 1;
 
  318        ci.dev_info_argv = dev_info_argv;
 
  319        ci.flags = CUSE_UNRESTRICTED_IOCTL;
 
  321        ret = cuse_lowlevel_main(args.
argc, args.
argv, &ci, &cusexmp_clop, NULL);
 
#define FUSE_IOCTL_COMPAT
int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *fi)
int fuse_reply_err(fuse_req_t req, int err)
int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
struct fuse_req * fuse_req_t
int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov, int count)
int fuse_reply_ioctl_retry(fuse_req_t req, const struct iovec *in_iov, size_t in_count, const struct iovec *out_iov, size_t out_count)
int fuse_reply_write(fuse_req_t req, size_t count)
int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size)
int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
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_ARGS_INIT(argc, argv)