// Copyright 2016 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 "devfs.h"

#include <fcntl.h>
#include <fuchsia/io/c/fidl.h>
#include <lib/async/cpp/wait.h>
#include <lib/fdio/directory.h>
#include <lib/fidl/coding.h>
#include <lib/fidl/txn_header.h>
#include <lib/memfs/cpp/vnode.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zircon/device/vfs.h>
#include <zircon/fidl.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include <algorithm>
#include <memory>

#include <ddk/driver.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/string.h>
#include <src/storage/deprecated-fs-fidl-handler/fidl-handler.h>

#include "async_loop_owned_rpc_handler.h"
#include "coordinator.h"
#include "lib/fidl/cpp/message_part.h"
#include "src/devices/lib/log/log.h"

namespace {

// On OpenMsg and Describe Msg are hand-rolled structs to mirror the `OnOpen`
// event and `Describe` method from fuchsia-io: see
// zircon/system/fidl/fuchsia-io/io.fidl. We are hand-rolling this because these
// methods contain NodeInfo unions which is not supported by the C FIDL
// bindings, and migrating this code to LLCPP is out-of-scope for now.
struct OnOpenMsg {
  FIDL_ALIGNDECL

  // This is the inline, or primary, part of the FIDL message.
  struct {
    fidl_message_header_t hdr;
    int32_t s;
    fidl_xunion_t node_info;
  } primary;

  // This is the out-of-line, or secondary, part of the FIDL message, which may
  // or may not be present, depending on the value of .node_info's tag.
  //
  // Note that `directory` is the _only_ NodeInfo union member used in this
  // file, whereas the actual definition of NodeInfo in io.fidl has many more
  // members. Including the other members here would extend the size of the
  // union beyond sizeof(fuchsia_io_DirectoryObject), which means that the
  // outgoing FIDL message would contain extraneous zero bytes.
  //
  // For extra context: Remember that the old-wireformat static unions' payload
  // size is the maximum of its union members' size, whereas the v1-wireformat
  // extensible unions' payload size depends on the specific union member that's
  // present. We are writing the v1 wire format, and this code only ever sets
  // NodeInfo's union member to be a Directory, so `directory` is only NodeInfo
  // union member needed in this definition.
  fuchsia_io_DirectoryObject directory;
};

// This is a hand-rolled FIDL struct, see OnOpenMsg
struct DescribeMsg {
  FIDL_ALIGNDECL

  // This is the inline, or primary, part of the FIDL message.
  struct {
    fidl_message_header_t hdr;
    fidl_xunion_t node_info;
  } primary;

  fuchsia_io_DirectoryObject directory;
};

// Sets |node_info| to be a Directory, in the encoded form. It is the caller's
// responsibility to ensure that the directory object is zeroed out.
void SetNodeInfoAsDirectory(fidl_xunion_t* node_info) {
  // kNodeInfoTagDirectory below is intentionally hard-coded to the ordinal
  // for NodeInfo.directory. We could also look this up in the coding
  // tables, but doing that is arguably less performant and less safe, since
  // we need to search the NodeInfo coding table's fields for the directory
  // union member, and there's questions around what to do if the field
  // isn't found. Given that a union member ordinal is part of its ABI, it's
  // extremely unlikely to ever change, so it's safe enough to hard-code it
  // here. See
  // <https://fuchsia-review.googlesource.com/c/fuchsia/+/383902/2/src/devices/bin/driver_manager/devfs.cc#495>
  // for more context.
  constexpr fidl_xunion_tag_t kNodeInfoTagDirectory = 3ul;
  node_info->tag = kNodeInfoTagDirectory;

  node_info->envelope.num_bytes = FIDL_ALIGN(sizeof(fuchsia_io_DirectoryObject));
  node_info->envelope.presence = FIDL_ALLOC_PRESENT;
}

zx_status_t SendOnOpenEvent(zx_handle_t ch, OnOpenMsg msg, zx_handle_t* handles,
                            uint32_t num_handles) {
  const bool contains_nodeinfo = msg.primary.node_info.tag != fidl_xunion_tag_t(0);
  uint32_t msg_size = contains_nodeinfo ? sizeof(msg) : sizeof(msg.primary);
  fidl::HLCPPOutgoingMessage fidl_msg(
      fidl::BytePart(reinterpret_cast<uint8_t*>(&msg), msg_size, msg_size),
      fidl::HandlePart(handles, num_handles, num_handles));
  return fidl_msg.Write(ch, 0);
}

uint64_t next_ino = 2;

std::unique_ptr<Devnode> root_devnode;

std::unique_ptr<Devnode> class_devnode;

std::unique_ptr<Devnode> devfs_mkdir(Devnode* parent, const fbl::String& name);

// Dummy node to represent dev/diagnostics directory.
std::unique_ptr<Devnode> diagnostics_devnode;

// Connection to diagnostics VFS server. Channel is owned by inspect manager.
zx::unowned_channel diagnostics_channel;

const char kDiagnosticsDirName[] = "diagnostics";
const size_t kDiagnosticsDirLen = strlen(kDiagnosticsDirName);

zx::channel g_devfs_root;

}  // namespace

