// 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 "../shared/async-loop-owned-rpc-handler.h"
#include "../shared/log.h"
#include "coordinator.h"
#include "devfs.h"

#include <zircon/device/vfs.h>
#include <zircon/fidl.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include <ddk/driver.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/string.h>
#include <fs/connection.h>
#include <fs/handler.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/memfs/cpp/vnode.h>

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

namespace devmgr {

namespace {

uint64_t next_ino = 2;

fbl::unique_ptr<Devnode> root_devnode;

fbl::unique_ptr<Devnode> class_devnode;

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

#define PNMAX 16
const char* proto_name(uint32_t id, char buf[PNMAX]) {
    switch (id) {
#define DDK_PROTOCOL_DEF(tag, val, name, flags)                                                    \
    case val:                                                                                      \
        return name;
#include <ddk/protodefs.h>
    default:
        snprintf(buf, PNMAX, "proto-%08x", id);
        return buf;
    }
}

zx::channel g_devfs_root;

} // namespace

struct Watcher : fbl::DoublyLinkedListable<fbl::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_msg_t* msg, fidl_txn_t* txn, void* cookie,
                                        async_dispatcher_t* dispatcher);

    static void HandleRpc(fbl::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(ZX-2868): 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<fbl::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;
    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;
        }
    }
    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).release();
        }
    }
}

void describe_error(zx::channel h, zx_status_t status) {
    fuchsia_io_NodeOnOpenEvent msg;
    memset(&msg, 0, sizeof(msg));
    msg.hdr.ordinal = fuchsia_io_NodeOnOpenOrdinal;
    msg.s = status;
    h.write(0, &msg, sizeof(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->channel()->is_valid());
    }
    return true;
}

// Local devnodes are ones that we should not hand off OPEN
// RPCs to the underlying devhost
bool devnode_is_local(Devnode* dn) {
    if (dn->device == nullptr) {
        return true;
    }
    if (!dn->device->channel()->is_valid()) {
        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(fbl::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 {

fbl::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;
}

fbl::unique_ptr<Devnode> devfs_mkdir(Devnode* parent, const fbl::String& name) {
    fbl::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.
            if (child.children.is_empty()) {
                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;

    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) {
            fs::OnOpenMsg msg;
            memset(&msg, 0, sizeof(msg));
            msg.primary.hdr.ordinal = fuchsia_io_NodeOnOpenOrdinal;
            msg.primary.s = ZX_OK;
            msg.primary.info = (fuchsia_io_NodeInfo*)FIDL_ALLOC_PRESENT;
            msg.extra.tag = fuchsia_io_NodeInfoTag_directory;

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

    // Otherwise we will pass the request on to the remote.
    fuchsia_io_DirectoryOpen(dn->device->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;
    }

    fbl::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:
        fbl::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->channel()->get(), 0 /* flags */, 0 /* mode */, ".", 1,
                             client_remote.release());
    return ZX_OK;
}

// 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_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;
    // This is an if statement because, depending on the state of the ordinal
    // migration, GenOrdinal and Ordinal may be the same value.  See FIDL-524.
    uint32_t ordinal = hdr->ordinal;
    if (ordinal == fuchsia_io_NodeCloneOrdinal ||
        ordinal == fuchsia_io_NodeCloneGenOrdinal) {
        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;
    } else if (ordinal == fuchsia_io_NodeDescribeOrdinal ||
               ordinal == fuchsia_io_NodeDescribeGenOrdinal) {
        DECODE_REQUEST(msg, NodeDescribe);
        fuchsia_io_NodeInfo info;
        memset(&info, 0, sizeof(info));
        info.tag = fuchsia_io_NodeInfoTag_directory;
        return fuchsia_io_NodeDescribe_reply(txn, &info);
    } else if (ordinal == fuchsia_io_DirectoryOpenOrdinal ||
               ordinal == fuchsia_io_DirectoryOpenGenOrdinal) {
        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;
    } else if (ordinal == fuchsia_io_NodeGetAttrOrdinal ||
               ordinal == fuchsia_io_NodeGetAttrGenOrdinal) {
        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);
    } else if (ordinal == fuchsia_io_DirectoryRewindOrdinal ||
               ordinal == fuchsia_io_DirectoryRewindGenOrdinal) {
        DECODE_REQUEST(msg, DirectoryRewind);
        ios->readdir_ino_ = 0;
        return fuchsia_io_DirectoryRewind_reply(txn, ZX_OK);
    } else if (ordinal == fuchsia_io_DirectoryReadDirentsOrdinal ||
               ordinal == fuchsia_io_DirectoryReadDirentsGenOrdinal) {
        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);
    } else if (ordinal == fuchsia_io_DirectoryWatchOrdinal ||
               ordinal == fuchsia_io_DirectoryWatchGenOrdinal) {
        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);
    } else if (ordinal == fuchsia_io_DirectoryAdminQueryFilesystemOrdinal ||
               ordinal == fuchsia_io_DirectoryAdminQueryFilesystemGenOrdinal) {
        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);
    } else if (ordinal == fuchsia_io_NodeIoctlOrdinal ||
               ordinal == fuchsia_io_NodeIoctlGenOrdinal) {
        DECODE_REQUEST(msg, NodeIoctl);
        zx_handle_close_many(msg->handles, msg->num_handles);
        return fuchsia_io_NodeIoctl_reply(txn, ZX_ERR_NOT_SUPPORTED, nullptr, 0, nullptr, 0);
    }

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

void DcIostate::HandleRpc(fbl::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) {
        log(ERROR, "devcoordinator: DcIostate::HandleRpc aborting, saw status %d\n", status);
        return;
    }

    if (signal->observed & ZX_CHANNEL_READABLE) {
        status = fs::ReadMessage(
            wait->object(), [&ios, dispatcher](fidl_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_msg_t* msg, fs::FidlConnection* txn) {
            return DcIostate::DevfsFidlHandler(msg, txn->Txn(), ios.get(), dispatcher);
        });
    } else {
        log(ERROR, "devcoordinator: DcIostate::HandleRpc: invalid signals %x\n", signal->observed);
        abort();
    }
    // 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) {
        printf("devcoordinator: failed to allocate devfs root node\n");
        return;
    }
    root_devnode->ino = 1;

    prepopulate_protocol_dirs();

    // 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::WrapRefPtr(inout->device);
    return ZX_OK;
}

} // namespace devmgr
