// Copyright 2017 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 "private.h"
#include "unistd.h"

#include <fuchsia/io/c/fidl.h>
#include <lib/fdio/io.h>
#include <lib/fdio/vfs.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>

#define MIN_WINDOW (PAGE_SIZE * 4)
#define MAX_WINDOW ((size_t)64 << 20)

static zx_status_t read_at(fdio_t* io, void* buf, size_t len, off_t offset,
                           size_t* out_actual) {
    size_t actual = 0u;
    zx_status_t status = ZX_OK;
    for (;;) {
        status = zxio_read_at(fdio_get_zxio(io), offset, buf, len, &actual);
        if (status != ZX_ERR_SHOULD_WAIT) {
            break;
        }
        status = fdio_wait(io, FDIO_EVT_READABLE, ZX_TIME_INFINITE, NULL);
        if (status != ZX_OK) {
            break;
        }
    }
    if (status != ZX_OK) {
        return status;
    }
    if (actual == 0) { // EOF (?)
        return ZX_ERR_OUT_OF_RANGE;
    }
    *out_actual = actual;
    return ZX_OK;
}

static zx_status_t read_file_into_vmo(fdio_t* io, zx_handle_t* out_vmo) {
    zx_handle_t current_vmar_handle = zx_vmar_root_self();

    fuchsia_io_NodeAttributes attr;
    zx_status_t status = fdio_get_ops(io)->get_attr(io, &attr);
    if (status != ZX_OK) {
        return ZX_ERR_BAD_HANDLE;
    }

    uint64_t size = attr.content_size;
    uint64_t offset = 0;

    status = zx_vmo_create(size, 0, out_vmo);
    if (status != ZX_OK) {
        return status;
    }

    while (size > 0) {
        if (size < MIN_WINDOW) {
            // There is little enough left that copying is less overhead
            // than fiddling with the page tables.
            char buffer[PAGE_SIZE];
            size_t xfer = size < sizeof(buffer) ? size : sizeof(buffer);
            size_t nread;
            status = read_at(io, buffer, xfer, offset, &nread);
            if (status != ZX_OK) {
                zx_handle_close(*out_vmo);
                return status;
            }
            status = zx_vmo_write(*out_vmo, buffer, offset, nread);
            if (status < 0) {
                zx_handle_close(*out_vmo);
                return status;
            }
            offset += nread;
            size -= nread;
        } else {
            // Map the VMO into our own address space so we can read into
            // it directly and avoid double-buffering.
            size_t chunk = size < MAX_WINDOW ? size : MAX_WINDOW;
            size_t window = (chunk + PAGE_SIZE - 1) & -PAGE_SIZE;
            uintptr_t start = 0;
            status = zx_vmar_map(current_vmar_handle,
                ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
                0, *out_vmo, offset, window, &start);
            if (status != ZX_OK) {
                zx_handle_close(*out_vmo);
                return status;
            }
            uint8_t* buffer = reinterpret_cast<uint8_t*>(start);
            while (chunk > 0) {
                size_t nread;
                status = read_at(io, buffer, chunk, offset, &nread);
                if (status != ZX_OK) {
                    zx_vmar_unmap(current_vmar_handle, start, window);
                    zx_handle_close(*out_vmo);
                    return status;
                }
                buffer += nread;
                offset += nread;
                size -= nread;
                chunk -= nread;
            }
            zx_vmar_unmap(current_vmar_handle, start, window);
        }
    }

    return ZX_OK;
}

static zx_status_t get_file_vmo(fdio_t* io, zx_handle_t* out_vmo) {
    return fdio_get_ops(io)->get_vmo(io, fuchsia_io_VMO_FLAG_READ | fuchsia_io_VMO_FLAG_PRIVATE,
                                     out_vmo);
}

static zx_status_t copy_file_vmo(fdio_t* io, zx_handle_t* out_vmo) {
    zx_status_t status = get_file_vmo(io, out_vmo);
    if (status == ZX_OK) {
        return ZX_OK;
    }

    zx_handle_t vmo;
    if ((status = read_file_into_vmo(io, &vmo)) == ZX_OK) {
        status = zx_handle_replace(
            vmo,
            ZX_RIGHTS_BASIC | ZX_RIGHTS_PROPERTY |
            ZX_RIGHT_READ | ZX_RIGHT_MAP,
            out_vmo);
    }
    return status;
}

__EXPORT
zx_status_t fdio_get_vmo_copy(int fd, zx_handle_t* out_vmo) {
    fdio_t* io = fd_to_io(fd);
    if (io == NULL) {
        return ZX_ERR_BAD_HANDLE;
    }
    zx_status_t status = copy_file_vmo(io, out_vmo);
    fdio_release(io);
    return status;
}

__EXPORT
zx_status_t fdio_get_vmo_clone(int fd, zx_handle_t* out_vmo) {
    fdio_t* io = fd_to_io(fd);
    if (io == NULL) {
        return ZX_ERR_BAD_HANDLE;
    }
    zx_status_t status = get_file_vmo(io, out_vmo);
    fdio_release(io);
    return status;
}

__EXPORT
zx_status_t fdio_get_vmo_exact(int fd, zx_handle_t* out_vmo) {
    fdio_t* io = fd_to_io(fd);
    if (io == NULL) {
        return ZX_ERR_BAD_HANDLE;
    }

    zx_status_t status = fdio_get_ops(io)->get_vmo(io, fuchsia_io_VMO_FLAG_READ |
                                                   fuchsia_io_VMO_FLAG_EXACT, out_vmo);
    fdio_release(io);
    return status;
}