struct Watcher : fbl::DoublyLinkedListable<std::unique_ptr<Watcher>> {
  Watcher(Devnode* dn, zx::channel ch, uint32_t mask);

  Watcher(const Watcher&) = delete;
  Watcher& operator=(const Watcher&) = delete;

  Watcher(Watcher&&) = delete;
  Watcher& operator=(Watcher&&) = delete;

  Devnode* devnode = nullptr;
  zx::channel handle;
  uint32_t mask = 0;
};

Watcher::Watcher(Devnode* dn, zx::channel ch, uint32_t mask)
    : devnode(dn), handle(std::move(ch)), mask(mask) {}

class DcIostate : public fbl::DoublyLinkedListable<DcIostate*>,
                  public AsyncLoopOwnedRpcHandler<DcIostate> {
 public:
  explicit DcIostate(Devnode* dn);
  ~DcIostate();

  // Remove this DcIostate from its devnode
  void DetachFromDevnode();

  // Claims ownership of |*h| on success
  static zx_status_t Create(Devnode* dn, async_dispatcher_t* dispatcher, zx::channel* h);

  static zx_status_t DevfsFidlHandler(fidl_incoming_msg_t* msg, fidl_txn_t* txn, void* cookie,
                                      async_dispatcher_t* dispatcher);

  static void HandleRpc(std::unique_ptr<DcIostate> ios, async_dispatcher_t* dispatcher,
                        async::WaitBase* wait, zx_status_t status,
                        const zx_packet_signal_t* signal);

 private:
  uint64_t readdir_ino_ = 0;

  // pointer to our devnode, nullptr if it has been removed
  Devnode* devnode_ = nullptr;
};

// BUG(fxbug.dev/32713): We currently never free these after allocating them
struct Devnode : public fbl::DoublyLinkedListable<Devnode*> {
  explicit Devnode(fbl::String name);
  ~Devnode();

  Devnode(const Devnode&) = delete;
  Devnode& operator=(const Devnode&) = delete;

  Devnode(Devnode&&) = delete;
  Devnode& operator=(Devnode&&) = delete;

  fbl::String name;
  uint64_t ino = 0;

  // nullptr if we are a pure directory node,
  // otherwise the device we are referencing
  Device* device = nullptr;

  fbl::DoublyLinkedList<std::unique_ptr<Watcher>> watchers;

  // list of our child devnodes
  fbl::DoublyLinkedList<Devnode*> children;

  // Pointer to our parent, for removing ourselves from its list of
  // children. Our parent must outlive us.
  Devnode* parent = nullptr;

  // list of attached iostates
  fbl::DoublyLinkedList<DcIostate*> iostate;

  // used to assign unique small device numbers
  // for class device links
  uint32_t seqcount = 0;
};

