#define FUSE_USE_VERSION 30 #define NOISER_COUNT 2 #include #include #include #include #include #include #include #include "noisebox.h" static void* do_init(struct fuse_conn_info *conn) { Noiser** noisers = malloc(sizeof(Noiser*) * NOISER_COUNT); noisers[0] = zero_init(); noisers[1] = mersenne_init(); return noisers; } static int getattr_root(struct stat *st) { st->st_mode = S_IFDIR | 0755; st->st_nlink = 2 + NOISER_COUNT; return 0; } static int lookup_path(const char *path, Noiser **n, NoiseFile **nf) { struct fuse_context* c = fuse_get_context(); Noiser** noisers = c->private_data; char* buf = strdup(path); char *mod = strtok(buf, "/"); for(int i=0; iname) == 0) { *n = noisers[i]; } } if(!*n) { printf("no noiser\n"); return -ENOENT; } char *fname = strtok(NULL, "/"); if(!fname) { // we already had a valid noiser, so it's fine. printf("returning noiser %p:%s, no fname\n", n, (*n)->name); return 0; } for(int i=0; i<(*n)->noisefile_count; i++) { if(strcmp(fname, (*n)->files[i]->name) == 0) { *nf = (*n)->files[i]; } } if(*nf) { printf("returning fname %p:%s\n", nf, (*nf)->name); return 0; } else { printf("file not found: %s\n", fname); return -ENOENT; } } static int getattr_leaf(const char *path, struct stat *st) { Noiser *n = NULL; NoiseFile *nf = NULL; int ret; ret = lookup_path(path, &n, &nf); if(ret !=0) { return ret; } if(!n) { printf("didn't find %s:%p\n", path, n); return -EINVAL; } if(!nf) { printf("return n, no nf\n"); st->st_mode = S_IFDIR | 0644; st->st_nlink = 2 + n->noisefile_count; printf("setup dir\n"); return 0; } printf("return n + nf: %p\n", nf); st->st_mode = S_IFREG | 0644; st->st_nlink = 1; st->st_size = nf->size; return 0; } static int do_getattr(const char *path, struct stat *st) { st->st_uid = 0; st->st_gid = 0; // st->st_atime = __DATE__; // st->st_mtime = __DATE__; st->st_atime = time(NULL); st->st_mtime = time(NULL); int ret; if(strcmp(path, "/") == 0) { ret = getattr_root(st); } else { ret = getattr_leaf(path, st); }; return ret; } static int do_open(const char* path, struct fuse_file_info* fi) { Noiser *n = NULL; NoiseFile *nf = NULL; int ret; ret = lookup_path(path, &n, &nf); if(ret !=0) { return ret; } ret = n->do_open(path, fi); return ret; } static int do_read(const char* path, char* buf, size_t sz, off_t offset, struct fuse_file_info* fi) { int ret; Noiser *n; NoiseFile *nf; ret = lookup_path(path, &n, &nf); if(ret != 0) { return ret; } ret = n->get_noise(sz, offset, buf, fi); return ret; } static int readdir_root(void *buffer, fuse_fill_dir_t filler) { struct fuse_context* c = fuse_get_context(); Noiser** noiser = c->private_data; int ret = 0; for(int i=0; iname, NULL, 0); if(ret != 0) { printf("failed to fill %s, dying\n", noiser[i]->name); break; } } return ret; } static int do_noiser_readdir(const Noiser *n, const char *path, void *buffer, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { NoiseFile **nfs = n->files; int ret; for(int i=0; inoisefile_count; i++) { printf("filling %i of %i: %s\n", i, n->noisefile_count, nfs[i]->name); ret = filler(buffer, nfs[i]->name, NULL, 0); if(ret != 0) { break; } } return ret; } static int do_readdir(const char *path, void *buffer, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { filler(buffer, ".", NULL, 0); filler(buffer, "..", NULL, 0); int ret; if(strcmp(path, "/") == 0) { ret = readdir_root(buffer, filler); } else { // find noiser, generate appropriate files struct fuse_context* c = fuse_get_context(); Noiser** noiser = c->private_data; char * pathbuf = strdup(path); char * toplevel = strtok(pathbuf, "/"); for(int i=0; iname, toplevel) == 0) { printf("found noiser: %s\n", noiser[i]->name); ret = do_noiser_readdir(noiser[i], path, buffer, filler, offset, fi); } } } return ret; } static struct fuse_operations ops = { // int (*getattr) (const char *, struct stat *); .getattr = do_getattr, // int (*readlink) (const char *, char *, size_t); // int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t); // int (*mknod) (const char *, mode_t, dev_t); // int (*mkdir) (const char *, mode_t); // int (*unlink) (const char *); // int (*rmdir) (const char *); // int (*symlink) (const char *, const char *); // int (*rename) (const char *, const char *); // int (*link) (const char *, const char *); // int (*chmod) (const char *, mode_t); // int (*chown) (const char *, uid_t, gid_t); // int (*truncate) (const char *, off_t); // int (*utime) (const char *, struct utimbuf *); // int (*open) (const char *, struct fuse_file_info *); .open = do_open, // int (*read) (const char *, char *, size_t, off_t, // struct fuse_file_info *); .read = do_read, // int (*write) (const char *, const char *, size_t, off_t, // struct fuse_file_info *); // int (*statfs) (const char *, struct statvfs *); // int (*flush) (const char *, struct fuse_file_info *); // int (*release) (const char *, struct fuse_file_info *); // int (*fsync) (const char *, int, struct fuse_file_info *); // int (*setxattr) (const char *, const char *, const char *, size_t, int); // int (*getxattr) (const char *, const char *, char *, size_t); // int (*listxattr) (const char *, char *, size_t); // int (*removexattr) (const char *, const char *); // int (*opendir) (const char *, struct fuse_file_info *); // int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t, // struct fuse_file_info *); .readdir = do_readdir, // int (*releasedir) (const char *, struct fuse_file_info *); // int (*fsyncdir) (const char *, int, struct fuse_file_info *); // void *(*init) (struct fuse_conn_info *conn); .init = do_init, // void (*destroy) (void *); // int (*access) (const char *, int); // int (*create) (const char *, mode_t, struct fuse_file_info *); // int (*ftruncate) (const char *, off_t, struct fuse_file_info *); // int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *); // int (*lock) (const char *, struct fuse_file_info *, int cmd, // struct flock *); // int (*utimens) (const char *, const struct timespec tv[2]); // int (*bmap) (const char *, size_t blocksize, uint64_t *idx); // int (*ioctl) (const char *, int cmd, void *arg, // struct fuse_file_info *, unsigned int flags, void *data); // int (*poll) (const char *, struct fuse_file_info *, // struct fuse_pollhandle *ph, unsigned *reventsp); // int (*write_buf) (const char *, struct fuse_bufvec *buf, off_t off, // struct fuse_file_info *); // int (*read_buf) (const char *, struct fuse_bufvec **bufp, // size_t size, off_t off, struct fuse_file_info *); // int (*flock) (const char *, struct fuse_file_info *, int op); // int (*fallocate) (const char *, int, off_t, off_t, // struct fuse_file_info *); .flag_nullpath_ok = 1, }; int main(int argc, char* argv[]) { return fuse_main(argc, argv, &ops, NULL); }