diff --git a/CMakeLists.txt b/CMakeLists.txt index 577f132..781d24e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,8 +36,12 @@ set(EXTRA_CFLAGS # libfuse-wsfs add_library(fuse-wsfs + src/wsfs/status.c src/wsfs/operations.c - src/wsfs/filesystem.c + src/wsfs/operation/getattr.c + src/wsfs/operation/readdir.c + src/wsfs/operation/open.c + src/wsfs/operation/read.c src/wsfs/response_parser.c src/wsfs/server.c src/wsfs/protocol.c diff --git a/src/wsfs/filesystem.c b/src/wsfs/filesystem.c deleted file mode 100644 index 603f8ef..0000000 --- a/src/wsfs/filesystem.c +++ /dev/null @@ -1,205 +0,0 @@ -#include "wsfs/filesystem.h" - -#include -#include -#include -#include - -#include "wsfs/util.h" -#include "wsfs/jsonrpc.h" - -struct wsfs_filesystem -{ - struct wsfs_jsonrpc * rpc; -}; - -struct wsfs_filesystem * wsfs_filesystem_create( - struct wsfs_jsonrpc * rpc) -{ - struct wsfs_filesystem * filesystem = malloc(sizeof(struct wsfs_filesystem)); - if (NULL != filesystem) - { - filesystem->rpc = rpc; - } - - return filesystem; -} - -void wsfs_filesystem_dispose( - struct wsfs_filesystem * filesystem) -{ - free(filesystem); -} - -static int wsfs_json_get_int(json_t * object, char const * key, int default_value) -{ - int result = default_value; - - json_t * holder = json_object_get(object, key); - if ((NULL != holder) && (json_is_integer(holder))) - { - result = json_integer_value(holder); - } - - return result; -} - -wsfs_status wsfs_filesystem_getattr( - struct wsfs_filesystem * filesystem, - char const * path, - struct stat * result) -{ - json_t * data = NULL; - wsfs_status status = wsfs_jsonrpc_invoke(filesystem->rpc, &data, "getattr", "s", path); - if (NULL != result) - { - 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))) - { - result->st_mode = json_integer_value(mode_holder) & 0777; - char const * type = json_string_value(type_holder); - if (0 == strcmp("file", type)) - { - result->st_mode |= S_IFREG; - } - else if (0 == strcmp("dir", type)) - { - 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_FORMAT; - } - - - json_decref(data); - } - - return status; -} - -wsfs_status wsfs_filesystem_readdir( - struct wsfs_filesystem * filesystem, - char const * path, - void * buffer, - wsfs_add_entry_fn * add_entry) -{ - json_t * result = NULL; - wsfs_status const status = wsfs_jsonrpc_invoke(filesystem->rpc, &result, "readdir", "s", path); - if (NULL != result) - { - if (json_is_array(result)) - { - bool has_capacity = true; - size_t const count = json_array_size(result); - for(size_t i = 0; (has_capacity) && (i < count); i++) - { - json_t * entry =json_array_get(result, i); - if (json_is_string(entry)) - { - has_capacity = add_entry(buffer, json_string_value(entry)); - } - } - } - - json_decref(result); - } - - 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 deleted file mode 100644 index fecc6e5..0000000 --- a/src/wsfs/filesystem.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _WSFS_FILESYSTEM_H -#define _WSFS_FILESYSTEM_H - -#include - -#include -#include -#include - -#include "wsfs/status.h" - - -struct wsfs_filesystem; -struct wsfs_jsonrpc; - -typedef bool wsfs_add_entry_fn(void * buffer, char const * path); - -extern struct wsfs_filesystem * wsfs_filesystem_create( - struct wsfs_jsonrpc * service); - -extern void wsfs_filesystem_dispose( - struct wsfs_filesystem * filesystem); - -extern wsfs_status wsfs_filesystem_getattr( - struct wsfs_filesystem * filesystem, - char const * path, - struct stat * result); - -extern wsfs_status wsfs_filesystem_readdir( - struct wsfs_filesystem * filesystem, - char const * path, - 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/operation/getattr.c b/src/wsfs/operation/getattr.c new file mode 100644 index 0000000..d4b563d --- /dev/null +++ b/src/wsfs/operation/getattr.c @@ -0,0 +1,72 @@ +#include "wsfs/operations.h" + +#include +#include +#include +#include + +#include + +#include "wsfs/util.h" +#include "wsfs/jsonrpc.h" + +static int wsfs_json_get_int(json_t * object, char const * key, int default_value) +{ + int result = default_value; + + json_t * holder = json_object_get(object, key); + if ((NULL != holder) && (json_is_integer(holder))) + { + result = json_integer_value(holder); + } + + return result; +} + +int wsfs_operation_getattr( + char const * path, + struct stat * buffer, + 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; + + json_t * data = NULL; + wsfs_status status = wsfs_jsonrpc_invoke(rpc, &data, "getattr", "s", path); + 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))) + { + 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); + } + + return wsfs_status_to_rc(status); +} diff --git a/src/wsfs/operation/open.c b/src/wsfs/operation/open.c new file mode 100644 index 0000000..0cf1d2d --- /dev/null +++ b/src/wsfs/operation/open.c @@ -0,0 +1,22 @@ +#include "wsfs/operations.h" + +#include +#include "wsfs/jsonrpc.h" + +int wsfs_operation_open( + char const *path, + struct fuse_file_info * file_info) +{ + struct fuse_context * context = fuse_get_context(); + struct wsfs_jsonrpc * rpc = context->private_data; + + json_t * result = NULL; + wsfs_status const status = wsfs_jsonrpc_invoke(rpc, &result, "open", "si", path, file_info->flags); + if (NULL != result) + { + // unused + json_decref(result); + } + + return wsfs_status_to_rc(status); +} diff --git a/src/wsfs/operation/read.c b/src/wsfs/operation/read.c new file mode 100644 index 0000000..35ab390 --- /dev/null +++ b/src/wsfs/operation/read.c @@ -0,0 +1,84 @@ +#include "wsfs/operations.h" + +#include +#include + +#include "wsfs/util.h" +#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; +} + +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 fuse_context * context = fuse_get_context(); + struct wsfs_jsonrpc * rpc = context->private_data; + + int const length = (buffer_size <= WSFS_MAX_READ_LENGTH) ? (int) buffer_size : WSFS_MAX_READ_LENGTH; + int result = 0; + json_t * data = NULL; + wsfs_status status = wsfs_jsonrpc_invoke(rpc, &data, "read", "sii", path, (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); + int const count = json_integer_value(count_holder); + + status = wsfs_fill_buffer(buffer, buffer_size, format, data, count); + if (WSFS_GOOD == status) + { + result = count; + } + } + else + { + status = WSFS_BAD_FORMAT; + } + + json_decref(data); + } + + if (WSFS_GOOD != status) + { + result = wsfs_status_to_rc(status); + } + + return result; +} diff --git a/src/wsfs/operation/readdir.c b/src/wsfs/operation/readdir.c new file mode 100644 index 0000000..eaf53ab --- /dev/null +++ b/src/wsfs/operation/readdir.c @@ -0,0 +1,41 @@ +#include "wsfs/operations.h" + +#include + +#include "wsfs/util.h" +#include "wsfs/jsonrpc.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)) +{ + struct fuse_context * context = fuse_get_context(); + struct wsfs_jsonrpc * rpc = context->private_data; + + json_t * result = NULL; + wsfs_status const status = wsfs_jsonrpc_invoke(rpc, &result, "readdir", "s", path); + 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_string(entry)) + { + buffer_full = filler(buffer, json_string_value(entry), NULL, 0, 0); + } + } + } + + json_decref(result); + } + + return wsfs_status_to_rc(status); +} \ No newline at end of file diff --git a/src/wsfs/operations.c b/src/wsfs/operations.c index 63a3a29..794c019 100644 --- a/src/wsfs/operations.c +++ b/src/wsfs/operations.c @@ -1,44 +1,9 @@ #include "wsfs/operations.h" -#include #include -#include #include "wsfs/util.h" -#include "wsfs/filesystem.h" - -struct wsfs_readdir_context -{ - void * buffer; - fuse_fill_dir_t filler; -}; - -static int wsfs_result_from_status(wsfs_status status) -{ - switch(status) - { - case WSFS_GOOD: return 0; - case WSFS_BAD_NOENTRY: return -ENOENT; - case WSFS_BAD_NOACCESS: return -EACCES; - default: return -ENOENT; - } -} - -static struct wsfs_filesystem * wsfs_get_filesystem(void) -{ - struct fuse_context * const context = fuse_get_context(); - struct wsfs_filesystem * const filesystem = context->private_data; - - return filesystem; -} - -static bool wsfs_add_entry(void * buffer, char const * path) -{ - struct wsfs_readdir_context * context = buffer; - int const result = context->filler(context->buffer, path, NULL, 0, 0); - - return (0 == result); -} +#include "wsfs/jsonrpc.h" static void* wsfs_operation_init( struct fuse_conn_info * WSFS_UNUSED_PARAM(connection), @@ -47,83 +12,7 @@ static void* wsfs_operation_init( struct fuse_context * const context = fuse_get_context(); config->kernel_cache = 1; - return wsfs_filesystem_create(context->private_data); -} - -static void wsfs_operation_destroy(void * private_data) -{ - struct wsfs_filesystem * const filesystem = private_data; - wsfs_filesystem_dispose(filesystem); -} - -static int wsfs_operation_getattr( - char const * path, - struct stat * buffer, - struct fuse_file_info * WSFS_UNUSED_PARAM(file_info)) -{ - struct fuse_context * const context = fuse_get_context(); - struct wsfs_filesystem * const filesystem = wsfs_get_filesystem(); - - wsfs_status const status = wsfs_filesystem_getattr(filesystem, path, buffer); - if (WSFS_GOOD == status) - { - buffer->st_uid = context->uid; - buffer->st_gid = context->gid; - buffer->st_nlink = 1; - } - - return wsfs_result_from_status(status); -} - -static 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)) -{ - struct wsfs_filesystem * filesystem = wsfs_get_filesystem(); - struct wsfs_readdir_context context = - { - .buffer = buffer, - .filler = filler - }; - - wsfs_status const status = wsfs_filesystem_readdir(filesystem, path, &context, &wsfs_add_entry); - 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); - } - + return context->private_data; } void wsfs_operations_init( @@ -131,7 +20,6 @@ void wsfs_operations_init( { memset(operations, 0, sizeof(struct fuse_operations)); operations->init = &wsfs_operation_init; - operations->destroy = &wsfs_operation_destroy; operations->getattr = &wsfs_operation_getattr; operations->readdir = &wsfs_operation_readdir; operations->open = &wsfs_operation_open; diff --git a/src/wsfs/operations.h b/src/wsfs/operations.h index 53242ff..ba9debd 100644 --- a/src/wsfs/operations.h +++ b/src/wsfs/operations.h @@ -6,5 +6,29 @@ extern void wsfs_operations_init( struct fuse_operations * operations); +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_read( + const char * path, + char * buffer, + size_t buffer_size, + off_t offset, + struct fuse_file_info * file_info); + #endif diff --git a/src/wsfs/status.c b/src/wsfs/status.c new file mode 100644 index 0000000..d16e66b --- /dev/null +++ b/src/wsfs/status.c @@ -0,0 +1,14 @@ +#include "wsfs/status.h" + +#include + + int wsfs_status_to_rc(wsfs_status status) +{ + switch(status) + { + case WSFS_GOOD: return 0; + case WSFS_BAD_NOENTRY: return -ENOENT; + case WSFS_BAD_NOACCESS: return -EACCES; + default: return -ENOENT; + } +} diff --git a/src/wsfs/status.h b/src/wsfs/status.h index 134e287..f44afb4 100644 --- a/src/wsfs/status.h +++ b/src/wsfs/status.h @@ -13,6 +13,7 @@ typedef int wsfs_status; +extern int wsfs_status_to_rc(wsfs_status status); #endif