namespace {

struct ProtocolInfo {
  const char* name;
  std::unique_ptr<Devnode> devnode;
  uint32_t id;
  uint32_t flags;
};

ProtocolInfo proto_infos[] = {
#define DDK_PROTOCOL_DEF(tag, val, name, flags) {name, nullptr, val, flags},
#include <ddk/protodefs.h>
};

Devnode* proto_dir(uint32_t id) {
  for (const auto& info : proto_infos) {
    if (info.id == id) {
      return info.devnode.get();
    }
  }
  return nullptr;
}

void prepopulate_protocol_dirs() {
  class_devnode = devfs_mkdir(root_devnode.get(), "class");
  for (auto& info : proto_infos) {
    if (!(info.flags & PF_NOPUB)) {
      info.devnode = devfs_mkdir(class_devnode.get(), info.name);
    }
  }
}

void describe_error(zx::channel h, zx_status_t status) {
  OnOpenMsg msg;
  memset(&msg, 0, sizeof(msg));
  fidl_init_txn_header(&msg.primary.hdr, 0, fuchsia_io_NodeOnOpenOrdinal);
  msg.primary.s = status;
  SendOnOpenEvent(h.get(), msg, nullptr, 0);
}

// A devnode is a directory (from stat's perspective) if
// it has children, or if it doesn't have a device, or if
// its device has no rpc handle
bool devnode_is_dir(const Devnode* dn) {
  if (dn->children.is_empty()) {
    return (dn->device == nullptr) || (!dn->device->device_controller().channel().is_valid()) ||
           (!dn->device->channel()->is_valid());
  }
  return true;
}

// Local devnodes are ones that we should not hand off OPEN
// RPCs to the underlying driver_host
bool devnode_is_local(Devnode* dn) {
  if (dn->device == nullptr) {
    return true;
  }
  if (!dn->device->device_controller().channel().get()) {
    return true;
  }
  if (dn->device->flags & DEV_CTX_MUST_ISOLATE) {
    return true;
  }
  return false;
}

// Notify a single watcher about the given operation and path.  On failure,
// frees the watcher.  This can only be called on a watcher that has not yet
// been added to a Devnode's watchers list.
void devfs_notify_single(std::unique_ptr<Watcher>* watcher, const fbl::String& name, unsigned op) {
  size_t len = name.length();
  if (!*watcher || len > fuchsia_io_MAX_FILENAME) {
    return;
  }

  ZX_ASSERT(!(*watcher)->InContainer());

  uint8_t msg[fuchsia_io_MAX_FILENAME + 2];
  const uint32_t msg_len = static_cast<uint32_t>(len + 2);
  msg[0] = static_cast<uint8_t>(op);
  msg[1] = static_cast<uint8_t>(len);
  memcpy(msg + 2, name.c_str(), len);

  // convert to mask
  op = (1u << op);

  if (!((*watcher)->mask & op)) {
    return;
  }

  if ((*watcher)->handle.write(0, msg, msg_len, nullptr, 0) != ZX_OK) {
    watcher->reset();
  }
}

void devfs_notify(Devnode* dn, const fbl::String& name, unsigned op) {
  if (dn->watchers.is_empty()) {
    return;
  }

  size_t len = name.length();
  if (len > fuchsia_io_MAX_FILENAME) {
    return;
  }

  uint8_t msg[fuchsia_io_MAX_FILENAME + 2];
  const uint32_t msg_len = static_cast<uint32_t>(len + 2);
  msg[0] = static_cast<uint8_t>(op);
  msg[1] = static_cast<uint8_t>(len);
  memcpy(msg + 2, name.c_str(), len);

  // convert to mask
  op = (1u << op);

  for (auto itr = dn->watchers.begin(); itr != dn->watchers.end();) {
    auto& cur = *itr;
    // Advance the iterator now instead of at the end of the loop because we
    // may erase the current element from the list.
    ++itr;

    if (!(cur.mask & op)) {
      continue;
    }

    if (cur.handle.write(0, msg, msg_len, nullptr, 0) != ZX_OK) {
      dn->watchers.erase(cur);
      // The Watcher is free'd here
    }
  }
}

}  // namespace

zx_status_t devfs_watch(Devnode* dn, zx::channel h, uint32_t mask) {
  auto watcher = std::make_unique<Watcher>(dn, std::move(h), mask);
  if (watcher == nullptr) {
    return ZX_ERR_NO_MEMORY;
  }

  // If the watcher has asked for all existing entries, send it all of them
  // followed by the end-of-existing marker (IDLE).
  if (mask & fuchsia_io_WATCH_MASK_EXISTING) {
    for (const auto& child : dn->children) {
      if (child.device && (child.device->flags & DEV_CTX_INVISIBLE)) {
        continue;
      }
      // TODO: send multiple per write
      devfs_notify_single(&watcher, child.name, fuchsia_io_WATCH_EVENT_EXISTING);
    }
    devfs_notify_single(&watcher, "", fuchsia_io_WATCH_EVENT_IDLE);
  }

  // Watcher may have been freed by devfs_notify_single, so check before
  // adding.
  if (watcher) {
    dn->watchers.push_front(std::move(watcher));
  }
  return ZX_OK;
}

