#define FUSE_USE_VERSION 26#include<stdio.h>#include<stdlib.h>#include<string.h>#include<errno.h>#include<fuse.h>#include"list.h"#define MAX_NAMELEN 255struct ou_entry { mode_t mode; struct list_node node; char name[MAX_NAMELEN + 1];};static struct list_node entries;staticintou_readdir(constchar* path, void* buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info* fi){ struct list_node* n; filler(buf, ".", NULL, 0); filler(buf, "..", NULL, 0); list_for_each (n, &entries) { struct ou_entry* o = list_entry(n, struct ou_entry, node); filler(buf, o->name, NULL, 0); } return 0;}staticintou_getattr(constchar* path, struct stat* st){ struct list_node* n; memset(st, 0, sizeof(struct stat)); if (strcmp(path, "/") == 0) { st->st_mode = 0755 | S_IFDIR; st->st_nlink = 2; st->st_size = 0; list_for_each (n, &entries) { struct ou_entry* o = list_entry(n, struct ou_entry, node); ++st->st_nlink; st->st_size += strlen(o->name); } return 0; } list_for_each (n, &entries) { struct ou_entry* o = list_entry(n, struct ou_entry, node); if (strcmp(path + 1, o->name) == 0) { st->st_mode = o->mode; st->st_nlink = 1; return 0; } } return -ENOENT;}staticintou_create(constchar* path, mode_t mode, struct fuse_file_info* fi){ struct ou_entry* o; struct list_node* n; if (strlen(path + 1) > MAX_NAMELEN) return -ENAMETOOLONG; list_for_each (n, &entries) { o = list_entry(n, struct ou_entry, node); if (strcmp(path + 1, o->name) == 0) return -EEXIST; } o = malloc(sizeof(struct ou_entry)); strcpy(o->name, path + 1); /* skip leading '/' */ o->mode = mode | S_IFREG; list_add_prev(&o->node, &entries); return 0;}staticintou_unlink(constchar* path){ struct list_node *n, *p; list_for_each_safe (n, p, &entries) { struct ou_entry* o = list_entry(n, struct ou_entry, node); if (strcmp(path + 1, o->name) == 0) { __list_del(n); free(o); return 0; } } return -ENOENT;}static struct fuse_operations oufs_ops = { .getattr = ou_getattr, .readdir = ou_readdir, .create = ou_create, .unlink = ou_unlink,};intmain(int argc, char* argv[]){ list_init(&entries); return fuse_main(argc, argv, &oufs_ops, NULL);}
#ifndef __LIST_H__#define __LIST_H__/* doubly linked list implementation from linux kernel */#define offset_of(type, member) \ ((unsigned long)(&(((type*)0)->member)))#define container_of(ptr, type, member) \ ((type*)((unsigned long)(ptr) - offset_of(type, member)))#define list_entry(ptr, type, member) container_of(ptr, type, member)struct list_node { struct list_node *prev, *next;};staticinlinevoidlist_init(struct list_node* list){ list->prev = list; list->next = list;}staticinlinevoidlist_add_prev(struct list_node* node, struct list_node* next){ node->next = next; node->prev = next->prev; next->prev = node; node->prev->next = node;}static inline void __list_del(struct list_node* node){ node->prev->next = node->next; node->next->prev = node->prev;}staticinlinevoidlist_del(struct list_node* node){ __list_del(node); list_init(node);}#define list_for_each(p, head) \ for ((p) = (head)->next; (p) != (head); (p) = (p)->next)#define list_for_each_safe(p, n, head) \ for ((p) = (head)->next, (n) = (p)->next; \ (p) != (head); \ (p) = (n), (n) = (p)->next)#endif