This example illustrates how to write a FUSE file system that can process (a restricted set of) ioctls. It can be tested with the ioctl_client.c program.
#define FUSE_USE_VERSION 35
#include <fuse.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
#include "ioctl.h"
#define FIOC_NAME       "fioc"
enum {
        FIOC_NONE,
        FIOC_ROOT,
        FIOC_FILE,
};
static void *fioc_buf;
static size_t fioc_size;
static int fioc_resize(size_t new_size)
{
        void *new_buf;
        if (new_size == fioc_size)
                return 0;
        new_buf = realloc(fioc_buf, new_size);
        if (!new_buf && new_size)
                return -ENOMEM;
        if (new_size > fioc_size)
                memset(new_buf + fioc_size, 0, new_size - fioc_size);
        fioc_buf = new_buf;
        fioc_size = new_size;
        return 0;
}
static int fioc_expand(size_t new_size)
{
        if (new_size > fioc_size)
                return fioc_resize(new_size);
        return 0;
}
static int fioc_file_type(const char *path)
{
        if (strcmp(path, "/") == 0)
                return FIOC_ROOT;
        if (strcmp(path, "/" FIOC_NAME) == 0)
                return FIOC_FILE;
        return FIOC_NONE;
}
static int fioc_getattr(const char *path, struct stat *stbuf,
{
        (void) fi;
        stbuf->st_uid = getuid();
        stbuf->st_gid = getgid();
        stbuf->st_atime = stbuf->st_mtime = time(NULL);
        switch (fioc_file_type(path)) {
        case FIOC_ROOT:
                stbuf->st_mode = S_IFDIR | 0755;
                stbuf->st_nlink = 2;
                break;
        case FIOC_FILE:
                stbuf->st_mode = S_IFREG | 0644;
                stbuf->st_nlink = 1;
                stbuf->st_size = fioc_size;
                break;
        case FIOC_NONE:
                return -ENOENT;
        }
        return 0;
}
{
        (void) fi;
        if (fioc_file_type(path) != FIOC_NONE)
                return 0;
        return -ENOENT;
}
static int fioc_do_read(char *buf, size_t size, off_t offset)
{
        if (offset >= fioc_size)
                return 0;
        if (size > fioc_size - offset)
                size = fioc_size - offset;
        memcpy(buf, fioc_buf + offset, size);
        return size;
}
static int fioc_read(const char *path, char *buf, size_t size,
{
        (void) fi;
        if (fioc_file_type(path) != FIOC_FILE)
                return -EINVAL;
        return fioc_do_read(buf, size, offset);
}
static int fioc_do_write(const char *buf, size_t size, off_t offset)
{
        if (fioc_expand(offset + size))
                return -ENOMEM;
        memcpy(fioc_buf + offset, buf, size);
        return size;
}
static int fioc_write(const char *path, const char *buf, size_t size,
{
        (void) fi;
        if (fioc_file_type(path) != FIOC_FILE)
                return -EINVAL;
        return fioc_do_write(buf, size, offset);
}
static int fioc_truncate(const char *path, off_t size,
{
        (void) fi;
        if (fioc_file_type(path) != FIOC_FILE)
                return -EINVAL;
        return fioc_resize(size);
}
static int fioc_readdir(
const char *path, 
void *buf, 
fuse_fill_dir_t filler,
 {
        (void) fi;
        (void) offset;
        (void) flags;
        if (fioc_file_type(path) != FIOC_ROOT)
                return -ENOENT;
        filler(buf, ".", NULL, 0, 0);
        filler(buf, "..", NULL, 0, 0);
        filler(buf, FIOC_NAME, NULL, 0, 0);
        return 0;
}
static int fioc_ioctl(const char *path, unsigned int cmd, void *arg,
{
        (void) arg;
        (void) fi;
        (void) flags;
        if (fioc_file_type(path) != FIOC_FILE)
                return -EINVAL;
        if (flags & FUSE_IOCTL_COMPAT)
                return -ENOSYS;
        switch (cmd) {
        case FIOC_GET_SIZE:
                *(size_t *)data = fioc_size;
                return 0;
        case FIOC_SET_SIZE:
                fioc_resize(*(size_t *)data);
                return 0;
        }
        return -EINVAL;
}
        .readdir        = fioc_readdir,
        .truncate       = fioc_truncate,
        .open           = fioc_open,
        .read           = fioc_read,
        .write          = fioc_write,
        .ioctl          = fioc_ioctl,
};
int main(int argc, char *argv[])
{
        return fuse_main(argc, argv, &fioc_oper, NULL);
 }