// 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 char* 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(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 char* 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 char* 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 char* name) {
    for (auto& child : parent->children) {
        if (!strcmp(name, child.name.c_str())) {
            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)) {
}

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;

        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
