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