command/storage: check if mount point is busy
When mounting something over a directory that is already a mount point, CompositeStorage::Mount() silently overwrites the previously mounted storage, disposing it. After that, SimpleDatabase::Mount() will fail and handle_mount() will roll back the CompositeStorage::Mount() command, effectively unmounting what was there before (and also leaking memory). Closes https://github.com/MusicPlayerDaemon/MPD/issues/918
This commit is contained in:
parent
5b291ff768
commit
33ee35ab92
1
NEWS
1
NEWS
|
@ -2,6 +2,7 @@ ver 0.21.25 (not yet released)
|
|||
* protocol:
|
||||
- fix crash when using "rangeid" while playing
|
||||
* storage
|
||||
- fix disappearing mounts after mounting twice
|
||||
- udisks: fix reading ".mpdignore"
|
||||
* input
|
||||
- file: detect premature end of file
|
||||
|
|
|
@ -198,6 +198,11 @@ handle_mount(Client &client, Request args, Response &r)
|
|||
return CommandResult::ERROR;
|
||||
}
|
||||
|
||||
if (composite.IsMountPoint(local_uri)) {
|
||||
r.Error(ACK_ERROR_ARG, "Mount point busy");
|
||||
return CommandResult::ERROR;
|
||||
}
|
||||
|
||||
auto &event_loop = instance.io_thread.GetEventLoop();
|
||||
auto storage = CreateStorageURI(event_loop, remote_uri);
|
||||
if (storage == nullptr) {
|
||||
|
|
|
@ -206,6 +206,7 @@ CompositeStorage::Mount(const char *uri, std::unique_ptr<Storage> storage)
|
|||
const std::lock_guard<Mutex> protect(mutex);
|
||||
|
||||
Directory &directory = root.Make(uri);
|
||||
assert(!directory.storage);
|
||||
directory.storage = std::move(storage);
|
||||
}
|
||||
|
||||
|
|
|
@ -100,6 +100,15 @@ public:
|
|||
gcc_pure gcc_nonnull_all
|
||||
Storage *GetMount(const char *uri) noexcept;
|
||||
|
||||
/**
|
||||
* Is the given URI a mount point, i.e. is something already
|
||||
* mounted on this path?
|
||||
*/
|
||||
gcc_pure gcc_nonnull_all
|
||||
bool IsMountPoint(const char *uri) noexcept {
|
||||
return GetMount(uri) != nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the given function for each mounted storage, including
|
||||
* the root storage. Passes mount point URI and the a const
|
||||
|
|
|
@ -106,6 +106,12 @@ storage_state_restore(const char *line, TextFile &file, Instance &instance)
|
|||
|
||||
FormatDebug(storage_domain, "Restoring mount %s => %s", uri.c_str(), url.c_str());
|
||||
|
||||
auto &composite_storage = *(CompositeStorage *)instance.storage;
|
||||
if (composite_storage.IsMountPoint(uri.c_str())) {
|
||||
LogError(storage_domain, "Mount point busy");
|
||||
return true;
|
||||
}
|
||||
|
||||
auto &event_loop = instance.io_thread.GetEventLoop();
|
||||
auto storage = CreateStorageURI(event_loop, url.c_str());
|
||||
if (storage == nullptr) {
|
||||
|
@ -124,8 +130,7 @@ storage_state_restore(const char *line, TextFile &file, Instance &instance)
|
|||
}
|
||||
}
|
||||
|
||||
((CompositeStorage*)instance.storage)->Mount(uri.c_str(),
|
||||
std::move(storage));
|
||||
composite_storage.Mount(uri.c_str(), std::move(storage));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue