This program tests the cuse.c example file system.
Example usage (assuming that /dev/foobar is a CUSE device provided by the cuse.c example file system): 
 
 
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include "ioctl.h"
 
const char *usage =
"Usage: cuse_client FIOC_FILE COMMAND\n"
"\n"
"COMMANDS\n"
"  s [SIZE]     : get size if SIZE is omitted, set size otherwise\n"
"  r SIZE [OFF] : read SIZE bytes @ OFF (dfl 0) and output to stdout\n"
"  w SIZE [OFF] : write SIZE bytes @ OFF (dfl 0) from stdin\n"
"\n";
 
static int do_rw(int fd, int is_read, size_t size, off_t offset,
                 size_t *prev_size, size_t *new_size)
{
        struct fioc_rw_arg arg = { .offset = offset };
        ssize_t ret;
 
        arg.buf = calloc(1, size);
        if (!arg.buf) {
                fprintf(stderr, "failed to allocated %zu bytes\n", size);
                return -1;
        }
 
        if (is_read) {
                arg.size = size;
                ret = ioctl(fd, FIOC_READ, &arg);
                if (ret >= 0)
                        fwrite(arg.buf, 1, ret, stdout);
        } else {
                arg.size = fread(arg.buf, 1, size, stdin);
                fprintf(stderr, "Writing %zu bytes\n", arg.size);
                ret = ioctl(fd, FIOC_WRITE, &arg);
        }
 
        if (ret >= 0) {
                *prev_size = arg.prev_size;
                *new_size = arg.new_size;
        } else
                perror("ioctl");
 
        free(arg.buf);
        return ret;
}
 
int main(int argc, char **argv)
{
        size_t param[2] = { };
        size_t size, prev_size = 0, new_size = 0;
        char cmd;
        int fd, i, rc;
 
        if (argc < 3)
                goto usage;
 
        fd = open(argv[1], O_RDWR);
        if (fd < 0) {
                perror("open");
                return 1;
        }
 
        cmd = tolower(argv[2][0]);
        argc -= 3;
        argv += 3;
 
        for (i = 0; i < argc; i++) {
                char *endp;
                param[i] = strtoul(argv[i], &endp, 0);
                if (endp == argv[i] || *endp != '\0')
                        goto usage;
        }
 
        switch (cmd) {
        case 's':
                if (!argc) {
                        if (ioctl(fd, FIOC_GET_SIZE, &size)) {
                                perror("ioctl");
                                goto error;
                        }
                        printf("%zu\n", size);
                } else {
                        size = param[0];
                        if (ioctl(fd, FIOC_SET_SIZE, &size)) {
                                perror("ioctl");
                                goto error;
                        }
                }
                close(fd);
                return 0;
 
        case 'r':
        case 'w':
                rc = do_rw(fd, cmd == 'r', param[0], param[1],
                           &prev_size, &new_size);
                if (rc < 0)
                        goto error;
                fprintf(stderr, "transferred %d bytes (%zu -> %zu)\n",
                        rc, prev_size, new_size);
                close(fd);
                return 0;
        }
 
usage:
        fprintf(stderr, "%s", usage);
        return 1;
 
error:
        close(fd);
        return 1;
}