// Copyright 2013 The Flutter 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 "file_in_namespace_buffer.h"

#include <fuchsia/io/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <zircon/status.h>

#include "flutter/fml/trace_event.h"
#include "runtime/dart/utils/files.h"
#include "runtime/dart/utils/handle_exception.h"
#include "runtime/dart/utils/mapped_resource.h"
#include "runtime/dart/utils/tempfs.h"
#include "runtime/dart/utils/vmo.h"

namespace flutter_runner {

FileInNamespaceBuffer::FileInNamespaceBuffer(int namespace_fd,
                                             const char* path,
                                             bool executable)
    : address_(nullptr), size_(0) {
  fuchsia::mem::Buffer buffer;
  if (!dart_utils::VmoFromFilenameAt(namespace_fd, path, executable, &buffer) ||
      buffer.size == 0) {
    return;
  }

  uint32_t flags = ZX_VM_PERM_READ;
  if (executable) {
    flags |= ZX_VM_PERM_EXECUTE;
  }

  uintptr_t addr;
  const zx_status_t status =
      zx::vmar::root_self()->map(flags, 0, buffer.vmo, 0, buffer.size, &addr);
  if (status != ZX_OK) {
    FML_LOG(FATAL) << "Failed to map " << path << ": "
                   << zx_status_get_string(status);
  }

  address_ = reinterpret_cast<void*>(addr);
  size_ = buffer.size;
}

FileInNamespaceBuffer::~FileInNamespaceBuffer() {
  if (address_ != nullptr) {
    zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(address_), size_);
    address_ = nullptr;
    size_ = 0;
  }
}

const uint8_t* FileInNamespaceBuffer::GetMapping() const {
  return reinterpret_cast<const uint8_t*>(address_);
}

size_t FileInNamespaceBuffer::GetSize() const {
  return size_;
}

bool FileInNamespaceBuffer::IsDontNeedSafe() const {
  return true;
}

std::unique_ptr<fml::Mapping> LoadFile(int namespace_fd,
                                       const char* path,
                                       bool executable) {
  FML_TRACE_EVENT("flutter", "LoadFile", "path", path);
  return std::make_unique<FileInNamespaceBuffer>(namespace_fd, path,
                                                 executable);
}

std::unique_ptr<fml::FileMapping> MakeFileMapping(const char* path,
                                                  bool executable) {
  auto flags = fuchsia::io::OpenFlags::RIGHT_READABLE;
  if (executable) {
    flags |= fuchsia::io::OpenFlags::RIGHT_EXECUTABLE;
  }

  // The returned file descriptor is compatible with standard posix operations
  // such as close, mmap, etc. We only need to treat open/open_at specially.
  int fd;
  const zx_status_t status =
      fdio_open_fd(path, static_cast<uint32_t>(flags), &fd);
  if (status != ZX_OK) {
    return nullptr;
  }

  using Protection = fml::FileMapping::Protection;

  std::initializer_list<Protection> protection_execute = {Protection::kRead,
                                                          Protection::kExecute};
  std::initializer_list<Protection> protection_read = {Protection::kRead};
  auto mapping = std::make_unique<fml::FileMapping>(
      fml::UniqueFD{fd}, executable ? protection_execute : protection_read);

  if (!mapping->IsValid()) {
    return nullptr;
  }
  return mapping;
}

}  // namespace flutter_runner
