blob: 1ff22930e1bc23619e89806be6f4a9be462c56f7 [file] [log] [blame]
george.karpenkov29efa6d2017-08-21 23:25:50 +00001//===- FuzzerIO.cpp - IO utils. -------------------------------------------===//
2//
chandlerc40284492019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
george.karpenkov29efa6d2017-08-21 23:25:50 +00006//
7//===----------------------------------------------------------------------===//
8// IO functions.
9//===----------------------------------------------------------------------===//
10
11#include "FuzzerIO.h"
12#include "FuzzerDefs.h"
13#include "FuzzerExtFunctions.h"
14#include <algorithm>
15#include <cstdarg>
16#include <fstream>
17#include <iterator>
18#include <sys/stat.h>
19#include <sys/types.h>
20
21namespace fuzzer {
22
23static FILE *OutputFile = stderr;
24
25long GetEpoch(const std::string &Path) {
26 struct stat St;
27 if (stat(Path.c_str(), &St))
28 return 0; // Can't stat, be conservative.
29 return St.st_mtime;
30}
31
32Unit FileToVector(const std::string &Path, size_t MaxSize, bool ExitOnError) {
metzman2a530982018-11-06 23:25:25 +000033 std::ifstream T(Path, std::ios::binary);
george.karpenkov29efa6d2017-08-21 23:25:50 +000034 if (ExitOnError && !T) {
35 Printf("No such directory: %s; exiting\n", Path.c_str());
36 exit(1);
37 }
38
39 T.seekg(0, T.end);
40 auto EndPos = T.tellg();
41 if (EndPos < 0) return {};
42 size_t FileLen = EndPos;
43 if (MaxSize)
44 FileLen = std::min(FileLen, MaxSize);
45
46 T.seekg(0, T.beg);
47 Unit Res(FileLen);
48 T.read(reinterpret_cast<char *>(Res.data()), FileLen);
49 return Res;
50}
51
52std::string FileToString(const std::string &Path) {
metzman2a530982018-11-06 23:25:25 +000053 std::ifstream T(Path, std::ios::binary);
george.karpenkov29efa6d2017-08-21 23:25:50 +000054 return std::string((std::istreambuf_iterator<char>(T)),
55 std::istreambuf_iterator<char>());
56}
57
58void CopyFileToErr(const std::string &Path) {
59 Printf("%s", FileToString(Path).c_str());
60}
61
62void WriteToFile(const Unit &U, const std::string &Path) {
63 // Use raw C interface because this function may be called from a sig handler.
64 FILE *Out = fopen(Path.c_str(), "w");
65 if (!Out) return;
66 fwrite(U.data(), sizeof(U[0]), U.size(), Out);
67 fclose(Out);
68}
69
george.karpenkovfbfa45c2017-08-27 23:20:09 +000070void ReadDirToVectorOfUnits(const char *Path, Vector<Unit> *V,
george.karpenkov29efa6d2017-08-21 23:25:50 +000071 long *Epoch, size_t MaxSize, bool ExitOnError) {
72 long E = Epoch ? *Epoch : 0;
george.karpenkovfbfa45c2017-08-27 23:20:09 +000073 Vector<std::string> Files;
george.karpenkov29efa6d2017-08-21 23:25:50 +000074 ListFilesInDirRecursive(Path, Epoch, &Files, /*TopDir*/true);
75 size_t NumLoaded = 0;
76 for (size_t i = 0; i < Files.size(); i++) {
77 auto &X = Files[i];
78 if (Epoch && GetEpoch(X) < E) continue;
79 NumLoaded++;
80 if ((NumLoaded & (NumLoaded - 1)) == 0 && NumLoaded >= 1024)
81 Printf("Loaded %zd/%zd files from %s\n", NumLoaded, Files.size(), Path);
82 auto S = FileToVector(X, MaxSize, ExitOnError);
83 if (!S.empty())
84 V->push_back(S);
85 }
86}
87
kcc7f5f2222017-09-12 21:58:07 +000088
89void GetSizedFilesFromDir(const std::string &Dir, Vector<SizedFile> *V) {
90 Vector<std::string> Files;
91 ListFilesInDirRecursive(Dir, 0, &Files, /*TopDir*/true);
92 for (auto &File : Files)
93 if (size_t Size = FileSize(File))
94 V->push_back({File, Size});
95}
96
george.karpenkov29efa6d2017-08-21 23:25:50 +000097std::string DirPlusFile(const std::string &DirPath,
98 const std::string &FileName) {
99 return DirPath + GetSeparator() + FileName;
100}
101
george.karpenkov29efa6d2017-08-21 23:25:50 +0000102void DupAndCloseStderr() {
103 int OutputFd = DuplicateFile(2);
104 if (OutputFd > 0) {
105 FILE *NewOutputFile = OpenFile(OutputFd, "w");
106 if (NewOutputFile) {
107 OutputFile = NewOutputFile;
108 if (EF->__sanitizer_set_report_fd)
109 EF->__sanitizer_set_report_fd(
110 reinterpret_cast<void *>(GetHandleFromFd(OutputFd)));
111 DiscardOutput(2);
112 }
113 }
114}
115
116void CloseStdout() {
117 DiscardOutput(1);
118}
119
120void Printf(const char *Fmt, ...) {
121 va_list ap;
122 va_start(ap, Fmt);
123 vfprintf(OutputFile, Fmt, ap);
124 va_end(ap);
125 fflush(OutputFile);
126}
127
128} // namespace fuzzer