diff --git a/CMakeLists.txt b/CMakeLists.txt index f008059..0221530 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,17 +44,12 @@ set(EXTRA_CFLAGS add_library(fuse-wsfs src/wsfs/status.c src/wsfs/operations.c + src/wsfs/operation/lookup.c src/wsfs/operation/getattr.c src/wsfs/operation/readdir.c src/wsfs/operation/open.c src/wsfs/operation/close.c src/wsfs/operation/read.c - src/wsfs/operation/ll_lookup.c - src/wsfs/operation/ll_getattr.c - src/wsfs/operation/ll_readdir.c - src/wsfs/operation/ll_open.c - src/wsfs/operation/ll_close.c - src/wsfs/operation/ll_read.c src/wsfs/response_parser.c src/wsfs/server.c src/wsfs/protocol.c diff --git a/src/app/main.c b/src/app/main.c index 46d9da1..b645246 100644 --- a/src/app/main.c +++ b/src/app/main.c @@ -139,7 +139,7 @@ int main(int argc, char * argv[]) wsfs_server_start(server); struct wsfs_jsonrpc * const rpc = wsfs_server_get_jsonrpc_service(server); - result = wsfs_operations_loop_ll(args.mount_point, rpc); + result = wsfs_operations_loop(args.mount_point, rpc); wsfs_server_dispose(server); } else diff --git a/src/app/www/js/filesystem.js b/src/app/www/js/filesystem.js index 19c2192..f2ef6c0 100644 --- a/src/app/www/js/filesystem.js +++ b/src/app/www/js/filesystem.js @@ -35,30 +35,10 @@ class FileSystem { } } } - - _getEntry(path) { - if ("number" === typeof(path)) { - const inode = path; - return this._inodes[inode]; - } - else { - let curItem = this.root; - - for(let item of path.split('/')) { - if ('' !== item) { - curItem = curItem.entries && curItem.entries[item]; - if (!curItem) { - return null; - } - } - } - - return curItem; - } - } - + + lookup(parent, name) { - const parentEntry = this._getEntry(parent); + const parentEntry = this._inodes[parent]; const entry = (parentEntry && parentEntry.entries && parentEntry.entries[name]) || null; if (entry) { return { @@ -77,8 +57,8 @@ class FileSystem { } - getattr(path) { - let entry = this._getEntry(path); + getattr(inode) { + let entry = this._inodes[inode]; if (entry) { return { mode: entry.mode || parseInt("755", 8), @@ -94,9 +74,9 @@ class FileSystem { } } - readdir(path) { + readdir(inode) { let result = FileSystem.BAD_NOENTRY; - let entry = this._getEntry(path); + let entry = this._inodes[inode]; if ((entry) && ("dir" === entry.type)) { result = [ @@ -113,9 +93,9 @@ class FileSystem { return result; } - open(path, mode) { + open(inode, mode) { let result = FileSystem.BAD_NOENTRY; - let entry = this._getEntry(path); + let entry = this._inodes[inode]; if (entry.type == "file") { result = ((mode & FileSystem.O_ACCMODE) == FileSystem.O_RDONLY) ? {handle: 1337} : FileSystem.BAD_NOACCESS; @@ -124,14 +104,14 @@ class FileSystem { return result; } - close(path, handle, mode) { + close(inode, handle, mode) { // do nothing return true; } - read(path, handle, offset, length) { + read(inode, handle, offset, length) { let result = FileSystem.BAD_NOENTRY; - let entry = this._getEntry(path); + let entry = this._inodes[inode]; if (entry.type == "file") { let end = Math.min(offset + length, entry.contents.length); diff --git a/src/app/www/js/filesystem_handler.js b/src/app/www/js/filesystem_handler.js index be8b25d..8b4d553 100644 --- a/src/app/www/js/filesystem_handler.js +++ b/src/app/www/js/filesystem_handler.js @@ -30,12 +30,6 @@ class FileSystemHandler { } break; case "getattr": - { - const path = request.params[0]; - result = this._fs.getattr(path); - } - break; - case "getattr_ll": { const inode = request.params[0]; result = this._fs.getattr(inode); @@ -43,32 +37,32 @@ class FileSystemHandler { break; case "readdir": { - const path = request.params[0]; - result = this._fs.readdir(path); + const inode = request.params[0]; + result = this._fs.readdir(inode); } break; case "open": { - const path = request.params[0]; + const inode = request.params[0]; const mode = request.params[1]; - result = this._fs.open(path, mode); + result = this._fs.open(inode, mode); } break; case "close": { - const path = request.params[0]; + const inode = request.params[0]; const handle = request.params[1]; const mode = request.params[2]; - result = this._fs.open(path, handle, mode); + result = this._fs.open(inode, handle, mode); } break; case "read": { - const path = request.params[0]; + const inode = request.params[0]; const handle = request.params[1]; const offset = request.params[2]; const length = request.params[3]; - result = this._fs.read(path, handle, offset, length); + result = this._fs.read(inode, handle, offset, length); } break; default: diff --git a/src/wsfs/operation/close.c b/src/wsfs/operation/close.c index cf4d945..78bc0c5 100644 --- a/src/wsfs/operation/close.c +++ b/src/wsfs/operation/close.c @@ -1,25 +1,30 @@ #include "wsfs/operations.h" #include - +#include #include -#include "wsfs/jsonrpc.h" -int wsfs_operation_close( - char const *path, +#include "wsfs/jsonrpc.h" +#include "wsfs/util.h" + + +void wsfs_operation_close( + fuse_req_t request, + fuse_ino_t inode, struct fuse_file_info * file_info) { - struct fuse_context * context = fuse_get_context(); - struct wsfs_jsonrpc * rpc = context->private_data; + struct wsfs_operations_context * user_data = fuse_req_userdata(request); + struct wsfs_jsonrpc * rpc = user_data->rpc; json_t * result = NULL; int handle = (int) (file_info->fh & INT_MAX); - wsfs_status const status = wsfs_jsonrpc_invoke(rpc, &result, "close", "sii", path, handle, file_info->flags); + wsfs_status const status = wsfs_jsonrpc_invoke(rpc, &result, "close", "iii", inode, handle, file_info->flags); if (NULL != result) { // unused json_decref(result); } - return wsfs_status_to_rc(status); + + fuse_reply_err(request, (WSFS_GOOD == status) ? 0 : ENOENT); } diff --git a/src/wsfs/operation/getattr.c b/src/wsfs/operation/getattr.c index 2f162cb..662dd11 100644 --- a/src/wsfs/operation/getattr.c +++ b/src/wsfs/operation/getattr.c @@ -1,25 +1,27 @@ #include "wsfs/operations.h" +#include #include -#include -#include -#include -#include +#include +#include +#include -#include "wsfs/util.h" #include "wsfs/jsonrpc.h" +#include "wsfs/util.h" -int wsfs_operation_getattr( - char const * path, - struct stat * buffer, +extern void wsfs_operation_getattr ( + fuse_req_t request, + fuse_ino_t inode, struct fuse_file_info * WSFS_UNUSED_PARAM(file_info)) { - struct fuse_context * const context = fuse_get_context(); - struct wsfs_jsonrpc * const rpc = context->private_data; + 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 stat buffer; json_t * data = NULL; - wsfs_status status = wsfs_jsonrpc_invoke(rpc, &data, "getattr", "s", path); + wsfs_status status = wsfs_jsonrpc_invoke(rpc, &data, "getattr", "i", inode); if (NULL != data) { json_t * mode_holder = json_object_get(data, "mode"); @@ -27,33 +29,42 @@ int wsfs_operation_getattr( if ((NULL != mode_holder) && (json_is_integer(mode_holder)) && (NULL != type_holder) && (json_is_string(type_holder))) { - buffer->st_mode = json_integer_value(mode_holder) & 0555; + memset(&buffer, 0, sizeof(struct stat)); + + buffer.st_mode = json_integer_value(mode_holder) & 0555; char const * type = json_string_value(type_holder); if (0 == strcmp("file", type)) { - buffer->st_mode |= S_IFREG; + buffer.st_mode |= S_IFREG; } else if (0 == strcmp("dir", type)) { - buffer->st_mode |= S_IFDIR; + buffer.st_mode |= S_IFDIR; } - buffer->st_uid = context->uid; - buffer->st_gid = context->gid; - buffer->st_nlink = 1; - buffer->st_size = wsfs_json_get_int(data, "size", 0); - buffer->st_atime = wsfs_json_get_int(data, "atime", 0); - buffer->st_mtime = wsfs_json_get_int(data, "mtime", 0); - buffer->st_ctime = wsfs_json_get_int(data, "ctime", 0); + buffer.st_uid = context->uid; + buffer.st_gid = context->gid; + buffer.st_nlink = 1; + buffer.st_size = wsfs_json_get_int(data, "size", 0); + buffer.st_atime = wsfs_json_get_int(data, "atime", 0); + buffer.st_mtime = wsfs_json_get_int(data, "mtime", 0); + buffer.st_ctime = wsfs_json_get_int(data, "ctime", 0); + } else { - status = WSFS_BAD_FORMAT; + status = WSFS_BAD_FORMAT; } - json_decref(data); } - return wsfs_status_to_rc(status); + if (WSFS_GOOD == status) + { + fuse_reply_attr(request, &buffer, user_data->timeout); + } + else + { + fuse_reply_err(request, ENOENT); + } } diff --git a/src/wsfs/operation/ll_close.c b/src/wsfs/operation/ll_close.c deleted file mode 100644 index 6d22302..0000000 --- a/src/wsfs/operation/ll_close.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "wsfs/operations.h" - -#include -#include -#include - -#include "wsfs/jsonrpc.h" -#include "wsfs/util.h" - - -void wsfs_operation_ll_close( - fuse_req_t request, - fuse_ino_t inode, - struct fuse_file_info * file_info) -{ - struct wsfs_operations_context * user_data = fuse_req_userdata(request); - struct wsfs_jsonrpc * rpc = user_data->rpc; - - json_t * result = NULL; - int handle = (int) (file_info->fh & INT_MAX); - wsfs_status const status = wsfs_jsonrpc_invoke(rpc, &result, "close", "iii", inode, handle, file_info->flags); - if (NULL != result) - { - // unused - json_decref(result); - } - - - fuse_reply_err(request, (WSFS_GOOD == status) ? 0 : ENOENT); -} diff --git a/src/wsfs/operation/ll_getattr.c b/src/wsfs/operation/ll_getattr.c deleted file mode 100644 index f0bcb64..0000000 --- a/src/wsfs/operation/ll_getattr.c +++ /dev/null @@ -1,70 +0,0 @@ -#include "wsfs/operations.h" - -#include -#include - -#include -#include -#include - -#include "wsfs/jsonrpc.h" -#include "wsfs/util.h" - -extern void wsfs_operation_ll_getattr ( - fuse_req_t request, - fuse_ino_t inode, - struct fuse_file_info * WSFS_UNUSED_PARAM(file_info)) -{ - 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 stat buffer; - json_t * data = NULL; - wsfs_status status = wsfs_jsonrpc_invoke(rpc, &data, "getattr", "i", inode); - if (NULL != data) - { - json_t * mode_holder = json_object_get(data, "mode"); - json_t * type_holder = json_object_get(data, "type"); - if ((NULL != mode_holder) && (json_is_integer(mode_holder)) && - (NULL != type_holder) && (json_is_string(type_holder))) - { - memset(&buffer, 0, sizeof(struct stat)); - - buffer.st_mode = json_integer_value(mode_holder) & 0555; - char const * type = json_string_value(type_holder); - if (0 == strcmp("file", type)) - { - buffer.st_mode |= S_IFREG; - } - else if (0 == strcmp("dir", type)) - { - buffer.st_mode |= S_IFDIR; - } - - buffer.st_uid = context->uid; - buffer.st_gid = context->gid; - buffer.st_nlink = 1; - buffer.st_size = wsfs_json_get_int(data, "size", 0); - buffer.st_atime = wsfs_json_get_int(data, "atime", 0); - buffer.st_mtime = wsfs_json_get_int(data, "mtime", 0); - buffer.st_ctime = wsfs_json_get_int(data, "ctime", 0); - - } - else - { - status = WSFS_BAD_FORMAT; - } - - json_decref(data); - } - - if (WSFS_GOOD == status) - { - fuse_reply_attr(request, &buffer, user_data->timeout); - } - else - { - fuse_reply_err(request, ENOENT); - } -} diff --git a/src/wsfs/operation/ll_open.c b/src/wsfs/operation/ll_open.c deleted file mode 100644 index 0a68c60..0000000 --- a/src/wsfs/operation/ll_open.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "wsfs/operations.h" - -#include -#include - -#include "wsfs/jsonrpc.h" -#include "wsfs/util.h" - -void wsfs_operation_ll_open( - fuse_req_t request, - fuse_ino_t inode, - struct fuse_file_info * file_info) -{ - struct wsfs_operations_context * user_data = fuse_req_userdata(request); - struct wsfs_jsonrpc * rpc = user_data->rpc; - - json_t * result = NULL; - wsfs_status status = wsfs_jsonrpc_invoke(rpc, &result, "open", "ii", inode, file_info->flags); - if (NULL != result) - { - json_t * handle_holder = json_object_get(result, "handle"); - if ((NULL != handle_holder) && (json_is_integer(handle_holder))) - { - file_info->fh = json_integer_value(handle_holder); - } - else - { - status = WSFS_BAD_FORMAT; - } - - json_decref(result); - } - - if (WSFS_GOOD == status) - { - fuse_reply_open(request, file_info); - } - else - { - fuse_reply_err(request, ENOENT); - } -} diff --git a/src/wsfs/operation/ll_read.c b/src/wsfs/operation/ll_read.c deleted file mode 100644 index 0450f67..0000000 --- a/src/wsfs/operation/ll_read.c +++ /dev/null @@ -1,87 +0,0 @@ -#include "wsfs/operations.h" - -#include -#include -#include -#include - -#include "wsfs/jsonrpc.h" - -#define WSFS_MAX_READ_LENGTH 4096 - -static wsfs_status wsfs_fill_buffer( - char * buffer, - size_t buffer_size, - char const * format, - char const * data, - size_t count) -{ - wsfs_status status = WSFS_GOOD; - - size_t const copy_count = (buffer_size < count) ? buffer_size : count; - if (0 < copy_count) - { - if (0 == strcmp("identity", format)) - { - memcpy(buffer, data, copy_count); - } - else - { - status = WSFS_BAD; - } - } - - return status; -} - -void wsfs_operation_ll_read( - fuse_req_t request, - fuse_ino_t inode, - size_t size, - off_t offset, - struct fuse_file_info * file_info) -{ - struct wsfs_operations_context * user_data = fuse_req_userdata(request); - struct wsfs_jsonrpc * rpc = user_data->rpc; - - int const length = (size <= WSFS_MAX_READ_LENGTH) ? (int) size : WSFS_MAX_READ_LENGTH; - char * buffer = malloc(length); - size_t count = 0; - json_t * data = NULL; - int handle = (file_info->fh & INT_MAX); - wsfs_status status = wsfs_jsonrpc_invoke(rpc, &data, "read", "iiii", inode, handle, (int) offset, length); - if (NULL != data) - { - json_t * data_holder = json_object_get(data, "data"); - json_t * format_holder = json_object_get(data, "format"); - json_t * count_holder = json_object_get(data, "count"); - - if ((NULL != data_holder) && (json_is_string(data_holder)) && - (NULL != format_holder) && (json_is_string(format_holder)) && - (NULL != count_holder) && (json_is_integer(count_holder))) - { - char const * const data = json_string_value(data_holder); - char const * const format = json_string_value(format_holder); - count = (size_t) json_integer_value(count_holder); - - status = wsfs_fill_buffer(buffer, length, format, data, count); - } - else - { - status = WSFS_BAD_FORMAT; - } - - json_decref(data); - } - - if (WSFS_GOOD == status) - { - fuse_reply_buf(request, buffer, count); - } - else - { - fuse_reply_err(request, ENOENT); - } - - free(buffer); -} diff --git a/src/wsfs/operation/ll_readdir.c b/src/wsfs/operation/ll_readdir.c deleted file mode 100644 index 55c9888..0000000 --- a/src/wsfs/operation/ll_readdir.c +++ /dev/null @@ -1,129 +0,0 @@ -#include "wsfs/operations.h" - -#include -#include -#include - -#include -#include -#include - -#include "wsfs/jsonrpc.h" -#include "wsfs/util.h" - - -#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 inode, - size_t size, - off_t offset, - struct fuse_file_info * WSFS_UNUSED_PARAM(file_info)) -{ - 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/ll_lookup.c b/src/wsfs/operation/lookup.c similarity index 98% rename from src/wsfs/operation/ll_lookup.c rename to src/wsfs/operation/lookup.c index f674248..20ad879 100644 --- a/src/wsfs/operation/ll_lookup.c +++ b/src/wsfs/operation/lookup.c @@ -10,7 +10,7 @@ #include "wsfs/jsonrpc.h" #include "wsfs/util.h" -void wsfs_operation_ll_lookup ( +void wsfs_operation_lookup ( fuse_req_t request, fuse_ino_t parent, char const * name) diff --git a/src/wsfs/operation/open.c b/src/wsfs/operation/open.c index 2e307b0..c6d2026 100644 --- a/src/wsfs/operation/open.c +++ b/src/wsfs/operation/open.c @@ -1,17 +1,21 @@ #include "wsfs/operations.h" +#include #include -#include "wsfs/jsonrpc.h" -int wsfs_operation_open( - char const *path, +#include "wsfs/jsonrpc.h" +#include "wsfs/util.h" + +void wsfs_operation_open( + fuse_req_t request, + fuse_ino_t inode, struct fuse_file_info * file_info) { - struct fuse_context * context = fuse_get_context(); - struct wsfs_jsonrpc * rpc = context->private_data; + struct wsfs_operations_context * user_data = fuse_req_userdata(request); + struct wsfs_jsonrpc * rpc = user_data->rpc; json_t * result = NULL; - wsfs_status status = wsfs_jsonrpc_invoke(rpc, &result, "open", "si", path, file_info->flags); + wsfs_status status = wsfs_jsonrpc_invoke(rpc, &result, "open", "ii", inode, file_info->flags); if (NULL != result) { json_t * handle_holder = json_object_get(result, "handle"); @@ -27,5 +31,12 @@ int wsfs_operation_open( json_decref(result); } - return wsfs_status_to_rc(status); + if (WSFS_GOOD == status) + { + fuse_reply_open(request, file_info); + } + else + { + fuse_reply_err(request, ENOENT); + } } diff --git a/src/wsfs/operation/read.c b/src/wsfs/operation/read.c index 266c442..9d91acc 100644 --- a/src/wsfs/operation/read.c +++ b/src/wsfs/operation/read.c @@ -1,5 +1,6 @@ #include "wsfs/operations.h" +#include #include #include #include @@ -33,21 +34,22 @@ static wsfs_status wsfs_fill_buffer( return status; } -int wsfs_operation_read( - const char * path, - char * buffer, - size_t buffer_size, - off_t offset, +void wsfs_operation_read( + fuse_req_t request, + fuse_ino_t inode, + size_t size, + off_t offset, struct fuse_file_info * file_info) { - struct fuse_context * context = fuse_get_context(); - struct wsfs_jsonrpc * rpc = context->private_data; + struct wsfs_operations_context * user_data = fuse_req_userdata(request); + struct wsfs_jsonrpc * rpc = user_data->rpc; - int const length = (buffer_size <= WSFS_MAX_READ_LENGTH) ? (int) buffer_size : WSFS_MAX_READ_LENGTH; - int result = 0; + int const length = (size <= WSFS_MAX_READ_LENGTH) ? (int) size : WSFS_MAX_READ_LENGTH; + char * buffer = malloc(length); + size_t count = 0; json_t * data = NULL; int handle = (file_info->fh & INT_MAX); - wsfs_status status = wsfs_jsonrpc_invoke(rpc, &data, "read", "siii", path, handle, (int) offset, length); + wsfs_status status = wsfs_jsonrpc_invoke(rpc, &data, "read", "iiii", inode, handle, (int) offset, length); if (NULL != data) { json_t * data_holder = json_object_get(data, "data"); @@ -60,13 +62,9 @@ int wsfs_operation_read( { char const * const data = json_string_value(data_holder); char const * const format = json_string_value(format_holder); - int const count = json_integer_value(count_holder); + count = (size_t) json_integer_value(count_holder); - status = wsfs_fill_buffer(buffer, buffer_size, format, data, count); - if (WSFS_GOOD == status) - { - result = count; - } + status = wsfs_fill_buffer(buffer, length, format, data, count); } else { @@ -76,10 +74,14 @@ int wsfs_operation_read( json_decref(data); } - if (WSFS_GOOD != status) + if (WSFS_GOOD == status) { - result = wsfs_status_to_rc(status); + fuse_reply_buf(request, buffer, count); } - - return result; + else + { + fuse_reply_err(request, ENOENT); + } + + free(buffer); } diff --git a/src/wsfs/operation/readdir.c b/src/wsfs/operation/readdir.c index dc6a10e..903d1ab 100644 --- a/src/wsfs/operation/readdir.c +++ b/src/wsfs/operation/readdir.c @@ -1,23 +1,84 @@ #include "wsfs/operations.h" -#include +#include +#include +#include + +#include +#include +#include -#include "wsfs/util.h" #include "wsfs/jsonrpc.h" +#include "wsfs/util.h" -int wsfs_operation_readdir( - char const * path, - void * buffer, - fuse_fill_dir_t filler, - off_t WSFS_UNUSED_PARAM(offset), - struct fuse_file_info * WSFS_UNUSED_PARAM(file_info), - enum fuse_readdir_flags WSFS_UNUSED_PARAM(flags)) + +#define WSFS_DIRBUFFER_INITIAL_SIZE 1024 + +struct wsfs_dirbuffer { - struct fuse_context * context = fuse_get_context(); - struct wsfs_jsonrpc * rpc = context->private_data; + 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_readdir ( + fuse_req_t request, + fuse_ino_t inode, + size_t size, + off_t offset, + struct fuse_file_info * WSFS_UNUSED_PARAM(file_info)) +{ + 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", "s", path); + wsfs_status const status = wsfs_jsonrpc_invoke(rpc, &result, "readdir", "i", inode); if (NULL != result) { if (json_is_array(result)) @@ -30,9 +91,14 @@ int wsfs_operation_readdir( if (json_is_object(entry)) { json_t * name_holder = json_object_get(entry, "name"); - if ((NULL != name_holder) && (json_is_string(name_holder))) + 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))) { - buffer_full = filler(buffer, json_string_value(name_holder), NULL, 0, 0); + 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); } } } @@ -40,6 +106,24 @@ int wsfs_operation_readdir( json_decref(result); } - - return wsfs_status_to_rc(status); -} \ No newline at end of file + + 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/operations.c b/src/wsfs/operations.c index 05838ef..c9f713b 100644 --- a/src/wsfs/operations.c +++ b/src/wsfs/operations.c @@ -2,56 +2,18 @@ #include -#include "wsfs/util.h" -#include "wsfs/jsonrpc.h" - -static void* wsfs_operation_init( - struct fuse_conn_info * WSFS_UNUSED_PARAM(connection), - struct fuse_config * config) -{ - struct fuse_context * const context = fuse_get_context(); - config->kernel_cache = 1; - - return context->private_data; -} - -static void wsfs_operations_init( - struct fuse_operations * operations) -{ - memset(operations, 0, sizeof(struct fuse_operations)); - operations->init = &wsfs_operation_init; - operations->getattr = &wsfs_operation_getattr; - operations->readdir = &wsfs_operation_readdir; - operations->open = &wsfs_operation_open; - operations->release = &wsfs_operation_close; - operations->read = &wsfs_operation_read; -} - int wsfs_operations_loop( char * mount_point, struct wsfs_jsonrpc * rpc) -{ - struct fuse_operations operations; - wsfs_operations_init(&operations); - - char * fuse_args[] = { "app", "-s", "-f", mount_point, NULL }; - int const result = fuse_main(4, fuse_args, &operations, rpc); - - return result; -} - -int wsfs_operations_loop_ll( - char * mount_point, - struct wsfs_jsonrpc * rpc) { struct fuse_lowlevel_ops operations; memset(&operations, 0, sizeof(struct fuse_lowlevel_ops)); - operations.lookup = &wsfs_operation_ll_lookup; - operations.getattr = &wsfs_operation_ll_getattr; - operations.readdir = &wsfs_operation_ll_readdir; - operations.open = &wsfs_operation_ll_open; - operations.release = &wsfs_operation_ll_close; - operations.read = &wsfs_operation_ll_read; + operations.lookup = &wsfs_operation_lookup; + operations.getattr = &wsfs_operation_getattr; + operations.readdir = &wsfs_operation_readdir; + operations.open = &wsfs_operation_open; + operations.release = &wsfs_operation_close; + operations.read = &wsfs_operation_read; int result = 1; const int argc = 1; diff --git a/src/wsfs/operations.h b/src/wsfs/operations.h index 14b3c65..dea1c50 100644 --- a/src/wsfs/operations.h +++ b/src/wsfs/operations.h @@ -19,68 +19,34 @@ extern int wsfs_operations_loop( char * mount_point, struct wsfs_jsonrpc * rpc); -extern int wsfs_operation_readdir( - char const * path, - void * buffer, - fuse_fill_dir_t filler, - off_t offset, - struct fuse_file_info * file_info, - enum fuse_readdir_flags flags); - -extern int wsfs_operation_getattr( - char const * path, - struct stat * buffer, - struct fuse_file_info * file_info); - -extern int wsfs_operation_open( - char const *path, - struct fuse_file_info * file_info); - -extern int wsfs_operation_close( - char const *path, - struct fuse_file_info * file_info); - -extern int wsfs_operation_read( - const char * path, - char * buffer, - size_t buffer_size, - off_t offset, - struct fuse_file_info * file_info); - -// low level operations - -extern int wsfs_operations_loop_ll( - char * mount_point, - struct wsfs_jsonrpc * rpc); - -extern void wsfs_operation_ll_lookup ( +extern void wsfs_operation_lookup ( fuse_req_t req, fuse_ino_t parent, char const * name); -extern void wsfs_operation_ll_getattr ( +extern void wsfs_operation_getattr ( fuse_req_t request, fuse_ino_t inode, struct fuse_file_info *file_info); -extern void wsfs_operation_ll_readdir ( +extern void wsfs_operation_readdir ( fuse_req_t request, fuse_ino_t inode, size_t size, off_t offset, struct fuse_file_info *file_info); -extern void wsfs_operation_ll_open( +extern void wsfs_operation_open( fuse_req_t request, fuse_ino_t inode, struct fuse_file_info * file_info); -extern void wsfs_operation_ll_close( +extern void wsfs_operation_close( fuse_req_t request, fuse_ino_t inode, struct fuse_file_info * file_info); -extern void wsfs_operation_ll_read( +extern void wsfs_operation_read( fuse_req_t request, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi);