// 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 <fs/vfs.h>
#include <fuchsia/io/c/fidl.h>
#include <zircon/assert.h>
#include <zircon/device/vfs.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::GetNodeInfo(uint32_t flags, fuchsia_io_NodeInfo* info) {
    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;
    }

    info->tag = fuchsia_io_NodeInfoTag_vmofile;
    info->vmofile.vmo = vmo.release();
    info->vmofile.offset = offset;
    info->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
