24 #define FUSE_USE_VERSION 31 45 static unsigned fsel_open_mask;
46 static const char fsel_hex_map[] =
"0123456789ABCDEF";
47 static struct fuse *fsel_fuse;
49 #define FSEL_CNT_MAX 10 52 static pthread_mutex_t fsel_mutex;
53 static unsigned fsel_poll_notify_mask;
54 static struct fuse_pollhandle *fsel_poll_handle[FSEL_FILES];
55 static unsigned fsel_cnt[FSEL_FILES];
57 static int fsel_path_index(
const char *path)
61 if (strlen(path) != 2 || path[0] !=
'/' || !isxdigit(ch) || islower(ch))
63 return ch <=
'9' ? ch -
'0' : ch -
'A' + 10;
66 static int fsel_getattr(
const char *path,
struct stat *stbuf,
72 memset(stbuf, 0,
sizeof(
struct stat));
74 if (strcmp(path,
"/") == 0) {
75 stbuf->st_mode = S_IFDIR | 0555;
80 idx = fsel_path_index(path);
84 stbuf->st_mode = S_IFREG | 0444;
86 stbuf->st_size = fsel_cnt[idx];
90 static int fsel_readdir(
const char *path,
void *buf,
fuse_fill_dir_t filler,
101 if (strcmp(path,
"/") != 0)
104 for (i = 0; i < FSEL_FILES; i++) {
105 name[0] = fsel_hex_map[i];
106 filler(buf, name, NULL, 0, 0);
114 int idx = fsel_path_index(path);
118 if ((fi->
flags & 3) != O_RDONLY)
120 if (fsel_open_mask & (1 << idx))
122 fsel_open_mask |= (1 << idx);
136 static int fsel_release(
const char *path,
struct fuse_file_info *fi)
142 fsel_open_mask &= ~(1 << idx);
146 static int fsel_read(
const char *path,
char *buf,
size_t size, off_t offset,
154 pthread_mutex_lock(&fsel_mutex);
155 if (fsel_cnt[idx] < size)
156 size = fsel_cnt[idx];
157 printf(
"READ %X transferred=%zu cnt=%u\n", idx, size, fsel_cnt[idx]);
158 fsel_cnt[idx] -= size;
159 pthread_mutex_unlock(&fsel_mutex);
161 memset(buf, fsel_hex_map[idx], size);
166 struct fuse_pollhandle *ph,
unsigned *reventsp)
168 static unsigned polled_zero;
182 fsel_fuse = cxt->
fuse;
185 pthread_mutex_lock(&fsel_mutex);
188 struct fuse_pollhandle *oldph = fsel_poll_handle[idx];
193 fsel_poll_notify_mask |= (1 << idx);
194 fsel_poll_handle[idx] = ph;
199 printf(
"POLL %X cnt=%u polled_zero=%u\n",
200 idx, fsel_cnt[idx], polled_zero);
205 pthread_mutex_unlock(&fsel_mutex);
211 .readdir = fsel_readdir,
213 .release = fsel_release,
218 static void *fsel_producer(
void *data)
220 const struct timespec interval = { 0, 250000000 };
221 unsigned idx = 0, nr = 1;
228 pthread_mutex_lock(&fsel_mutex);
236 for (i = 0, t = idx; i < nr;
237 i++, t = (t + FSEL_FILES / nr) % FSEL_FILES) {
238 if (fsel_cnt[t] == FSEL_CNT_MAX)
242 if (fsel_fuse && (fsel_poll_notify_mask & (1 << t))) {
243 struct fuse_pollhandle *ph;
245 printf(
"NOTIFY %X\n", t);
246 ph = fsel_poll_handle[t];
247 fuse_notify_poll(ph);
249 fsel_poll_notify_mask &= ~(1 << t);
250 fsel_poll_handle[t] = NULL;
254 idx = (idx + 1) % FSEL_FILES;
258 pthread_mutex_unlock(&fsel_mutex);
260 nanosleep(&interval, NULL);
266 int main(
int argc,
char *argv[])
272 errno = pthread_mutex_init(&fsel_mutex, NULL);
274 perror(
"pthread_mutex_init");
278 errno = pthread_attr_init(&attr);
280 perror(
"pthread_attr_init");
284 errno = pthread_create(&producer, &attr, fsel_producer, NULL);
286 perror(
"pthread_create");
290 ret =
fuse_main(argc, argv, &fsel_oper, NULL);
292 pthread_cancel(producer);
293 pthread_join(producer, 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)
void fuse_pollhandle_destroy(struct fuse_pollhandle *ph)
int(* getattr)(const char *, struct stat *, struct fuse_file_info *fi)
struct fuse_context * fuse_get_context(void)