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