// 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 <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/build_config.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) {
  FX_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|.
fbl::unique_fd MksTempAt(int root_fd, char* tp, size_t tp_length) {
  FX_DCHECK(strlen(tp) == tp_length);
  FX_DCHECK(tp_length >= 6);
  FX_DCHECK(memcmp(tp + tp_length - 6, "XXXXXX", 6) == 0);
  int retries = 100;
  do {
    GenerateRandName(tp + tp_length - 6);
    fbl::unique_fd 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 fbl::unique_fd();
}

// Creates a unique temporary directory under |root_fd| from template |tp|.
char* MkdTempAt(int root_fd, char* tp, size_t tp_length) {
  FX_DCHECK(strlen(tp) == tp_length);
  FX_DCHECK(tp_length >= 6);
  FX_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)) {
      FX_LOGS(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";
  fbl::unique_fd 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
