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)