// 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 "devcoordinator.h"
#include "devmgr.h"
#include "memfs-private.h"

#include <zircon/listnode.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include <zircon/device/vfs.h>

#include <fdio/remoteio.h>
#include <fdio/util.h>

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

typedef struct dc_watcher watcher_t;
typedef struct dc_iostate iostate_t;

struct dc_watcher {
    watcher_t* next;
    devnode_t* devnode;
    uint32_t mask;
    zx_handle_t handle;
};

struct dc_devnode {
    const char* name;
    uint64_t ino;

    // NULL if we are a pure directory node,
    // otherwise the device we are referencing
    device_t* device;

    watcher_t* watchers;

    // entry in our parent devnode's children list
    list_node_t node;

    // list of our child devnodes
    list_node_t children;

    // list of attached iostates
    list_node_t iostate;

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

struct dc_iostate {
    port_handler_t ph;

    // entry in our devnode's iostate list
    list_node_t node;

    // pointer to our devnode, NULL if it has been removed
    devnode_t* devnode;

    uint64_t readdir_ino;
};

extern port_t dc_port;

static uint64_t next_ino = 2;

static devnode_t root_devnode = {
    .name = "",
    .ino = 1,
    .children = LIST_INITIAL_VALUE(root_devnode.children),
    .iostate = LIST_INITIAL_VALUE(root_devnode.iostate),
};

static devnode_t* class_devnode;

static zx_status_t dc_rio_handler(port_handler_t* ph, zx_signals_t signals, uint32_t evt);
static devnode_t* devfs_mkdir(devnode_t* parent, const char* name);

#define PNMAX 16
static 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;
    }
}

typedef struct {
    const char* name;
    devnode_t* devnode;
    uint32_t id;
    uint32_t flags;
} pinfo_t;

static pinfo_t proto_info[] = {
#define DDK_PROTOCOL_DEF(tag, val, name, flags) { name, NULL, val, flags },
#include <ddk/protodefs.h>
    { NULL, NULL, 0, 0 },
};

static devnode_t* proto_dir(uint32_t id) {
    for (pinfo_t* info = proto_info; info->name; info++) {
        if (info->id == id) {
            return info->devnode;
        }
    }
    return NULL;
}

static void prepopulate_protocol_dirs(void) {
    class_devnode = devfs_mkdir(&root_devnode, "class");
    for (pinfo_t* info = proto_info; info->name; info++) {
        if (!(info->flags & PF_NOPUB)) {
            info->devnode = devfs_mkdir(class_devnode, info->name);
        }
    }
}

static zx_status_t iostate_create(devnode_t* dn, zx_handle_t h) {
    iostate_t* ios = calloc(1, sizeof(iostate_t));
    if (ios == NULL) {
        return ZX_ERR_NO_MEMORY;
    }

    ios->ph.handle = h;
    ios->ph.waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED;
    ios->ph.func = dc_rio_handler;
    ios->devnode = dn;
    list_add_tail(&dn->iostate, &ios->node);

    zx_status_t r;
    if ((r = port_wait(&dc_port, &ios->ph)) < 0) {
        list_delete(&ios->node);
        free(ios);
    }
    return r;
}

static void iostate_destroy(iostate_t* ios) {
    if (ios->devnode) {
        list_delete(&ios->node);
        ios->devnode = NULL;
    }
    zx_handle_close(ios->ph.handle);
    ios->ph.handle = ZX_HANDLE_INVALID;
    free(ios);
}

// 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
static bool devnode_is_dir(devnode_t* dn) {
    if (list_is_empty(&dn->children)) {
        return (dn->device == NULL) || (dn->device->hrpc == ZX_HANDLE_INVALID);
    }
    return true;
}

// Local devnodes are ones that we should not hand off OPEN
// RPCs to the underlying devhost
static bool devnode_is_local(devnode_t* dn) {
    if (dn->device == NULL) {
        return true;
    }
    if (dn->device->hrpc == ZX_HANDLE_INVALID) {
        return true;
    }
    if (dn->device->flags & DEV_CTX_MUST_ISOLATE) {
        return true;
    }
    return false;
}