namespace {

std::unique_ptr<Devnode> devfs_mknode(const fbl::RefPtr<Device>& dev, const fbl::String& name) {
  auto dn = std::make_unique<Devnode>(name);
  if (!dn) {
    return nullptr;
  }
  dn->ino = next_ino++;
  // TODO(teisenbe): This should probably be refcounted
  dn->device = dev.get();
  return dn;
}

std::unique_ptr<Devnode> devfs_mkdir(Devnode* parent, const fbl::String& name) {
  std::unique_ptr<Devnode> dn = devfs_mknode(nullptr, name);
  if (dn == nullptr) {
    return nullptr;
  }
  dn->parent = parent;
  parent->children.push_back(dn.get());
  return dn;
}

Devnode* devfs_lookup(Devnode* parent, const fbl::String& name) {
  for (auto& child : parent->children) {
    if (name == child.name) {
      return &child;
    }
  }
  return nullptr;
}

zx_status_t fill_dirent(vdirent_t* de, size_t delen, uint64_t ino, const fbl::String& name,
                        uint8_t type) {
  size_t len = name.length();
  size_t sz = sizeof(vdirent_t) + len;

  if (sz > delen || len > NAME_MAX) {
    return ZX_ERR_INVALID_ARGS;
  }
  de->ino = ino;
  de->size = static_cast<uint8_t>(len);
  de->type = type;
  memcpy(de->name, name.c_str(), len);
  return static_cast<zx_status_t>(sz);
}

zx_status_t devfs_readdir(Devnode* dn, uint64_t* ino_inout, void* data, size_t len) {
  char* ptr = static_cast<char*>(data);
  uint64_t ino = *ino_inout;

  for (const auto& child : dn->children) {
    if (child.ino <= ino) {
      continue;
    }
    if (child.device == nullptr) {
      // "pure" directories (like /dev/class/$NAME) do not show up
      // if they have no children, to avoid clutter and confusion.
      // They remain openable, so they can be watched.
      // An exception being /dev/diagnostics which is served by different VFS and
      // should be listed even though it has no DevNode childrens.
      if (child.children.is_empty() && child.ino != diagnostics_devnode->ino) {
        continue;
      }
    } else {
      // invisible devices also do not show up
      if (child.device->flags & DEV_CTX_INVISIBLE) {
        continue;
      }
    }
    ino = child.ino;
    auto vdirent = reinterpret_cast<vdirent_t*>(ptr);
    zx_status_t r = fill_dirent(vdirent, len, ino, child.name, VTYPE_TO_DTYPE(V_TYPE_DIR));
    if (r < 0) {
      break;
    }
    ptr += r;
    len -= r;
  }

  *ino_inout = ino;
  return static_cast<zx_status_t>(ptr - static_cast<char*>(data));
}

zx_status_t devfs_walk(Devnode** dn_inout, char* path) {
  Devnode* dn = *dn_inout;

again:
  if ((path == nullptr) || (path[0] == 0)) {
    *dn_inout = dn;
    return ZX_OK;
  }
  char* name = path;
  if ((path = strchr(path, '/')) != nullptr) {
    *path++ = 0;
  }
  if (name[0] == 0) {
    return ZX_ERR_BAD_PATH;
  }
  for (auto& child : dn->children) {
    if (!strcmp(child.name.c_str(), name)) {
      if (child.device && (child.device->flags & DEV_CTX_INVISIBLE)) {
        continue;
      }
      dn = &child;
      goto again;
    }
  }
  // The path only partially matched.
  return ZX_ERR_NOT_FOUND;
}

void devfs_open(Devnode* dirdn, async_dispatcher_t* dispatcher, zx_handle_t h, char* path,
                uint32_t flags) {
  zx::channel ipc(h);
  h = ZX_HANDLE_INVALID;

  // Filter requests for diagnostics path and pass it on to diagnostics vfs server.
  if (!strncmp(path, kDiagnosticsDirName, kDiagnosticsDirLen) &&
      (path[kDiagnosticsDirLen] == '\0' || path[kDiagnosticsDirLen] == '/')) {
    char* dir_path = path + kDiagnosticsDirLen;
    char current_dir[] = ".";
    if (dir_path[0] == '/') {
      dir_path++;
    } else {
      dir_path = current_dir;
    }
    fuchsia_io_DirectoryOpen(diagnostics_channel->get(), flags, 0, dir_path, strlen(dir_path),
                             ipc.release());
    return;
  }

  if (!strcmp(path, ".")) {
    path = nullptr;
  }

  Devnode* dn = dirdn;
  zx_status_t r = devfs_walk(&dn, path);

  bool describe = flags & ZX_FS_FLAG_DESCRIBE;
  if (r != ZX_OK) {
    if (describe) {
      describe_error(std::move(ipc), r);
    }
    return;
  }

  // If we are a local-only node, or we are asked to not go remote, or we are asked to
  // open-as-a-directory, open locally:
  if (devnode_is_local(dn) || flags & (ZX_FS_FLAG_NOREMOTE | ZX_FS_FLAG_DIRECTORY)) {
    zx::unowned_channel unowned_ipc(ipc);
    if ((r = DcIostate::Create(dn, dispatcher, &ipc)) != ZX_OK) {
      if (describe) {
        describe_error(std::move(ipc), r);
      }
      return;
    }
    if (describe) {
      OnOpenMsg msg;
      memset(&msg, 0, sizeof(msg));
      fidl_init_txn_header(&msg.primary.hdr, 0, fuchsia_io_NodeOnOpenOrdinal);

      msg.primary.s = ZX_OK;

      SetNodeInfoAsDirectory(&msg.primary.node_info);

      // We don't need to set the union member (i.e. the directory)'s data here,
      // because Directory is an empty struct and has no data. The empty struct
      // is zeroed out by the memset() earlier in this function.

      // Writing to unowned_ipc is safe because this is executing on the same
      // thread as the DcAsyncLoop(), so the handle can't be closed underneath us.
      SendOnOpenEvent(unowned_ipc->get(), msg, nullptr, 0);
    }
    return;
  }

  // Otherwise we will pass the request on to the remote.
  fuchsia_io_DirectoryOpen(dn->device->device_controller().channel().get(), flags, 0, ".", 1,
                           ipc.release());
}

void devfs_remove(Devnode* dn) {
  if (dn->InContainer()) {
    dn->parent->children.erase(*dn);
  }

  // detach all connected iostates
  while (!dn->iostate.is_empty()) {
    dn->iostate.front().DetachFromDevnode();
  }

  // notify own file watcher
  if ((dn->device == nullptr) || !(dn->device->flags & DEV_CTX_INVISIBLE)) {
    devfs_notify(dn, "", fuchsia_io_WATCH_EVENT_DELETED);
  }

  // disconnect from device and notify parent/link directory watchers
  if (dn->device != nullptr) {
    if (dn->device->self == dn) {
      dn->device->self = nullptr;

      if ((dn->device->parent() != nullptr) && (dn->device->parent()->self != nullptr) &&
          !(dn->device->flags & DEV_CTX_INVISIBLE)) {
        devfs_notify(dn->device->parent()->self, dn->name, fuchsia_io_WATCH_EVENT_REMOVED);
      }
    }
    if (dn->device->link == dn) {
      dn->device->link = nullptr;

      if (!(dn->device->flags & DEV_CTX_INVISIBLE)) {
        Devnode* dir = proto_dir(dn->device->protocol_id());
        devfs_notify(dir, dn->name, fuchsia_io_WATCH_EVENT_REMOVED);
      }
    }
    dn->device = nullptr;
  }

  // destroy all watchers
  dn->watchers.clear();

  // detach children
  // They will be unpublished when the devices they're associated with are
  // eventually destroyed.
  dn->children.clear();
}

}  // namespace

