blob: 892f848af30f17d06e87a56d4958c87bcacd6ba4 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/storage/lib/vfs/cpp/connection/node_connection.h"
#include <fidl/fuchsia.io/cpp/wire.h>
#include <lib/zx/handle.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <zircon/assert.h>
#include <utility>
#include <fbl/string_buffer.h>
#include "src/storage/lib/vfs/cpp/vfs_types.h"
#include "src/storage/lib/vfs/cpp/vnode.h"
namespace fio = fuchsia_io;
namespace fs::internal {
NodeConnection::NodeConnection(fs::FuchsiaVfs* vfs, fbl::RefPtr<fs::Vnode> vnode,
fuchsia_io::Rights rights)
: Connection(vfs, std::move(vnode), rights) {
// Ensure the VFS does not create connections that have privileges which cannot be used.
ZX_DEBUG_ASSERT(internal::DownscopeRights(rights, VnodeProtocol::kNode) == rights);
}
void NodeConnection::BindImpl(zx::channel channel, OnUnbound on_unbound) {
ZX_DEBUG_ASSERT(!binding_);
binding_.emplace(fidl::BindServer(vfs()->dispatcher(),
fidl::ServerEnd<fuchsia_io::Node>{std::move(channel)}, this,
[on_unbound = std::move(on_unbound)](
NodeConnection* self, fidl::UnbindInfo,
fidl::ServerEnd<fuchsia_io::Node>) { on_unbound(self); }));
}
void NodeConnection::Unbind() {
// NOTE: This needs to be thread-safe!
if (binding_)
binding_->Unbind();
}
#if FUCHSIA_API_LEVEL_AT_LEAST(26)
void NodeConnection::DeprecatedClone(DeprecatedCloneRequestView request,
DeprecatedCloneCompleter::Sync& completer) {
#else
void NodeConnection::Clone(CloneRequestView request, CloneCompleter::Sync& completer) {
#endif
Connection::NodeCloneDeprecated(request->flags, VnodeProtocol::kNode, std::move(request->object));
}
#if FUCHSIA_API_LEVEL_AT_LEAST(26)
void NodeConnection::Clone(CloneRequestView request, CloneCompleter::Sync& completer) {
#else
void NodeConnection::Clone2(Clone2RequestView request, Clone2Completer::Sync& completer) {
#endif
Connection::NodeClone(fio::Flags::kProtocolNode | fs::internal::RightsToFlags(rights()),
request->request.TakeChannel());
}
void NodeConnection::Close(CloseCompleter::Sync& completer) {
completer.Reply(zx::ok());
Unbind();
}
void NodeConnection::Query(QueryCompleter::Sync& completer) {
std::string_view protocol = fio::kNodeProtocolName;
// TODO(https://fxbug.dev/42052765): avoid the const cast.
uint8_t* data = reinterpret_cast<uint8_t*>(const_cast<char*>(protocol.data()));
completer.Reply(fidl::VectorView<uint8_t>::FromExternal(data, protocol.size()));
}
void NodeConnection::GetConnectionInfo(GetConnectionInfoCompleter::Sync& completer) {
fidl::Arena arena;
completer.Reply(fio::wire::ConnectionInfo::Builder(arena).rights(rights()).Build());
}
void NodeConnection::Sync(SyncCompleter::Sync& completer) {
completer.Reply(zx::make_result(ZX_ERR_BAD_HANDLE));
}
void NodeConnection::GetAttr(GetAttrCompleter::Sync& completer) {
zx::result attrs = vnode()->GetAttributes();
if (attrs.is_ok()) {
completer.Reply(ZX_OK, attrs->ToIoV1NodeAttributes(*vnode()));
} else {
completer.Reply(attrs.error_value(), fio::wire::NodeAttributes());
}
}
void NodeConnection::SetAttr(SetAttrRequestView request, SetAttrCompleter::Sync& completer) {
completer.Reply(ZX_ERR_BAD_HANDLE);
}
void NodeConnection::GetAttributes(fio::wire::NodeGetAttributesRequest* request,
GetAttributesCompleter::Sync& completer) {
// TODO(https://fxbug.dev/346585458): This operation should require the GET_ATTRIBUTES right.
internal::NodeAttributeBuilder builder(vnode());
completer.Reply(builder.Build(request->query));
}
void NodeConnection::UpdateAttributes(fio::wire::MutableNodeAttributes* request,
UpdateAttributesCompleter::Sync& completer) {
completer.ReplyError(ZX_ERR_BAD_HANDLE);
}
#if FUCHSIA_API_LEVEL_AT_LEAST(NEXT)
void NodeConnection::GetFlags(GetFlagsCompleter::Sync& completer) {
completer.ReplySuccess(fio::Flags::kProtocolNode | RightsToFlags(rights()));
}
void NodeConnection::SetFlags(SetFlagsRequestView, SetFlagsCompleter::Sync& completer) {
completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
}
#endif
#if FUCHSIA_API_LEVEL_AT_LEAST(NEXT)
void NodeConnection::DeprecatedGetFlags(DeprecatedGetFlagsCompleter::Sync& completer) {
#else
void NodeConnection::GetFlags(GetFlagsCompleter::Sync& completer) {
#endif
completer.Reply(ZX_OK, fio::OpenFlags::kNodeReference);
}
#if FUCHSIA_API_LEVEL_AT_LEAST(NEXT)
void NodeConnection::DeprecatedSetFlags(DeprecatedSetFlagsRequestView,
DeprecatedSetFlagsCompleter::Sync& completer) {
#else
void NodeConnection::SetFlags(SetFlagsRequestView, SetFlagsCompleter::Sync& completer) {
#endif
completer.Reply(ZX_ERR_BAD_HANDLE);
}
void NodeConnection::QueryFilesystem(QueryFilesystemCompleter::Sync& completer) {
zx::result result = Connection::NodeQueryFilesystem();
completer.Reply(result.status_value(),
result.is_ok()
? fidl::ObjectView<fio::wire::FilesystemInfo>::FromExternal(&result.value())
: nullptr);
}
zx::result<> NodeConnection::WithRepresentation(
fit::callback<zx::result<>(fio::wire::Representation)> handler,
std::optional<fio::NodeAttributesQuery> query) const {
using NodeRepresentation = fio::wire::ConnectorInfo;
fidl::WireTableFrame<NodeRepresentation> representation_frame;
auto builder = NodeRepresentation::ExternalBuilder(
fidl::ObjectView<fidl::WireTableFrame<NodeRepresentation>>::FromExternal(
&representation_frame));
#if FUCHSIA_API_LEVEL_AT_LEAST(18)
std::optional<NodeAttributeBuilder> attributes_builder;
if (query) {
attributes_builder.emplace(vnode());
zx::result<fio::wire::NodeAttributes2*> attributes = attributes_builder->Build(*query);
if (attributes.is_error()) {
return attributes.take_error();
}
builder.attributes(fidl::ObjectView<fio::wire::NodeAttributes2>::FromExternal(*attributes));
}
#endif
auto representation = builder.Build();
return handler(fuchsia_io::wire::Representation::WithConnector(
fidl::ObjectView<NodeRepresentation>::FromExternal(&representation)));
}
zx_status_t NodeConnection::WithNodeInfoDeprecated(
fit::callback<zx_status_t(fuchsia_io::wire::NodeInfoDeprecated)> handler) const {
// In io1, node reference connections are mapped to the service variant of NodeInfoDeprecated.
return handler(fuchsia_io::wire::NodeInfoDeprecated::WithService({}));
}
} // namespace fs::internal