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

#include <zircon/fidl.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>
#include <zircon/device/vfs.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/util.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 AsyncLoopOwnedRpcHandler<DcIostate> {
public:
    explicit DcIostate(Devnode* dn);
    ~DcIostate();

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

    struct Node {
        static fbl::DoublyLinkedListNodeState<DcIostate*>& node_state(DcIostate& obj) {
            return obj.node_;
        }
    };
    // Remove this DcIostate from its devnode
    void DetachFromDevnode();

 private:
    uint64_t readdir_ino_ = 0;

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

    // entry in our devnode's iostate list
    fbl::DoublyLinkedListNodeState<DcIostate*> node_;
};

// BUG(ZX-2868): We currently never free these after allocating them
struct 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;

    // entry in our parent devnode's children list
    struct Node {
        static fbl::DoublyLinkedListNodeState<Devnode*>& node_state(Devnode& obj) {
            return obj.node;
        }
    };
    fbl::DoublyLinkedListNodeState<Devnode*> node;

    // list of our child devnodes
    fbl::DoublyLinkedList<Devnode*, Devnode::Node> 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*, DcIostate::Node> 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->hrpc == ZX_HANDLE_INVALID);
    }
    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->hrpc == ZX_HANDLE_INVALID) {
        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 = fbl::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(Device* dev, const fbl::String& name) {
    auto dn = fbl::make_unique<Devnode>(name);
    if (!dn) {
        return nullptr;
    }
    dn->ino = next_ino++;
    dn->device = dev;
    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, char** pathout) {
    Devnode* dn = *dn_inout;

again:
    if ((path == nullptr) || (path[0] == 0)) {
        *dn_inout = dn;
        return ZX_OK;
    }
    char* name = path;
    char* undo = nullptr;
    if ((path = strchr(path, '/')) != nullptr) {
        undo = path;
        *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;
        }
    }
    if (dn == *dn_inout) {
        return ZX_ERR_NOT_FOUND;
    }
    if (undo) {
        *undo = '/';
    }
    *dn_inout = dn;
    *pathout = name;
    return ZX_ERR_NEXT;
}

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, &path);

    bool describe = flags & ZX_FS_FLAG_DESCRIBE;

    bool no_remote = (dn->device == nullptr) || (dn->device->hrpc == ZX_HANDLE_INVALID);
    bool local_required = devnode_is_local(dn);
    bool local_requested = flags & (ZX_FS_FLAG_NOREMOTE | ZX_FS_FLAG_DIRECTORY);

    if (r == ZX_ERR_NEXT) {
        // We only partially matched -- there's more path to walk.
        if (no_remote || local_required) {
            // No remote to pass this on to.
            r = ZX_ERR_NOT_FOUND;
        } else if (local_requested) {
            // Local requested, but this is remote only.
            r = ZX_ERR_NOT_SUPPORTED;
        } else {
            // There is more path to walk, and this node can accept
            // remote requests.
            r = ZX_OK;
        }
    } else {
        path = (char*) ".";
    }

    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 (local_requested || local_required) {
        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->hrpc.get(), flags, 0, path, strlen(path), ipc.release());
}

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

    // detach all connected iostates
    while (!dn->iostate.is_empty()) {
        dn->iostate.pop_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
    while ((dn->children.pop_front() != nullptr)) {
        // they will be unpublished when the devices they're
        // associated with are eventually destroyed
    }
}

} // 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);
}

zx_status_t DcIostate::Create(Devnode* dn, async_dispatcher_t* dispatcher, zx::channel* ipc) {
    auto ios = fbl::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 DcIostate::DetachFromDevnode() {
    if (devnode_) {
        devnode_->iostate.erase(*this);
        devnode_ = nullptr;
    }
    set_channel(zx::channel());
}

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

void devfs_advertise(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->parent && dev->parent->self) {
        devfs_notify(dev->parent->self, 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(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->parent && dev->parent->self) {
        devfs_notify(dev->parent->self, dev->self->name, fuchsia_io_WATCH_EVENT_REMOVED);
        devfs_notify(dev->parent->self, dev->self->name, fuchsia_io_WATCH_EVENT_ADDED);
    }
}

zx_status_t devfs_publish(Device* parent, 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;
}

void devfs_unpublish(Device* dev) {
    if (dev->self != nullptr) {
        devfs_remove(dev->self);
        dev->self = nullptr;
    }
    if (dev->link != nullptr) {
        devfs_remove(dev->link);
        dev->link = nullptr;
    }
}

zx_status_t devfs_connect(Device* dev, zx::channel client_remote) {
    if (!client_remote.is_valid()) {
        return ZX_ERR_BAD_HANDLE;
    }
    fuchsia_io_DirectoryOpen(dev->hrpc.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;
    switch (hdr->ordinal) {
    case fuchsia_io_NodeCloneOrdinal: {
        DECODE_REQUEST(msg, NodeClone);
        DEFINE_REQUEST(msg, NodeClone);
        zx_handle_t h = request->object;
        uint32_t flags = request->flags;
        char path[PATH_MAX];
        path[0] = '\0';
        devfs_open(dn, dispatcher, h, path, flags | ZX_FS_FLAG_NOREMOTE);
        return ZX_OK;
    }
    case fuchsia_io_NodeDescribeOrdinal: {
        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);
    }
    case fuchsia_io_DirectoryOpenOrdinal: {
        DECODE_REQUEST(msg, DirectoryOpen);
        DEFINE_REQUEST(msg, DirectoryOpen);
        uint32_t len = static_cast<uint32_t>(request->path.size);
        char* path = request->path.data;
        zx_handle_t h = request->object;
        uint32_t flags = request->flags;
        if ((len < 1) || (len > 1024)) {
            zx_handle_close(h);
        } else {
            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 > ZXFIDL_MAX_MSG_BYTES) {
            return fuchsia_io_DirectoryReadDirents_reply(txn, ZX_ERR_INVALID_ARGS, nullptr, 0);
        }

        uint8_t data[request->max_bytes];
        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);
    }
    case fuchsia_io_NodeIoctlOrdinal: {
        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, "devcoord: 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, "devcoord: DcIostate::HandleRpc: invalid signals %x\n", signal->observed);
        exit(0);
    }
    // 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(Device* device, async_dispatcher_t* dispatcher) {
    printf("devmgr: init\n");

    root_devnode = fbl::make_unique<Devnode>("");
    if (!root_devnode) {
        printf("devmgr: failed to allocate devfs root node\n");
        return;
    }
    root_devnode->ino = 1;

    prepopulate_protocol_dirs();

    root_devnode->device = device;
    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);
}

} // namespace devmgr
