diff options
author | Paul Lawrence <paullawrence@google.com> | 2019-08-02 16:45:27 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-08-02 16:45:27 -0700 |
commit | 1ca65fd045ff0aad723cfb4c740ee9250ae5c360 (patch) | |
tree | eb415748db51aed7c3d08a5e7dae57c8576ea940 /example/cuse.c | |
parent | be83b553fef2fa13ecc8edbea974f450637cc60e (diff) | |
parent | c77441c6bcfb18dd3c887cdf24a778960fbe0c41 (diff) |
Remove GPL files am: 94aa887ced am: b4099f5e0f am: 2609a900fb
am: c77441c6bc
Change-Id: I849d56bb6f9909131b449f4f472f21aabd6d2aeb
Diffstat (limited to 'example/cuse.c')
-rw-r--r-- | example/cuse.c | 320 |
1 files changed, 0 insertions, 320 deletions
diff --git a/example/cuse.c b/example/cuse.c deleted file mode 100644 index d192de2..0000000 --- a/example/cuse.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - CUSE example: Character device in Userspace - Copyright (C) 2008-2009 SUSE Linux Products GmbH - Copyright (C) 2008-2009 Tejun Heo <tj@kernel.org> - - This program can be distributed under the terms of the GNU GPL. - See the file COPYING. - -*/ - -/** @file - * - * This example demonstrates how to implement a character device in - * userspace ("CUSE"). This is only allowed for root. The character - * device should appear in /dev under the specified name. It can be - * tested with the cuse_client.c program. - * - * Mount the file system with: - * - * cuse -f --name=mydevice - * - * You should now have a new /dev/mydevice character device. To "unmount" it, - * kill the "cuse" process. - * - * To compile this example, run - * - * gcc -Wall cuse.c `pkg-config fuse3 --cflags --libs` -o cuse - * - * ## Source code ## - * \include cuse.c - */ - - -#define FUSE_USE_VERSION 31 - -#include <cuse_lowlevel.h> -#include <fuse_opt.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> - -#include "ioctl.h" - -static void *cusexmp_buf; -static size_t cusexmp_size; - -static const char *usage = -"usage: cusexmp [options]\n" -"\n" -"options:\n" -" --help|-h print this help message\n" -" --maj=MAJ|-M MAJ device major number\n" -" --min=MIN|-m MIN device minor number\n" -" --name=NAME|-n NAME device name (mandatory)\n" -" -d -o debug enable debug output (implies -f)\n" -" -f foreground operation\n" -" -s disable multi-threaded operation\n" -"\n"; - -static int cusexmp_resize(size_t new_size) -{ - void *new_buf; - - if (new_size == cusexmp_size) - return 0; - - new_buf = realloc(cusexmp_buf, new_size); - if (!new_buf && new_size) - return -ENOMEM; - - if (new_size > cusexmp_size) - memset(new_buf + cusexmp_size, 0, new_size - cusexmp_size); - - cusexmp_buf = new_buf; - cusexmp_size = new_size; - - return 0; -} - -static int cusexmp_expand(size_t new_size) -{ - if (new_size > cusexmp_size) - return cusexmp_resize(new_size); - return 0; -} - -static void cusexmp_open(fuse_req_t req, struct fuse_file_info *fi) -{ - fuse_reply_open(req, fi); -} - -static void cusexmp_read(fuse_req_t req, size_t size, off_t off, - struct fuse_file_info *fi) -{ - (void)fi; - - if (off >= cusexmp_size) - off = cusexmp_size; - if (size > cusexmp_size - off) - size = cusexmp_size - off; - - fuse_reply_buf(req, cusexmp_buf + off, size); -} - -static void cusexmp_write(fuse_req_t req, const char *buf, size_t size, - off_t off, struct fuse_file_info *fi) -{ - (void)fi; - - if (cusexmp_expand(off + size)) { - fuse_reply_err(req, ENOMEM); - return; - } - - memcpy(cusexmp_buf + off, buf, size); - fuse_reply_write(req, size); -} - -static void fioc_do_rw(fuse_req_t req, void *addr, const void *in_buf, - size_t in_bufsz, size_t out_bufsz, int is_read) -{ - const struct fioc_rw_arg *arg; - struct iovec in_iov[2], out_iov[3], iov[3]; - size_t cur_size; - - /* read in arg */ - in_iov[0].iov_base = addr; - in_iov[0].iov_len = sizeof(*arg); - if (!in_bufsz) { - fuse_reply_ioctl_retry(req, in_iov, 1, NULL, 0); - return; - } - arg = in_buf; - in_buf += sizeof(*arg); - in_bufsz -= sizeof(*arg); - - /* prepare size outputs */ - out_iov[0].iov_base = - addr + offsetof(struct fioc_rw_arg, prev_size); - out_iov[0].iov_len = sizeof(arg->prev_size); - - out_iov[1].iov_base = - addr + offsetof(struct fioc_rw_arg, new_size); - out_iov[1].iov_len = sizeof(arg->new_size); - - /* prepare client buf */ - if (is_read) { - out_iov[2].iov_base = arg->buf; - out_iov[2].iov_len = arg->size; - if (!out_bufsz) { - fuse_reply_ioctl_retry(req, in_iov, 1, out_iov, 3); - return; - } - } else { - in_iov[1].iov_base = arg->buf; - in_iov[1].iov_len = arg->size; - if (arg->size && !in_bufsz) { - fuse_reply_ioctl_retry(req, in_iov, 2, out_iov, 2); - return; - } - } - - /* we're all set */ - cur_size = cusexmp_size; - iov[0].iov_base = &cur_size; - iov[0].iov_len = sizeof(cur_size); - - iov[1].iov_base = &cusexmp_size; - iov[1].iov_len = sizeof(cusexmp_size); - - if (is_read) { - size_t off = arg->offset; - size_t size = arg->size; - - if (off >= cusexmp_size) - off = cusexmp_size; - if (size > cusexmp_size - off) - size = cusexmp_size - off; - - iov[2].iov_base = cusexmp_buf + off; - iov[2].iov_len = size; - fuse_reply_ioctl_iov(req, size, iov, 3); - } else { - if (cusexmp_expand(arg->offset + in_bufsz)) { - fuse_reply_err(req, ENOMEM); - return; - } - - memcpy(cusexmp_buf + arg->offset, in_buf, in_bufsz); - fuse_reply_ioctl_iov(req, in_bufsz, iov, 2); - } -} - -static void cusexmp_ioctl(fuse_req_t req, int cmd, void *arg, - struct fuse_file_info *fi, unsigned flags, - const void *in_buf, size_t in_bufsz, size_t out_bufsz) -{ - int is_read = 0; - - (void)fi; - - if (flags & FUSE_IOCTL_COMPAT) { - fuse_reply_err(req, ENOSYS); - return; - } - - switch (cmd) { - case FIOC_GET_SIZE: - if (!out_bufsz) { - struct iovec iov = { arg, sizeof(size_t) }; - - fuse_reply_ioctl_retry(req, NULL, 0, &iov, 1); - } else - fuse_reply_ioctl(req, 0, &cusexmp_size, - sizeof(cusexmp_size)); - break; - - case FIOC_SET_SIZE: - if (!in_bufsz) { - struct iovec iov = { arg, sizeof(size_t) }; - - fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0); - } else { - cusexmp_resize(*(size_t *)in_buf); - fuse_reply_ioctl(req, 0, NULL, 0); - } - break; - - case FIOC_READ: - is_read = 1; - /* fall through */ - case FIOC_WRITE: - fioc_do_rw(req, arg, in_buf, in_bufsz, out_bufsz, is_read); - break; - - default: - fuse_reply_err(req, EINVAL); - } -} - -struct cusexmp_param { - unsigned major; - unsigned minor; - char *dev_name; - int is_help; -}; - -#define CUSEXMP_OPT(t, p) { t, offsetof(struct cusexmp_param, p), 1 } - -static const struct fuse_opt cusexmp_opts[] = { - CUSEXMP_OPT("-M %u", major), - CUSEXMP_OPT("--maj=%u", major), - CUSEXMP_OPT("-m %u", minor), - CUSEXMP_OPT("--min=%u", minor), - CUSEXMP_OPT("-n %s", dev_name), - CUSEXMP_OPT("--name=%s", dev_name), - FUSE_OPT_KEY("-h", 0), - FUSE_OPT_KEY("--help", 0), - FUSE_OPT_END -}; - -static int cusexmp_process_arg(void *data, const char *arg, int key, - struct fuse_args *outargs) -{ - struct cusexmp_param *param = data; - - (void)outargs; - (void)arg; - - switch (key) { - case 0: - param->is_help = 1; - fprintf(stderr, "%s", usage); - return fuse_opt_add_arg(outargs, "-ho"); - default: - return 1; - } -} - -static const struct cuse_lowlevel_ops cusexmp_clop = { - .open = cusexmp_open, - .read = cusexmp_read, - .write = cusexmp_write, - .ioctl = cusexmp_ioctl, -}; - -int main(int argc, char **argv) -{ - struct fuse_args args = FUSE_ARGS_INIT(argc, argv); - struct cusexmp_param param = { 0, 0, NULL, 0 }; - char dev_name[128] = "DEVNAME="; - const char *dev_info_argv[] = { dev_name }; - struct cuse_info ci; - - if (fuse_opt_parse(&args, ¶m, cusexmp_opts, cusexmp_process_arg)) { - printf("failed to parse option\n"); - return 1; - } - - if (!param.is_help) { - if (!param.dev_name) { - fprintf(stderr, "Error: device name missing\n"); - return 1; - } - strncat(dev_name, param.dev_name, sizeof(dev_name) - 9); - } - - memset(&ci, 0, sizeof(ci)); - ci.dev_major = param.major; - ci.dev_minor = param.minor; - ci.dev_info_argc = 1; - ci.dev_info_argv = dev_info_argv; - ci.flags = CUSE_UNRESTRICTED_IOCTL; - - return cuse_lowlevel_main(args.argc, args.argv, &ci, &cusexmp_clop, - NULL); -} |