Devnode::Devnode(fbl::String name) : name(std::move(name)) {}

Devnode::~Devnode() { devfs_remove(this); }

DcIostate::DcIostate(Devnode* dn) : devnode_(dn) { devnode_->iostate.push_back(this); }

DcIostate::~DcIostate() { DetachFromDevnode(); }

void DcIostate::DetachFromDevnode() {
  if (devnode_ != nullptr) {
    devnode_->iostate.erase(*this);
    devnode_ = nullptr;
  }
  set_channel(zx::channel());
}

zx_status_t DcIostate::Create(Devnode* dn, async_dispatcher_t* dispatcher, zx::channel* ipc) {
  auto ios = std::make_unique<DcIostate>(dn);
  if (ios == nullptr) {
    return ZX_ERR_NO_MEMORY;
  }

  ios->set_channel(std::move(*ipc));
  zx_status_t status = DcIostate::BeginWait(&ios, dispatcher);
  if (status != ZX_OK) {
    // Take the handle back from |ios| so it doesn't close it when it's
    // destroyed
    *ipc = ios->set_channel(zx::channel());
  }
  return status;
}

void devfs_advertise(const fbl::RefPtr<Device>& dev) {
  if (dev->link) {
    Devnode* dir = proto_dir(dev->protocol_id());
    devfs_notify(dir, dev->link->name, fuchsia_io_WATCH_EVENT_ADDED);
  }
  if (dev->self->parent) {
    devfs_notify(dev->self->parent, dev->self->name, fuchsia_io_WATCH_EVENT_ADDED);
  }
}

