// 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 <fcntl.h>
#include <stdatomic.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>

#include <zircon/processargs.h>
#include <zircon/syscalls.h>
#include <lib/fdio/io.h>
#include <lib/fdio/util.h>

#include <lib/fdio/remoteio.h>
#include <lib/fdio/vfs.h>

#include "private.h"

typedef struct vmofile {
    fdio_t io;
    zx_handle_t vmo;
    zx_off_t off;
    zx_off_t end;
    zx_off_t ptr;
    mtx_t lock;
} vmofile_t;

static ssize_t vmofile_read(fdio_t* io, void* data, size_t len) {
    vmofile_t* vf = (vmofile_t*)io;
    zx_off_t at;

    mtx_lock(&vf->lock);
    if (len > (vf->end - vf->ptr)) {
        len = vf->end - vf->ptr;
    }
    at = vf->ptr;
    vf->ptr += len;
    mtx_unlock(&vf->lock);

    zx_status_t status = zx_vmo_read(vf->vmo, data, at, len);
    if (status < 0) {
        return status;
    } else {
        return len;
    }
}

static ssize_t vmofile_read_at(fdio_t* io, void* data, size_t len, off_t at) {
    vmofile_t* vf = (vmofile_t*)io;

    // make sure we're within the file's bounds
    if (at > (off_t)(vf->end - vf->off)) {
        return ZX_ERR_INVALID_ARGS;
    }

    // adjust to vmo offset
    at += vf->off;

    // clip length to file bounds
    if (len > (vf->end - at)) {
        len = vf->end - at;
    }

    zx_status_t status = zx_vmo_read(vf->vmo, data, at, len);
    if (status < 0) {
        return status;
    } else {
        return len;
    }
}

static ssize_t vmofile_write_at(fdio_t* io, const void* data, size_t len, off_t at) {
    return ZX_ERR_NOT_SUPPORTED;
}

static off_t vmofile_seek(fdio_t* io, off_t offset, int whence) {
    vmofile_t* vf = (vmofile_t*)io;
    mtx_lock(&vf->lock);
    zx_off_t at;
    switch (whence) {
    case SEEK_SET:
        at = offset;
        break;
    case SEEK_CUR:
        at = (vf->ptr - vf->off) + offset;
        break;
    case SEEK_END:
        at = (vf->end - vf->off) + offset;
        break;
    default:
        mtx_unlock(&vf->lock);
        return ZX_ERR_INVALID_ARGS;
    }
    if (at > (vf->end - vf->off)) {
        at = ZX_ERR_OUT_OF_RANGE;
    } else {
        vf->ptr = vf->off + at;
    }
    mtx_unlock(&vf->lock);
    return at;
}

static zx_status_t vmofile_close(fdio_t* io) {
    vmofile_t* vf = (vmofile_t*)io;
    zx_handle_t h = vf->vmo;
    vf->vmo = 0;
    zx_handle_close(h);
    return 0;
}

static zx_status_t vmofile_misc(fdio_t* io, uint32_t op, int64_t off, uint32_t maxreply, void* ptr, size_t len) {
    vmofile_t* vf = (vmofile_t*)io;
    switch (op) {
    case ZXRIO_STAT: {
        vnattr_t attr;
        memset(&attr, 0, sizeof(attr));
        attr.size = vf->end - vf->off;
        attr.mode = V_TYPE_FILE | V_IRUSR;
        if (maxreply < sizeof(attr)) {
            return ZX_ERR_INVALID_ARGS;
        }
        memcpy(ptr, &attr, sizeof(attr));
        return sizeof(attr);
    }
    case ZXRIO_MMAP: {
        if (len != sizeof(zxrio_mmap_data_t) || maxreply < sizeof(zxrio_mmap_data_t)) {
            return ZX_ERR_INVALID_ARGS;
        }
        zxrio_mmap_data_t* data = ptr;
        zx_rights_t rights = ZX_RIGHTS_BASIC | ZX_RIGHT_MAP | ZX_RIGHT_GET_PROPERTY;
        if (data->flags & FDIO_MMAP_FLAG_WRITE) {
            return ZX_ERR_ACCESS_DENIED;
        }
        rights |= (data->flags & FDIO_MMAP_FLAG_READ) ? ZX_RIGHT_READ : 0;
        rights |= (data->flags & FDIO_MMAP_FLAG_EXEC) ? ZX_RIGHT_EXECUTE : 0;

        // Make a tiny clone of the portion of the portion of the VMO representing this file
        zx_handle_t h;
        // TODO(smklein): In the future, "vf->vmo" will already be a cloned vmo
        // representing this file (logically, making "vf->off" always zero), and
        // nothing past "vf->end". As a consequence, we will be able to
        // duplicate "vf->vmo" instead of cloning it.
        zx_status_t status = zx_vmo_clone(vf->vmo, ZX_VMO_CLONE_COPY_ON_WRITE,
                                          vf->off, vf->end - vf->off, &h);
        if (status != ZX_OK) {
            return status;
        }
        // Only return this clone with the requested rights
        zx_handle_t out;
        if ((status = zx_handle_replace(h, rights, &out)) != ZX_OK) {
            return status;
        }
        return out;
    }
    case ZXRIO_FCNTL: {
        uint32_t cmd = maxreply;
        switch (cmd) {
        case F_GETFL: {
            uint32_t* flags = (uint32_t*) ptr;
            if (flags) {
                *flags = 0;
            }
            return ZX_OK;
        }
        case F_SETFL:
            return ZX_OK;
        default:
            return ZX_ERR_NOT_SUPPORTED;
        }
    }
    default:
        return ZX_ERR_INVALID_ARGS;
    }
}

