1 //===- FuzzerIO.cpp - IO utils. -------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 //===----------------------------------------------------------------------===//
11 #include "FuzzerInternal.h"
15 #include <sys/types.h>
23 static FILE *OutputFile = stderr;
25 bool IsFile(const std::string &Path) {
27 if (stat(Path.c_str(), &St))
29 return S_ISREG(St.st_mode);
32 static long GetEpoch(const std::string &Path) {
34 if (stat(Path.c_str(), &St))
35 return 0; // Can't stat, be conservative.
39 static void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
40 std::vector<std::string> *V, bool TopDir) {
41 auto E = GetEpoch(Dir);
43 if (E && *Epoch >= E) return;
45 DIR *D = opendir(Dir.c_str());
47 Printf("No such directory: %s; exiting\n", Dir.c_str());
50 while (auto E = readdir(D)) {
51 std::string Path = DirPlusFile(Dir, E->d_name);
52 if (E->d_type == DT_REG || E->d_type == DT_LNK)
54 else if (E->d_type == DT_DIR && *E->d_name != '.')
55 ListFilesInDirRecursive(Path, Epoch, V, false);
62 Unit FileToVector(const std::string &Path, size_t MaxSize) {
63 std::ifstream T(Path);
65 Printf("No such directory: %s; exiting\n", Path.c_str());
70 size_t FileLen = T.tellg();
72 FileLen = std::min(FileLen, MaxSize);
76 T.read(reinterpret_cast<char *>(Res.data()), FileLen);
80 std::string FileToString(const std::string &Path) {
81 std::ifstream T(Path);
82 return std::string((std::istreambuf_iterator<char>(T)),
83 std::istreambuf_iterator<char>());
86 void CopyFileToErr(const std::string &Path) {
87 Printf("%s", FileToString(Path).c_str());
90 void WriteToFile(const Unit &U, const std::string &Path) {
91 // Use raw C interface because this function may be called from a sig handler.
92 FILE *Out = fopen(Path.c_str(), "w");
94 fwrite(U.data(), sizeof(U[0]), U.size(), Out);
98 void ReadDirToVectorOfUnits(const char *Path, std::vector<Unit> *V,
99 long *Epoch, size_t MaxSize) {
100 long E = Epoch ? *Epoch : 0;
101 std::vector<std::string> Files;
102 ListFilesInDirRecursive(Path, Epoch, &Files, /*TopDir*/true);
103 size_t NumLoaded = 0;
104 for (size_t i = 0; i < Files.size(); i++) {
106 if (Epoch && GetEpoch(X) < E) continue;
108 if ((NumLoaded & (NumLoaded - 1)) == 0 && NumLoaded >= 1024)
109 Printf("Loaded %zd/%zd files from %s\n", NumLoaded, Files.size(), Path);
110 V->push_back(FileToVector(X, MaxSize));
114 std::string DirPlusFile(const std::string &DirPath,
115 const std::string &FileName) {
116 return DirPath + "/" + FileName;
119 void DupAndCloseStderr() {
120 int OutputFd = dup(2);
122 FILE *NewOutputFile = fdopen(OutputFd, "w");
124 OutputFile = NewOutputFile;
130 void CloseStdout() { close(1); }
132 void Printf(const char *Fmt, ...) {
135 vfprintf(OutputFile, Fmt, ap);
140 } // namespace fuzzer