// TODO: generate a MODIFIED event rather than back to back REMOVED and ADDED
void devfs_advertise_modified(const fbl::RefPtr<Device>& dev) {
  if (dev->link) {
    Devnode* dir = proto_dir(dev->protocol_id());
    devfs_notify(dir, dev->link->name, fuchsia_io_WATCH_EVENT_REMOVED);
    devfs_notify(dir, dev->link->name, fuchsia_io_WATCH_EVENT_ADDED);
  }
  if (dev->self->parent) {
    devfs_notify(dev->self->parent, dev->self->name, fuchsia_io_WATCH_EVENT_REMOVED);
    devfs_notify(dev->self->parent, dev->self->name, fuchsia_io_WATCH_EVENT_ADDED);
  }
}

zx_status_t devfs_publish(const fbl::RefPtr<Device>& parent, const fbl::RefPtr<Device>& dev) {
  if ((parent->self == nullptr) || (dev->self != nullptr) || (dev->link != nullptr)) {
    return ZX_ERR_INTERNAL;
  }

  std::unique_ptr<Devnode> dnself = devfs_mknode(dev, dev->name());
  if (dnself == nullptr) {
    return ZX_ERR_NO_MEMORY;
  }

  if ((dev->protocol_id() == ZX_PROTOCOL_TEST_PARENT) ||
      (dev->protocol_id() == ZX_PROTOCOL_MISC_PARENT) || (dev->protocol_id() == ZX_PROTOCOL_MISC)) {
    // misc devices are singletons, not a class
    // in the sense of other device classes.
    // They do not get aliases in /dev/class/misc/...
    // instead they exist only under their parent
    // device.
    goto done;
  }

  // Create link in /dev/class/... if this id has a published class
  Devnode* dir;
  dir = proto_dir(dev->protocol_id());
  if (dir != nullptr) {
    char tmp[32];
    const char* name = dev->name().data();

    if (dev->protocol_id() != ZX_PROTOCOL_CONSOLE) {
      for (unsigned n = 0; n < 1000; n++) {
        snprintf(tmp, sizeof(tmp), "%03u", (dir->seqcount++) % 1000);
        if (devfs_lookup(dir, tmp) == nullptr) {
          name = tmp;
          goto got_name;
        }
      }
      return ZX_ERR_ALREADY_EXISTS;
    }

  got_name:
    std::unique_ptr<Devnode> dnlink = devfs_mknode(dev, name);
    if (dnlink == nullptr) {
      return ZX_ERR_NO_MEMORY;
    }

    // add link node to class directory
    dnlink->parent = dir;
    dir->children.push_back(dnlink.get());
    dev->link = dnlink.release();
  }

done:
  // add self node to parent directory
  dnself->parent = parent->self;
  parent->self->children.push_back(dnself.get());
  dev->self = dnself.release();

  if (!(dev->flags & DEV_CTX_INVISIBLE)) {
    devfs_advertise(dev);
  }
  return ZX_OK;
}

// TODO(teisenbe): Ideally this would take a RefPtr, but currently this is
// invoked in the dtor for Device.
void devfs_unpublish(Device* dev) {
  if (dev->self != nullptr) {
    delete dev->self;
    dev->self = nullptr;
  }
  if (dev->link != nullptr) {
    delete dev->link;
    dev->link = nullptr;
  }
}

zx_status_t devfs_connect(const Device* dev, zx::channel client_remote) {
  if (!client_remote.is_valid()) {
    return ZX_ERR_BAD_HANDLE;
  }
  fuchsia_io_DirectoryOpen(dev->device_controller().channel().get(), 0 /* flags */, 0 /* mode */,
                           ".", 1, client_remote.release());
  return ZX_OK;
}

void devfs_connect_diagnostics(zx::unowned_channel h) { diagnostics_channel = h; }

// Helper macros for |DevfsFidlHandler| which make it easier
// avoid typing generated names.

