//===- 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) {

  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

