diff --git a/lib/webfuse/provider/impl/static_filesystem.c b/lib/webfuse/provider/impl/static_filesystem.c index 51386fe..27b1ce4 100644 --- a/lib/webfuse/provider/impl/static_filesystem.c +++ b/lib/webfuse/provider/impl/static_filesystem.c @@ -1,19 +1,24 @@ #include "webfuse/provider/impl/static_filesystem.h" #include "webfuse/provider/client_config.h" +#include "webfuse/provider/dirbuffer.h" #include "webfuse/provider/operation/error.h" +#include #include +#include #include #define WFP_STATIC_FILESYSTEM_DEFAULT_CAPACITY (16) struct wfp_static_filesystem_entry { - struct wfp_static_filesystem * parent; - char const * name; + size_t inode; + size_t parent; + char * name; bool is_file; int mode; size_t size; + char * content; wfp_static_filesystem_read_fn * read; wfp_static_filesystem_get_info_fn * get_info; void * user_data; @@ -26,17 +31,152 @@ struct wfp_static_filesystem size_t capacity; }; +static struct wfp_static_filesystem_entry * +wfp_static_filesystem_get_entry( + struct wfp_static_filesystem * filesystem, + size_t inode) +{ + struct wfp_static_filesystem_entry * entry = NULL; + + if ((0 < inode) && (inode <= filesystem->size)) + { + entry = &filesystem->entries[inode - 1]; + } + + return entry; +} + +static struct wfp_static_filesystem_entry * +wfp_static_filesystem_get_entry_by_name( + struct wfp_static_filesystem * filesystem, + size_t parent, + char const * name) +{ + struct wfp_static_filesystem_entry * entry = NULL; + for(size_t i = 0; i < filesystem->size; i++) + { + struct wfp_static_filesystem_entry * current = &filesystem->entries[i]; + if ((parent == current->parent) && (0 == strcmp(name, current->name))) + { + entry = current; + break; + } + } + + return entry; +} + +static struct wfp_static_filesystem_entry * +wfp_static_filesystem_add_entry( + struct wfp_static_filesystem * filesystem) +{ + struct wfp_static_filesystem_entry * entry = NULL; + + if (filesystem->size < filesystem->capacity) + { + entry = &filesystem->entries[filesystem->size]; + entry->inode = filesystem->size + 1; + filesystem->size++; + } + else + { + fprintf(stderr, "fatal: static filessystem: unable to add entry\n"); + exit(EXIT_FAILURE); + } + + + return entry; +} + +static size_t +wfp_static_filesystem_entry_read( + size_t offset, + char * buffer, + size_t buffer_size, + void * user_data) +{ + (void) user_data; + (void) offset; + (void) buffer; + (void) buffer_size; + + //struct wfp_static_filesystem_entry * entry = user_data; + size_t result = 0; + + return result; +} + +static void +wfp_static_filesystem_entry_get_info( + void * user_data, + int * result_mode, + size_t * result_size) +{ + struct wfp_static_filesystem_entry * entry = user_data; + *result_mode = entry->mode; + *result_size = entry->size; +} + + +static void +wfp_static_filesystem_add_dir( + struct wfp_static_filesystem * filesystem, + size_t parent, + char const * name +) +{ + struct wfp_static_filesystem_entry * entry = wfp_static_filesystem_get_entry_by_name(filesystem, parent, name); + if (NULL == entry) + { + entry = wfp_static_filesystem_add_entry(filesystem); + entry->parent = parent; + entry->is_file = false; + entry->mode = 0555; + entry->name = strdup(name); + entry->user_data = entry; + entry->read = &wfp_static_filesystem_entry_read; + entry->get_info = &wfp_static_filesystem_entry_get_info; + entry->size = 0; + entry->content = NULL; + } +} + +static void wfp_static_filesystem_stat( + struct wfp_static_filesystem_entry * entry, + struct stat * stat +) +{ + memset(stat, 0, sizeof(struct stat)); + + int mode; + size_t size; + entry->get_info(entry->user_data, &mode, &size); + + stat->st_ino = entry->inode; + stat->st_size = entry->size; + stat->st_mode = entry->mode & 0777; + stat->st_mode |= (entry->is_file) ? S_IFREG: S_IFDIR; +} + static void wfp_static_filesystem_lookup( struct wfp_request * request, ino_t parent, char const * name, void * user_data) { - (void) parent; - (void) name; - (void) user_data; + struct wfp_static_filesystem * filesystem = user_data; + struct wfp_static_filesystem_entry * entry = wfp_static_filesystem_get_entry_by_name(filesystem, parent, name); - wfp_respond_error(request, WF_BAD_NOENTRY); + if (NULL != entry) + { + struct stat stat; + wfp_static_filesystem_stat(entry, &stat); + wfp_respond_lookup(request, &stat); + } + else + { + wfp_respond_error(request, WF_BAD_NOENTRY); + } } @@ -45,10 +185,19 @@ static void wfp_static_filesystem_getattr( ino_t inode, void * user_data) { - (void) inode; - (void) user_data; + struct wfp_static_filesystem * filesystem = user_data; + struct wfp_static_filesystem_entry * entry = wfp_static_filesystem_get_entry(filesystem, inode); - wfp_respond_error(request, WF_BAD_NOENTRY); + if (NULL != entry) + { + struct stat stat; + wfp_static_filesystem_stat(entry, &stat); + wfp_respond_getattr(request, &stat); + } + else + { + wfp_respond_error(request, WF_BAD_NOENTRY); + } } static void wfp_static_filesystem_readdir( @@ -56,10 +205,31 @@ static void wfp_static_filesystem_readdir( ino_t directory, void * user_data) { - (void) directory; - (void) user_data; + struct wfp_static_filesystem * filesystem = user_data; + struct wfp_static_filesystem_entry * dir = wfp_static_filesystem_get_entry(filesystem, directory); - wfp_respond_error(request, WF_BAD_NOENTRY); + if ((NULL != dir) && (!dir->is_file)) + { + struct wfp_dirbuffer * buffer = wfp_dirbuffer_create(); + wfp_dirbuffer_add(buffer, ".", dir->inode); + wfp_dirbuffer_add(buffer, "..", dir->inode); + + for(size_t i = 0; i < filesystem->size; i++) + { + struct wfp_static_filesystem_entry const * entry = &filesystem->entries[i]; + if (directory == entry->parent) + { + wfp_dirbuffer_add(buffer, entry->name, entry->inode); + } + } + + wfp_respond_readdir(request, buffer); + wfp_dirbuffer_dispose(buffer); + } + else + { + wfp_respond_error(request, WF_BAD_NOENTRY); + } } static void wfp_static_filesystem_open( @@ -106,14 +276,14 @@ wfp_impl_static_filesystem_create( filesystem->size = 0; filesystem->capacity = WFP_STATIC_FILESYSTEM_DEFAULT_CAPACITY; + wfp_static_filesystem_add_dir(filesystem, 0, ""); + wfp_client_config_set_userdata(config, filesystem); wfp_client_config_set_onlookup(config, &wfp_static_filesystem_lookup); wfp_client_config_set_ongetattr(config, &wfp_static_filesystem_getattr); wfp_client_config_set_onreaddir(config, &wfp_static_filesystem_readdir); wfp_client_config_set_onopen(config, &wfp_static_filesystem_open); wfp_client_config_set_onread(config, &wfp_static_filesystem_read); - - } return filesystem; @@ -123,6 +293,13 @@ void wfp_impl_static_filesystem_dispose( struct wfp_static_filesystem * filesystem) { + for(size_t i = 0; i < filesystem->size; i++) + { + struct wfp_static_filesystem_entry * entry = &filesystem->entries[i]; + free(entry->name); + free(entry->content); + } + free(filesystem->entries); free(filesystem); }