34 #define FUSE_USE_VERSION 31 
   36 #include <cuse_lowlevel.h> 
   47 static void *cusexmp_buf;
 
   48 static size_t cusexmp_size;
 
   50 static 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" 
   63 static 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;
 
   83 static int cusexmp_expand(
size_t new_size)
 
   85         if (new_size > cusexmp_size)
 
   86                 return cusexmp_resize(new_size);
 
   95 static 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;
 
  108 static 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);
 
  122 static 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);
 
  197 static 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);
 
  244 struct cusexmp_param {
 
  251 #define CUSEXMP_OPT(t, p) { t, offsetof(struct cusexmp_param, p), 1 } 
  253 static 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),
 
  265 static int cusexmp_process_arg(
void *data, 
const char *arg, 
int key,
 
  268         struct cusexmp_param *param = data;
 
  276                 fprintf(stderr, 
"%s", usage);
 
  283 static const struct cuse_lowlevel_ops cusexmp_clop = {
 
  284         .open           = cusexmp_open,
 
  285         .read           = cusexmp_read,
 
  286         .write          = cusexmp_write,
 
  287         .ioctl          = cusexmp_ioctl,
 
  290 int 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)