From cfadf85f49f16a1f3396950d3a3d72b13b3e47fb Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 16 Feb 2020 04:02:23 +0100 Subject: [PATCH] added uuid mountpoint and factory --- cmake/webfuse_adapter.cmake | 2 + include/webfuse/adapter/mountpoint.h | 11 +- lib/webfuse/adapter/api.c | 7 +- lib/webfuse/adapter/impl/mountpoint.c | 28 ++-- lib/webfuse/adapter/impl/mountpoint.h | 7 +- lib/webfuse/adapter/impl/uuid_mountpoint.c | 123 ++++++++++++++++++ lib/webfuse/adapter/impl/uuid_mountpoint.h | 20 +++ .../adapter/impl/uuid_mountpoint_factory.c | 47 +++++++ .../adapter/impl/uuid_mountpoint_factory.h | 29 +++++ test/adapter/test_mountpoint.cc | 18 +-- 10 files changed, 259 insertions(+), 33 deletions(-) create mode 100644 lib/webfuse/adapter/impl/uuid_mountpoint.c create mode 100644 lib/webfuse/adapter/impl/uuid_mountpoint.h create mode 100644 lib/webfuse/adapter/impl/uuid_mountpoint_factory.c create mode 100644 lib/webfuse/adapter/impl/uuid_mountpoint_factory.h diff --git a/cmake/webfuse_adapter.cmake b/cmake/webfuse_adapter.cmake index f970ef7..aa343b7 100644 --- a/cmake/webfuse_adapter.cmake +++ b/cmake/webfuse_adapter.cmake @@ -16,6 +16,8 @@ add_library(webfuse-adapter-static STATIC lib/webfuse/adapter/impl/credentials.c lib/webfuse/adapter/impl/operations.c lib/webfuse/adapter/impl/mountpoint.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 index 7936b83..62f59f3 100644 --- a/include/webfuse/adapter/mountpoint.h +++ b/include/webfuse/adapter/mountpoint.h @@ -9,8 +9,8 @@ extern "C" struct wf_mountpoint; typedef void -wf_mountpoint_ondispose_fn( - struct wf_mountpoint * mountpoint); +wf_mountpoint_userdata_dispose_fn( + void * user_data); extern struct wf_mountpoint * wf_mountpoint_create( @@ -25,9 +25,10 @@ wf_mountpoint_get_path( struct wf_mountpoint const * mountpoint); extern void -wf_mountpoint_set_ondispose( - struct wf_mountpoint * mountpoint, - wf_mountpoint_ondispose_fn * ondispose); +wf_mountpoint_set_userdata( + struct wf_mountpoint * mointpoint, + void * user_data, + wf_mountpoint_userdata_dispose_fn * dispose); #ifdef __cplusplus } diff --git a/lib/webfuse/adapter/api.c b/lib/webfuse/adapter/api.c index 64f55a3..2d1bac2 100644 --- a/lib/webfuse/adapter/api.c +++ b/lib/webfuse/adapter/api.c @@ -160,9 +160,10 @@ wf_mountpoint_get_path( } void -wf_mountpoint_set_ondispose( +wf_mountpoint_set_userdata( struct wf_mountpoint * mountpoint, - wf_mountpoint_ondispose_fn * ondispose) + void * user_data, + wf_mountpoint_userdata_dispose_fn * dispose) { - wf_impl_mountpoint_set_ondispose(mountpoint, ondispose); + wf_impl_mountpoint_set_userdata(mountpoint, user_data, dispose); } diff --git a/lib/webfuse/adapter/impl/mountpoint.c b/lib/webfuse/adapter/impl/mountpoint.c index ade1223..a459510 100644 --- a/lib/webfuse/adapter/impl/mountpoint.c +++ b/lib/webfuse/adapter/impl/mountpoint.c @@ -6,23 +6,18 @@ struct wf_mountpoint { char * path; - wf_mountpoint_ondispose_fn * ondispose; + void * user_data; + wf_mountpoint_userdata_dispose_fn * dispose; }; -static void wf_impl_mountpoint_default_ondispose( - struct wf_mountpoint * mountpoint) -{ - (void) mountpoint; - // empty -} - struct wf_mountpoint * wf_impl_mountpoint_create( char const * path) { struct wf_mountpoint * mountpoint = malloc(sizeof(struct wf_mountpoint)); mountpoint->path = strdup(path); - mountpoint->ondispose = &wf_impl_mountpoint_default_ondispose; + mountpoint->user_data = NULL; + mountpoint->dispose = NULL; return mountpoint; } @@ -31,7 +26,10 @@ void wf_impl_mountpoint_dispose( struct wf_mountpoint * mountpoint) { - mountpoint->ondispose(mountpoint); + if (NULL != mountpoint->dispose) + { + mountpoint->dispose(mountpoint->user_data); + } free(mountpoint->path); free(mountpoint); @@ -44,10 +42,12 @@ wf_impl_mountpoint_get_path( return mountpoint->path; } -void -wf_impl_mountpoint_set_ondispose( +extern void +wf_impl_mountpoint_set_userdata( struct wf_mountpoint * mountpoint, - wf_mountpoint_ondispose_fn * ondispose) + void * user_data, + wf_mountpoint_userdata_dispose_fn * dispose) { - mountpoint->ondispose = ondispose; + mountpoint->user_data = user_data; + mountpoint->dispose = dispose; } diff --git a/lib/webfuse/adapter/impl/mountpoint.h b/lib/webfuse/adapter/impl/mountpoint.h index a7041f8..77fc0ea 100644 --- a/lib/webfuse/adapter/impl/mountpoint.h +++ b/lib/webfuse/adapter/impl/mountpoint.h @@ -21,9 +21,10 @@ wf_impl_mountpoint_get_path( struct wf_mountpoint const * mountpoint); extern void -wf_impl_mountpoint_set_ondispose( - struct wf_mountpoint * mointpoint, - wf_mountpoint_ondispose_fn * ondispose); +wf_impl_mountpoint_set_userdata( + struct wf_mountpoint * mountpoint, + void * user_data, + wf_mountpoint_userdata_dispose_fn * dispose); #ifdef __cplusplus } diff --git a/lib/webfuse/adapter/impl/uuid_mountpoint.c b/lib/webfuse/adapter/impl/uuid_mountpoint.c new file mode 100644 index 0000000..1b0cd8a --- /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_filesystem_is_link_broken(data->default_path, data->id)) + { + unlink(data->default_path); + + bool const success = wf_impl_filesystem_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(); + char * 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, data->filesystem_path); + symlink(data->id, data->default_path); + + struct wf_mountpoint * mountpoint = wf_impl_mountpoint_create(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..f982f5b --- /dev/null +++ b/lib/webfuse/adapter/impl/uuid_mountpoint_factory.c @@ -0,0 +1,47 @@ +#include "webfuse/adapter/impl/uuid_mountpoint_factory.h" +#include "webfuse/adapter/impl/uuid_mountpoint.h" + +#include +#include +#include + +#include +#include + +struct wf_impl_uuid_mountpoint_factory +{ + char * root_path; +}; + +void * +wf_impl_uuid_mountpoint_factory_create( + char * root_path) +{ + mkdir(root_path, 0755); + + struct wf_impl_uuid_mountpoint_factory * factory = malloc(sizeof(struct wf_impl_uuid_mountpoint_factory)); + factory->root_path = strdup(root_path); + + return factory; +} + +void +wf_impl_uuid_mountpoint_factory_dispose( + void * user_data) +{ + struct wf_impl_uuid_mountpoint_factory * factory = user_data; + + rmdir(factory->root_path); + free(factory->root_path); + free(factory); +} + +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); +} 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..a406597 --- /dev/null +++ b/lib/webfuse/adapter/impl/uuid_mountpoint_factory.h @@ -0,0 +1,29 @@ +#ifndef WF_IMPL_UUID_MOUNTPOINT_FACTORY_H +#define WF_IMPL_UUID_MOUNTPOINT_FACTORY_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wf_mountpoint; + +extern void * +wf_impl_uuid_mountpoint_factory_create( + char * root_path); + +extern void +wf_impl_uuid_mountpoint_factory_dispose( + void * user_data); + +extern struct wf_mountpoint * +wf_impl_uuid_mountpoint_factory_create_mountpiont( + char const * filesystem, + void * user_data); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/adapter/test_mountpoint.cc b/test/adapter/test_mountpoint.cc index a3d82c6..6bb486b 100644 --- a/test/adapter/test_mountpoint.cc +++ b/test/adapter/test_mountpoint.cc @@ -4,17 +4,17 @@ namespace { - class MockMountpointDisposer + class MockUserDataDisposer { public: - MOCK_METHOD1(ondispose, void(wf_mountpoint * mountpoint)); + MOCK_METHOD1(dispose, void(void * mountpoint)); }; - MockMountpointDisposer * global_disposer = nullptr; + MockUserDataDisposer * global_disposer = nullptr; - void ondispose(wf_mountpoint * mountpoint) + void ondispose(void * user_data) { - global_disposer->ondispose(mountpoint); + global_disposer->dispose(user_data); } } @@ -32,14 +32,16 @@ TEST(mountpoint, get_path) TEST(mountpoint, ondispose) { - MockMountpointDisposer disposer; + MockUserDataDisposer disposer; global_disposer = &disposer; wf_mountpoint * mountpoint = wf_mountpoint_create("/some/path"); ASSERT_NE(nullptr, mountpoint); - wf_mountpoint_set_ondispose(mountpoint, ondispose); - EXPECT_CALL(disposer, ondispose(mountpoint)).Times(1); + 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