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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <errno.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;
 
                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);
 
}
int(* fuse_fill_dir_t)(void *buf, const char *name, const struct stat *stbuf, off_t off, enum fuse_fill_dir_flags flags)
#define fuse_main(argc, argv, op, private_data)
#define FUSE_IOCTL_COMPAT
int(* getattr)(const char *, struct stat *, struct fuse_file_info *fi)