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

#include <fcntl.h>
#include <sys/stat.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 <zircon/status.h>

#include "logging.h"

namespace {

bool VmoFromFd(int fd, bool executable, fuchsia::mem::Buffer* buffer) {
  if (!buffer) {
    FX_LOG(FATAL, LOG_TAG, "Invalid buffer pointer");
  }

  struct stat stat_struct;
  if (fstat(fd, &stat_struct) == -1) {
    FX_LOGF(ERROR, LOG_TAG, "fstat failed: %s", strerror(errno));
    return false;
  }

  zx_handle_t result = ZX_HANDLE_INVALID;
  zx_status_t status;
  if (executable) {
    status = fdio_get_vmo_exec(fd, &result);
  } else {
    status = fdio_get_vmo_copy(fd, &result);
  }

  if (status != ZX_OK) {
    FX_LOGF(ERROR, LOG_TAG, "fdio_get_vmo_%s failed: %s",
            executable ? "exec" : "copy", zx_status_get_string(status));
    return false;
  }

  buffer->vmo = zx::vmo(result);
  buffer->size = stat_struct.st_size;

  return true;
}

}  // namespace

namespace dart_utils {

bool VmoFromFilename(const std::string& filename,
                     bool executable,
                     fuchsia::mem::Buffer* buffer) {
  // Note: the implementation here cannot be shared with VmoFromFilenameAt
  // because fdio_open_fd_at does not aim to provide POSIX compatibility, and
  // thus does not handle AT_FDCWD as dirfd.
  auto flags = fuchsia::io::OpenFlags::RIGHT_READABLE;
  if (executable) {
    flags |= fuchsia::io::OpenFlags::RIGHT_EXECUTABLE;
  }

  int fd;
  const zx_status_t status =
      fdio_open_fd(filename.c_str(), static_cast<uint32_t>(flags), &fd);
  if (status != ZX_OK) {
    FX_LOGF(ERROR, LOG_TAG, "fdio_open_fd(\"%s\", %08x) failed: %s",
            filename.c_str(), flags, zx_status_get_string(status));
    return false;
  }
  bool result = VmoFromFd(fd, executable, buffer);
  close(fd);
  return result;
}

bool VmoFromFilenameAt(int dirfd,
                       const std::string& filename,
                       bool executable,
                       fuchsia::mem::Buffer* buffer) {
  auto flags = fuchsia::io::OpenFlags::RIGHT_READABLE;
  if (executable) {
    flags |= fuchsia::io::OpenFlags::RIGHT_EXECUTABLE;
  }

  int fd;
  const zx_status_t status = fdio_open_fd_at(dirfd, filename.c_str(),
                                             static_cast<uint32_t>(flags), &fd);
  if (status != ZX_OK) {
    FX_LOGF(ERROR, LOG_TAG, "fdio_open_fd_at(%d, \"%s\", %08x) failed: %s",
            dirfd, filename.c_str(), flags, zx_status_get_string(status));
    return false;
  }
  bool result = VmoFromFd(fd, executable, buffer);
  close(fd);
  return result;
}

zx_status_t IsSizeValid(const fuchsia::mem::Buffer& buffer, bool* is_valid) {
  size_t vmo_size;
  zx_status_t status = buffer.vmo.get_size(&vmo_size);
  if (status == ZX_OK) {
    *is_valid = vmo_size >= buffer.size;
  } else {
    *is_valid = false;
  }
  return status;
}

}  // namespace dart_utils
