// 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 "flutter/fml/file.h"

#include <dirent.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>

#include <memory>
#include <sstream>

#include "flutter/fml/eintr_wrapper.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/mapping.h"
#include "flutter/fml/unique_fd.h"

namespace fml {

std::string CreateTemporaryDirectory() {
  char directory_name[] = "/tmp/flutter_XXXXXXXX";
  auto* result = ::mkdtemp(directory_name);
  if (result == nullptr) {
    return "";
  }
  return {result};
}

static int ToPosixAccessFlags(FilePermission permission) {
  int flags = 0;
  switch (permission) {
    case FilePermission::kRead:
      flags |= O_RDONLY;  // read only
      break;
    case FilePermission::kWrite:
      flags |= O_WRONLY;  // write only
      break;
    case FilePermission::kReadWrite:
      flags |= O_RDWR;  // read-write
      break;
  }
  return flags;
}

static int ToPosixCreateModeFlags(FilePermission permission) {
  int mode = 0;
  switch (permission) {
    case FilePermission::kRead:
      mode |= S_IRUSR;
      break;
    case FilePermission::kWrite:
      mode |= S_IWUSR;
      break;
    case FilePermission::kReadWrite:
      mode |= S_IRUSR | S_IWUSR;
      break;
  }
  return mode;
}

fml::UniqueFD OpenFile(const char* path,
                       bool create_if_necessary,
                       FilePermission permission) {
  return OpenFile(fml::UniqueFD{AT_FDCWD}, path, create_if_necessary,
                  permission);
}

fml::UniqueFD OpenFile(const fml::UniqueFD& base_directory,
                       const char* path,
                       bool create_if_necessary,
                       FilePermission permission) {
  if (path == nullptr) {
    return {};
  }

  int flags = 0;
  int mode = 0;

  if (create_if_necessary && !FileExists(base_directory, path)) {
    flags = ToPosixAccessFlags(permission) | O_CREAT | O_TRUNC;
    mode = ToPosixCreateModeFlags(permission);
  } else {
    flags = ToPosixAccessFlags(permission);
    mode = 0;  // Not creating since it already exists.
  }

  return fml::UniqueFD{
      FML_HANDLE_EINTR(::openat(base_directory.get(), path, flags, mode))};
}

fml::UniqueFD OpenDirectory(const char* path,
                            bool create_if_necessary,
                            FilePermission permission) {
  return OpenDirectory(fml::UniqueFD{AT_FDCWD}, path, create_if_necessary,
                       permission);
}

fml::UniqueFD OpenDirectory(const fml::UniqueFD& base_directory,
                            const char* path,
                            bool create_if_necessary,
                            FilePermission permission) {
  if (path == nullptr) {
    return {};
  }

  if (create_if_necessary && !FileExists(base_directory, path)) {
    if (::mkdirat(base_directory.get(), path,
                  ToPosixCreateModeFlags(permission) | S_IXUSR) != 0) {
      return {};
    }
  }

  return fml::UniqueFD{FML_HANDLE_EINTR(
      ::openat(base_directory.get(), path, O_RDONLY | O_DIRECTORY))};
}

fml::UniqueFD Duplicate(fml::UniqueFD::element_type descriptor) {
  return fml::UniqueFD{FML_HANDLE_EINTR(::dup(descriptor))};
}

bool IsDirectory(const fml::UniqueFD& directory) {
  if (!directory.is_valid()) {
    return false;
  }

  struct stat stat_result = {};

  if (::fstat(directory.get(), &stat_result) != 0) {
    return false;
  }

  return S_ISDIR(stat_result.st_mode);
}

bool IsDirectory(const fml::UniqueFD& base_directory, const char* path) {
  UniqueFD file = OpenFileReadOnly(base_directory, path);
  return (file.is_valid() && IsDirectory(file));
}

bool IsFile(const std::string& path) {
  struct stat buf;
  if (stat(path.c_str(), &buf) != 0) {
    return false;
  }

  return S_ISREG(buf.st_mode);
}

bool TruncateFile(const fml::UniqueFD& file, size_t size) {
  if (!file.is_valid()) {
    return false;
  }

  return ::ftruncate(file.get(), size) == 0;
}

bool UnlinkDirectory(const char* path) {
  return UnlinkDirectory(fml::UniqueFD{AT_FDCWD}, path);
}

bool UnlinkDirectory(const fml::UniqueFD& base_directory, const char* path) {
  return ::unlinkat(base_directory.get(), path, AT_REMOVEDIR) == 0;
}

bool UnlinkFile(const char* path) {
  return UnlinkFile(fml::UniqueFD{AT_FDCWD}, path);
}

bool UnlinkFile(const fml::UniqueFD& base_directory, const char* path) {
  int code = ::unlinkat(base_directory.get(), path, 0);
  if (code != 0) {
    FML_DLOG(ERROR) << strerror(errno);
  }
  return code == 0;
}

bool FileExists(const fml::UniqueFD& base_directory, const char* path) {
  if (!base_directory.is_valid()) {
    return false;
  }

  return ::faccessat(base_directory.get(), path, F_OK, 0) == 0;
}

bool WriteAtomically(const fml::UniqueFD& base_directory,
                     const char* file_name,
                     const Mapping& data) {
  if (file_name == nullptr || data.GetMapping() == nullptr) {
    return false;
  }

  std::stringstream stream;
  stream << file_name << ".temp";
  const auto temp_file_name = stream.str();

  auto temp_file = OpenFile(base_directory, temp_file_name.c_str(), true,
                            FilePermission::kReadWrite);
  if (!temp_file.is_valid()) {
    return false;
  }

  if (!TruncateFile(temp_file, data.GetSize())) {
    return false;
  }

  FileMapping mapping(temp_file, {FileMapping::Protection::kWrite});
  if (mapping.GetMutableMapping() == nullptr ||
      data.GetSize() != mapping.GetSize()) {
    return false;
  }

  ::memcpy(mapping.GetMutableMapping(), data.GetMapping(), data.GetSize());

  if (::msync(mapping.GetMutableMapping(), data.GetSize(), MS_SYNC) != 0) {
    return false;
  }

  return ::renameat(base_directory.get(), temp_file_name.c_str(),
                    base_directory.get(), file_name) == 0;
}

bool VisitFiles(const fml::UniqueFD& directory, const FileVisitor& visitor) {
  fml::UniqueFD dup_fd(dup(directory.get()));
  if (!dup_fd.is_valid()) {
    FML_DLOG(ERROR) << "Can't dup the directory fd. Error: " << strerror(errno);
    return true;  // continue to visit other files
  }

  fml::UniqueDir dir(::fdopendir(dup_fd.get()));
  if (!dir.is_valid()) {
    FML_DLOG(ERROR) << "Can't open the directory. Error: " << strerror(errno);
    return true;  // continue to visit other files
  }

  // The directory fd will be closed by `closedir`.
  (void)dup_fd.release();

  // Without `rewinddir`, `readir` will directly return NULL (end of dir is
  // reached) after a previuos `VisitFiles` call for the same `const
  // fml::UniqueFd& directory`.
  rewinddir(dir.get());
  while (dirent* ent = readdir(dir.get())) {
    std::string filename = ent->d_name;
    if (filename != "." && filename != "..") {
      if (!visitor(directory, filename)) {
        return false;
      }
    }
  }

  return true;
}

}  // namespace fml
