From b62e9fc67b252a843871ea2e4ee1fb2e47bdb1c8 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Tue, 17 Mar 2020 21:51:04 +0100 Subject: [PATCH] parse filesystem info --- CMakeLists.txt | 2 + src/webfused/config/builder.c | 9 ++ src/webfused/config/builder.h | 12 +++ src/webfused/config/config.c | 23 ++++- src/webfused/config/factory.c | 50 +++++++++++ src/webfused/mountpoint_factory.c | 145 ++++++++++++++++++++++++++++++ src/webfused/mountpoint_factory.h | 39 ++++++++ test/mock_config_builder.cc | 15 +++- test/mock_config_builder.hpp | 2 + test/test_config.cc | 19 ++++ test/test_config_factory.cc | 100 +++++++++++++++++++++ test/test_mountpoint_factory.cc | 135 ++++++++++++++++++++++++++++ 12 files changed, 546 insertions(+), 5 deletions(-) create mode 100644 src/webfused/mountpoint_factory.c create mode 100644 src/webfused/mountpoint_factory.h create mode 100644 test/test_mountpoint_factory.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index ce13d3d..cb57ec6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,7 @@ target_compile_options(userdb PUBLIC ${OPENSSL_CFLAGS_OTHER}) add_library(webfused-static STATIC src/webfused/daemon.c + src/webfused/mountpoint_factory.c src/webfused/config/config.c src/webfused/config/factory.c src/webfused/config/builder.c @@ -119,6 +120,7 @@ add_executable(alltests test/test_auth_settings.cc test/test_auth_factory.cc test/test_file_authenticator.cc + test/test_mountpoint_factory.cc test/test_log.cc ) diff --git a/src/webfused/config/builder.c b/src/webfused/config/builder.c index e59c9d5..af13c09 100644 --- a/src/webfused/config/builder.c +++ b/src/webfused/config/builder.c @@ -48,4 +48,13 @@ wfd_config_builder_add_auth_provider( return builder.vtable->add_auth_provider(builder.data, settings); } +bool +wfd_config_builder_add_filesystem( + struct wfd_config_builder builder, + char const * name, + char const * mount_point) +{ + return builder.vtable->add_filesystem(builder.data, name, mount_point); +} + diff --git a/src/webfused/config/builder.h b/src/webfused/config/builder.h index 0e75f2d..8e23fd1 100644 --- a/src/webfused/config/builder.h +++ b/src/webfused/config/builder.h @@ -42,6 +42,12 @@ wfd_config_builder_add_auth_provider_fn( void * data, struct wfd_auth_settings * settings); +typedef bool +wfd_config_builder_add_filesystem_fn( + void * data, + char const * name, + char const * mount_point); + struct wfd_config_builder_vtable { wfd_config_builder_set_server_vhostname_fn * set_server_vhostname; @@ -50,6 +56,7 @@ struct wfd_config_builder_vtable wfd_config_builder_set_server_cert_fn * set_server_cert; wfd_config_builder_set_server_document_root_fn * set_server_document_root; wfd_config_builder_add_auth_provider_fn * add_auth_provider; + wfd_config_builder_add_filesystem_fn * add_filesystem; }; struct wfd_config_builder @@ -88,6 +95,11 @@ wfd_config_builder_add_auth_provider( struct wfd_config_builder builder, struct wfd_auth_settings * settings); +extern bool +wfd_config_builder_add_filesystem( + struct wfd_config_builder builder, + char const * name, + char const * mount_point); #ifdef __cplusplus } diff --git a/src/webfused/config/config.c b/src/webfused/config/config.c index 868bb5b..6499f12 100644 --- a/src/webfused/config/config.c +++ b/src/webfused/config/config.c @@ -2,6 +2,7 @@ #include "webfuse/adapter/server_config.h" #include "webfused/auth/factory.h" #include "webfused/auth/authenticator.h" +#include "webfused/mountpoint_factory.h" #include @@ -13,6 +14,7 @@ struct wfd_config struct wf_server_config * server; bool has_authenticator; struct wfd_authenticator authenticator; + struct wfd_mountpoint_factory * mountpoint_factory; }; static void @@ -86,6 +88,16 @@ wfd_config_add_auth_provider( return result; } +static bool +wfd_config_add_filesystem( + void * data, + char const * name, + char const * mount_point) +{ + struct wfd_config * config = data; + return wfd_mountpoint_factory_add_filesystem( + config->mountpoint_factory, name, mount_point); +} static const struct wfd_config_builder_vtable wfd_config_vtable_config_builder = @@ -95,7 +107,8 @@ wfd_config_vtable_config_builder = .set_server_key = &wfd_config_set_server_key, .set_server_cert = &wfd_config_set_server_cert, .set_server_document_root = &wfd_config_set_server_document_root, - .add_auth_provider = &wfd_config_add_auth_provider + .add_auth_provider = &wfd_config_add_auth_provider, + .add_filesystem = &wfd_config_add_filesystem }; struct wfd_config * @@ -103,11 +116,14 @@ wfd_config_create(void) { struct wfd_config * config = malloc(sizeof(struct wfd_config)); + config->mountpoint_factory = wfd_mountpoint_factory_create(); + config->has_authenticator = false; config->server = wf_server_config_create(); wf_server_config_set_vhostname(config->server, WFD_CONFIG_DEFAULT_VHOSTNAME); wf_server_config_set_port(config->server, WFD_CONFIG_DEFAULT_PORT); - - config->has_authenticator = false; + wf_server_config_set_mountpoint_factory(config->server, + wfd_mountpoint_factory_create_mountpoint, + config->mountpoint_factory); return config; } @@ -121,6 +137,7 @@ wfd_config_dispose( { wfd_authenticator_dispose(config->authenticator); } + wfd_mountpoint_factory_dispose(config->mountpoint_factory); free(config); } diff --git a/src/webfused/config/factory.c b/src/webfused/config/factory.c index 6be06bf..9343b38 100644 --- a/src/webfused/config/factory.c +++ b/src/webfused/config/factory.c @@ -143,6 +143,55 @@ wfd_config_read_authentication( return result; } +static bool +wfd_config_read_filesystems( + config_t * config, + struct wfd_config_builder builder) +{ + bool result = true; + config_setting_t * filesystems = config_lookup(config, "filesystems"); + if (NULL != filesystems) + { + int length = config_setting_length(filesystems); + for (int i = 0; i < length; i++) + { + config_setting_t * fs = config_setting_get_elem(filesystems, i); + if (NULL == fs) + { + WFD_ERROR("failed to load config: invalid filesystem section"); + result = false; + break; + } + + char const * name; + int rc = config_setting_lookup_string(fs, "name", &name); + if (rc != CONFIG_TRUE) + { + WFD_ERROR("failed to load config: missing required filesystem property \'name\'"); + result = false; + break; + } + + char const * mount_point; + rc = config_setting_lookup_string(fs, "mount_point", &mount_point); + if (rc != CONFIG_TRUE) + { + WFD_ERROR("failed to load config: missing required filesystem property \'mount_point\'"); + result = false; + break; + } + + result = wfd_config_builder_add_filesystem(builder, name, mount_point); + if (!result) + { + break; + } + } + } + + return result; +} + static bool wfd_config_load( struct wfd_config_builder builder, @@ -152,6 +201,7 @@ wfd_config_load( bool result = wfd_config_check_version(config) && wfd_config_read_server(config, builder) && wfd_config_read_authentication(config, builder) + && wfd_config_read_filesystems(config, builder) ; return result; diff --git a/src/webfused/mountpoint_factory.c b/src/webfused/mountpoint_factory.c new file mode 100644 index 0000000..a327937 --- /dev/null +++ b/src/webfused/mountpoint_factory.c @@ -0,0 +1,145 @@ +#include "webfused/mountpoint_factory.h" +#include "webfused/log/log.h" + +#include + +#include +#include +#include + +#define WFD_FILESYSTEM_DEFAULT_CAPACITY 16 + +struct wfd_filesystem +{ + char * name; + char * mount_point; + bool in_use; +}; + +struct wfd_mountpoint_factory +{ + struct wfd_filesystem * filesystems; + size_t capacity; + size_t count; +}; + +static struct wfd_filesystem * +wfd_mountpoint_factory_find( + struct wfd_mountpoint_factory * factory, + char const * name) +{ + for (size_t i = 0; i < factory->count; i++) + { + struct wfd_filesystem * filesystem = &(factory->filesystems[i]); + if (0 == strcmp(name, filesystem->name)) + { + return filesystem; + } + } + + return NULL; +} + +static void +wfd_mountpoint_factory_release_mountpoint( + void * user_data) +{ + bool * in_use = user_data; + *in_use = false; +} + +struct wfd_mountpoint_factory * +wfd_mountpoint_factory_create(void) +{ + struct wfd_mountpoint_factory * factory = malloc(sizeof(struct wfd_mountpoint_factory)); + factory->filesystems = malloc(sizeof(struct wfd_filesystem) * WFD_FILESYSTEM_DEFAULT_CAPACITY); + factory->count = 0; + factory->capacity = WFD_FILESYSTEM_DEFAULT_CAPACITY; + + return factory; +} + +void +wfd_mountpoint_factory_dispose( + struct wfd_mountpoint_factory * factory) +{ + for(size_t i = 0; i < factory->count; i++) + { + struct wfd_filesystem * filesystem = &(factory->filesystems[i]); + free(filesystem->name); + free(filesystem->mount_point); + } + + free(factory->filesystems); + free(factory); +} + +bool +wfd_mountpoint_factory_add_filesystem( + struct wfd_mountpoint_factory * factory, + char const * name, + char const * mount_point) +{ + bool result = (NULL == wfd_mountpoint_factory_find(factory, name)); + if (!result) + { + WFD_ERROR("mount_point already defined: \'%s\'", mount_point); + } + + char * path = NULL; + if (result) + { + mkdir(mount_point, 0755); + path = realpath(mount_point, NULL); + if (NULL == path) + { + WFD_ERROR("invalid mount_point: \'%s\'", mount_point); + result = false; + } + } + + if (result) + { + if (factory->count >= factory->capacity) + { + factory->capacity *= 2; + factory->filesystems = realloc(factory->filesystems, + sizeof(struct wfd_filesystem) * factory->capacity); + } + + struct wfd_filesystem * actual = &(factory->filesystems[factory->count]); + actual->name = strdup(name); + actual->mount_point = path; + actual->in_use = false; + factory->count++; + } + + return result; +} + +extern struct wf_mountpoint * +wfd_mountpoint_factory_create_mountpoint( + char const * filesystem, + void * user_data) +{ + struct wfd_mountpoint_factory * factory = user_data; + struct wfd_filesystem * fs = wfd_mountpoint_factory_find(factory, filesystem); + if (NULL == fs) + { + WFD_INFO("failed to create mountpoint: filesystem \'%s\' not found", filesystem); + return NULL; + } + + if (fs->in_use) + { + WFD_INFO("failed to create mountpoint: filesystem \'%s\' already in use", filesystem); + return NULL; + } + + fs->in_use = true; + struct wf_mountpoint * result = wf_mountpoint_create(fs->mount_point); + wf_mountpoint_set_userdata(result, + &fs->in_use, &wfd_mountpoint_factory_release_mountpoint); + + return result; +} diff --git a/src/webfused/mountpoint_factory.h b/src/webfused/mountpoint_factory.h new file mode 100644 index 0000000..3459ad4 --- /dev/null +++ b/src/webfused/mountpoint_factory.h @@ -0,0 +1,39 @@ +#ifndef WFD_MOUNTPOINT_FACTORY_H +#define WFD_MOUNTPOINT_FACTORY_H + +#include "webfuse/adapter/mountpoint_factory.h" + +#ifndef __cplusplus +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wfd_mountpoint_factory; + +extern struct wfd_mountpoint_factory * +wfd_mountpoint_factory_create(void); + +extern void +wfd_mountpoint_factory_dispose( + struct wfd_mountpoint_factory * factory); + +extern bool +wfd_mountpoint_factory_add_filesystem( + struct wfd_mountpoint_factory * factory, + char const * name, + char const * mount_point); + +extern struct wf_mountpoint * +wfd_mountpoint_factory_create_mountpoint( + char const * filesystem, + void * user_data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/mock_config_builder.cc b/test/mock_config_builder.cc index 0fb7f11..f872edf 100644 --- a/test/mock_config_builder.cc +++ b/test/mock_config_builder.cc @@ -55,7 +55,17 @@ wfd_MockConfigBuilder_add_auth_provider( struct wfd_auth_settings * settings) { auto * builder = reinterpret_cast(data); - builder->addAuthProvider(settings); + return builder->addAuthProvider(settings); +} + +static bool +wfd_MockConfigBuilder_add_filesystem( + void * data, + char const * name, + char const * mountpoint) +{ + auto * builder = reinterpret_cast(data); + return builder->addFilesystem(name, mountpoint); } @@ -66,7 +76,8 @@ static const wfd_config_builder_vtable wfd_MockConfigBuilder_vtable = &wfd_MockConfigBuilder_set_server_key, &wfd_MockConfigBuilder_set_server_cert, &wfd_MockConfigBuilder_set_server_document_root, - &wfd_MockConfigBuilder_add_auth_provider + &wfd_MockConfigBuilder_add_auth_provider, + &wfd_MockConfigBuilder_add_filesystem }; } diff --git a/test/mock_config_builder.hpp b/test/mock_config_builder.hpp index 7141c17..d37c47a 100644 --- a/test/mock_config_builder.hpp +++ b/test/mock_config_builder.hpp @@ -17,6 +17,7 @@ public: virtual void setServerCert(char const * cert_path) = 0; virtual void setServerDocumentRoot(char const * document_root) = 0; virtual bool addAuthProvider(wfd_auth_settings * settings) = 0; + virtual bool addFilesystem(char const * name, char const * mountpoint) = 0; }; class MockConfigBuilder: public IConfigBuilder @@ -29,6 +30,7 @@ public: MOCK_METHOD1(setServerCert, void (char const * cert_path)); MOCK_METHOD1(setServerDocumentRoot, void (char const * document_root)); MOCK_METHOD1(addAuthProvider, bool (wfd_auth_settings * settings)); + MOCK_METHOD2(addFilesystem, bool (char const * name, char const * mountpoint)); struct wfd_config_builder getBuilder(); }; diff --git a/test/test_config.cc b/test/test_config.cc index d07abd9..a86a777 100644 --- a/test/test_config.cc +++ b/test/test_config.cc @@ -2,6 +2,12 @@ #include "webfused/config/config.h" #include "mock_auth_settings.hpp" +#include "webfused/log/logger.h" +#include "webfused/log/log.h" +#include "mock_logger.hpp" +using ::webfused_test::MockLogger; +using ::testing::_; + using ::webfused_test::MockAuthSettings; using ::testing::Return; using ::testing::StrEq; @@ -74,5 +80,18 @@ TEST(config, auth_config_failed_to_add_unknown_provider) bool success = wfd_config_builder_add_auth_provider(builder, nullptr); ASSERT_FALSE(success); + wfd_config_dispose(config); +} + +TEST(config, add_filesystem) +{ + wfd_config * config = wfd_config_create(); + ASSERT_NE(nullptr, config); + + wfd_config_builder builder = wfd_config_get_builder(config); + + bool success = wfd_config_builder_add_filesystem(builder, "test", "/tmp/test"); + ASSERT_TRUE(success); + wfd_config_dispose(config); } \ No newline at end of file diff --git a/test/test_config_factory.cc b/test/test_config_factory.cc index 425d161..ba83165 100644 --- a/test/test_config_factory.cc +++ b/test/test_config_factory.cc @@ -20,6 +20,7 @@ TEST(config, is_loadable) EXPECT_CALL(builder, setServerVhostname(StrEq("localhost"))).Times(1); EXPECT_CALL(builder, setServerPort(8080)).Times(1); EXPECT_CALL(builder, addAuthProvider(_)).Times(1).WillOnce(Return(true)); + EXPECT_CALL(builder, addFilesystem(_,_)).Times(1).WillOnce(Return(true)); bool result = wfd_config_load_file(builder.getBuilder(), "webfused.conf"); ASSERT_TRUE(result); @@ -333,3 +334,102 @@ TEST(config, failed_missing_auth_settings) bool result = wfd_config_load_string(builder.getBuilder(), config_text); ASSERT_FALSE(result); } + +TEST(config, filesystems) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, addFilesystem(_, _)).Times(1).WillOnce(Return(true)); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "filesystems:\n" + "(\n" + " {name = \"foo\", mount_point = \"/tmp/test\" }\n" + ")\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_TRUE(result); +} + +TEST(config, filesystems_empty) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, addFilesystem(_, _)).Times(0); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "filesystems:\n" + "(\n" + ")\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_TRUE(result); +} + +TEST(config, filesystems_failed_add) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, addFilesystem(_, _)).Times(1).WillOnce(Return(false)); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "filesystems:\n" + "(\n" + " {name = \"foo\", mount_point = \"/tmp/test\" }\n" + ")\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_FALSE(result); +} + +TEST(config, filesystems_failed_missing_name) +{ + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, addFilesystem(_, _)).Times(0); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "filesystems:\n" + "(\n" + " {mount_point = \"/tmp/test\" }\n" + ")\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_FALSE(result); +} + +TEST(config, filesystems_failed_missing_mountpoint) +{ + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, addFilesystem(_, _)).Times(0); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "filesystems:\n" + "(\n" + " {name = \"foo\"}\n" + ")\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_FALSE(result); +} diff --git a/test/test_mountpoint_factory.cc b/test/test_mountpoint_factory.cc new file mode 100644 index 0000000..0509d0f --- /dev/null +++ b/test/test_mountpoint_factory.cc @@ -0,0 +1,135 @@ +#include +#include "webfused/mountpoint_factory.h" +#include + +#include + +TEST(mountpoint_factory, create) +{ + wfd_mountpoint_factory * factory = wfd_mountpoint_factory_create(); + ASSERT_NE(nullptr, factory); + + wfd_mountpoint_factory_dispose(factory); +} + +TEST(mountpiont_factory, add_filesystem) +{ + wfd_mountpoint_factory * factory = wfd_mountpoint_factory_create(); + ASSERT_NE(nullptr, factory); + + bool success = wfd_mountpoint_factory_add_filesystem(factory, "test", "/tmp/webfused_test"); + ASSERT_TRUE(success); + + wfd_mountpoint_factory_dispose(factory); +} + +TEST(mountpiont_factory, add_filesystem_fail_to_add_twice) +{ + wfd_mountpoint_factory * factory = wfd_mountpoint_factory_create(); + ASSERT_NE(nullptr, factory); + + bool success = wfd_mountpoint_factory_add_filesystem(factory, "test", "/tmp/webfused_test"); + ASSERT_TRUE(success); + + success = wfd_mountpoint_factory_add_filesystem(factory, "test", "/tmp/webfused_test"); + ASSERT_FALSE(success); + + wfd_mountpoint_factory_dispose(factory); +} + +TEST(mountpiont_factory, add_filesystem_multi) +{ + wfd_mountpoint_factory * factory = wfd_mountpoint_factory_create(); + ASSERT_NE(nullptr, factory); + + + for (size_t i = 0; i < 24; i++) + { + char name[10]; + snprintf(name, 10, "test_%zu", i); + bool success = wfd_mountpoint_factory_add_filesystem(factory, name, "/tmp/webfused_test"); + ASSERT_TRUE(success) << i; + } + + wfd_mountpoint_factory_dispose(factory); +} + +TEST(mountpiont_factory, add_filesystem_fail_invalid_path) +{ + wfd_mountpoint_factory * factory = wfd_mountpoint_factory_create(); + ASSERT_NE(nullptr, factory); + + bool success = wfd_mountpoint_factory_add_filesystem(factory, "test", "/do/not/allow/nested/paths"); + ASSERT_FALSE(success); + + wfd_mountpoint_factory_dispose(factory); +} + +TEST(mountpiont_factory, create_mountpoint) +{ + wfd_mountpoint_factory * factory = wfd_mountpoint_factory_create(); + ASSERT_NE(nullptr, factory); + + bool success = wfd_mountpoint_factory_add_filesystem(factory, "test", "/tmp/webfuse_test"); + ASSERT_TRUE(success); + + wf_mountpoint * mountpoint = wfd_mountpoint_factory_create_mountpoint("test", factory); + ASSERT_NE(nullptr, mountpoint); + ASSERT_STREQ("/tmp/webfuse_test", wf_mountpoint_get_path(mountpoint)); + + wf_mountpoint_dispose(mountpoint); + wfd_mountpoint_factory_dispose(factory); +} + +TEST(mountpiont_factory, create_mountpoint_fail_already_in_use) +{ + wfd_mountpoint_factory * factory = wfd_mountpoint_factory_create(); + ASSERT_NE(nullptr, factory); + + bool success = wfd_mountpoint_factory_add_filesystem(factory, "test", "/tmp/webfuse_test"); + ASSERT_TRUE(success); + + wf_mountpoint * mountpoint = wfd_mountpoint_factory_create_mountpoint("test", factory); + ASSERT_NE(nullptr, mountpoint); + ASSERT_STREQ("/tmp/webfuse_test", wf_mountpoint_get_path(mountpoint)); + + wf_mountpoint * mountpoint2 = wfd_mountpoint_factory_create_mountpoint("test", factory); + ASSERT_EQ(nullptr, mountpoint2); + + wf_mountpoint_dispose(mountpoint); + wfd_mountpoint_factory_dispose(factory); +} + +TEST(mountpiont_factory, create_mountpoint_fail_unknown_filesystem) +{ + wfd_mountpoint_factory * factory = wfd_mountpoint_factory_create(); + ASSERT_NE(nullptr, factory); + + bool success = wfd_mountpoint_factory_add_filesystem(factory, "test", "/tmp/webfuse_test"); + ASSERT_TRUE(success); + + wf_mountpoint * mountpoint = wfd_mountpoint_factory_create_mountpoint("unkown", factory); + ASSERT_EQ(nullptr, mountpoint); + + wfd_mountpoint_factory_dispose(factory); +} + +TEST(mountpiont_factory, create_mountpoint_multi) +{ + wfd_mountpoint_factory * factory = wfd_mountpoint_factory_create(); + ASSERT_NE(nullptr, factory); + + bool success = wfd_mountpoint_factory_add_filesystem(factory, "test", "/tmp/webfuse_test"); + ASSERT_TRUE(success); + + for(int i = 0; i < 5; i++) + { + wf_mountpoint * mountpoint = wfd_mountpoint_factory_create_mountpoint("test", factory); + ASSERT_NE(nullptr, mountpoint) << i; + ASSERT_STREQ("/tmp/webfuse_test", wf_mountpoint_get_path(mountpoint)) << i; + + wf_mountpoint_dispose(mountpoint); + } + + wfd_mountpoint_factory_dispose(factory); +}