blob: e9640403fbef6542dc6c2d4a30560a5ba55ba382 [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 "virtual_devices.h"
#include <fs/service.h>
#include <lib/async/default.h>
#include <lib/fxl/logging.h>
#include <lib/fxl/strings/split_string.h>
#include <zircon/status.h>
namespace netemul {
VirtualDevices::VirtualDevices()
: vdev_vfs_(async_get_default_dispatcher()),
dir_(fbl::AdoptRef(new fs::PseudoDir())) {}
void VirtualDevices::AddEntry(const std::string& path,
fidl::InterfacePtr<DevProxy> dev) {
auto components =
fxl::SplitString(path, "/", fxl::WhiteSpaceHandling::kKeepWhitespace,
fxl::SplitResult::kSplitWantNonEmpty);
if (components.empty()) {
FXL_LOG(ERROR) << "Invalid device mount path '" << path << "'";
return;
}
fbl::RefPtr<fs::PseudoDir> dir = dir_;
auto last = components.end() - 1;
for (auto i = components.begin(); i != last; i++) {
fbl::RefPtr<fs::Vnode> node;
if (dir->Lookup(&node, *i) == ZX_OK) {
dir.reset(reinterpret_cast<fs::PseudoDir*>(node.get()));
} else {
auto ndir = fbl::AdoptRef(new fs::PseudoDir());
auto status = dir->AddEntry(*i, ndir);
if (status != ZX_OK) {
FXL_LOG(ERROR) << "Error creating mount path: " << path << ": "
<< zx_status_get_string(status);
}
dir = ndir;
}
}
auto status = dir->AddEntry(
*last,
fbl::AdoptRef(new fs::Service([dev = std::move(dev)](zx::channel chann) {
if (!dev.is_bound()) {
return ZX_ERR_PEER_CLOSED;
}
dev->ServeDevice(std::move(chann));
return ZX_OK;
})));
if (status != ZX_OK) {
FXL_LOG(ERROR) << "Can't add device entry " << path << ": "
<< zx_status_get_string(status);
}
}
zx::channel VirtualDevices::OpenAsDirectory() {
zx::channel h1, h2;
if (zx::channel::create(0, &h1, &h2) != ZX_OK)
return zx::channel();
if (vdev_vfs_.ServeDirectory(dir_, std::move(h1)) != ZX_OK)
return zx::channel();
return h2;
}
} // namespace netemul