static void devfs_notify(devnode_t* dn, const char* name, unsigned op) {
    watcher_t* w = dn->watchers;
    if (w == NULL) {
        return;
    }

    size_t len = strlen(name);
    if (len > VFS_WATCH_NAME_MAX) {
        return;
    }

    uint8_t msg[VFS_WATCH_NAME_MAX + 2];
    msg[0] = op;
    msg[1] = len;
    memcpy(msg + 2, name, len);

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

    watcher_t** wp;
    watcher_t* next;
    for (wp = &dn->watchers; w != NULL; w = next) {
        next = w->next;
        if (!(w->mask & op)) {
            continue;
        }
        if (zx_channel_write(w->handle, 0, msg, len + 2, NULL, 0) < 0) {
            *wp = next;
            zx_handle_close(w->handle);
            free(w);
        } else {
            wp = &w->next;
        }
    }
}

static zx_status_t devfs_watch(devnode_t* dn, zx_handle_t h, uint32_t mask) {
    watcher_t* watcher = calloc(1, sizeof(watcher_t));
    if (watcher == NULL) {
        return ZX_ERR_NO_MEMORY;
    }

    watcher->devnode = dn;
    watcher->next = dn->watchers;
    watcher->handle = h;
    watcher->mask = mask;
    dn->watchers = watcher;

    if (mask & VFS_WATCH_MASK_EXISTING) {
        devnode_t* child;
        list_for_every_entry(&dn->children, child, devnode_t, node) {
            if (child->device && (child->device->flags & DEV_CTX_INVISIBLE)) {
                continue;
            }
            //TODO: send multiple per write
            devfs_notify(dn, child->name, VFS_WATCH_EVT_EXISTING);
        }
        devfs_notify(dn, "", VFS_WATCH_EVT_IDLE);

    }

    // Don't send EXISTING or IDLE events from now on...
    watcher->mask &= ~(VFS_WATCH_MASK_EXISTING | VFS_WATCH_MASK_IDLE);

    return ZX_OK;
}

// If namelen is nonzero, it is the null-terminator-inclusive length
// of name, which should be copied into the devnode.  Otherwise name
// is guaranteed to exist for the lifetime of the devnode.
static devnode_t* devfs_mknode(device_t* dev, const char* name, size_t namelen) {
    devnode_t* dn = calloc(1, sizeof(devnode_t) + namelen);
    if (dn == NULL) {
        return NULL;
    }
    if (namelen > 0) {
        char* p = (char*) (dn + 1);
        memcpy(p, name, namelen);
        dn->name = p;
    } else {
        dn->name = name;
    }
    dn->ino = next_ino++;
    dn->device = dev;
    list_initialize(&dn->children);
    list_initialize(&dn->iostate);
    return dn;
}

static devnode_t* devfs_mkdir(devnode_t* parent, const char* name) {
    devnode_t* dn = devfs_mknode(NULL, name, 0);
    if (dn == NULL) {
        return NULL;
    }
    list_add_tail(&parent->children, &dn->node);
    return dn;
}

static devnode_t* devfs_lookup(devnode_t* parent, const char* name) {
    devnode_t* child;
    list_for_every_entry(&parent->children, child, devnode_t, node) {
        if (!strcmp(name, child->name)) {
            return child;
        }
    }
    return NULL;
}

void devfs_advertise(device_t* dev) {
    if (dev->link) {
        devnode_t* dir = proto_dir(dev->protocol_id);
        devfs_notify(dir, dev->link->name, VFS_WATCH_EVT_ADDED);
    }
    devfs_notify(dev->parent->self, dev->self->name, VFS_WATCH_EVT_ADDED);
}

