1c5f01b2fSopenharmony_ci//===- FuzzerIO.cpp - IO utils. -------------------------------------------===//
2c5f01b2fSopenharmony_ci//
3c5f01b2fSopenharmony_ci//                     The LLVM Compiler Infrastructure
4c5f01b2fSopenharmony_ci//
5c5f01b2fSopenharmony_ci// This file is distributed under the University of Illinois Open Source
6c5f01b2fSopenharmony_ci// License. See LICENSE.TXT for details.
7c5f01b2fSopenharmony_ci//
8c5f01b2fSopenharmony_ci//===----------------------------------------------------------------------===//
9c5f01b2fSopenharmony_ci// IO functions.
10c5f01b2fSopenharmony_ci//===----------------------------------------------------------------------===//
11c5f01b2fSopenharmony_ci
12c5f01b2fSopenharmony_ci#include "FuzzerIO.h"
13c5f01b2fSopenharmony_ci#include "FuzzerDefs.h"
14c5f01b2fSopenharmony_ci#include "FuzzerExtFunctions.h"
15c5f01b2fSopenharmony_ci#include <algorithm>
16c5f01b2fSopenharmony_ci#include <cstdarg>
17c5f01b2fSopenharmony_ci#include <fstream>
18c5f01b2fSopenharmony_ci#include <iterator>
19c5f01b2fSopenharmony_ci#include <sys/stat.h>
20c5f01b2fSopenharmony_ci#include <sys/types.h>
21c5f01b2fSopenharmony_ci
22c5f01b2fSopenharmony_cinamespace fuzzer {
23c5f01b2fSopenharmony_ci
24c5f01b2fSopenharmony_cistatic FILE *OutputFile = stderr;
25c5f01b2fSopenharmony_ci
26c5f01b2fSopenharmony_cilong GetEpoch(const std::string &Path) {
27c5f01b2fSopenharmony_ci  struct stat St;
28c5f01b2fSopenharmony_ci  if (stat(Path.c_str(), &St))
29c5f01b2fSopenharmony_ci    return 0;  // Can't stat, be conservative.
30c5f01b2fSopenharmony_ci  return St.st_mtime;
31c5f01b2fSopenharmony_ci}
32c5f01b2fSopenharmony_ci
33c5f01b2fSopenharmony_ciUnit FileToVector(const std::string &Path, size_t MaxSize, bool ExitOnError) {
34c5f01b2fSopenharmony_ci  std::ifstream T(Path);
35c5f01b2fSopenharmony_ci  if (ExitOnError && !T) {
36c5f01b2fSopenharmony_ci    Printf("No such directory: %s; exiting\n", Path.c_str());
37c5f01b2fSopenharmony_ci    exit(1);
38c5f01b2fSopenharmony_ci  }
39c5f01b2fSopenharmony_ci
40c5f01b2fSopenharmony_ci  T.seekg(0, T.end);
41c5f01b2fSopenharmony_ci  size_t FileLen = T.tellg();
42c5f01b2fSopenharmony_ci  if (MaxSize)
43c5f01b2fSopenharmony_ci    FileLen = std::min(FileLen, MaxSize);
44c5f01b2fSopenharmony_ci
45c5f01b2fSopenharmony_ci  T.seekg(0, T.beg);
46c5f01b2fSopenharmony_ci  Unit Res(FileLen);
47c5f01b2fSopenharmony_ci  T.read(reinterpret_cast<char *>(Res.data()), FileLen);
48c5f01b2fSopenharmony_ci  return Res;
49c5f01b2fSopenharmony_ci}
50c5f01b2fSopenharmony_ci
51c5f01b2fSopenharmony_cistd::string FileToString(const std::string &Path) {
52c5f01b2fSopenharmony_ci  std::ifstream T(Path);
53c5f01b2fSopenharmony_ci  return std::string((std::istreambuf_iterator<char>(T)),
54c5f01b2fSopenharmony_ci                     std::istreambuf_iterator<char>());
55c5f01b2fSopenharmony_ci}
56c5f01b2fSopenharmony_ci
57c5f01b2fSopenharmony_civoid CopyFileToErr(const std::string &Path) {
58c5f01b2fSopenharmony_ci  Printf("%s", FileToString(Path).c_str());
59c5f01b2fSopenharmony_ci}
60c5f01b2fSopenharmony_ci
61c5f01b2fSopenharmony_civoid WriteToFile(const Unit &U, const std::string &Path) {
62c5f01b2fSopenharmony_ci  // Use raw C interface because this function may be called from a sig handler.
63c5f01b2fSopenharmony_ci  FILE *Out = fopen(Path.c_str(), "w");
64c5f01b2fSopenharmony_ci  if (!Out) return;
65c5f01b2fSopenharmony_ci  fwrite(U.data(), sizeof(U[0]), U.size(), Out);
66c5f01b2fSopenharmony_ci  fclose(Out);
67c5f01b2fSopenharmony_ci}
68c5f01b2fSopenharmony_ci
69c5f01b2fSopenharmony_civoid ReadDirToVectorOfUnits(const char *Path, std::vector<Unit> *V,
70c5f01b2fSopenharmony_ci                            long *Epoch, size_t MaxSize, bool ExitOnError) {
71c5f01b2fSopenharmony_ci  long E = Epoch ? *Epoch : 0;
72c5f01b2fSopenharmony_ci  std::vector<std::string> Files;
73c5f01b2fSopenharmony_ci  ListFilesInDirRecursive(Path, Epoch, &Files, /*TopDir*/true);
74c5f01b2fSopenharmony_ci  size_t NumLoaded = 0;
75c5f01b2fSopenharmony_ci  for (size_t i = 0; i < Files.size(); i++) {
76c5f01b2fSopenharmony_ci    auto &X = Files[i];
77c5f01b2fSopenharmony_ci    if (Epoch && GetEpoch(X) < E) continue;
78c5f01b2fSopenharmony_ci    NumLoaded++;
79c5f01b2fSopenharmony_ci    if ((NumLoaded & (NumLoaded - 1)) == 0 && NumLoaded >= 1024)
80c5f01b2fSopenharmony_ci      Printf("Loaded %zd/%zd files from %s\n", NumLoaded, Files.size(), Path);
81c5f01b2fSopenharmony_ci    auto S = FileToVector(X, MaxSize, ExitOnError);
82c5f01b2fSopenharmony_ci    if (!S.empty())
83c5f01b2fSopenharmony_ci      V->push_back(S);
84c5f01b2fSopenharmony_ci  }
85c5f01b2fSopenharmony_ci}
86c5f01b2fSopenharmony_ci
87c5f01b2fSopenharmony_cistd::string DirPlusFile(const std::string &DirPath,
88c5f01b2fSopenharmony_ci                        const std::string &FileName) {
89c5f01b2fSopenharmony_ci  return DirPath + GetSeparator() + FileName;
90c5f01b2fSopenharmony_ci}
91c5f01b2fSopenharmony_ci
92c5f01b2fSopenharmony_civoid DupAndCloseStderr() {
93c5f01b2fSopenharmony_ci  int OutputFd = DuplicateFile(2);
94c5f01b2fSopenharmony_ci  if (OutputFd > 0) {
95c5f01b2fSopenharmony_ci    FILE *NewOutputFile = OpenFile(OutputFd, "w");
96c5f01b2fSopenharmony_ci    if (NewOutputFile) {
97c5f01b2fSopenharmony_ci      OutputFile = NewOutputFile;
98c5f01b2fSopenharmony_ci      if (EF->__sanitizer_set_report_fd)
99c5f01b2fSopenharmony_ci        EF->__sanitizer_set_report_fd(reinterpret_cast<void *>(OutputFd));
100c5f01b2fSopenharmony_ci      CloseFile(2);
101c5f01b2fSopenharmony_ci    }
102c5f01b2fSopenharmony_ci  }
103c5f01b2fSopenharmony_ci}
104c5f01b2fSopenharmony_ci
105c5f01b2fSopenharmony_civoid CloseStdout() {
106c5f01b2fSopenharmony_ci  CloseFile(1);
107c5f01b2fSopenharmony_ci}
108c5f01b2fSopenharmony_ci
109c5f01b2fSopenharmony_civoid Printf(const char *Fmt, ...) {
110c5f01b2fSopenharmony_ci  va_list ap;
111c5f01b2fSopenharmony_ci  va_start(ap, Fmt);
112c5f01b2fSopenharmony_ci  vfprintf(OutputFile, Fmt, ap);
113c5f01b2fSopenharmony_ci  va_end(ap);
114c5f01b2fSopenharmony_ci  fflush(OutputFile);
115c5f01b2fSopenharmony_ci}
116c5f01b2fSopenharmony_ci
117c5f01b2fSopenharmony_ci}  // namespace fuzzer
118