blob: 815d54980b3b16c7d65184fbc3b2de0eeb8ad07d [file] [log] [blame]
// Copyright 2018 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 <lib/async/default.h>
#include <lib/fdio/directory.h>
#include <lib/vfs/cpp/composed_service_dir.h>
#include <zircon/status.h>
namespace vfs {
ComposedServiceDir::ComposedServiceDir() : root_(std::make_unique<vfs::PseudoDir>()) {}
ComposedServiceDir::~ComposedServiceDir() {}
void ComposedServiceDir::set_fallback(fidl::InterfaceHandle<fuchsia::io::Directory> fallback_dir) {
fallback_dir_ = fallback_dir.TakeChannel();
}
void ComposedServiceDir::AddService(const std::string& service_name,
std::unique_ptr<vfs::Service> service) {
root_->AddEntry(service_name, std::move(service));
}
zx_status_t ComposedServiceDir::GetAttr(fuchsia::io::NodeAttributes* out_attributes) const {
return root_->GetAttr(out_attributes);
}
zx_status_t ComposedServiceDir::Readdir(uint64_t offset, void* data, uint64_t len,
uint64_t* out_offset, uint64_t* out_actual) {
return root_->Readdir(offset, data, len, out_offset, out_actual);
}
zx_status_t ComposedServiceDir::Lookup(const std::string& name, vfs::internal::Node** out) const {
zx_status_t status = root_->Lookup(name, out);
if (status == ZX_OK) {
return status;
}
if (fallback_dir_) {
auto entry = fallback_services_.find(name);
if (entry != fallback_services_.end()) {
*out = entry->second.get();
} else {
auto service = std::make_unique<vfs::Service>(
[name = std::string(name.data(), name.length()), dir = &fallback_dir_](
zx::channel request, async_dispatcher_t* dispatcher) {
fdio_service_connect_at(dir->get(), name.c_str(), request.release());
});
*out = service.get();
fallback_services_[name] = std::move(service);
}
} else {
return ZX_ERR_NOT_FOUND;
}
return ZX_OK;
}
} // namespace vfs