blob: 4a952d904212b72a84f4c65d28393e73fb943682 [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 <lib/async-loop/cpp/loop.h>
#include <lib/fdio/directory.h>
#include <lib/fs-pty/service.h>
#include <lib/zx/eventpair.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include "pty-server-vnode.h"
#include "pty-server.h"
#include "src/lib/storage/vfs/cpp/pseudo_dir.h"
#include "src/lib/storage/vfs/cpp/synchronous_vfs.h"
#include "src/lib/storage/vfs/cpp/vfs_types.h"
#include "src/lib/storage/vfs/cpp/vnode.h"
#include "src/sys/lib/stdout-to-debuglog/cpp/stdout-to-debuglog.h"
// Each Open() on this Vnode redirects to a new PtyServerVnode
class PtyGeneratingVnode : public fs::Vnode {
PtyGeneratingVnode(fs::Vfs* vfs) : vfs_(vfs) {}
~PtyGeneratingVnode() override = default;
zx_status_t GetNodeInfoForProtocol([[maybe_unused]] fs::VnodeProtocol protocol,
[[maybe_unused]] fs::Rights rights,
fs::VnodeRepresentation* info) override {
// This should only actually be seen by something querying with VNODE_REF_ONLY.
*info = fs::VnodeRepresentation::Tty{.event = {}};
return ZX_OK;
fs::VnodeProtocolSet GetProtocols() const final { return fs::VnodeProtocol::kTty; }
zx_status_t OpenNode(ValidatedOptions options, fbl::RefPtr<Vnode>* out_redirect) override {
fbl::RefPtr<PtyServer> server;
zx_status_t status = PtyServer::Create(&server, vfs_);
if (status != ZX_OK) {
return status;
*out_redirect = fbl::MakeRefCounted<PtyServerVnode>(std::move(server));
return ZX_OK;
fs::Vfs* vfs_;
int main(int argc, const char** argv) {
zx_status_t status;
if ((status = StdoutToDebuglog::Init()) != ZX_OK) {
printf("console: failed to init stdout to debuglog: %s\n", zx_status_get_string(status));
return -1;
async::Loop loop(&kAsyncLoopConfigNeverAttachToThread);
async_dispatcher_t* dispatcher = loop.dispatcher();
fs::SynchronousVfs vfs(dispatcher);
auto root_dir = fbl::MakeRefCounted<fs::PseudoDir>();
auto svc_dir = fbl::MakeRefCounted<fs::PseudoDir>();
if ((status = root_dir->AddEntry("svc", svc_dir)) != ZX_OK) {
printf("console: failed to add svc to root dir: %s\n", zx_status_get_string(status));
return -1;
if ((status = svc_dir->AddEntry(fidl::DiscoverableProtocolName<fuchsia_hardware_pty::Device>,
fbl::MakeRefCounted<PtyGeneratingVnode>(&vfs))) != ZX_OK) {
printf("console: failed to add %s to svc dir: %s\n",
return -1;
if ((status = vfs.ServeDirectory(root_dir, fidl::ServerEnd<fuchsia_io::Directory>(zx::channel(
zx_take_startup_handle(PA_DIRECTORY_REQUEST))))) !=
ZX_OK) {
printf("console: failed to serve startup handle: %s\n", zx_status_get_string(status));
return -1;
ZX_ASSERT_MSG((status = loop.Run()) == ZX_OK, "%s", zx_status_get_string(status));
return 0;