diff --git a/src/command/StorageCommands.cxx b/src/command/StorageCommands.cxx index 288f341d0..2dea85e8d 100644 --- a/src/command/StorageCommands.cxx +++ b/src/command/StorageCommands.cxx @@ -203,6 +203,11 @@ handle_mount(Client &client, Request args, Response &r) return CommandResult::ERROR; } + if (composite.IsMounted(remote_uri)) { + r.Error(ACK_ERROR_ARG, "This storage is already mounted"); + return CommandResult::ERROR; + } + auto &event_loop = instance.io_thread.GetEventLoop(); auto storage = CreateStorageURI(event_loop, remote_uri); if (storage == nullptr) { diff --git a/src/storage/CompositeStorage.hxx b/src/storage/CompositeStorage.hxx index d6c424d54..c06240403 100644 --- a/src/storage/CompositeStorage.hxx +++ b/src/storage/CompositeStorage.hxx @@ -121,6 +121,15 @@ public: VisitMounts(uri, root, t); } + /** + * Is a storage with the given URI already mounted? + */ + gcc_pure gcc_nonnull_all + bool IsMounted(const char *storage_uri) const noexcept { + const std::lock_guard<Mutex> protect(mutex); + return IsMounted(root, storage_uri); + } + void Mount(const char *uri, std::unique_ptr<Storage> storage); bool Unmount(const char *uri); @@ -155,6 +164,22 @@ private: } } + gcc_pure gcc_nonnull_all + static bool IsMounted(const Directory &directory, + const char *storage_uri) noexcept { + if (directory.storage) { + const auto uri = directory.storage->MapUTF8(""); + if (uri == storage_uri) + return true; + } + + for (const auto &i : directory.children) + if (IsMounted(i.second, storage_uri)) + return true; + + return false; + } + /** * Follow the given URI path, and find the outermost directory * which is a #Storage mount point. If there are no mounts, diff --git a/src/storage/StorageState.cxx b/src/storage/StorageState.cxx index 34e669787..404dfeeb3 100644 --- a/src/storage/StorageState.cxx +++ b/src/storage/StorageState.cxx @@ -112,6 +112,11 @@ storage_state_restore(const char *line, TextFile &file, Instance &instance) return true; } + if (composite_storage.IsMounted(url.c_str())) { + LogError(storage_domain, "This storage is already mounted"); + return true; + } + auto &event_loop = instance.io_thread.GetEventLoop(); auto storage = CreateStorageURI(event_loop, url.c_str()); if (storage == nullptr) {