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 };
   298         if (
fuse_opt_parse(&args, ¶m, cusexmp_opts, cusexmp_process_arg)) {
   299                 printf(
"failed to parse option\n");
   303         if (!param.is_help) {
   304                 if (!param.dev_name) {
   305                         fprintf(stderr, 
"Error: device name missing\n");
   308                 strncat(dev_name, param.dev_name, 
sizeof(dev_name) - 9);
   311         memset(&ci, 0, 
sizeof(ci));
   312         ci.dev_major = param.major;
   313         ci.dev_minor = param.minor;
   314         ci.dev_info_argc = 1;
   315         ci.dev_info_argv = dev_info_argv;
   316         ci.flags = CUSE_UNRESTRICTED_IOCTL;
   318         return cuse_lowlevel_main(args.
argc, args.
argv, &ci, &cusexmp_clop,
 int fuse_opt_parse(struct fuse_args *args, void *data, const struct fuse_opt opts[], fuse_opt_proc_t proc)
struct fuse_req * fuse_req_t
#define FUSE_IOCTL_COMPAT
int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov, int count)
#define FUSE_ARGS_INIT(argc, argv)
int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
int fuse_reply_write(fuse_req_t req, size_t 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_err(fuse_req_t req, int err)
#define FUSE_OPT_KEY(templ, key)
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)
int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *fi)