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);
 
   90static void cusexmp_init(
void *userdata, 
struct fuse_conn_info *conn)
 
  103static void cusexmp_read(
fuse_req_t req, 
size_t size, off_t off,
 
  108        if (off >= cusexmp_size)
 
  110        if (size > cusexmp_size - off)
 
  111                size = cusexmp_size - off;
 
  116static void cusexmp_write(
fuse_req_t req, 
const char *buf, 
size_t size,
 
  121        if (cusexmp_expand(off + size)) {
 
  126        memcpy(cusexmp_buf + off, buf, size);
 
  130static void fioc_do_rw(
fuse_req_t req, 
void *addr, 
const void *in_buf,
 
  131                       size_t in_bufsz, 
size_t out_bufsz, 
int is_read)
 
  133        const struct fioc_rw_arg *arg;
 
  134        struct iovec in_iov[2], out_iov[3], iov[3];
 
  138        in_iov[0].iov_base = addr;
 
  139        in_iov[0].iov_len = 
sizeof(*arg);
 
  145        in_buf += 
sizeof(*arg);
 
  146        in_bufsz -= 
sizeof(*arg);
 
  149        out_iov[0].iov_base =
 
  150                addr + offsetof(
struct fioc_rw_arg, prev_size);
 
  151        out_iov[0].iov_len = 
sizeof(arg->prev_size);
 
  153        out_iov[1].iov_base =
 
  154                addr + offsetof(
struct fioc_rw_arg, new_size);
 
  155        out_iov[1].iov_len = 
sizeof(arg->new_size);
 
  159                out_iov[2].iov_base = arg->buf;
 
  160                out_iov[2].iov_len = arg->size;
 
  166                in_iov[1].iov_base = arg->buf;
 
  167                in_iov[1].iov_len = arg->size;
 
  168                if (arg->size && !in_bufsz) {
 
  175        cur_size = cusexmp_size;
 
  176        iov[0].iov_base = &cur_size;
 
  177        iov[0].iov_len = 
sizeof(cur_size);
 
  179        iov[1].iov_base = &cusexmp_size;
 
  180        iov[1].iov_len = 
sizeof(cusexmp_size);
 
  183                size_t off = arg->offset;
 
  184                size_t size = arg->size;
 
  186                if (off >= cusexmp_size)
 
  188                if (size > cusexmp_size - off)
 
  189                        size = cusexmp_size - off;
 
  191                iov[2].iov_base = cusexmp_buf + off;
 
  192                iov[2].iov_len = size;
 
  195                if (cusexmp_expand(arg->offset + in_bufsz)) {
 
  200                memcpy(cusexmp_buf + arg->offset, in_buf, in_bufsz);
 
  205static void cusexmp_ioctl(
fuse_req_t req, 
int cmd, 
void *arg,
 
  207                          const void *in_buf, 
size_t in_bufsz, 
size_t out_bufsz)
 
  221                        struct iovec iov = { arg, 
sizeof(size_t) };
 
  226                                         sizeof(cusexmp_size));
 
  231                        struct iovec iov = { arg, 
sizeof(size_t) };
 
  235                        cusexmp_resize(*(
size_t *)in_buf);
 
  244                fioc_do_rw(req, arg, in_buf, in_bufsz, out_bufsz, is_read);
 
  252struct cusexmp_param {
 
  259#define CUSEXMP_OPT(t, p) { t, offsetof(struct cusexmp_param, p), 1 } 
  261static const struct fuse_opt cusexmp_opts[] = {
 
  262        CUSEXMP_OPT(
"-M %u",            major),
 
  263        CUSEXMP_OPT(
"--maj=%u",         major),
 
  264        CUSEXMP_OPT(
"-m %u",            minor),
 
  265        CUSEXMP_OPT(
"--min=%u",         minor),
 
  266        CUSEXMP_OPT(
"-n %s",            dev_name),
 
  267        CUSEXMP_OPT(
"--name=%s",        dev_name),
 
  273static int cusexmp_process_arg(
void *data, 
const char *arg, 
int key,
 
  276        struct cusexmp_param *param = data;
 
  284                fprintf(stderr, 
"%s", usage);
 
  291static const struct cuse_lowlevel_ops cusexmp_clop = {
 
  292        .init           = cusexmp_init,
 
  293        .open           = cusexmp_open,
 
  294        .read           = cusexmp_read,
 
  295        .write          = cusexmp_write,
 
  296        .ioctl          = cusexmp_ioctl,
 
  299int main(
int argc, 
char **argv)
 
  302        struct cusexmp_param param = { 0, 0, NULL, 0 };
 
  303        char dev_name[128] = 
"DEVNAME=";
 
  304        const char *dev_info_argv[] = { dev_name };
 
  308        if (
fuse_opt_parse(&args, ¶m, cusexmp_opts, cusexmp_process_arg)) {
 
  309                printf(
"failed to parse option\n");
 
  310                free(param.dev_name);
 
  314        if (!param.is_help) {
 
  315                if (!param.dev_name) {
 
  316                        fprintf(stderr, 
"Error: device name missing\n");
 
  319                strncat(dev_name, param.dev_name, 
sizeof(dev_name) - 
sizeof(
"DEVNAME="));
 
  320                free(param.dev_name);
 
  323        memset(&ci, 0, 
sizeof(ci));
 
  324        ci.dev_major = param.major;
 
  325        ci.dev_minor = param.minor;
 
  326        ci.dev_info_argc = 1;
 
  327        ci.dev_info_argv = dev_info_argv;
 
  328        ci.flags = CUSE_UNRESTRICTED_IOCTL;
 
  330        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)