// 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 "mapped_resource.h"

#include <dlfcn.h>
#include <fcntl.h>
#include <fuchsia/io/cpp/fidl.h>
#include <fuchsia/mem/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/io.h>
#include <lib/syslog/global.h>
#include <lib/trace/event.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <zircon/dlfcn.h>
#include <zircon/status.h>

#include "third_party/dart/runtime/include/dart_api.h"

#include "inlines.h"
#include "logging.h"
#include "vmo.h"

namespace dart_utils {

static bool OpenVmo(fuchsia::mem::Buffer* resource_vmo,
                    fdio_ns_t* namespc,
                    const std::string& path,
                    bool executable) {
  TRACE_DURATION("dart", "LoadFromNamespace", "path", path);

  if (namespc == nullptr) {
    // Opening a file in the root namespace expects an absolute path.
    dart_utils::Check(path[0] == '/', LOG_TAG);
    if (!VmoFromFilename(path, executable, resource_vmo)) {
      return false;
    }
  } else {
    // openat of a path with a leading '/' ignores the namespace fd.
    // require a relative path.
    dart_utils::Check(path[0] != '/', LOG_TAG);

    auto root_dir = fdio_ns_opendir(namespc);
    if (root_dir < 0) {
      FX_LOG(ERROR, LOG_TAG, "Failed to open namespace directory");
      return false;
    }

    bool result =
        dart_utils::VmoFromFilenameAt(root_dir, path, executable, resource_vmo);
    close(root_dir);
    if (!result) {
      return result;
    }
  }

  return true;
}

bool MappedResource::LoadFromNamespace(fdio_ns_t* namespc,
                                       const std::string& path,
                                       MappedResource& resource,
                                       bool executable) {
  fuchsia::mem::Buffer resource_vmo;
  return OpenVmo(&resource_vmo, namespc, path, executable) &&
         LoadFromVmo(path, std::move(resource_vmo), resource, executable);
}

bool MappedResource::LoadFromVmo(const std::string& path,
                                 fuchsia::mem::Buffer resource_vmo,
                                 MappedResource& resource,
                                 bool executable) {
  if (resource_vmo.size == 0) {
    return true;
  }

  uint32_t flags = ZX_VM_PERM_READ;
  if (executable) {
    flags |= ZX_VM_PERM_EXECUTE;
  }
  uintptr_t addr;
  zx_status_t status = zx::vmar::root_self()->map(flags, 0, resource_vmo.vmo, 0,
                                                  resource_vmo.size, &addr);
  if (status != ZX_OK) {
    FX_LOGF(ERROR, LOG_TAG, "Failed to map: %s", zx_status_get_string(status));
    return false;
  }

  resource.address_ = reinterpret_cast<void*>(addr);
  resource.size_ = resource_vmo.size;
  return true;
}

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

static int OpenFdExec(const std::string& path, int dirfd) {
  int fd = -1;
  zx_status_t result;
  if (dirfd == AT_FDCWD) {
    // fdio_open_fd_at does not support AT_FDCWD, by design.  Use fdio_open_fd
    // and expect an absolute path for that usage pattern.
    dart_utils::Check(path[0] == '/', LOG_TAG);
    result = fdio_open_fd(
        path.c_str(),
        fuchsia::io::OPEN_RIGHT_READABLE | fuchsia::io::OPEN_RIGHT_EXECUTABLE,
        &fd);
  } else {
    dart_utils::Check(path[0] != '/', LOG_TAG);
    result = fdio_open_fd_at(
        dirfd, path.c_str(),
        fuchsia::io::OPEN_RIGHT_READABLE | fuchsia::io::OPEN_RIGHT_EXECUTABLE,
        &fd);
  }
  if (result != ZX_OK) {
    FX_LOGF(ERROR, LOG_TAG, "fdio_open_fd_at(%s) failed: %s", path.c_str(),
            zx_status_get_string(result));
    return -1;
  }
  return fd;
}

bool ElfSnapshot::Load(fdio_ns_t* namespc, const std::string& path) {
  int root_dir = -1;
  if (namespc == nullptr) {
    root_dir = AT_FDCWD;
  } else {
    root_dir = fdio_ns_opendir(namespc);
    if (root_dir < 0) {
      FX_LOG(ERROR, LOG_TAG, "Failed to open namespace directory");
      return false;
    }
  }
  return Load(root_dir, path);
}

bool ElfSnapshot::Load(int dirfd, const std::string& path) {
  const int fd = OpenFdExec(path, dirfd);
  if (fd < 0) {
    FX_LOGF(ERROR, LOG_TAG, "Failed to open VMO for %s from dir.",
            path.c_str());
    return false;
  }
  return Load(fd);
}

bool ElfSnapshot::Load(int fd) {
  const char* error;
  handle_ = Dart_LoadELF_Fd(fd, 0, &error, &vm_data_, &vm_instrs_,
                            &isolate_data_, &isolate_instrs_);
  if (handle_ == nullptr) {
    FX_LOGF(ERROR, LOG_TAG, "Failed load ELF: %s", error);
    return false;
  }
  return true;
}

ElfSnapshot::~ElfSnapshot() {
  Dart_UnloadELF(handle_);
}

}  // namespace dart_utils
