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