diff --git a/cmake/unit_tests.cmake b/cmake/unit_tests.cmake index 5af183a..b49cca9 100644 --- a/cmake/unit_tests.cmake +++ b/cmake/unit_tests.cmake @@ -7,6 +7,8 @@ include(GoogleTest) pkg_check_modules(GMOCK gmock) add_executable(alltests + test/tempdir.cc + test/file_utils.cc test/msleep.cc test/die_if.cc test/mock_authenticator.cc @@ -21,11 +23,15 @@ add_executable(alltests test/core/test_message_queue.cc test/adapter/test_response_parser.cc test/adapter/test_server.cc + test/adapter/test_server_config.cc test/adapter/test_timepoint.cc test/adapter/test_timer.cc test/adapter/test_credentials.cc test/adapter/test_authenticator.cc test/adapter/test_authenticators.cc + test/adapter/test_mountpoint.cc + test/adapter/test_uuid_mountpoint.cc + test/adapter/test_uuid_mountpoint_factory.cc test/adapter/test_fuse_req.cc test/adapter/jsonrpc/test_util.cc test/adapter/jsonrpc/test_is_request.cc diff --git a/cmake/webfuse_adapter.cmake b/cmake/webfuse_adapter.cmake index 329a123..269204d 100644 --- a/cmake/webfuse_adapter.cmake +++ b/cmake/webfuse_adapter.cmake @@ -15,6 +15,10 @@ add_library(webfuse-adapter-static STATIC lib/webfuse/adapter/impl/authenticators.c lib/webfuse/adapter/impl/credentials.c lib/webfuse/adapter/impl/operations.c + lib/webfuse/adapter/impl/mountpoint.c + lib/webfuse/adapter/impl/mountpoint_factory.c + lib/webfuse/adapter/impl/uuid_mountpoint_factory.c + lib/webfuse/adapter/impl/uuid_mountpoint.c lib/webfuse/adapter/impl/time/timepoint.c lib/webfuse/adapter/impl/time/timer.c lib/webfuse/adapter/impl/time/timeout_manager.c diff --git a/include/webfuse/adapter/mountpoint.h b/include/webfuse/adapter/mountpoint.h new file mode 100644 index 0000000..62f59f3 --- /dev/null +++ b/include/webfuse/adapter/mountpoint.h @@ -0,0 +1,38 @@ +#ifndef WF_ADAPTER_MOUNTPOINT_H +#define WF_ADAPTER_MOUNTPOINT_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wf_mountpoint; + +typedef void +wf_mountpoint_userdata_dispose_fn( + void * user_data); + +extern struct wf_mountpoint * +wf_mountpoint_create( + char const * path); + +extern void +wf_mountpoint_dispose( + struct wf_mountpoint * mountpoint); + +extern char const * +wf_mountpoint_get_path( + struct wf_mountpoint const * mountpoint); + +extern void +wf_mountpoint_set_userdata( + struct wf_mountpoint * mointpoint, + void * user_data, + wf_mountpoint_userdata_dispose_fn * dispose); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/include/webfuse/adapter/mountpoint_factory.h b/include/webfuse/adapter/mountpoint_factory.h new file mode 100644 index 0000000..a265c6f --- /dev/null +++ b/include/webfuse/adapter/mountpoint_factory.h @@ -0,0 +1,24 @@ +#ifndef WF_ADAPTER_MOUNTPOINT_FACTORY_H +#define WF_ADAPTER_MOUNTPOINT_FACTORY_H + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wf_mountpoint; + +typedef struct wf_mountpoint * +wf_create_mountpoint_fn( + char const * filesystem, + void * user_data); + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/include/webfuse/adapter/server_config.h b/include/webfuse/adapter/server_config.h index cc1b6d3..778cc8c 100644 --- a/include/webfuse/adapter/server_config.h +++ b/include/webfuse/adapter/server_config.h @@ -3,6 +3,7 @@ #include "webfuse/adapter/api.h" #include "webfuse/adapter/authenticate.h" +#include "webfuse/adapter/mountpoint_factory.h" #ifdef __cplusplus extern "C" @@ -16,11 +17,15 @@ extern WF_API struct wf_server_config * wf_server_config_create(void); extern WF_API void wf_server_config_dispose( struct wf_server_config * config); - extern WF_API void wf_server_config_set_mountpoint( struct wf_server_config * config, char const * mount_point); +extern WF_API void wf_server_config_set_mountpoint_factory( + struct wf_server_config * config, + wf_create_mountpoint_fn * create_mountpoint, + void * user_data); + extern WF_API void wf_server_config_set_documentroot( struct wf_server_config * config, char const * document_root); diff --git a/include/webfuse/adapter/server_protocol.h b/include/webfuse/adapter/server_protocol.h index d77cbc3..6491a05 100644 --- a/include/webfuse/adapter/server_protocol.h +++ b/include/webfuse/adapter/server_protocol.h @@ -3,6 +3,7 @@ #include #include +#include #ifdef __cplusplus extern "C" @@ -15,6 +16,10 @@ struct lws_protocols; extern WF_API struct wf_server_protocol * wf_server_protocol_create( char * mount_point); +extern WF_API struct wf_server_protocol * wf_server_protocol_create2( + wf_create_mountpoint_fn * create_mountpoint, + void * create_mountpoint_context); + extern WF_API void wf_server_protocol_dispose( struct wf_server_protocol * protocol); diff --git a/include/webfuse_adapter.h b/include/webfuse_adapter.h index 8edad51..37c39c2 100644 --- a/include/webfuse_adapter.h +++ b/include/webfuse_adapter.h @@ -9,5 +9,6 @@ #include #include #include +#include #endif diff --git a/lib/webfuse/adapter/api.c b/lib/webfuse/adapter/api.c index af68a8e..adecac2 100644 --- a/lib/webfuse/adapter/api.c +++ b/lib/webfuse/adapter/api.c @@ -4,6 +4,7 @@ #include "webfuse/adapter/impl/server_protocol.h" #include "webfuse/adapter/impl/server_config.h" #include "webfuse/adapter/impl/credentials.h" +#include "webfuse/adapter/impl/mountpoint.h" // server @@ -34,6 +35,13 @@ struct wf_server_protocol * wf_server_protocol_create( return wf_impl_server_protocol_create(mount_point); } +struct wf_server_protocol * wf_server_protocol_create2( + wf_create_mountpoint_fn * create_mountpoint, + void * create_mountpoint_context) +{ + return wf_impl_server_protocol_create2(create_mountpoint, create_mountpoint_context); +} + void wf_server_protocol_dispose( struct wf_server_protocol * protocol) { @@ -76,6 +84,15 @@ void wf_server_config_set_mountpoint( wf_impl_server_config_set_mountpoint(config, mount_point); } +void wf_server_config_set_mountpoint_factory( + struct wf_server_config * config, + wf_create_mountpoint_fn * create_mountpoint, + void * user_data) +{ + wf_impl_server_config_set_mountpoint_factory( + config, create_mountpoint, user_data); +} + void wf_server_config_set_documentroot( struct wf_server_config * config, char const * document_root) @@ -134,3 +151,35 @@ char const * wf_credentials_get( { return wf_impl_credentials_get(credentials, key); } + +// mountpoint + +struct wf_mountpoint * +wf_mountpoint_create( + char const * path) +{ + return wf_impl_mountpoint_create(path); +} + +void +wf_mountpoint_dispose( + struct wf_mountpoint * mountpoint) +{ + wf_impl_mountpoint_dispose(mountpoint); +} + +char const * +wf_mountpoint_get_path( + struct wf_mountpoint const * mountpoint) +{ + return wf_impl_mountpoint_get_path(mountpoint); +} + +void +wf_mountpoint_set_userdata( + struct wf_mountpoint * mountpoint, + void * user_data, + wf_mountpoint_userdata_dispose_fn * dispose) +{ + wf_impl_mountpoint_set_userdata(mountpoint, user_data, dispose); +} diff --git a/lib/webfuse/adapter/impl/filesystem.c b/lib/webfuse/adapter/impl/filesystem.c index 3cfcca7..e4a3435 100644 --- a/lib/webfuse/adapter/impl/filesystem.c +++ b/lib/webfuse/adapter/impl/filesystem.c @@ -1,6 +1,7 @@ #include "webfuse/adapter/impl/filesystem.h" #include "webfuse/adapter/impl/operations.h" #include "webfuse/adapter/impl/session.h" +#include "webfuse/adapter/impl/mountpoint.h" #include "webfuse/core/string.h" @@ -27,58 +28,6 @@ static struct fuse_lowlevel_ops const filesystem_operations = .read = &wf_impl_operation_read }; -static char * wf_impl_filesystem_create_id(void) -{ - uuid_t uuid; - uuid_generate(uuid); - char id[UUID_STR_LEN]; - uuid_unparse(uuid, id); - - return strdup(id); -} - -static bool wf_impl_filesystem_is_link_broken(char const * path, char const * id) -{ - bool result = false; - - char buffer[UUID_STR_LEN]; - ssize_t count = readlink(path, buffer, UUID_STR_LEN); - if ((0 < count) && (count < UUID_STR_LEN)) - { - buffer[count] = '\0'; - result = (0 == strcmp(buffer, id)); - } - - return result; -} - -static bool wf_impl_filesystem_link_first_subdir( - char const * link_path, - char const * path) -{ - bool result = false; - DIR * dir = opendir(path); - if (NULL != dir) - { - struct dirent * entry = readdir(dir); - while (NULL != entry) - { - if ((DT_DIR == entry->d_type) && ('.' != entry->d_name[0])) - { - symlink(entry->d_name, link_path); - result = true; - break; - } - - entry = readdir(dir); - } - - closedir(dir); - } - - return result; -} - static void wf_impl_filesystem_cleanup( struct wf_impl_filesystem * filesystem) { @@ -90,32 +39,17 @@ static void wf_impl_filesystem_cleanup( free(filesystem->buffer.mem); fuse_opt_free_args(&filesystem->args); - rmdir(filesystem->root_path); - - if (wf_impl_filesystem_is_link_broken(filesystem->default_path, filesystem->id)) - { - unlink(filesystem->default_path); - - bool const success = wf_impl_filesystem_link_first_subdir(filesystem->default_path, filesystem->service_path); - if (!success) - { - rmdir(filesystem->service_path); - } - } - + wf_mountpoint_dispose(filesystem->mountpoint); free(filesystem->user_data.name); - free(filesystem->id); - free(filesystem->root_path); - free(filesystem->default_path); - free(filesystem->service_path); } static bool wf_impl_filesystem_init( struct wf_impl_filesystem * filesystem, struct wf_impl_session * session, - char const * name) + char const * name, + struct wf_mountpoint * mountpoint) { bool result = false; @@ -129,15 +63,7 @@ static bool wf_impl_filesystem_init( filesystem->user_data.name = strdup(name); memset(&filesystem->buffer, 0, sizeof(struct fuse_buf)); - filesystem->service_path = wf_create_string("%s/%s", session->mount_point, name); - mkdir(filesystem->service_path, 0755); - - filesystem->id = wf_impl_filesystem_create_id(); - filesystem->root_path = wf_create_string("%s/%s/%s", session->mount_point, name, filesystem->id); - mkdir(filesystem->root_path, 0755); - - filesystem->default_path = wf_create_string("%s/%s/default", session->mount_point, name); - symlink(filesystem->id, filesystem->default_path); + filesystem->mountpoint = mountpoint; filesystem->session = fuse_session_new( &filesystem->args, @@ -146,7 +72,8 @@ static bool wf_impl_filesystem_init( &filesystem->user_data); if (NULL != filesystem->session) { - result = (0 == fuse_session_mount(filesystem->session, filesystem->root_path)); + char const * path = wf_mountpoint_get_path(filesystem->mountpoint); + result = (0 == fuse_session_mount(filesystem->session, path)); } if (result) @@ -169,12 +96,13 @@ static bool wf_impl_filesystem_init( struct wf_impl_filesystem * wf_impl_filesystem_create( struct wf_impl_session * session, - char const * name) + char const * name, + struct wf_mountpoint * mountpoint) { struct wf_impl_filesystem * filesystem = malloc(sizeof(struct wf_impl_filesystem)); if (NULL != filesystem) { - bool success = wf_impl_filesystem_init(filesystem, session, name); + bool success = wf_impl_filesystem_init(filesystem, session, name, mountpoint); if (!success) { free(filesystem); diff --git a/lib/webfuse/adapter/impl/filesystem.h b/lib/webfuse/adapter/impl/filesystem.h index 648dfbd..83660d8 100644 --- a/lib/webfuse/adapter/impl/filesystem.h +++ b/lib/webfuse/adapter/impl/filesystem.h @@ -14,6 +14,7 @@ extern "C" { #endif +struct wf_mountpoint; struct wf_impl_session; struct lws; @@ -25,16 +26,13 @@ struct wf_impl_filesystem struct fuse_buf buffer; struct wf_impl_operations_context user_data; struct lws * wsi; - char * name; - char * id; - char * service_path; - char * default_path; - char * root_path; + struct wf_mountpoint * mountpoint; }; extern struct wf_impl_filesystem * wf_impl_filesystem_create( struct wf_impl_session * session, - char const * name); + char const * name, + struct wf_mountpoint * mountpoint); extern void wf_impl_filesystem_dispose( struct wf_impl_filesystem * filesystem); diff --git a/lib/webfuse/adapter/impl/mountpoint.c b/lib/webfuse/adapter/impl/mountpoint.c new file mode 100644 index 0000000..a459510 --- /dev/null +++ b/lib/webfuse/adapter/impl/mountpoint.c @@ -0,0 +1,53 @@ +#include "webfuse/adapter/impl/mountpoint.h" + +#include +#include + +struct wf_mountpoint +{ + char * path; + void * user_data; + wf_mountpoint_userdata_dispose_fn * dispose; +}; + +struct wf_mountpoint * +wf_impl_mountpoint_create( + char const * path) +{ + struct wf_mountpoint * mountpoint = malloc(sizeof(struct wf_mountpoint)); + mountpoint->path = strdup(path); + mountpoint->user_data = NULL; + mountpoint->dispose = NULL; + + return mountpoint; +} + +void +wf_impl_mountpoint_dispose( + struct wf_mountpoint * mountpoint) +{ + if (NULL != mountpoint->dispose) + { + mountpoint->dispose(mountpoint->user_data); + } + + free(mountpoint->path); + free(mountpoint); +} + +char const * +wf_impl_mountpoint_get_path( + struct wf_mountpoint const * mountpoint) +{ + return mountpoint->path; +} + +extern void +wf_impl_mountpoint_set_userdata( + struct wf_mountpoint * mountpoint, + void * user_data, + wf_mountpoint_userdata_dispose_fn * dispose) +{ + mountpoint->user_data = user_data; + mountpoint->dispose = dispose; +} diff --git a/lib/webfuse/adapter/impl/mountpoint.h b/lib/webfuse/adapter/impl/mountpoint.h new file mode 100644 index 0000000..77fc0ea --- /dev/null +++ b/lib/webfuse/adapter/impl/mountpoint.h @@ -0,0 +1,33 @@ +#ifndef WF_IMPL_MOUNTPOINT_H +#define WF_IMPL_MOUNTPOINT_H + +#include "webfuse/adapter/mountpoint.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern struct wf_mountpoint * +wf_impl_mountpoint_create( + char const * path); + +extern void +wf_impl_mountpoint_dispose( + struct wf_mountpoint * mountpoint); + +extern char const * +wf_impl_mountpoint_get_path( + struct wf_mountpoint const * mountpoint); + +extern void +wf_impl_mountpoint_set_userdata( + struct wf_mountpoint * mountpoint, + void * user_data, + wf_mountpoint_userdata_dispose_fn * dispose); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/webfuse/adapter/impl/mountpoint_factory.c b/lib/webfuse/adapter/impl/mountpoint_factory.c new file mode 100644 index 0000000..54679ef --- /dev/null +++ b/lib/webfuse/adapter/impl/mountpoint_factory.c @@ -0,0 +1,67 @@ +#include "webfuse/adapter/impl/mountpoint_factory.h" +#include + +void +wf_impl_mountpoint_factory_init_default( + struct wf_impl_mountpoint_factory * factory) +{ + factory->create_mountpoint = NULL; + factory->user_data = NULL; + factory->dispose = NULL; +} + +void +wf_impl_mountpoint_factory_init( + struct wf_impl_mountpoint_factory * factory, + wf_create_mountpoint_fn * create_mountpoint, + void * user_data, + wf_impl_mountpoint_factory_dispose_fn * dispose) +{ + factory->create_mountpoint = create_mountpoint; + factory->user_data = user_data; + factory->dispose = dispose; +} + +void +wf_impl_mountpoint_factory_move( + struct wf_impl_mountpoint_factory * factory, + struct wf_impl_mountpoint_factory * other) +{ + other->create_mountpoint = factory->create_mountpoint; + other->user_data = factory->user_data; + other->dispose = factory->dispose; + + factory->create_mountpoint = NULL; + factory->dispose = NULL; + factory->user_data = NULL; +} + +bool +wf_impl_mountpoint_factory_isvalid( + struct wf_impl_mountpoint_factory * factory) +{ + return (NULL != factory->create_mountpoint); +} + +void +wf_impl_mountpoint_factory_cleanup( + struct wf_impl_mountpoint_factory * factory) +{ + if (NULL != factory->dispose) + { + factory->dispose(factory->user_data); + } + + factory->create_mountpoint = NULL; + factory->dispose = NULL; + factory->user_data = NULL; +} + +struct wf_mountpoint * +wf_impl_mountpoint_factory_create_mountpoint( + struct wf_impl_mountpoint_factory * factory, + char const * filesystem) +{ + return factory->create_mountpoint(filesystem, factory->user_data); +} + diff --git a/lib/webfuse/adapter/impl/mountpoint_factory.h b/lib/webfuse/adapter/impl/mountpoint_factory.h new file mode 100644 index 0000000..98e5469 --- /dev/null +++ b/lib/webfuse/adapter/impl/mountpoint_factory.h @@ -0,0 +1,61 @@ +#ifndef WF_ADAPTER_IMPL_MOUNTPOINT_FACTORY_H +#define WF_ADAPTER_IMPL_MOUNTPOINT_FACTORY_H + +#include "webfuse/adapter/mountpoint_factory.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef void +wf_impl_mountpoint_factory_dispose_fn( + void * user_data); + +struct wf_impl_mountpoint_factory +{ + wf_create_mountpoint_fn * create_mountpoint; + wf_impl_mountpoint_factory_dispose_fn * dispose; + void * user_data; +}; + +extern void +wf_impl_mountpoint_factory_init_default( + struct wf_impl_mountpoint_factory * factory); + +extern void +wf_impl_mountpoint_factory_init( + struct wf_impl_mountpoint_factory * factory, + wf_create_mountpoint_fn * create_mountpoint, + void * user_data, + wf_impl_mountpoint_factory_dispose_fn * dispose); + +extern void +wf_impl_mountpoint_factory_move( + struct wf_impl_mountpoint_factory * factory, + struct wf_impl_mountpoint_factory * other); + +extern bool +wf_impl_mountpoint_factory_isvalid( + struct wf_impl_mountpoint_factory * factory); + +extern void +wf_impl_mountpoint_factory_init_from( + struct wf_impl_mountpoint_factory * factory, + struct wf_impl_mountpoint_factory * other); + +extern void +wf_impl_mountpoint_factory_cleanup( + struct wf_impl_mountpoint_factory * factory); + +extern struct wf_mountpoint * +wf_impl_mountpoint_factory_create_mountpoint( + struct wf_impl_mountpoint_factory * factory, + char const * filesystem); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/webfuse/adapter/impl/server.c b/lib/webfuse/adapter/impl/server.c index 15e18f4..ad3e5c2 100644 --- a/lib/webfuse/adapter/impl/server.c +++ b/lib/webfuse/adapter/impl/server.c @@ -76,37 +76,17 @@ static struct lws_context * wf_impl_server_context_create( } -static bool wf_impl_server_check_mountpoint( - struct wf_server_config * config) -{ - bool result = false; - - if (NULL != config->mount_point) - { - struct stat info; - int const rc = stat(config->mount_point, &info); - result = ((0 == rc) && (S_ISDIR(info.st_mode))); - - if (!result) - { - result = (0 == mkdir(config->mount_point, 0755)); - } - } - - return result; -} - struct wf_server * wf_impl_server_create( struct wf_server_config * config) { struct wf_server * server = NULL; - if (wf_impl_server_check_mountpoint(config)) + if (wf_impl_mountpoint_factory_isvalid(&config->mountpoint_factory)) { server = malloc(sizeof(struct wf_server)); if (NULL != server) { - wf_impl_server_protocol_init(&server->protocol, config->mount_point); + wf_impl_server_protocol_init(&server->protocol, &config->mountpoint_factory); wf_impl_server_config_clone(config, &server->config); wf_impl_authenticators_move(&server->config.authenticators, &server->protocol.authenticators); server->context = wf_impl_server_context_create(server); diff --git a/lib/webfuse/adapter/impl/server_config.c b/lib/webfuse/adapter/impl/server_config.c index 7098dac..2d9fc6d 100644 --- a/lib/webfuse/adapter/impl/server_config.c +++ b/lib/webfuse/adapter/impl/server_config.c @@ -1,4 +1,5 @@ #include "webfuse/adapter/impl/server_config.h" +#include "webfuse/adapter/impl/uuid_mountpoint_factory.h" #include #include @@ -20,14 +21,15 @@ void wf_impl_server_config_init( memset(config, 0, sizeof(struct wf_server_config)); wf_impl_authenticators_init(&config->authenticators); + wf_impl_mountpoint_factory_init_default(&config->mountpoint_factory); } void wf_impl_server_config_cleanup( struct wf_server_config * config) { wf_impl_authenticators_cleanup(&config->authenticators); + wf_impl_mountpoint_factory_cleanup(&config->mountpoint_factory); - free(config->mount_point); free(config->document_root); free(config->key_path); free(config->cert_path); @@ -40,7 +42,6 @@ void wf_impl_server_config_clone( struct wf_server_config * config, struct wf_server_config * clone) { - clone->mount_point = wf_impl_server_config_strdup(config->mount_point); clone->document_root = wf_impl_server_config_strdup(config->document_root); clone->key_path = wf_impl_server_config_strdup(config->key_path); clone->cert_path = wf_impl_server_config_strdup(config->cert_path); @@ -48,6 +49,9 @@ void wf_impl_server_config_clone( clone->port = config->port; wf_impl_authenticators_clone(&config->authenticators, &clone->authenticators); + + // ToDo: remove this: move is not clone :-/ + wf_impl_mountpoint_factory_move(&config->mountpoint_factory, &clone->mountpoint_factory); } struct wf_server_config * wf_impl_server_config_create(void) @@ -72,10 +76,20 @@ void wf_impl_server_config_set_mountpoint( struct wf_server_config * config, char const * mount_point) { - free(config->mount_point); - config->mount_point = strdup(mount_point); + wf_impl_uuid_mountpoint_factory_init(&config->mountpoint_factory, + mount_point); } +void wf_impl_server_config_set_mountpoint_factory( + struct wf_server_config * config, + wf_create_mountpoint_fn * create_mountpoint, + void * create_mountpoint_context) +{ + wf_impl_mountpoint_factory_init(&config->mountpoint_factory, + create_mountpoint, create_mountpoint_context, NULL); +} + + void wf_impl_server_config_set_documentroot( struct wf_server_config * config, char const * document_root) diff --git a/lib/webfuse/adapter/impl/server_config.h b/lib/webfuse/adapter/impl/server_config.h index 734c83a..48de4ed 100644 --- a/lib/webfuse/adapter/impl/server_config.h +++ b/lib/webfuse/adapter/impl/server_config.h @@ -2,6 +2,7 @@ #define WF_ADAPTER_IMPL_SERVER_CONFIG_H #include "webfuse/adapter/impl/authenticators.h" +#include "webfuse/adapter/impl/mountpoint_factory.h" #ifdef __cplusplus extern "C" { @@ -9,13 +10,13 @@ extern "C" { struct wf_server_config { - char * mount_point; char * document_root; char * key_path; char * cert_path; char * vhost_name; int port; struct wf_impl_authenticators authenticators; + struct wf_impl_mountpoint_factory mountpoint_factory; }; extern struct wf_server_config * wf_impl_server_config_create(void); @@ -37,6 +38,11 @@ extern void wf_impl_server_config_set_mountpoint( struct wf_server_config * config, char const * mount_point); +extern void wf_impl_server_config_set_mountpoint_factory( + struct wf_server_config * config, + wf_create_mountpoint_fn * create_mountpoint, + void * create_mountpoint_context); + extern void wf_impl_server_config_set_documentroot( struct wf_server_config * config, char const * document_root); diff --git a/lib/webfuse/adapter/impl/server_protocol.c b/lib/webfuse/adapter/impl/server_protocol.c index 65f6047..02efd80 100644 --- a/lib/webfuse/adapter/impl/server_protocol.c +++ b/lib/webfuse/adapter/impl/server_protocol.c @@ -9,6 +9,7 @@ #include "webfuse/adapter/impl/credentials.h" #include "webfuse/adapter/impl/jsonrpc/request.h" +#include "webfuse/adapter/impl/uuid_mountpoint_factory.h" static int wf_impl_server_protocol_callback( struct lws * wsi, @@ -38,9 +39,9 @@ static int wf_impl_server_protocol_callback( &protocol->session_manager, wsi, &protocol->authenticators, + &protocol->mountpoint_factory, &protocol->timeout_manager, - &protocol->server, - protocol->mount_point); + &protocol->server); if (NULL != session) { @@ -81,12 +82,34 @@ struct wf_server_protocol * wf_impl_server_protocol_create( struct wf_server_protocol * protocol = malloc(sizeof(struct wf_server_protocol)); if (NULL != protocol) { - wf_impl_server_protocol_init(protocol, mount_point); + struct wf_impl_mountpoint_factory mountpoint_factory; + wf_impl_uuid_mountpoint_factory_init(&mountpoint_factory, mount_point); + + wf_impl_server_protocol_init(protocol, &mountpoint_factory); } return protocol; } +struct wf_server_protocol * wf_impl_server_protocol_create2( + wf_create_mountpoint_fn * create_mountpoint, + void * create_mountpoint_context) +{ + struct wf_server_protocol * protocol = malloc(sizeof(struct wf_server_protocol)); + if (NULL != protocol) + { + struct wf_impl_mountpoint_factory mountpoint_factory; + wf_impl_mountpoint_factory_init(&mountpoint_factory, + create_mountpoint, create_mountpoint_context, NULL); + + wf_impl_server_protocol_init(protocol, &mountpoint_factory); + } + + return protocol; + +} + + void wf_impl_server_protocol_dispose( struct wf_server_protocol * protocol) { @@ -203,14 +226,14 @@ static void wf_impl_server_protocol_add_filesystem( } - void wf_impl_server_protocol_init( struct wf_server_protocol * protocol, - char * mount_point) + struct wf_impl_mountpoint_factory * mountpoint_factory) { - protocol->mount_point = strdup(mount_point); protocol->is_operational = false; + wf_impl_mountpoint_factory_move(mountpoint_factory, &protocol->mountpoint_factory); + wf_impl_timeout_manager_init(&protocol->timeout_manager); wf_impl_session_manager_init(&protocol->session_manager); wf_impl_authenticators_init(&protocol->authenticators); @@ -223,13 +246,13 @@ void wf_impl_server_protocol_init( void wf_impl_server_protocol_cleanup( struct wf_server_protocol * protocol) { - free(protocol->mount_point); protocol->is_operational = false; wf_impl_jsonrpc_server_cleanup(&protocol->server); wf_impl_timeout_manager_cleanup(&protocol->timeout_manager); wf_impl_authenticators_cleanup(&protocol->authenticators); wf_impl_session_manager_cleanup(&protocol->session_manager); + wf_impl_mountpoint_factory_cleanup(&protocol->mountpoint_factory); } void wf_impl_server_protocol_add_authenticator( diff --git a/lib/webfuse/adapter/impl/server_protocol.h b/lib/webfuse/adapter/impl/server_protocol.h index 8e4cd8d..16da34d 100644 --- a/lib/webfuse/adapter/impl/server_protocol.h +++ b/lib/webfuse/adapter/impl/server_protocol.h @@ -4,6 +4,7 @@ #include "webfuse/adapter/impl/jsonrpc/proxy.h" #include "webfuse/adapter/impl/time/timeout_manager.h" #include "webfuse/adapter/impl/authenticators.h" +#include "webfuse/adapter/impl/mountpoint_factory.h" #include "webfuse/adapter/impl/session_manager.h" #include "webfuse/adapter/impl/jsonrpc/server.h" @@ -20,9 +21,9 @@ struct lws_protocols; struct wf_server_protocol { - char * mount_point; struct wf_impl_timeout_manager timeout_manager; struct wf_impl_authenticators authenticators; + struct wf_impl_mountpoint_factory mountpoint_factory; struct wf_impl_session_manager session_manager; struct wf_impl_jsonrpc_server server; bool is_operational; @@ -30,7 +31,7 @@ struct wf_server_protocol extern void wf_impl_server_protocol_init( struct wf_server_protocol * protocol, - char * mount_point); + struct wf_impl_mountpoint_factory * mountpoint_factory); extern void wf_impl_server_protocol_cleanup( struct wf_server_protocol * protocol); @@ -38,6 +39,10 @@ extern void wf_impl_server_protocol_cleanup( extern struct wf_server_protocol * wf_impl_server_protocol_create( char * mount_point); +extern WF_API struct wf_server_protocol * wf_impl_server_protocol_create2( + wf_create_mountpoint_fn * create_mountpoint, + void * create_mountpoint_context); + extern void wf_impl_server_protocol_dispose( struct wf_server_protocol * protocol); diff --git a/lib/webfuse/adapter/impl/session.c b/lib/webfuse/adapter/impl/session.c index 82f9b80..fb2885a 100644 --- a/lib/webfuse/adapter/impl/session.c +++ b/lib/webfuse/adapter/impl/session.c @@ -5,6 +5,8 @@ #include "webfuse/adapter/impl/jsonrpc/proxy.h" #include "webfuse/adapter/impl/jsonrpc/request.h" #include "webfuse/adapter/impl/jsonrpc/response.h" +#include "webfuse/adapter/impl/mountpoint_factory.h" +#include "webfuse/adapter/impl/mountpoint.h" #include "webfuse/core/container_of.h" #include "webfuse/core/util.h" @@ -44,7 +46,7 @@ struct wf_impl_session * wf_impl_session_create( struct wf_impl_authenticators * authenticators, struct wf_impl_timeout_manager * timeout_manager, struct wf_impl_jsonrpc_server * server, - char const * mount_point) + struct wf_impl_mountpoint_factory * mountpoint_factory) { struct wf_impl_session * session = malloc(sizeof(struct wf_impl_session)); @@ -52,11 +54,11 @@ struct wf_impl_session * wf_impl_session_create( { wf_slist_init(&session->filesystems); - session->mount_point = strdup(mount_point); session->wsi = wsi; session->is_authenticated = false; session->authenticators = authenticators; session->server = server; + session->mountpoint_factory = mountpoint_factory; wf_impl_jsonrpc_proxy_init(&session->rpc, timeout_manager, WF_DEFAULT_TIMEOUT, &wf_impl_session_send, session); wf_slist_init(&session->messages); } @@ -88,8 +90,8 @@ void wf_impl_session_dispose( session->is_authenticated = false; session->wsi = NULL; session->authenticators = NULL; + session->mountpoint_factory = NULL; session->server = NULL; - free(session->mount_point); free(session); } @@ -106,9 +108,28 @@ bool wf_impl_session_add_filesystem( struct wf_impl_session * session, char const * name) { - struct wf_impl_filesystem * filesystem = wf_impl_filesystem_create(session, name); - wf_slist_append(&session->filesystems, &filesystem->item); - return (NULL != filesystem); + bool result; + + struct wf_mountpoint * mountpoint = wf_impl_mountpoint_factory_create_mountpoint(session->mountpoint_factory, name); + result = (NULL != mountpoint); + + if (result) + { + struct wf_impl_filesystem * filesystem = wf_impl_filesystem_create(session, name, mountpoint); + wf_slist_append(&session->filesystems, &filesystem->item); + result = (NULL != filesystem); + } + + // cleanup on error + if (!result) + { + if (NULL != mountpoint) + { + wf_impl_mountpoint_dispose(mountpoint); + } + } + + return result; } diff --git a/lib/webfuse/adapter/impl/session.h b/lib/webfuse/adapter/impl/session.h index cb1a19d..9f9b10a 100644 --- a/lib/webfuse/adapter/impl/session.h +++ b/lib/webfuse/adapter/impl/session.h @@ -24,16 +24,17 @@ struct lws; struct wf_message; struct wf_credentials; struct wf_impl_authenticators; +struct wf_impl_mountpoint_factory; struct wf_impl_timeout_manager; struct wf_impl_session { struct wf_slist_item item; - char * mount_point; struct lws * wsi; bool is_authenticated; struct wf_slist messages; struct wf_impl_authenticators * authenticators; + struct wf_impl_mountpoint_factory * mountpoint_factory; struct wf_impl_jsonrpc_server * server; struct wf_impl_jsonrpc_proxy rpc; struct wf_slist filesystems; @@ -44,7 +45,7 @@ extern struct wf_impl_session * wf_impl_session_create( struct wf_impl_authenticators * authenticators, struct wf_impl_timeout_manager * timeout_manager, struct wf_impl_jsonrpc_server * server, - char const * mount_point); + struct wf_impl_mountpoint_factory * mountpoint_factory); extern void wf_impl_session_dispose( struct wf_impl_session * session); diff --git a/lib/webfuse/adapter/impl/session_manager.c b/lib/webfuse/adapter/impl/session_manager.c index a48489b..0574c98 100644 --- a/lib/webfuse/adapter/impl/session_manager.c +++ b/lib/webfuse/adapter/impl/session_manager.c @@ -27,12 +27,12 @@ struct wf_impl_session * wf_impl_session_manager_add( struct wf_impl_session_manager * manager, struct lws * wsi, struct wf_impl_authenticators * authenticators, + struct wf_impl_mountpoint_factory * mountpoint_factory, struct wf_impl_timeout_manager * timeout_manager, - struct wf_impl_jsonrpc_server * server, - char const * mount_point) + struct wf_impl_jsonrpc_server * server) { struct wf_impl_session * session = wf_impl_session_create( - wsi, authenticators, timeout_manager, server, mount_point); + wsi, authenticators, timeout_manager, server, mountpoint_factory); if (NULL != session) { wf_slist_append(&manager->sessions, &session->item); diff --git a/lib/webfuse/adapter/impl/session_manager.h b/lib/webfuse/adapter/impl/session_manager.h index bfe4aa3..25b4367 100644 --- a/lib/webfuse/adapter/impl/session_manager.h +++ b/lib/webfuse/adapter/impl/session_manager.h @@ -33,9 +33,9 @@ extern struct wf_impl_session * wf_impl_session_manager_add( struct wf_impl_session_manager * manager, struct lws * wsi, struct wf_impl_authenticators * authenticators, + struct wf_impl_mountpoint_factory * mountpoint_factory, struct wf_impl_timeout_manager * timeout_manager, - struct wf_impl_jsonrpc_server * server, - char const * mount_point); + struct wf_impl_jsonrpc_server * server); extern struct wf_impl_session * wf_impl_session_manager_get( struct wf_impl_session_manager * manager, diff --git a/lib/webfuse/adapter/impl/uuid_mountpoint.c b/lib/webfuse/adapter/impl/uuid_mountpoint.c new file mode 100644 index 0000000..eafa444 --- /dev/null +++ b/lib/webfuse/adapter/impl/uuid_mountpoint.c @@ -0,0 +1,123 @@ +#include "webfuse/adapter/impl/uuid_mountpoint.h" +#include "webfuse/adapter/impl/mountpoint.h" + +#include "webfuse/core/string.h" + +#include + +#include +#include +#include +#include + +#include +#include +#include + +struct wf_impl_uuid_mountpoint_data +{ + char * id; + char * filesystem_path; + char * default_path; + char * full_path; +}; + +static char * wf_impl_uuid_mountpoint_create_id(void) +{ + uuid_t uuid; + uuid_generate(uuid); + char id[UUID_STR_LEN]; + uuid_unparse(uuid, id); + + return strdup(id); +} + +static bool wf_impl_uuid_mountpoint_is_link_broken(char const * path, char const * id) +{ + bool result = false; + + char buffer[UUID_STR_LEN]; + ssize_t count = readlink(path, buffer, UUID_STR_LEN); + if ((0 < count) && (count < UUID_STR_LEN)) + { + buffer[count] = '\0'; + result = (0 == strcmp(buffer, id)); + } + + return result; +} + +static bool wf_impl_uuid_mountpoint_link_first_subdir( + char const * link_path, + char const * path) +{ + bool result = false; + DIR * dir = opendir(path); + if (NULL != dir) + { + struct dirent * entry = readdir(dir); + while (NULL != entry) + { + if ((DT_DIR == entry->d_type) && ('.' != entry->d_name[0])) + { + symlink(entry->d_name, link_path); + result = true; + break; + } + + entry = readdir(dir); + } + + closedir(dir); + } + + return result; +} + +static void +wf_impl_uuid_mountpoint_data_dispose( + void * user_data) +{ + struct wf_impl_uuid_mountpoint_data * data = user_data; + + rmdir(data->full_path); + + if (wf_impl_uuid_mountpoint_is_link_broken(data->default_path, data->id)) + { + unlink(data->default_path); + + bool const success = wf_impl_uuid_mountpoint_link_first_subdir(data->default_path, data->filesystem_path); + if (!success) + { + rmdir(data->filesystem_path); + } + } + + free(data->id); + free(data->filesystem_path); + free(data->default_path); + free(data->full_path); + free(data); +} + +struct wf_mountpoint * +wf_impl_uuid_mountpoint_create( + char const * root_path, + char const * filesystem) +{ + struct wf_impl_uuid_mountpoint_data * data = malloc(sizeof(struct wf_impl_uuid_mountpoint_data)); + data->filesystem_path = wf_create_string("%s/%s", root_path, filesystem); + mkdir(data->filesystem_path, 0755); + + data->id = wf_impl_uuid_mountpoint_create_id(); + data->full_path = wf_create_string("%s/%s/%s", root_path, filesystem, data->id); + mkdir(data->full_path, 0755); + + data->default_path = wf_create_string("%s/%s/default", root_path, filesystem); + symlink(data->id, data->default_path); + + struct wf_mountpoint * mountpoint = wf_impl_mountpoint_create(data->full_path); + wf_impl_mountpoint_set_userdata(mountpoint, data, &wf_impl_uuid_mountpoint_data_dispose); + + return mountpoint; +} diff --git a/lib/webfuse/adapter/impl/uuid_mountpoint.h b/lib/webfuse/adapter/impl/uuid_mountpoint.h new file mode 100644 index 0000000..7287be3 --- /dev/null +++ b/lib/webfuse/adapter/impl/uuid_mountpoint.h @@ -0,0 +1,20 @@ +#ifndef WF_IMPL_UUID_MOUNTPOINT_H +#define WF_IMPL_UUID_MOUNTPOINT_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wf_mountpoint; + +extern struct wf_mountpoint * +wf_impl_uuid_mountpoint_create( + char const * root_path, + char const * filesystem); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/webfuse/adapter/impl/uuid_mountpoint_factory.c b/lib/webfuse/adapter/impl/uuid_mountpoint_factory.c new file mode 100644 index 0000000..3b4d543 --- /dev/null +++ b/lib/webfuse/adapter/impl/uuid_mountpoint_factory.c @@ -0,0 +1,84 @@ +#include "webfuse/adapter/impl/uuid_mountpoint_factory.h" +#include "webfuse/adapter/impl/uuid_mountpoint.h" + +#include +#include +#include + +#include +#include +#include + +struct wf_impl_uuid_mountpoint_factory +{ + char * root_path; + bool root_created; +}; + +static void * +wf_impl_uuid_mountpoint_factory_create_context( + char const * root_path) +{ + struct wf_impl_uuid_mountpoint_factory * factory = NULL; + bool root_created = false; + + struct stat info; + int rc = stat(root_path, &info); + if ((0 != rc) || (!S_ISDIR(info.st_mode))) + { + rc = mkdir(root_path, 0755); + root_created = true; + } + + if (0 == rc) + { + factory = malloc(sizeof(struct wf_impl_uuid_mountpoint_factory)); + factory->root_path = strdup(root_path); + factory->root_created = root_created; + } + + return factory; +} + +static void +wf_impl_uuid_mountpoint_factory_dispose( + void * user_data) +{ + struct wf_impl_uuid_mountpoint_factory * factory = user_data; + + if (factory->root_created) + { + rmdir(factory->root_path); + } + + free(factory->root_path); + free(factory); +} + +static struct wf_mountpoint * +wf_impl_uuid_mountpoint_factory_create_mountpoint( + char const * filesystem, + void * user_data) +{ + struct wf_impl_uuid_mountpoint_factory * factory = user_data; + + return wf_impl_uuid_mountpoint_create(factory->root_path, filesystem); +} + +bool +wf_impl_uuid_mountpoint_factory_init( + struct wf_impl_mountpoint_factory * factory, + char const * root_path) +{ + void * context = wf_impl_uuid_mountpoint_factory_create_context(root_path); + bool const result = (NULL != context); + + if (result) + { + factory->create_mountpoint = &wf_impl_uuid_mountpoint_factory_create_mountpoint; + factory->user_data = context; + factory->dispose = &wf_impl_uuid_mountpoint_factory_dispose; + } + + return result; +} diff --git a/lib/webfuse/adapter/impl/uuid_mountpoint_factory.h b/lib/webfuse/adapter/impl/uuid_mountpoint_factory.h new file mode 100644 index 0000000..eed8fa0 --- /dev/null +++ b/lib/webfuse/adapter/impl/uuid_mountpoint_factory.h @@ -0,0 +1,21 @@ +#ifndef WF_IMPL_UUID_MOUNTPOINT_FACTORY_H +#define WF_IMPL_UUID_MOUNTPOINT_FACTORY_H + +#include "webfuse/adapter/impl/mountpoint_factory.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern bool +wf_impl_uuid_mountpoint_factory_init( + struct wf_impl_mountpoint_factory * factory, + char const * root_path); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/adapter/test_mountpoint.cc b/test/adapter/test_mountpoint.cc new file mode 100644 index 0000000..6bb486b --- /dev/null +++ b/test/adapter/test_mountpoint.cc @@ -0,0 +1,47 @@ +#include +#include +#include "webfuse/adapter/mountpoint.h" + +namespace +{ + class MockUserDataDisposer + { + public: + MOCK_METHOD1(dispose, void(void * mountpoint)); + }; + + MockUserDataDisposer * global_disposer = nullptr; + + void ondispose(void * user_data) + { + global_disposer->dispose(user_data); + } +} + +TEST(mountpoint, get_path) +{ + wf_mountpoint * mountpoint = wf_mountpoint_create("/some/path"); + ASSERT_NE(nullptr, mountpoint); + + ASSERT_STREQ("/some/path", wf_mountpoint_get_path(mountpoint)); + + wf_mountpoint_dispose(mountpoint); +} + + + +TEST(mountpoint, ondispose) +{ + MockUserDataDisposer disposer; + global_disposer = &disposer; + + wf_mountpoint * mountpoint = wf_mountpoint_create("/some/path"); + ASSERT_NE(nullptr, mountpoint); + + int value = 42; + void * user_data = reinterpret_cast(&value); + wf_mountpoint_set_userdata(mountpoint, user_data, ondispose); + EXPECT_CALL(disposer, dispose(user_data)).Times(1); + + wf_mountpoint_dispose(mountpoint); +} \ No newline at end of file diff --git a/test/adapter/test_server_config.cc b/test/adapter/test_server_config.cc new file mode 100644 index 0000000..cb176d6 --- /dev/null +++ b/test/adapter/test_server_config.cc @@ -0,0 +1,175 @@ +#include +#include "webfuse/adapter/server_config.h" +#include "webfuse/adapter/impl/server_config.h" +#include "webfuse/adapter/impl/authenticator.h" +#include "tempdir.hpp" + +using webfuse_test::TempDir; + +namespace +{ + +wf_mountpoint * create_mountpoint( + char const * filesystem, + void * user_data) +{ + (void) filesystem; + (void) user_data; + + return nullptr; +} + +bool authenticate( + wf_credentials * credentials, + void * user_data) +{ + (void) credentials; + (void) user_data; + + return false; +} + +} + + +TEST(server_config, create_dispose) +{ + wf_server_config * config = wf_server_config_create(); + ASSERT_NE(nullptr, config); + + wf_server_config_dispose(config); +} + +TEST(server_config, set_documentroot) +{ + wf_server_config * config = wf_server_config_create(); + ASSERT_NE(nullptr, config); + + ASSERT_EQ(nullptr, config->document_root); + + wf_server_config_set_documentroot(config, "www"); + ASSERT_STREQ("www", config->document_root); + + wf_server_config_set_documentroot(config, "/var/www"); + ASSERT_STREQ("/var/www", config->document_root); + + wf_server_config_dispose(config); +} + +TEST(server_config, set_keypath) +{ + wf_server_config * config = wf_server_config_create(); + ASSERT_NE(nullptr, config); + + ASSERT_EQ(nullptr, config->key_path); + + wf_server_config_set_keypath(config, "key.pem"); + ASSERT_STREQ("key.pem", config->key_path); + + wf_server_config_set_keypath(config, "pki/self/key.pem"); + ASSERT_STREQ("pki/self/key.pem", config->key_path); + + wf_server_config_dispose(config); +} + +TEST(server_config, set_certpath) +{ + wf_server_config * config = wf_server_config_create(); + ASSERT_NE(nullptr, config); + + ASSERT_EQ(nullptr, config->key_path); + + wf_server_config_set_certpath(config, "cert.pem"); + ASSERT_STREQ("cert.pem", config->cert_path); + + wf_server_config_set_certpath(config, "pki/self/cert.pem"); + ASSERT_STREQ("pki/self/cert.pem", config->cert_path); + + wf_server_config_dispose(config); +} + +TEST(server_config, set_vhostname) +{ + wf_server_config * config = wf_server_config_create(); + ASSERT_NE(nullptr, config); + + ASSERT_EQ(nullptr, config->key_path); + + wf_server_config_set_vhostname(config, "webfuse"); + ASSERT_STREQ("webfuse", config->vhost_name); + + wf_server_config_set_vhostname(config, "localhost"); + ASSERT_STREQ("localhost", config->vhost_name); + + wf_server_config_dispose(config); +} + +TEST(server_config, set_port) +{ + wf_server_config * config = wf_server_config_create(); + ASSERT_NE(nullptr, config); + + ASSERT_EQ(0, config->port); + + wf_server_config_set_port(config, 8443); + ASSERT_EQ(8443, config->port); + + wf_server_config_set_port(config, 8080); + ASSERT_EQ(8080, config->port); + + wf_server_config_dispose(config); +} + +TEST(server_config, set_mountpoint) +{ + TempDir temp("server_config"); + + wf_server_config * config = wf_server_config_create(); + ASSERT_NE(nullptr, config); + ASSERT_EQ(nullptr, config->mountpoint_factory.create_mountpoint); + ASSERT_EQ(nullptr, config->mountpoint_factory.user_data); + ASSERT_EQ(nullptr, config->mountpoint_factory.dispose); + + wf_server_config_set_mountpoint(config, temp.path()); + ASSERT_NE(nullptr, config->mountpoint_factory.create_mountpoint); + ASSERT_NE(nullptr, config->mountpoint_factory.user_data); + ASSERT_NE(nullptr, config->mountpoint_factory.dispose); + + wf_server_config_dispose(config); +} + +TEST(server_config, set_mounpoint_factory) +{ + wf_server_config * config = wf_server_config_create(); + ASSERT_NE(nullptr, config); + ASSERT_EQ(nullptr, config->mountpoint_factory.create_mountpoint); + ASSERT_EQ(nullptr, config->mountpoint_factory.user_data); + ASSERT_EQ(nullptr, config->mountpoint_factory.dispose); + + int value = 42; + void * user_data = reinterpret_cast(&value); + wf_server_config_set_mountpoint_factory(config, &create_mountpoint, user_data); + ASSERT_EQ(&create_mountpoint, config->mountpoint_factory.create_mountpoint); + ASSERT_EQ(user_data, config->mountpoint_factory.user_data); + ASSERT_EQ(nullptr, config->mountpoint_factory.dispose); + + wf_server_config_dispose(config); +} + +TEST(server_config, add_authenticator) +{ + wf_server_config * config = wf_server_config_create(); + ASSERT_NE(nullptr, config); + ASSERT_EQ(nullptr, config->authenticators.first); + + int value = 42; + void * user_data = reinterpret_cast(&value); + wf_server_config_add_authenticator(config, "username", &authenticate, user_data); + + wf_impl_authenticator * authenticator = config->authenticators.first; + ASSERT_STREQ("username", authenticator->type); + ASSERT_EQ(&authenticate, authenticator->authenticate); + ASSERT_EQ(user_data, authenticator->user_data); + + wf_server_config_dispose(config); +} \ No newline at end of file diff --git a/test/adapter/test_uuid_mountpoint.cc b/test/adapter/test_uuid_mountpoint.cc new file mode 100644 index 0000000..8bff760 --- /dev/null +++ b/test/adapter/test_uuid_mountpoint.cc @@ -0,0 +1,72 @@ +#include + +#include "tempdir.hpp" +#include "file_utils.hpp" +#include "webfuse_adapter.h" +#include "webfuse/adapter/impl/uuid_mountpoint.h" + +#include + +using webfuse_test::TempDir; +using webfuse_test::is_dir; +using webfuse_test::is_symlink; +using webfuse_test::is_same_path; + +TEST(uuid_mountpoint, create) +{ + TempDir temp("uuid_mountpoint"); + + std::string filesystem_path = std::string(temp.path()) + "/dummy"; + std::string default_path = std::string(temp.path()) + "/dummy/default"; + + wf_mountpoint * mountpoint = wf_impl_uuid_mountpoint_create(temp.path(), "dummy"); + std::string path = wf_mountpoint_get_path(mountpoint); + ASSERT_NE(nullptr, mountpoint); + ASSERT_TRUE(is_dir(filesystem_path)); + ASSERT_TRUE(is_symlink(default_path)); + ASSERT_TRUE(is_dir(default_path)); + ASSERT_TRUE(is_dir(path)); + ASSERT_TRUE(is_same_path(default_path, path)); + + wf_mountpoint_dispose(mountpoint); + ASSERT_FALSE(is_dir(filesystem_path)); + ASSERT_FALSE(is_symlink(default_path)); + ASSERT_FALSE(is_dir(default_path)); + ASSERT_FALSE(is_dir(path)); +} + +TEST(uuid_mountpoint, relink_default) +{ + TempDir temp("uuid_mountpoint"); + + std::string filesystem_path = std::string(temp.path()) + "/dummy"; + std::string default_path = std::string(temp.path()) + "/dummy/default"; + + wf_mountpoint * mountpoint_a = wf_impl_uuid_mountpoint_create(temp.path(), "dummy"); + std::string path_a = wf_mountpoint_get_path(mountpoint_a); + + wf_mountpoint * mountpoint_b = wf_impl_uuid_mountpoint_create(temp.path(), "dummy"); + std::string path_b = wf_mountpoint_get_path(mountpoint_b); + + ASSERT_TRUE(is_dir(filesystem_path)); + ASSERT_TRUE(is_symlink(default_path)); + ASSERT_TRUE(is_dir(default_path)); + ASSERT_TRUE(is_dir(path_a)); + ASSERT_TRUE(is_dir(path_b)); + ASSERT_TRUE(is_same_path(default_path, path_a)); + + wf_mountpoint_dispose(mountpoint_a); + ASSERT_TRUE(is_dir(filesystem_path)); + ASSERT_TRUE(is_symlink(default_path)); + ASSERT_TRUE(is_dir(default_path)); + ASSERT_FALSE(is_dir(path_a)); + ASSERT_TRUE(is_dir(path_b)); + ASSERT_TRUE(is_same_path(default_path, path_b)); + + wf_mountpoint_dispose(mountpoint_b); + ASSERT_FALSE(is_dir(filesystem_path)); + ASSERT_FALSE(is_symlink(default_path)); + ASSERT_FALSE(is_dir(default_path)); + ASSERT_FALSE(is_dir(path_a)); + ASSERT_FALSE(is_dir(path_b)); +} diff --git a/test/adapter/test_uuid_mountpoint_factory.cc b/test/adapter/test_uuid_mountpoint_factory.cc new file mode 100644 index 0000000..b097ae0 --- /dev/null +++ b/test/adapter/test_uuid_mountpoint_factory.cc @@ -0,0 +1,61 @@ +#include +#include "webfuse_adapter.h" +#include "webfuse/adapter/impl/uuid_mountpoint_factory.h" +#include "tempdir.hpp" +#include "file_utils.hpp" + +using webfuse_test::TempDir; +using webfuse_test::is_dir; + +TEST(uuid_mountpoint_factory, create_existing_dir) +{ + TempDir temp("uuid_mountpoint_factory"); + + struct wf_impl_mountpoint_factory factory; + bool factory_created = wf_impl_uuid_mountpoint_factory_init(&factory, temp.path()); + ASSERT_TRUE(factory_created); + ASSERT_TRUE(is_dir(temp.path())); + + wf_mountpoint * mountpoint = wf_impl_mountpoint_factory_create_mountpoint(&factory, "dummy"); + std::string path = wf_mountpoint_get_path(mountpoint); + ASSERT_TRUE(is_dir(path)); + + wf_mountpoint_dispose(mountpoint); + ASSERT_FALSE(is_dir(path)); + + wf_impl_mountpoint_factory_cleanup(&factory); + // keep dir not created by factory + ASSERT_TRUE(is_dir(temp.path())); +} + +TEST(uuid_mountpoint_factory, create_nonexisting_dir) +{ + TempDir temp("uuid_mountpoint_factory"); + std::string root_path = std::string(temp.path()) + "/root"; + + struct wf_impl_mountpoint_factory factory; + bool factory_created = wf_impl_uuid_mountpoint_factory_init(&factory, root_path.c_str()); + ASSERT_TRUE(factory_created); + ASSERT_TRUE(is_dir(root_path)); + + wf_mountpoint * mountpoint = wf_impl_mountpoint_factory_create_mountpoint(&factory, "dummy"); + std::string path = wf_mountpoint_get_path(mountpoint); + ASSERT_TRUE(is_dir(path)); + + wf_mountpoint_dispose(mountpoint); + ASSERT_FALSE(is_dir(path)); + + wf_impl_mountpoint_factory_cleanup(&factory); + // remove dir, created by factory + ASSERT_FALSE(is_dir(root_path)); +} + +TEST(uuid_mountpoint_factory, fail_to_created_nested_dir) +{ + TempDir temp("uuid_mountpoint_factory"); + std::string root_path = std::string(temp.path()) + "/nested/root"; + + struct wf_impl_mountpoint_factory factory; + bool factory_created = wf_impl_uuid_mountpoint_factory_init(&factory, root_path.c_str()); + ASSERT_FALSE(factory_created); +} \ No newline at end of file diff --git a/test/file_utils.cc b/test/file_utils.cc new file mode 100644 index 0000000..0d3ff81 --- /dev/null +++ b/test/file_utils.cc @@ -0,0 +1,38 @@ +#include "file_utils.hpp" + +#include +#include +#include + +namespace webfuse_test +{ + +bool is_dir(std::string const & path) +{ + struct stat info; + int rc = stat(path.c_str(), &info); + + return (0 == rc) && (S_ISDIR(info.st_mode)); +} + +bool is_symlink(std::string const & path) +{ + struct stat info; + int rc = lstat(path.c_str(), &info); + + return (0 == rc) && (S_ISLNK(info.st_mode)); +} + +bool is_same_path(std::string const & path, std::string const & other) +{ + struct stat info; + int rc = stat(path.c_str(), &info); + + struct stat info_other; + int rc_other = stat(other.c_str(), &info_other); + + return (0 == rc) && (0 == rc_other) && (info.st_ino == info_other.st_ino); +} + + +} \ No newline at end of file diff --git a/test/file_utils.hpp b/test/file_utils.hpp new file mode 100644 index 0000000..0c8cbc1 --- /dev/null +++ b/test/file_utils.hpp @@ -0,0 +1,17 @@ +#ifndef WF_TEST_FILE_UTILS_HPP +#define WF_TEST_FILE_UTILS_HPP + +#include + +namespace webfuse_test +{ + +bool is_dir(std::string const & path); + +bool is_symlink(std::string const & path); + +bool is_same_path(std::string const & path, std::string const & other); + +} + +#endif diff --git a/test/tempdir.cc b/test/tempdir.cc new file mode 100644 index 0000000..040aed1 --- /dev/null +++ b/test/tempdir.cc @@ -0,0 +1,33 @@ +#include "webfuse/core/string.h" +#include "tempdir.hpp" + +#include +#include +#include + +namespace webfuse_test +{ + +TempDir::TempDir(char const * prefix) +: path_(wf_create_string("/tmp/%s_XXXXXX", prefix)) +{ + char * result = mkdtemp(path_); + if (NULL == result) + { + throw std::runtime_error("unable to create temp dir"); + } +} + +TempDir::~TempDir() +{ + rmdir(path_); + free(path_); +} + +char const * TempDir::path() +{ + return path_; +} + + +} \ No newline at end of file diff --git a/test/tempdir.hpp b/test/tempdir.hpp new file mode 100644 index 0000000..6a03fc5 --- /dev/null +++ b/test/tempdir.hpp @@ -0,0 +1,21 @@ +#ifndef WF_TEST_TEMPDIR_HPP +#define WF_TEST_TEMPDIR_HPP + +namespace webfuse_test +{ + +class TempDir +{ + TempDir(TempDir const &) = delete; + TempDir & operator=(TempDir const &) = delete; +public: + explicit TempDir(char const * prefix); + ~TempDir(); + char const * path(); +private: + char * path_; +}; + +} + +#endif