zx_status_t vmofile_get_vmo(fdio_t* io, int flags, zx_handle_t* out) {
    vmofile_t* vf = (vmofile_t*)io;

    if (out == NULL) {
        return ZX_ERR_INVALID_ARGS;
    }

    size_t len = vf->end - vf->off;
    if (flags & FDIO_MMAP_FLAG_PRIVATE) {
        return zx_vmo_clone(vf->vmo, ZX_VMO_CLONE_COPY_ON_WRITE, 0, len, out);
    } else {
        size_t vmo_len = 0;
        if (vf->off != 0 || zx_vmo_get_size(vf->vmo, &vmo_len) != ZX_OK ||
            len != vmo_len) {
            return ZX_ERR_NOT_FOUND;
        }
        zx_rights_t rights = ZX_RIGHTS_BASIC | ZX_RIGHT_GET_PROPERTY |
                ZX_RIGHT_MAP;
        rights |= (flags & FDIO_MMAP_FLAG_READ) ? ZX_RIGHT_READ : 0;
        rights |= (flags & FDIO_MMAP_FLAG_WRITE) ? ZX_RIGHT_WRITE : 0;
        rights |= (flags & FDIO_MMAP_FLAG_EXEC) ? ZX_RIGHT_EXECUTE : 0;
        return zx_handle_duplicate(vf->vmo, rights, out);
    }
}

static fdio_ops_t vmofile_ops = {
    .read = vmofile_read,
    .read_at = vmofile_read_at,
    .write = fdio_default_write,
    .write_at = vmofile_write_at,
    .recvfrom = fdio_default_recvfrom,
    .sendto = fdio_default_sendto,
    .recvmsg = fdio_default_recvmsg,
    .sendmsg = fdio_default_sendmsg,
    .seek = vmofile_seek,
    .misc = vmofile_misc,
    .close = vmofile_close,
    .open = fdio_default_open,
    .clone = fdio_default_clone,
    .ioctl = fdio_default_ioctl,
    .wait_begin = fdio_default_wait_begin,
    .wait_end = fdio_default_wait_end,
    .unwrap = fdio_default_unwrap,
    .shutdown = fdio_default_shutdown,
    .posix_ioctl = fdio_default_posix_ioctl,
    .get_vmo = vmofile_get_vmo,
};

fdio_t* fdio_vmofile_create(zx_handle_t h, zx_off_t off, zx_off_t len) {
    vmofile_t* vf = fdio_alloc(sizeof(vmofile_t));
    if (vf == NULL) {
        zx_handle_close(h);
        return NULL;
    }
    vf->io.ops = &vmofile_ops;
    vf->io.magic = FDIO_MAGIC;
    atomic_init(&vf->io.refcount, 1);
    vf->vmo = h;
    vf->off = off;
    vf->end = off + len;
    vf->ptr = off;
    mtx_init(&vf->lock, mtx_plain);
    return &vf->io;
}

int fdio_vmo_fd(zx_handle_t vmo, uint64_t offset, uint64_t length) {
    fdio_t* io;
    int fd;
    if ((io = fdio_vmofile_create(vmo, offset, length)) == NULL) {
        return -1;
    }
    if ((fd = fdio_bind_to_fd(io, -1, 0)) < 0) {
        fdio_close(io);
        fdio_release(io);
        return -1;
    }
    return fd;
}
