From 0935ae330abe4aca1b63d46eaaa2f8a67c06375f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 12 Feb 2014 21:46:32 +0100 Subject: [PATCH] StorageCommands: add command "listmounts" --- src/command/AllCommands.cxx | 1 + src/command/StorageCommands.cxx | 50 ++++++++++++++++++++++++++++++++ src/command/StorageCommands.hxx | 3 ++ src/storage/CompositeStorage.hxx | 32 ++++++++++++++++++++ 4 files changed, 86 insertions(+) diff --git a/src/command/AllCommands.cxx b/src/command/AllCommands.cxx index 793a78078..a27bfd79c 100644 --- a/src/command/AllCommands.cxx +++ b/src/command/AllCommands.cxx @@ -107,6 +107,7 @@ static const struct command commands[] = { { "list", PERMISSION_READ, 1, -1, handle_list }, { "listall", PERMISSION_READ, 0, 1, handle_listall }, { "listallinfo", PERMISSION_READ, 0, 1, handle_listallinfo }, + { "listmounts", PERMISSION_READ, 0, 0, handle_listmounts }, #endif #ifdef ENABLE_NEIGHBOR_PLUGINS { "listneighbors", PERMISSION_READ, 0, 0, handle_listneighbors }, diff --git a/src/command/StorageCommands.cxx b/src/command/StorageCommands.cxx index 051deebac..8e26f3a9a 100644 --- a/src/command/StorageCommands.cxx +++ b/src/command/StorageCommands.cxx @@ -21,13 +21,63 @@ #include "StorageCommands.hxx" #include "CommandError.hxx" #include "protocol/Result.hxx" +#include "util/UriUtil.hxx" #include "util/Error.hxx" +#include "fs/Traits.hxx" #include "client/Client.hxx" #include "Partition.hxx" #include "Instance.hxx" #include "storage/Registry.hxx" #include "storage/CompositeStorage.hxx" +static void +print_storage_uri(Client &client, const Storage &storage) +{ + std::string uri = storage.MapUTF8(""); + if (uri.empty()) + return; + + if (PathTraitsFS::IsAbsolute(uri.c_str())) { + /* storage points to local directory */ + + if (!client.IsLocal()) + /* only "local" clients may see local paths + (same policy as with the "config" + command) */ + return; + } else { + /* hide username/passwords from client */ + + std::string allocated = uri_remove_auth(uri.c_str()); + if (!allocated.empty()) + uri = std::move(allocated); + } + + client_printf(client, "storage: %s\n", uri.c_str()); +} + +CommandResult +handle_listmounts(Client &client, gcc_unused int argc, gcc_unused char *argv[]) +{ + Storage *_composite = client.partition.instance.storage; + if (_composite == nullptr) { + command_error(client, ACK_ERROR_NO_EXIST, "No database"); + return CommandResult::ERROR; + } + + CompositeStorage &composite = *(CompositeStorage *)_composite; + + const auto visitor = [&client](const char *mount_uri, + const Storage &storage){ + client_printf(client, "mount: %s\n", mount_uri); + print_storage_uri(client, storage); + }; + + composite.VisitMounts(visitor); + + return CommandResult::OK; +} + CommandResult handle_mount(Client &client, gcc_unused int argc, char *argv[]) { diff --git a/src/command/StorageCommands.hxx b/src/command/StorageCommands.hxx index 588cf8ac2..33afda34a 100644 --- a/src/command/StorageCommands.hxx +++ b/src/command/StorageCommands.hxx @@ -24,6 +24,9 @@ class Client; +CommandResult +handle_listmounts(Client &client, int argc, char *argv[]); + CommandResult handle_mount(Client &client, int argc, char *argv[]); diff --git a/src/storage/CompositeStorage.hxx b/src/storage/CompositeStorage.hxx index 696ffff61..9c10f76f4 100644 --- a/src/storage/CompositeStorage.hxx +++ b/src/storage/CompositeStorage.hxx @@ -95,6 +95,18 @@ public: CompositeStorage(); virtual ~CompositeStorage(); + /** + * Call the given function for each mounted storage, including + * the root storage. Passes mount point URI and the a const + * Storage reference to the function. + */ + template + void VisitMounts(T t) const { + const ScopeLock protect(mutex); + std::string uri; + VisitMounts(uri, root, t); + } + void Mount(const char *uri, Storage *storage); bool Unmount(const char *uri); @@ -112,6 +124,26 @@ public: virtual const char *MapToRelativeUTF8(const char *uri) const override; private: + template + void VisitMounts(std::string &uri, const Directory &directory, + T t) const { + const Storage *const storage = directory.storage; + if (storage != nullptr) + t(uri.c_str(), *storage); + + if (!uri.empty()) + uri.push_back('/'); + + const size_t uri_length = uri.length(); + + for (const auto &i : directory.children) { + uri.resize(uri_length); + uri.append(i.first); + + VisitMounts(uri, i.second, t); + } + } + gcc_pure FindResult FindStorage(const char *uri) const; FindResult FindStorage(const char *uri, Error &error) const;