//===- FuzzerIOPosix.cpp - IO utils for Posix. ----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// IO functions implementation using Posix API.
//===----------------------------------------------------------------------===//
#include "FuzzerPlatform.h"
#if LIBFUZZER_POSIX || LIBFUZZER_FUCHSIA

#include "FuzzerExtFunctions.h"
#include "FuzzerIO.h"
#include <cstdarg>
#include <cstdio>
#include <dirent.h>
#include <fstream>
#include <iterator>
#include <libgen.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

namespace fuzzer {

bool IsFile(const std::string &Path) {
  struct stat St;
  if (stat(Path.c_str(), &St))
    return false;
  return S_ISREG(St.st_mode);
}

bool IsDirectory(const std::string &Path) {
  struct stat St;
  if (stat(Path.c_str(), &St))
    return false;
  return S_ISDIR(St.st_mode);
}

size_t FileSize(const std::string &Path) {
  struct stat St;
  if (stat(Path.c_str(), &St))
    return 0;
  return St.st_size;
}

std::string Basename(const std::string &Path) {
  size_t Pos = Path.rfind(GetSeparator());
  if (Pos == std::string::npos) return Path;
  assert(Pos < Path.size());
  return Path.substr(Pos + 1);
}

void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
                             Vector<std::string> *V, bool TopDir) {
  auto E = GetEpoch(Dir);
  if (Epoch)
    if (E && *Epoch >= E) return;

  DIR *D = opendir(Dir.c_str());
  if (!D) {
    Printf("%s: %s; exiting\n", strerror(errno), Dir.c_str());
    exit(1);
  }
  while (auto E = readdir(D)) {
    std::string Path = DirPlusFile(Dir, E->d_name);
    if (E->d_type == DT_REG || E->d_type == DT_LNK ||
        (E->d_type == DT_UNKNOWN && IsFile(Path)))
      V->push_back(Path);
    else if ((E->d_type == DT_DIR ||
             (E->d_type == DT_UNKNOWN && IsDirectory(Path))) &&
             *E->d_name != '.')
      ListFilesInDirRecursive(Path, Epoch, V, false);
  }
  closedir(D);
  if (Epoch && TopDir)
    *Epoch = E;
}


void IterateDirRecursive(const std::string &Dir,
                         void (*DirPreCallback)(const std::string &Dir),
                         void (*DirPostCallback)(const std::string &Dir),
                         void (*FileCallback)(const std::string &Dir)) {
  DirPreCallback(Dir);
  DIR *D = opendir(Dir.c_str());
  if (!D) return;
  while (auto E = readdir(D)) {
    std::string Path = DirPlusFile(Dir, E->d_name);
    if (E->d_type == DT_REG || E->d_type == DT_LNK ||
        (E->d_type == DT_UNKNOWN && IsFile(Path)))
      FileCallback(Path);
    else if ((E->d_type == DT_DIR ||
             (E->d_type == DT_UNKNOWN && IsDirectory(Path))) &&
             *E->d_name != '.')
      IterateDirRecursive(Path, DirPreCallback, DirPostCallback, FileCallback);
  }
  closedir(D);
  DirPostCallback(Dir);
}

char GetSeparator() {
  return '/';
}

bool IsSeparator(char C) {
  return C == '/';
}

FILE* OpenFile(int Fd, const char* Mode) {
  return fdopen(Fd, Mode);
}

int CloseFile(int fd) {
  return close(fd);
}

int DuplicateFile(int Fd) {
  return dup(Fd);
}

void RemoveFile(const std::string &Path) {
  unlink(Path.c_str());
}

void RenameFile(const std::string &OldPath, const std::string &NewPath) {
  rename(OldPath.c_str(), NewPath.c_str());
}

intptr_t GetHandleFromFd(int fd) {
  return static_cast<intptr_t>(fd);
}

std::string DirName(const std::string &FileName) {
  char *Tmp = new char[FileName.size() + 1];
  memcpy(Tmp, FileName.c_str(), FileName.size() + 1);
  std::string Res = dirname(Tmp);
  delete [] Tmp;
  return Res;
}

std::string TmpDir() {
  if (auto Env = getenv("TMPDIR"))
    return Env;
  return "/tmp";
}

bool IsInterestingCoverageFile(const std::string &FileName) {
  if (FileName.find("compiler-rt/lib/") != std::string::npos)
    return false; // sanitizer internal.
  if (FileName.find("/usr/lib/") != std::string::npos)
    return false;
  if (FileName.find("/usr/include/") != std::string::npos)
    return false;
  if (FileName == "<null>")
    return false;
  return true;
}

void RawPrint(const char *Str) {
  (void)write(2, Str, strlen(Str));
}

void MkDir(const std::string &Path) {
  mkdir(Path.c_str(), 0700);
}

void RmDir(const std::string &Path) {
  rmdir(Path.c_str());
}

const std::string &getDevNull() {
  static const std::string devNull = "/dev/null";
  return devNull;
}

}  // namespace fuzzer

#endif // LIBFUZZER_POSIX
