// Copyright 2016 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 "src/lib/files/scoped_temp_dir.h"

#include "src/lib/fxl/build_config.h"

#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>

#include "src/lib/files/directory.h"
#include "src/lib/files/eintr_wrapper.h"
#include "src/lib/files/file.h"
#include "src/lib/files/path.h"
#include "src/lib/files/unique_fd.h"
#include "src/lib/fxl/logging.h"

namespace files {

namespace {
fxl::StringView GetGlobalTmpDir() {
  const char* env_var = getenv("TMPDIR");
  return fxl::StringView(env_var ? env_var : "/tmp");
}

// Fills the first 6 bytes of |tp| with random characters suitable for the file
// system. The implementation is taken from __randname.c in //zircon
void GenerateRandName(char* tp) {
  FXL_DCHECK(strlen(tp) >= 6);

  struct timespec ts;
  unsigned long r;

  clock_gettime(CLOCK_REALTIME, &ts);
  r = ts.tv_nsec * 65537 ^
      (reinterpret_cast<uintptr_t>(&ts) / 16 + reinterpret_cast<uintptr_t>(tp));
  for (size_t i = 0; i < 6; i++, r >>= 5) {
    tp[i] = 'A' + (r & 15) + (r & 16) * 2;
  }
}

// Creates a unique temporary file under |root_fd| from template |tp|.
fxl::UniqueFD MksTempAt(int root_fd, char* tp, size_t tp_length) {
  FXL_DCHECK(strlen(tp) == tp_length);
  FXL_DCHECK(tp_length >= 6);
  FXL_DCHECK(memcmp(tp + tp_length - 6, "XXXXXX", 6) == 0);
  int retries = 100;
  do {
    GenerateRandName(tp + tp_length - 6);
    fxl::UniqueFD result(
        HANDLE_EINTR(openat(root_fd, tp, O_CREAT | O_EXCL, 0700)));
    if (result.is_valid()) {
      return result;
    }
  } while (--retries && errno == EEXIST);

  memcpy(tp + tp_length - 6, "XXXXXX", 6);
  return fxl::UniqueFD();
}

// Creates a unique temporary directory under |root_fd| from template |tp|.
char* MkdTempAt(int root_fd, char* tp, size_t tp_length) {
  FXL_DCHECK(strlen(tp) == tp_length);
  FXL_DCHECK(tp_length >= 6);
  FXL_DCHECK(memcmp(tp + tp_length - 6, "XXXXXX", 6) == 0);
  int retries = 100;
  do {
    GenerateRandName(tp + tp_length - 6);
    if (mkdirat(root_fd, tp, 0700) == 0) {
      return tp;
    }
  } while (--retries && errno == EEXIST);

  memcpy(tp + tp_length - 6, "XXXXXX", 6);
  return nullptr;
}
}  // namespace

ScopedTempDirAt::ScopedTempDirAt(int root_fd) : ScopedTempDirAt(root_fd, ".") {}

ScopedTempDirAt::ScopedTempDirAt(int root_fd, fxl::StringView parent_path)
    : root_fd_(root_fd) {
  const std::string parent_path_str = parent_path.ToString();
  // MkdTempAt replaces "XXXXXX" so that the resulting directory path is unique.
  directory_path_ = parent_path_str + "/temp_dir_XXXXXX";
  if (!CreateDirectoryAt(root_fd_, parent_path_str) ||
      !MkdTempAt(root_fd, &directory_path_[0], directory_path_.size())) {
    directory_path_ = "";
  }
}

ScopedTempDirAt::~ScopedTempDirAt() {
  if (directory_path_.size()) {
    if (!DeletePathAt(root_fd_, directory_path_, true)) {
      FXL_LOG(WARNING) << "Unable to delete: " << directory_path_;
    }
  }
}

const std::string& ScopedTempDirAt::path() { return directory_path_; }

int ScopedTempDirAt::root_fd() { return root_fd_; }

bool ScopedTempDirAt::NewTempFile(std::string* output) {
  // MksTempAt replaces "XXXXXX" so that the resulting file path is unique.
  std::string file_path = directory_path_ + "/XXXXXX";
  fxl::UniqueFD fd = MksTempAt(root_fd_, &file_path[0], file_path.size());
  if (!fd.is_valid()) {
    return false;
  }
  output->swap(file_path);
  return true;
}

bool ScopedTempDirAt::NewTempFileWithData(const std::string& data,
                                          std::string* output) {
  if (!NewTempFile(output)) {
    return false;
  }
  return WriteFile(*output, data.data(), data.size());
}

bool ScopedTempDirAt::NewTempDir(std::string* output) {
  std::string dir_path = directory_path_ + "/XXXXXX";
  char* out_path = MkdTempAt(root_fd_, &dir_path[0], dir_path.size());
  if (out_path == nullptr) {
    return false;
  }
  output->swap(dir_path);
  return true;
}

ScopedTempDir::ScopedTempDir() : ScopedTempDir("") {}

ScopedTempDir::ScopedTempDir(fxl::StringView parent_path)
    : base_(AT_FDCWD, parent_path.empty() ? GetGlobalTmpDir() : parent_path) {}

ScopedTempDir::~ScopedTempDir() {}

const std::string& ScopedTempDir::path() { return base_.path(); }

bool ScopedTempDir::NewTempFile(std::string* output) {
  return base_.NewTempFile(output);
}

bool ScopedTempDir::NewTempFileWithData(const std::string& data,
                                        std::string* output) {
  return base_.NewTempFileWithData(data, output);
}

bool ScopedTempDir::NewTempDir(std::string* path) {
  return base_.NewTempDir(path);
}

}  // namespace files
