From 59caed8600bd807801ce08e8e3ad1b74bd9cdf45 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 27 Jan 2019 12:01:01 +0100 Subject: [PATCH] basic implementation of read added --- src/app/www/script.js | 66 +++++++++++++++++++++++++--- src/wsfs/filesystem.c | 90 +++++++++++++++++++++++++++++++++++++- src/wsfs/filesystem.h | 11 +++++ src/wsfs/operations.c | 35 +++++++++++++++ src/wsfs/response_parser.c | 6 +-- src/wsfs/status.h | 12 ++--- 6 files changed, 203 insertions(+), 17 deletions(-) diff --git a/src/app/www/script.js b/src/app/www/script.js index 2682c80..f5dee78 100644 --- a/src/app/www/script.js +++ b/src/app/www/script.js @@ -4,7 +4,25 @@ function startup() this.root = root; }; - FileSystem.BAD_NO_ENTRY = -1; + FileSystem.GOOD = 0; + FileSystem.BAD = 1; + + FileSystem.BAD_NOTIMPLEMENTED = 2; + FileSystem.BAD_TIMEOUT = 3; + FileSystem.BAD_FORMAT = 4; + + FileSystem.BAD_NOENTRY = 101; + FileSystem.BAD_NOACCESS = 102; + + FileSystem.O_ACCMODE = 00003; + FileSystem.O_RDONLY = 00000; + FileSystem.O_WRONLY = 00001; + FileSystem.O_RDWR = 00002; + FileSystem.O_CREAT = 00100; + FileSystem.O_EXCL = 00200; + FileSystem.O_TRUNK = 01000; + FileSystem.O_APPEND = 02000; + FileSystem.prototype.getEntry = function(path) { var items = path.split('/'); @@ -28,14 +46,14 @@ function startup() return { mode: entry.mode || 0755, type: entry.type || 'file', - size: entry.size || 0, + 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_NO_ENTRY; + return FileSystem.BAD_NOENTRY; } }; @@ -52,17 +70,45 @@ function startup() } } else { - result = FileSystem.BAD_NO_ENTRY; + result = FileSystem.BAD_NOENTRY; } return result; }; + FileSystem.prototype.open = function(path, mode) { + var result = FileSystem.BAD_NOENTRY; + var entry = this.getEntry(path); + + if (entry.type == "file") { + result = ((mode & FileSystem.O_ACCMODE) == FileSystem.O_RDONLY) ? true : FileSystem.BAD_NOACCESS; + } + + return result; + }; + + FileSystem.prototype.read = function(path, offset, length) { + var result = FileSystem.BAD_NOENTRY; + var entry = this.getEntry(path); + + if (entry.type == "file") { + var end = Math.min(offset + length, entry.contents.length); + var data = (offset < entry.contents.length) ? entry.contents.substring(offset, end) : ""; + result = { + data: data, + format: "identity", + count: data.length + }; + } + + return result; + }; + var fs = new FileSystem({ mode: 0755, type: "dir", entries: { - "hello": { mode: 0755, type: "file", size: 10, contents: "Hello, World!"} + "hello": { mode: 0755, type: "file", /* size: 10 , */contents: "Hello, World!"} } }); @@ -74,13 +120,13 @@ function startup() console.log('close'); }; ws.onmessage = function(message) { - console.log(message); try { var request = JSON.parse(message.data); var result = -42; var response; + console.log(request); if (("string" === typeof(request.method)) && ("number" === typeof(request.id)) && (request.params)) { @@ -92,6 +138,12 @@ function startup() case "readdir": result = fs.readdir(request.params[0]); break; + case "open": + result = fs.open(request.params[0], request.params[1]); + break; + case "read": + result = fs.read(request.params[0], request.params[1], request.params[2]); + break; default: break; } @@ -106,7 +158,7 @@ function startup() ws.send(JSON.stringify(response)); } } - catch (ex) { console.log(ex); } + catch (ex) { console.log(ex, message); } }; var sendButton = document.getElementById('sendButton'); diff --git a/src/wsfs/filesystem.c b/src/wsfs/filesystem.c index 590123d..603f8ef 100644 --- a/src/wsfs/filesystem.c +++ b/src/wsfs/filesystem.c @@ -69,13 +69,14 @@ wsfs_status wsfs_filesystem_getattr( result->st_mode |= S_IFDIR; } + result->st_size = wsfs_json_get_int(data, "size", 0); result->st_atime = wsfs_json_get_int(data, "atime", 0); result->st_mtime = wsfs_json_get_int(data, "mtime", 0); result->st_ctime = wsfs_json_get_int(data, "ctime", 0); } else { - status = WSFS_BAD_PARSEERROR; + status = WSFS_BAD_FORMAT; } @@ -115,3 +116,90 @@ wsfs_status wsfs_filesystem_readdir( return status; } +wsfs_status wsfs_filesystem_open( + struct wsfs_filesystem * filesystem, + char const * path, + int flags) +{ + json_t * result = NULL; + wsfs_status const status = wsfs_jsonrpc_invoke(filesystem->rpc, &result, "open", "si", path, flags); + if (NULL != result) + { + // unused + json_decref(result); + } + + return status; +} + +#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; +} + +wsfs_status wsfs_filesystem_read( + struct wsfs_filesystem * filesystem, + char const * path, + char * buffer, + size_t buffer_size, + size_t offset, + size_t * read_count) +{ + int const length = (buffer_size <= WSFS_MAX_READ_LENGTH) ? (int) buffer_size : WSFS_MAX_READ_LENGTH; + *read_count = 0; + + json_t * result = NULL; + wsfs_status status = wsfs_jsonrpc_invoke(filesystem->rpc, &result, "read", "sii", path, (int) offset, length); + if (NULL != result) + { + json_t * data_holder = json_object_get(result, "data"); + json_t * format_holder = json_object_get(result, "format"); + json_t * count_holder = json_object_get(result, "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); + size_t const count = (size_t) json_integer_value(count_holder); + + status = wsfs_fill_buffer(buffer, buffer_size, format, data, count); + if (WSFS_GOOD == status) + { + *read_count = count; + } + } + else + { + status = WSFS_BAD_FORMAT; + } + + json_decref(result); + } + + return status; +} + diff --git a/src/wsfs/filesystem.h b/src/wsfs/filesystem.h index 1ffe5fe..fecc6e5 100644 --- a/src/wsfs/filesystem.h +++ b/src/wsfs/filesystem.h @@ -32,7 +32,18 @@ extern wsfs_status wsfs_filesystem_readdir( void * buffer, wsfs_add_entry_fn * add_entry); +extern wsfs_status wsfs_filesystem_open( + struct wsfs_filesystem * filesystem, + char const * path, + int flags); +extern wsfs_status wsfs_filesystem_read( + struct wsfs_filesystem * filesystem, + char const * path, + char * buffer, + size_t buffer_size, + size_t offset, + size_t * read_count); #endif diff --git a/src/wsfs/operations.c b/src/wsfs/operations.c index 528f347..63a3a29 100644 --- a/src/wsfs/operations.c +++ b/src/wsfs/operations.c @@ -19,6 +19,7 @@ static int wsfs_result_from_status(wsfs_status status) { case WSFS_GOOD: return 0; case WSFS_BAD_NOENTRY: return -ENOENT; + case WSFS_BAD_NOACCESS: return -EACCES; default: return -ENOENT; } } @@ -93,6 +94,38 @@ static int wsfs_operation_readdir( return wsfs_result_from_status(status); } +static int wsfs_operation_open( + char const *path, + struct fuse_file_info * file_info) +{ + struct wsfs_filesystem * filesystem = wsfs_get_filesystem(); + wsfs_status const status = wsfs_filesystem_open(filesystem, path, file_info->flags); + + return wsfs_result_from_status(status); +} + +static int wsfs_operation_read( + const char * path, + char * buffer, + size_t buffer_size, + off_t offset, + struct fuse_file_info * WSFS_UNUSED_PARAM(file_info)) +{ + struct wsfs_filesystem * filesystem = wsfs_get_filesystem(); + + size_t count; + wsfs_status const status = wsfs_filesystem_read(filesystem, path, buffer, buffer_size, offset, &count); + if (WSFS_GOOD == status) + { + return count; + } + else + { + return wsfs_result_from_status(status); + } + +} + void wsfs_operations_init( struct fuse_operations * operations) { @@ -101,5 +134,7 @@ void wsfs_operations_init( operations->destroy = &wsfs_operation_destroy; operations->getattr = &wsfs_operation_getattr; operations->readdir = &wsfs_operation_readdir; + operations->open = &wsfs_operation_open; + operations->read = &wsfs_operation_read; } diff --git a/src/wsfs/response_parser.c b/src/wsfs/response_parser.c index f77bf6f..320e94c 100644 --- a/src/wsfs/response_parser.c +++ b/src/wsfs/response_parser.c @@ -12,14 +12,14 @@ void wsfs_response_parse( json_t * response = json_loadb(buffer, length, 0, NULL); if (NULL == response) { - result->status = WSFS_BAD_PARSEERROR; + result->status = WSFS_BAD_FORMAT; return; } json_t * id_holder = json_object_get(response, "id"); if ((NULL == id_holder) || (!json_is_integer(id_holder))) { - result->status = WSFS_BAD_INVALIDID; + result->status = WSFS_BAD_FORMAT; json_decref(response); return; } @@ -33,7 +33,7 @@ void wsfs_response_parse( } else { - result->status = WSFS_BAD_NODATA; + result->status = WSFS_BAD_FORMAT; json_t * error = json_object_get(response, "error"); if (NULL != error) diff --git a/src/wsfs/status.h b/src/wsfs/status.h index 6e7c3f2..134e287 100644 --- a/src/wsfs/status.h +++ b/src/wsfs/status.h @@ -2,14 +2,14 @@ #define _WSFS_STATUS_H #define WSFS_GOOD 0 -#define WSFS_BAD 1 +#define WSFS_BAD 1 + +#define WSFS_BAD_NOTIMPLEMENTED 2 +#define WSFS_BAD_TIMEOUT 3 +#define WSFS_BAD_FORMAT 4 #define WSFS_BAD_NOENTRY 101 -#define WSFS_BAD_TIMEOUT 102 - -#define WSFS_BAD_PARSEERROR 200 -#define WSFS_BAD_INVALIDID 201 -#define WSFS_BAD_NODATA 202 +#define WSFS_BAD_NOACCESS 102 typedef int wsfs_status;