This example illustrates how to write a FUSE file system that supports polling for changes that don't come through the kernel. It can be tested with the poll_client.c program.
 
 
#define FUSE_USE_VERSION 31
 
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#include <pthread.h>
#include <poll.h>
 
static unsigned fsel_open_mask;
static const char fsel_hex_map[] = "0123456789ABCDEF";
static struct fuse *fsel_fuse;  
 
#define FSEL_CNT_MAX    10      
#define FSEL_FILES      16
 
static pthread_mutex_t fsel_mutex;      
static unsigned fsel_poll_notify_mask;  
static struct fuse_pollhandle *fsel_poll_handle[FSEL_FILES]; 
static unsigned fsel_cnt[FSEL_FILES];   
 
static int fsel_path_index(const char *path)
{
        char ch = path[1];
 
        if (strlen(path) != 2 || path[0] != '/' || !isxdigit(ch) || islower(ch))
                return -1;
        return ch <= '9' ? ch - '0' : ch - 'A' + 10;
}
 
static int fsel_getattr(const char *path, struct stat *stbuf,
{
        (void) fi;
        int idx;
 
        memset(stbuf, 0, sizeof(struct stat));
 
        if (strcmp(path, "/") == 0) {
                stbuf->st_mode = S_IFDIR | 0555;
                stbuf->st_nlink = 2;
                return 0;
        }
 
        idx = fsel_path_index(path);
        if (idx < 0)
                return -ENOENT;
 
        stbuf->st_mode = S_IFREG | 0444;
        stbuf->st_nlink = 1;
        stbuf->st_size = fsel_cnt[idx];
        return 0;
}
 
static int fsel_readdir(
const char *path, 
void *buf, 
fuse_fill_dir_t filler,
 
{
        char name[2] = { };
        int i;
 
        (void) offset;
        (void) fi;
        (void) flags;
 
        if (strcmp(path, "/") != 0)
                return -ENOENT;
 
        for (i = 0; i < FSEL_FILES; i++) {
                name[0] = fsel_hex_map[i];
                filler(buf, name, NULL, 0, 0);
        }
 
        return 0;
}
 
{
        int idx = fsel_path_index(path);
 
        if (idx < 0)
                return -ENOENT;
        if ((fi->
flags & O_ACCMODE) != O_RDONLY)
 
                return -EACCES;
        if (fsel_open_mask & (1 << idx))
                return -EBUSY;
        fsel_open_mask |= (1 << idx);
 
        
 
        return 0;
}
 
{
 
        (void) path;
 
        fsel_open_mask &= ~(1 << idx);
        return 0;
}
 
static int fsel_read(const char *path, char *buf, size_t size, off_t offset,
{
 
        (void) path;
        (void) offset;
 
        pthread_mutex_lock(&fsel_mutex);
        if (fsel_cnt[idx] < size)
                size = fsel_cnt[idx];
        printf("READ   %X transferred=%zu cnt=%u\n", idx, size, fsel_cnt[idx]);
        fsel_cnt[idx] -= size;
        pthread_mutex_unlock(&fsel_mutex);
 
        memset(buf, fsel_hex_map[idx], size);
        return size;
}
 
                     struct fuse_pollhandle *ph, unsigned *reventsp)
{
        static unsigned polled_zero;
 
        (void) path;
 
        
        if (!fsel_fuse) {
                if (cxt)
        }
 
        pthread_mutex_lock(&fsel_mutex);
 
        if (ph != NULL) {
                struct fuse_pollhandle *oldph = fsel_poll_handle[idx];
 
                if (oldph)
 
                fsel_poll_notify_mask |= (1 << idx);
                fsel_poll_handle[idx] = ph;
        }
 
        if (fsel_cnt[idx]) {
                *reventsp |= POLLIN;
                printf("POLL   %X cnt=%u polled_zero=%u\n",
                       idx, fsel_cnt[idx], polled_zero);
                polled_zero = 0;
        } else
                polled_zero++;
 
        pthread_mutex_unlock(&fsel_mutex);
        return 0;
}
 
        .readdir        = fsel_readdir,
        .open           = fsel_open,
        .release        = fsel_release,
        .read           = fsel_read,
        .poll           = fsel_poll,
};
 
static void *fsel_producer(void *data)
{
        const struct timespec interval = { 0, 250000000 };
        unsigned idx = 0, nr = 1;
 
        (void) data;
 
        while (1) {
                int i, t;
 
                pthread_mutex_lock(&fsel_mutex);
 
                
                for (i = 0, t = idx; i < nr;
                     i++, t = (t + FSEL_FILES / nr) % FSEL_FILES) {
                        if (fsel_cnt[t] == FSEL_CNT_MAX)
                                continue;
 
                        fsel_cnt[t]++;
                        if (fsel_fuse && (fsel_poll_notify_mask & (1 << t))) {
                                struct fuse_pollhandle *ph;
 
                                printf("NOTIFY %X\n", t);
                                ph = fsel_poll_handle[t];
                                fuse_notify_poll(ph);
                                fsel_poll_notify_mask &= ~(1 << t);
                                fsel_poll_handle[t] = NULL;
                        }
                }
 
                idx = (idx + 1) % FSEL_FILES;
                if (idx == 0)
                        nr = (nr * 2) % 7;      
 
                pthread_mutex_unlock(&fsel_mutex);
 
                nanosleep(&interval, NULL);
        }
 
        return NULL;
}
 
int main(int argc, char *argv[])
{
        pthread_t producer;
        pthread_attr_t attr;
        int ret;
 
        errno = pthread_mutex_init(&fsel_mutex, NULL);
        if (errno) {
                perror("pthread_mutex_init");
                return 1;
        }
 
        errno = pthread_attr_init(&attr);
        if (errno) {
                perror("pthread_attr_init");
                return 1;
        }
 
        errno = pthread_create(&producer, &attr, fsel_producer, NULL);
        if (errno) {
                perror("pthread_create");
                return 1;
        }
 
        ret = 
fuse_main(argc, argv, &fsel_oper, NULL);
 
        pthread_cancel(producer);
        pthread_join(producer, NULL);
 
        return ret;
}
struct fuse_context * fuse_get_context(void)
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)
void fuse_pollhandle_destroy(struct fuse_pollhandle *ph)
int(* getattr)(const char *, struct stat *, struct fuse_file_info *fi)