// 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 <fs/vmo-file.h>

#include <limits.h>
#include <string.h>

#include <fbl/algorithm.h>
#include <fbl/auto_lock.h>
#include <fuchsia/io/c/fidl.h>
#include <zircon/assert.h>
#include <zircon/syscalls.h>

namespace fs {
namespace {
constexpr uint64_t kVmoFileBlksize = PAGE_SIZE;

zx_rights_t GetVmoRightsForAccessMode(uint32_t flags) {
    zx_rights_t rights = ZX_RIGHTS_BASIC | ZX_RIGHT_MAP;
    if (flags & ZX_FS_RIGHT_READABLE) {
        rights |= ZX_RIGHT_READ;
    }
    if (flags & ZX_FS_RIGHT_WRITABLE) {
        rights |= ZX_RIGHT_WRITE;
    }
    if ((flags & ZX_FS_RIGHT_READABLE) & !(flags & ZX_FS_RIGHT_WRITABLE)) {
        rights |= ZX_RIGHT_EXECUTE;
    }
    return rights;
}

} // namespace

VmoFile::VmoFile(const zx::vmo& unowned_vmo,
                 size_t offset,
                 size_t length,
                 bool writable,
                 VmoSharing vmo_sharing)
    : vmo_handle_(unowned_vmo.get()),
      offset_(offset), length_(length), writable_(writable), vmo_sharing_(vmo_sharing) {
    ZX_DEBUG_ASSERT(vmo_handle_ != ZX_HANDLE_INVALID);
}

VmoFile::~VmoFile() {}

zx_status_t VmoFile::ValidateFlags(uint32_t flags) {
    if (flags & ZX_FS_FLAG_DIRECTORY) {
        return ZX_ERR_NOT_DIR;
    }
    if (IsWritable(flags) && !writable_) {
        return ZX_ERR_ACCESS_DENIED;
    }
    return ZX_OK;
}

zx_status_t VmoFile::Getattr(vnattr_t* attr) {
    memset(attr, 0, sizeof(vnattr_t));
    attr->mode = V_TYPE_FILE | V_IRUSR;
    if (writable_) {
        attr->mode |= V_IWUSR;
    }
    attr->size = length_;
    attr->blksize = kVmoFileBlksize;
    attr->blkcount = fbl::round_up(attr->size, kVmoFileBlksize) / VNATTR_BLKSIZE;
    attr->nlink = 1;
    return ZX_OK;
}

zx_status_t VmoFile::Read(void* data, size_t length, size_t offset, size_t* out_actual) {
    if (length == 0u || offset >= length_) {
        *out_actual = 0u;
        return ZX_OK;
    }

    size_t remaining_length = length_ - offset;
    if (length > remaining_length) {
        length = remaining_length;
    }
    zx_status_t status = zx_vmo_read(vmo_handle_, data, offset_ + offset, length);
    if (status != ZX_OK) {
        return status;
    }
    *out_actual = length;
    return ZX_OK;
}

zx_status_t VmoFile::Write(const void* data, size_t length, size_t offset, size_t* out_actual) {
    ZX_DEBUG_ASSERT(writable_); // checked by the VFS

    if (length == 0u) {
        *out_actual = 0u;
        return ZX_OK;
    }
    if (offset >= length_) {
        return ZX_ERR_NO_SPACE;
    }

    size_t remaining_length = length_ - offset;
    if (length > remaining_length) {
        length = remaining_length;
    }
    zx_status_t status = zx_vmo_write(vmo_handle_, data, offset_ + offset, length);
    if (status == ZX_OK) {
        *out_actual = length;
    }
    return status;
}

zx_status_t VmoFile::GetHandles(uint32_t flags, zx_handle_t* hnd, uint32_t* type,
                                zxrio_node_info_t* extra) {
    ZX_DEBUG_ASSERT(!IsWritable(flags) || writable_); // checked by the VFS

    zx::vmo vmo;
    size_t offset;
    zx_status_t status = AcquireVmo(GetVmoRightsForAccessMode(flags), &vmo, &offset);
    if (status != ZX_OK) {
        return status;
    }

    *hnd = vmo.release();
    *type = fuchsia_io_NodeInfoTag_vmofile;
    extra->vmofile.offset = offset;
    extra->vmofile.length = length_;
    return ZX_OK;
}

zx_status_t VmoFile::AcquireVmo(zx_rights_t rights, zx::vmo* out_vmo, size_t* out_offset) {
    ZX_DEBUG_ASSERT(!(rights & ZX_RIGHT_WRITE) || writable_); // checked by the VFS

    switch (vmo_sharing_) {
    case VmoSharing::NONE:
        return ZX_ERR_NOT_SUPPORTED;
    case VmoSharing::DUPLICATE:
        return DuplicateVmo(rights, out_vmo, out_offset);
    case VmoSharing::CLONE_COW:
        return CloneVmo(rights, out_vmo, out_offset);
    }
    __UNREACHABLE;
}

zx_status_t VmoFile::DuplicateVmo(zx_rights_t rights, zx::vmo* out_vmo, size_t* out_offset) {
    zx_status_t status = zx_handle_duplicate(vmo_handle_, rights, out_vmo->reset_and_get_address());
    if (status != ZX_OK)
        return status;

    *out_offset = offset_;
    return ZX_OK;
}

zx_status_t VmoFile::CloneVmo(zx_rights_t rights, zx::vmo* out_vmo, size_t* out_offset) {
    size_t clone_offset = fbl::round_down(offset_, static_cast<size_t>(PAGE_SIZE));
    size_t clone_length = fbl::round_up(offset_ + length_, static_cast<size_t>(PAGE_SIZE)) -
                          clone_offset;

    if (!(rights & ZX_RIGHT_WRITE)) {
        // Use a shared clone for read-only content.
        // TODO(ZX-1154): Replace the mutex with fbl::call_once() once that's implemented.
        // The shared clone is only initialized at most once so using a mutex is excessive.
        fbl::AutoLock lock(&mutex_);
        zx_status_t status;
        if (!shared_clone_) {
            status = zx_vmo_clone(vmo_handle_, ZX_VMO_CLONE_COPY_ON_WRITE,
                                  clone_offset, clone_length,
                                  shared_clone_.reset_and_get_address());
            if (status != ZX_OK)
                return status;
        }

        status = shared_clone_.duplicate(rights, out_vmo);
        if (status != ZX_OK)
            return status;
    } else {
        // Use separate clone for each client with writable COW access.
        zx::vmo private_clone;
        zx_status_t status = zx_vmo_clone(vmo_handle_, ZX_VMO_CLONE_COPY_ON_WRITE,
                                          clone_offset, clone_length,
                                          private_clone.reset_and_get_address());
        if (status != ZX_OK)
            return status;

        status = private_clone.replace(rights, out_vmo);
        if (status != ZX_OK)
            return status;
    }

    *out_offset = offset_ - clone_offset;
    return ZX_OK;
}

} // namespace fs
