From ad798654df66dc9c2d5ad8c0cd93a7fbb200202e Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 3 Feb 2019 18:12:14 +0100 Subject: [PATCH] added implementation of low level functions lookup and readdir --- src/app/www/js/filesystem.js | 31 ++++++- src/app/www/js/filesystem_handler.js | 7 ++ src/wsfs/operation/ll_getattr.c | 4 - src/wsfs/operation/ll_lookup.c | 68 ++++++++++++++- src/wsfs/operation/ll_readdir.c | 125 +++++++++++++++++++++++++-- src/wsfs/operation/readdir.c | 8 +- 6 files changed, 224 insertions(+), 19 deletions(-) diff --git a/src/app/www/js/filesystem.js b/src/app/www/js/filesystem.js index 5cb0af4..e14290e 100644 --- a/src/app/www/js/filesystem.js +++ b/src/app/www/js/filesystem.js @@ -57,6 +57,26 @@ class FileSystem { } } + lookup(parent, name) { + const parentEntry = this._getEntry(parent); + const entry = (parentEntry && parentEntry.entries && parentEntry.entries[name]) || null; + if (entry) { + return { + inode: entry.inode, + mode: entry.mode || parseInt("755", 8), + type: entry.type || 'file', + size: entry.size || (entry.contents && entry.contents.length) || 0, + atime: entry.atime || 0, + mtime: entry.mtime || 0, + ctime: entry.ctime || 0 + }; + } + else { + return FileSystem.BAD_NOENTRY; + } + } + + getattr(path) { let entry = this._getEntry(path); if (entry) { @@ -79,9 +99,14 @@ class FileSystem { let entry = this._getEntry(path); if ((entry) && ("dir" === entry.type)) { - result = [".", ".."]; - for(let subdir of Object.keys(entry.entries)) { - result.push(subdir); + result = [ + {name: '.', inode: entry.inode}, + {name: '..', inode: 0} + ]; + for(let subdir of Object.entries(entry.entries)) { + const name = subdir[0]; + const inode = subdir[1].inode; + result.push({name: name, inode: inode}); } } diff --git a/src/app/www/js/filesystem_handler.js b/src/app/www/js/filesystem_handler.js index 796f156..be8b25d 100644 --- a/src/app/www/js/filesystem_handler.js +++ b/src/app/www/js/filesystem_handler.js @@ -22,6 +22,13 @@ class FileSystemHandler { (request.params)) { switch(request.method) { + case "lookup": + { + const parent = request.params[0]; + const name = request.params[1]; + result = this._fs.lookup(parent, name); + } + break; case "getattr": { const path = request.params[0]; diff --git a/src/wsfs/operation/ll_getattr.c b/src/wsfs/operation/ll_getattr.c index c0facf7..f0bcb64 100644 --- a/src/wsfs/operation/ll_getattr.c +++ b/src/wsfs/operation/ll_getattr.c @@ -1,9 +1,7 @@ #include "wsfs/operations.h" - #include #include -#include #include #include @@ -17,8 +15,6 @@ extern void wsfs_operation_ll_getattr ( fuse_ino_t inode, struct fuse_file_info * WSFS_UNUSED_PARAM(file_info)) { - printf("getattr: inode=%lu\n", inode); - struct fuse_ctx const * context = fuse_req_ctx(request); struct wsfs_operations_context * user_data = fuse_req_userdata(request); struct wsfs_jsonrpc * rpc = user_data->rpc; diff --git a/src/wsfs/operation/ll_lookup.c b/src/wsfs/operation/ll_lookup.c index 3041db4..f674248 100644 --- a/src/wsfs/operation/ll_lookup.c +++ b/src/wsfs/operation/ll_lookup.c @@ -1,15 +1,75 @@ #include "wsfs/operations.h" + #include -#include "wsfs/util.h" +#include -#include +#include +#include +#include + +#include "wsfs/jsonrpc.h" +#include "wsfs/util.h" void wsfs_operation_ll_lookup ( fuse_req_t request, fuse_ino_t parent, char const * name) { + struct fuse_ctx const * context = fuse_req_ctx(request); + struct wsfs_operations_context * user_data = fuse_req_userdata(request); + struct wsfs_jsonrpc * rpc = user_data->rpc; + + struct fuse_entry_param buffer; + json_t * data = NULL; + wsfs_status status = wsfs_jsonrpc_invoke(rpc, &data, "lookup", "is", parent, name); + if (NULL != data) + { + json_t * inode_holder = json_object_get(data, "inode"); + json_t * mode_holder = json_object_get(data, "mode"); + json_t * type_holder = json_object_get(data, "type"); + if ((NULL != inode_holder) && (json_is_integer(inode_holder)) && + (NULL != mode_holder) && (json_is_integer(mode_holder)) && + (NULL != type_holder) && (json_is_string(type_holder))) + { + memset(&buffer, 0, sizeof(struct stat)); + + buffer.ino = json_integer_value(inode_holder); + buffer.attr.st_mode = json_integer_value(mode_holder) & 0555; + char const * type = json_string_value(type_holder); + if (0 == strcmp("file", type)) + { + buffer.attr.st_mode |= S_IFREG; + } + else if (0 == strcmp("dir", type)) + { + buffer.attr.st_mode |= S_IFDIR; + } + + + buffer.attr_timeout = user_data->timeout; + buffer.entry_timeout = user_data->timeout; + buffer.attr.st_uid = context->uid; + buffer.attr.st_gid = context->gid; + buffer.attr.st_nlink = 1; + buffer.attr.st_size = wsfs_json_get_int(data, "size", 0); + buffer.attr.st_atime = wsfs_json_get_int(data, "atime", 0); + buffer.attr.st_mtime = wsfs_json_get_int(data, "mtime", 0); + buffer.attr.st_ctime = wsfs_json_get_int(data, "ctime", 0); + } + else + { + status = WSFS_BAD_FORMAT; + } + + json_decref(data); + } - printf("lookup: inode=%lu, name=%s\n", parent, name); - fuse_reply_err(request, ENOENT); + if (WSFS_GOOD == status) + { + fuse_reply_entry(request, &buffer); + } + else + { + fuse_reply_err(request, ENOENT); + } } diff --git a/src/wsfs/operation/ll_readdir.c b/src/wsfs/operation/ll_readdir.c index 97012b7..55c9888 100644 --- a/src/wsfs/operation/ll_readdir.c +++ b/src/wsfs/operation/ll_readdir.c @@ -1,16 +1,129 @@ #include "wsfs/operations.h" + +#include +#include #include + +#include +#include +#include + +#include "wsfs/jsonrpc.h" #include "wsfs/util.h" -#include + +#define WSFS_DIRBUFFER_INITIAL_SIZE 1024 + +struct wsfs_dirbuffer +{ + char * data; + size_t position; + size_t capacity; +}; + +static void wsfs_dirbuffer_init( + struct wsfs_dirbuffer * buffer) +{ + buffer->data = malloc(WSFS_DIRBUFFER_INITIAL_SIZE); + buffer->position = 0; + buffer->capacity = WSFS_DIRBUFFER_INITIAL_SIZE; +} + +static void wsfs_dirbuffer_dispose( + struct wsfs_dirbuffer * buffer) +{ + free(buffer->data); +} + +static void wsfs_dirbuffer_add( + fuse_req_t request, + struct wsfs_dirbuffer * buffer, + char const * name, + fuse_ino_t inode) +{ + size_t const size = fuse_add_direntry(request, NULL, 0, name, NULL, 0); + size_t remaining = buffer->capacity - buffer->position; + while (remaining < size) + { + buffer->capacity *= 2; + buffer->data = realloc(buffer->data, buffer->capacity); + remaining = buffer->capacity - buffer->position; + } + + struct stat stat_buffer; + memset(&stat_buffer, 0, sizeof(struct stat)); + stat_buffer.st_ino = inode; + fuse_add_direntry(request, + &buffer->data[buffer->position], remaining, name, + &stat_buffer, buffer->position + size); + buffer->position += size; +} + +static size_t min(size_t a, size_t b) +{ + return (a < b) ? a : b; +} void wsfs_operation_ll_readdir ( fuse_req_t request, - fuse_ino_t WSFS_UNUSED_PARAM(inode), - size_t WSFS_UNUSED_PARAM(size), - off_t WSFS_UNUSED_PARAM(offset), + fuse_ino_t inode, + size_t size, + off_t offset, struct fuse_file_info * WSFS_UNUSED_PARAM(file_info)) { - puts("readdir"); - fuse_reply_err(request, ENOENT); + struct wsfs_operations_context * user_data = fuse_req_userdata(request); + struct wsfs_jsonrpc * rpc = user_data->rpc; + + struct wsfs_dirbuffer buffer; + wsfs_dirbuffer_init(&buffer); + + json_t * result = NULL; + wsfs_status const status = wsfs_jsonrpc_invoke(rpc, &result, "readdir", "i", inode); + if (NULL != result) + { + if (json_is_array(result)) + { + bool buffer_full = false; + size_t const count = json_array_size(result); + for(size_t i = 0; (!buffer_full) && (i < count); i++) + { + json_t * entry =json_array_get(result, i); + if (json_is_object(entry)) + { + json_t * name_holder = json_object_get(entry, "name"); + json_t * inode_holder = json_object_get(entry, "inode"); + + if ((NULL != name_holder) && (json_is_string(name_holder)) && + (NULL != inode_holder) && (json_is_integer(inode_holder))) + { + char const * name = json_string_value(name_holder); + fuse_ino_t entry_inode = (fuse_ino_t) json_integer_value(inode_holder); + wsfs_dirbuffer_add(request, &buffer, name, entry_inode); + } + } + } + } + + json_decref(result); + } + + if (WSFS_GOOD == status) + { + if (((size_t) offset) < buffer.position) + { + fuse_reply_buf(request, &buffer.data[offset], + min(buffer.position - offset, size)); + } + else + { + fuse_reply_buf(request, NULL, 0); + } + + } + else + { + fuse_reply_err(request, ENOENT); + } + + wsfs_dirbuffer_dispose(&buffer); } diff --git a/src/wsfs/operation/readdir.c b/src/wsfs/operation/readdir.c index eaf53ab..dc6a10e 100644 --- a/src/wsfs/operation/readdir.c +++ b/src/wsfs/operation/readdir.c @@ -27,9 +27,13 @@ int wsfs_operation_readdir( for(size_t i = 0; (!buffer_full) && (i < count); i++) { json_t * entry =json_array_get(result, i); - if (json_is_string(entry)) + if (json_is_object(entry)) { - buffer_full = filler(buffer, json_string_value(entry), NULL, 0, 0); + json_t * name_holder = json_object_get(entry, "name"); + if ((NULL != name_holder) && (json_is_string(name_holder))) + { + buffer_full = filler(buffer, json_string_value(name_holder), NULL, 0, 0); + } } } }