| // 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 |