// Decode the incoming request, returning an error and consuming
// all handles on error.
#define DECODE_REQUEST(MSG, METHOD)                                                         \
  do {                                                                                      \
    zx_status_t r;                                                                          \
    if ((r = fidl_decode_msg(&fuchsia_io_##METHOD##RequestTable, msg, nullptr)) != ZX_OK) { \
      return r;                                                                             \
    }                                                                                       \
  } while (0);

// Define a variable |request| from the incoming method, of
// the requested type.
#define DEFINE_REQUEST(MSG, METHOD) \
  fuchsia_io_##METHOD##Request* request = (fuchsia_io_##METHOD##Request*)MSG->bytes;

zx_status_t DcIostate::DevfsFidlHandler(fidl_incoming_msg_t* msg, fidl_txn_t* txn, void* cookie,
                                        async_dispatcher_t* dispatcher) {
  auto ios = static_cast<DcIostate*>(cookie);
  Devnode* dn = ios->devnode_;
  if (dn == nullptr) {
    return ZX_ERR_PEER_CLOSED;
  }

  auto hdr = static_cast<fidl_message_header_t*>(msg->bytes);

  zx_status_t r;
  uint64_t ordinal = hdr->ordinal;
  switch (ordinal) {
    case fuchsia_io_NodeCloneOrdinal: {
      DECODE_REQUEST(msg, NodeClone);
      DEFINE_REQUEST(msg, NodeClone);
      zx_handle_t h = request->object;
      uint32_t flags = request->flags;
      if (request->flags & ZX_FS_FLAG_CLONE_SAME_RIGHTS) {
        flags |= ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE;
      }
      char path[] = ".";
      devfs_open(dn, dispatcher, h, path, flags | ZX_FS_FLAG_NOREMOTE);
      return ZX_OK;
    }
    case fuchsia_io_NodeDescribeOrdinal: {
      DECODE_REQUEST(msg, NodeDescribe);

      DescribeMsg msg;
      memset(&msg, 0, sizeof(msg));
      fidl_init_txn_header(&msg.primary.hdr, 0, fuchsia_io_NodeDescribeOrdinal);
      SetNodeInfoAsDirectory(&msg.primary.node_info);

      fidl_outgoing_msg_t raw_msg = {
          .bytes = reinterpret_cast<uint8_t*>(&msg),
          .handles = nullptr,
          .num_bytes = sizeof(msg),
          .num_handles = 0,
      };
      return txn->reply(txn, &raw_msg);
    }
    case fuchsia_io_DirectoryOpenOrdinal: {
      DECODE_REQUEST(msg, DirectoryOpen);
      DEFINE_REQUEST(msg, DirectoryOpen);
      uint32_t len = static_cast<uint32_t>(request->path.size);
      zx_handle_t h = request->object;
      uint32_t flags = request->flags;
      if (len == 0 || len > fuchsia_io_MAX_PATH) {
        zx_handle_close(h);
      } else {
        char path[fuchsia_io_MAX_PATH + 1];
        memcpy(path, request->path.data, len);
        path[len] = 0;
        devfs_open(dn, dispatcher, h, path, flags);
      }
      return ZX_OK;
    }
    case fuchsia_io_NodeGetAttrOrdinal: {
      DECODE_REQUEST(msg, NodeGetAttr);
      uint32_t mode;
      if (devnode_is_dir(dn)) {
        mode = V_TYPE_DIR | V_IRUSR | V_IWUSR;
      } else {
        mode = V_TYPE_CDEV | V_IRUSR | V_IWUSR;
      }

      fuchsia_io_NodeAttributes attributes;
      memset(&attributes, 0, sizeof(attributes));
      attributes.mode = mode;
      attributes.content_size = 0;
      attributes.link_count = 1;
      attributes.id = dn->ino;
      return fuchsia_io_NodeGetAttr_reply(txn, ZX_OK, &attributes);
    }
    case fuchsia_io_DirectoryRewindOrdinal: {
      DECODE_REQUEST(msg, DirectoryRewind);
      ios->readdir_ino_ = 0;
      return fuchsia_io_DirectoryRewind_reply(txn, ZX_OK);
    }
    case fuchsia_io_DirectoryReadDirentsOrdinal: {
      DECODE_REQUEST(msg, DirectoryReadDirents);
      DEFINE_REQUEST(msg, DirectoryReadDirents);

      if (request->max_bytes > fuchsia_io_MAX_BUF) {
        return fuchsia_io_DirectoryReadDirents_reply(txn, ZX_ERR_INVALID_ARGS, nullptr, 0);
      }

      uint8_t data[fuchsia_io_MAX_BUF];
      size_t actual = 0;
      r = devfs_readdir(dn, &ios->readdir_ino_, data, request->max_bytes);
      if (r >= 0) {
        actual = r;
        r = ZX_OK;
      }
      return fuchsia_io_DirectoryReadDirents_reply(txn, r, data, actual);
    }
    case fuchsia_io_DirectoryWatchOrdinal: {
      DECODE_REQUEST(msg, DirectoryWatch);
      DEFINE_REQUEST(msg, DirectoryWatch);
      zx::channel watcher(request->watcher);

      request->watcher = ZX_HANDLE_INVALID;
      if (request->mask & (~fuchsia_io_WATCH_MASK_ALL) || request->options != 0) {
        return fuchsia_io_DirectoryWatch_reply(txn, ZX_ERR_INVALID_ARGS);
      }
      r = devfs_watch(dn, std::move(watcher), request->mask);
      return fuchsia_io_DirectoryWatch_reply(txn, r);
    }
    case fuchsia_io_DirectoryAdminQueryFilesystemOrdinal: {
      DECODE_REQUEST(msg, DirectoryAdminQueryFilesystem);
      fuchsia_io_FilesystemInfo info;
      memset(&info, 0, sizeof(info));
      strlcpy((char*)info.name, "devfs", fuchsia_io_MAX_FS_NAME_BUFFER);
      return fuchsia_io_DirectoryAdminQueryFilesystem_reply(txn, ZX_OK, &info);
    }
  }  // switch

  // close inbound handles so they do not leak
  FidlHandleInfoCloseMany(msg->handles, msg->num_handles);
  return ZX_ERR_NOT_SUPPORTED;
}

void DcIostate::HandleRpc(std::unique_ptr<DcIostate> ios, async_dispatcher_t* dispatcher,
                          async::WaitBase* wait, zx_status_t status,
                          const zx_packet_signal_t* signal) {
  if (status != ZX_OK) {
    LOGF(ERROR, "Failed to wait for RPC: %s", zx_status_get_string(status));
    return;
  }

  if (signal->observed & ZX_CHANNEL_READABLE) {
    status = fs::ReadMessage(
        wait->object(), [&ios, dispatcher](fidl_incoming_msg_t* msg, fs::FidlConnection* txn) {
          return DcIostate::DevfsFidlHandler(msg, txn->Txn(), ios.get(), dispatcher);
        });
    if (status == ZX_OK) {
      ios->BeginWait(std::move(ios), dispatcher);
      return;
    }
  } else if (signal->observed & ZX_CHANNEL_PEER_CLOSED) {
    fs::CloseMessage([&ios, dispatcher](fidl_incoming_msg_t* msg, fs::FidlConnection* txn) {
      return DcIostate::DevfsFidlHandler(msg, txn->Txn(), ios.get(), dispatcher);
    });
  } else {
    LOGF(FATAL, "Unexpected signal state %#08x", signal->observed);
  }
  // Do not start waiting again, and destroy |ios|
}

zx::unowned_channel devfs_root_borrow() { return zx::unowned_channel(g_devfs_root); }

zx::channel devfs_root_clone() { return zx::channel(fdio_service_clone(g_devfs_root.get())); }

void devfs_init(const fbl::RefPtr<Device>& device, async_dispatcher_t* dispatcher) {
  root_devnode = std::make_unique<Devnode>("");
  if (!root_devnode) {
    return;
  }
  root_devnode->ino = 1;

  prepopulate_protocol_dirs();

  // Create dummy diagnostics devnode, so that the directory is listed.
  diagnostics_devnode = devfs_mkdir(root_devnode.get(), "diagnostics");

  // TODO(teisenbe): Should this take a reference?
  root_devnode->device = device.get();
  root_devnode->device->self = root_devnode.get();

  zx::channel h0, h1;
  if (zx::channel::create(0, &h0, &h1) != ZX_OK) {
    return;
  } else if (DcIostate::Create(root_devnode.get(), dispatcher, &h0) != ZX_OK) {
    return;
  }

  g_devfs_root = std::move(h1);
  // This is actually owned by |device| and will be freed in unpublish
  __UNUSED auto ptr = root_devnode.release();
}

zx_status_t devfs_walk(Devnode* dn, const char* path, fbl::RefPtr<Device>* dev) {
  Devnode* inout = dn;

  char path_copy[PATH_MAX];
  if (strlen(path) + 1 > sizeof(path_copy)) {
    return ZX_ERR_BUFFER_TOO_SMALL;
  }
  strcpy(path_copy, path);

  zx_status_t status = devfs_walk(&inout, path_copy);
  if (status != ZX_OK) {
    return status;
  }
  *dev = fbl::RefPtr(inout->device);
  return ZX_OK;
}