zx_status_t devfs_publish(device_t* parent, device_t* dev) {
    if ((parent->self == NULL) || (dev->self != NULL) || (dev->link != NULL)) {
        return ZX_ERR_INTERNAL;
    }

    devnode_t* dnself = devfs_mknode(dev, dev->name, 0);
    if (dnself == NULL) {
        return ZX_ERR_NO_MEMORY;
    }

    if ((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_t* dir = proto_dir(dev->protocol_id);
    if (dir != NULL) {
        char tmp[32];
        const char* name = dev->name;
        size_t namelen = 0;

        if ((dev->protocol_id != ZX_PROTOCOL_MISC) &&
            (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) == NULL) {
                    name = tmp;
                    namelen = 4;
                    goto got_name;
                }
            }
            free(dnself);
            return ZX_ERR_ALREADY_EXISTS;
got_name:
            ;
        }

        devnode_t* dnlink = devfs_mknode(dev, name, namelen);
        if (dnlink == NULL) {
            free(dnself);
            return ZX_ERR_NO_MEMORY;
        }

        // add link node to class directory
        list_add_tail(&dir->children, &dnlink->node);
        dev->link = dnlink;
    }

done:
    // add self node to parent directory
    list_add_tail(&parent->self->children, &dnself->node);
    dev->self = dnself;

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

static void _devfs_remove(devnode_t* dn) {
    if (list_in_list(&dn->node)) {
        list_delete(&dn->node);
    }

    // disconnect from device
    if (dn->device != NULL) {
        if (dn->device->self == dn) {
            dn->device->self = NULL;
        }
        if (dn->device->link == dn) {
            dn->device->link = NULL;
        }
        dn->device = NULL;
    }

    // detach all connected iostates
    iostate_t* ios;
    list_for_every_entry(&dn->iostate, ios, iostate_t, node) {
        ios->devnode = NULL;
        zx_handle_close(ios->ph.handle);
        ios->ph.handle = ZX_HANDLE_INVALID;
    }

    if ((dn->device == NULL) ||
        !(dn->device->flags & DEV_CTX_INVISIBLE)) {
        devfs_notify(dn, "", VFS_WATCH_EVT_DELETED);
    }

    // destroy all watchers
    watcher_t* watcher;
    watcher_t* next;
    for (watcher = dn->watchers; watcher != NULL; watcher = next) {
        next = watcher->next;
        zx_handle_close(watcher->handle);
        free(watcher);
    }
    dn->watchers = NULL;

    // detach children
    while (list_remove_head(&dn->children) != NULL) {
        // they will be unpublished when the devices they're
        // associated with are eventually destroyed
    }
}

void devfs_unpublish(device_t* dev) {
    if (dev->self != NULL) {
        _devfs_remove(dev->self);
        dev->self = NULL;
    }
    if (dev->link != NULL) {
        _devfs_remove(dev->link);
        dev->link = NULL;
    }
}

static zx_status_t devfs_walk(devnode_t** _dn, char* path, char** pathout) {
    devnode_t* dn = *_dn;

again:
    if ((path == NULL) || (path[0] == 0)) {
        *_dn = dn;
        return ZX_OK;
    }
    char* name = path;
    char* undo = NULL;
    if ((path = strchr(path, '/')) != NULL) {
        undo = path;
        *path++ = 0;
    }
    if (name[0] == 0) {
        return ZX_ERR_BAD_PATH;
    }
    devnode_t* child;
    list_for_every_entry(&dn->children, child, devnode_t, node) {
        if (!strcmp(child->name, name)) {
            if(child->device && (child->device->flags & DEV_CTX_INVISIBLE)) {
                continue;
            }
            dn = child;
            goto again;
        }
    }
    if (dn == *_dn) {
        return ZX_ERR_NOT_FOUND;
    }
    if (undo) {
        *undo = '/';
    }
    *_dn = dn;
    *pathout = name;
    return ZX_ERR_NEXT;
}

static void devfs_open(devnode_t* dirdn, zx_handle_t h, char* path, uint32_t flags) {
    if (!strcmp(path, ".")) {
        path = NULL;
    }

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

    bool pipeline = flags & O_PIPELINE;

    if (r == ZX_ERR_NEXT) {
        // we only partially matched -- there's more path to walk
        if ((dn->device == NULL) || (dn->device->hrpc == ZX_HANDLE_INVALID)) {
            // no remote to pass this on to
            r = ZX_ERR_NOT_FOUND;
        } else if (flags & (O_NOREMOTE | O_DIRECTORY)) {
            // local requested, but this is remote only
            r = ZX_ERR_NOT_SUPPORTED;
        } else {
            r = ZX_OK;
        }
    } else {
        path = (char*) ".";
    }

    if (r < 0) {
fail:
        if (!pipeline) {
            zxrio_object_t obj;
            obj.status = r;
            obj.type = 0;
            zx_channel_write(h, 0, &obj, ZXRIO_OBJECT_MINSIZE, NULL, 0);
        }
        zx_handle_close(h);
        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 ((flags & (O_NOREMOTE | O_DIRECTORY)) || devnode_is_local(dn)) {
        if ((r = iostate_create(dn, h)) < 0) {
            goto fail;
        }
        if (!pipeline) {
            zxrio_object_t obj;
            obj.status = ZX_OK;
            obj.type = FDIO_PROTOCOL_REMOTE;
            zx_channel_write(h, 0, &obj, ZXRIO_OBJECT_MINSIZE, NULL, 0);
        }
        return;
    }

    // Otherwise we will pass the request on to the remote
    zxrio_msg_t msg;
    memset(&msg, 0, ZXRIO_HDR_SZ);
    msg.op = ZXRIO_OPEN;
    msg.datalen = strlen(path);
    msg.arg = flags;
    msg.hcount = 1;
    msg.handle[0] = h;
    memcpy(msg.data, path, msg.datalen);

    if ((r = zx_channel_write(dn->device->hrpc, 0, &msg, ZXRIO_HDR_SZ + msg.datalen,
                              msg.handle, 1)) < 0) {
        goto fail;
    }
}

static zx_status_t fill_dirent(vdirent_t* de, size_t delen,
                               const char* name, size_t len, uint32_t type) {
    size_t sz = sizeof(vdirent_t) + len + 1;

    // round up to uint32 aligned
    if (sz & 3)
        sz = (sz + 3) & (~3);
    if (sz > delen)
        return ZX_ERR_INVALID_ARGS;
    de->size = sz;
    de->type = type;
    memcpy(de->name, name, len);
    de->name[len] = 0;
    return sz;
}

static zx_status_t devfs_readdir(devnode_t* dn, uint64_t* _ino, void* data, size_t len) {
    void* ptr = data;
    uint64_t ino = *_ino;

    devnode_t* child;
    list_for_every_entry(&dn->children, child, devnode_t, node) {
        if (child->ino <= ino) {
            continue;
        }
        if (child->device == NULL) {
            // "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 (list_is_empty(&child->children)) {
                continue;
            }
        } else {
            // invisible devices also do not show up
            if (child->device->flags & DEV_CTX_INVISIBLE) {
                continue;
            }
        }
        ino = child->ino;
        zx_status_t r = fill_dirent(ptr, len, child->name, strlen(child->name),
                                    VTYPE_TO_DTYPE(V_TYPE_DIR));
        if (r < 0) {
            break;
        }
        ptr += r;
        len -= r;
    }

    *_ino = ino;
    return ptr - data;
}

static zx_status_t devfs_rio_handler(zxrio_msg_t* msg, void* cookie) {
    iostate_t* ios = cookie;
    devnode_t* dn = ios->devnode;
    if (dn == NULL) {
        return ZX_ERR_PEER_CLOSED;
    }

    // ensure handle count specified by opcode matches reality
    if (msg->hcount != ZXRIO_HC(msg->op)) {
        return ZX_ERR_IO;
    }
    msg->hcount = 0;

    uint32_t len = msg->datalen;
    int32_t arg = msg->arg;
    msg->datalen = 0;

    switch (ZXRIO_OP(msg->op)) {
    case ZXRIO_CLONE:
        msg->data[0] = 0;
        devfs_open(dn, msg->handle[0], (char*) msg->data, arg | O_NOREMOTE);
        return ERR_DISPATCHER_INDIRECT;
    case ZXRIO_OPEN:
        if ((len < 1) || (len > 1024)) {
            zx_handle_close(msg->handle[0]);
        } else {
            msg->data[len] = 0;
            devfs_open(dn, msg->handle[0], (char*) msg->data, arg);
        }
        return ERR_DISPATCHER_INDIRECT;
    case ZXRIO_STAT:
        msg->datalen = sizeof(vnattr_t);
        vnattr_t* attr = (void*)msg->data;
        memset(attr, 0, sizeof(vnattr_t));
        if (devnode_is_dir(dn)) {
            attr->mode = V_TYPE_DIR | V_IRUSR | V_IWUSR;
        } else {
            attr->mode = V_TYPE_CDEV | V_IRUSR | V_IWUSR;
        }
        attr->size = 0;
        attr->nlink = 1;
        return msg->datalen;
    case ZXRIO_READDIR:
        if (arg > FDIO_CHUNK_SIZE) {
            return ZX_ERR_INVALID_ARGS;
        }
        if (msg->arg2.off == READDIR_CMD_RESET) {
            ios->readdir_ino = 0;
        }
        zx_status_t r = devfs_readdir(dn, &ios->readdir_ino, msg->data, arg);
        if (r >= 0) {
            msg->datalen = r;
        }
        return r;
    case ZXRIO_IOCTL_1H:
        switch (msg->arg2.op) {
        case IOCTL_VFS_WATCH_DIR: {
            vfs_watch_dir_t* wd = (vfs_watch_dir_t*) msg->data;
            if ((len != sizeof(vfs_watch_dir_t)) ||
                (wd->options != 0) ||
                (wd->mask & (~VFS_WATCH_MASK_ALL))) {
                r = ZX_ERR_INVALID_ARGS;
            } else {
                r = devfs_watch(dn, msg->handle[0], wd->mask);
            }
            if (r != ZX_OK) {
                zx_handle_close(msg->handle[0]);
            }
            return r;
        }
        }
        break;
    case ZXRIO_IOCTL:
        switch (msg->arg2.op) {
        case IOCTL_VFS_QUERY_FS: {
            const char* devfs_name = "devfs";
            if (arg < (int32_t) (sizeof(vfs_query_info_t) + strlen(devfs_name))) {
                return ZX_ERR_INVALID_ARGS;
            }
            vfs_query_info_t* info = (vfs_query_info_t*) msg->data;
            memset(info, 0, sizeof(*info));
            memcpy(info->name, devfs_name, strlen(devfs_name));
            msg->datalen = sizeof(vfs_query_info_t) + strlen(devfs_name);
            return sizeof(vfs_query_info_t) + strlen(devfs_name);
        }
        }
        break;
    }

    // close inbound handles so they do not leak
    for (unsigned i = 0; i < ZXRIO_HC(msg->op); i++) {
        zx_handle_close(msg->handle[i]);
    }
    return ZX_ERR_NOT_SUPPORTED;
}

static zx_status_t dc_rio_handler(port_handler_t* ph, zx_signals_t signals, uint32_t evt) {
    iostate_t* ios = containerof(ph, iostate_t, ph);

    zx_status_t r;
    zxrio_msg_t msg;
    if (signals & ZX_CHANNEL_READABLE) {
        if ((r = zxrio_handle_rpc(ph->handle, &msg, devfs_rio_handler, ios)) == ZX_OK) {
            return ZX_OK;
        }
    } else if (signals & ZX_CHANNEL_PEER_CLOSED) {
        zxrio_handle_close(devfs_rio_handler, ios);
        r = ZX_ERR_STOP;
    } else {
        printf("dc_rio_handler: invalid signals %x\n", signals);
        exit(0);
    }

    iostate_destroy(ios);
    return r;
}

static zx_handle_t devfs_root;

zx_handle_t devfs_root_clone(void) {
    return fdio_service_clone(devfs_root);
}

void devfs_init(zx_handle_t root_job) {
    printf("devmgr: init\n");

    prepopulate_protocol_dirs();

    root_devnode.device = coordinator_init(root_job);
    root_devnode.device->self = &root_devnode;

    zx_handle_t h0, h1;
    if (zx_channel_create(0, &h0, &h1) != ZX_OK) {
        return;
    } else if (iostate_create(&root_devnode, h0) != ZX_OK) {
        zx_handle_close(h0);
        zx_handle_close(h1);
        return;
    }

    devfs_root = h1;
}

