OSDN Git Service

[libfuzzer] adding license headers to cpp files
[android-x86/external-llvm.git] / lib / Fuzzer / FuzzerIO.cpp
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 #include "FuzzerInternal.h"
12 #include <iterator>
13 #include <fstream>
14 #include <dirent.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <unistd.h>
18 #include <cstdarg>
19 #include <cstdio>
20
21 namespace fuzzer {
22
23 static FILE *OutputFile = stderr;
24
25 bool IsFile(const std::string &Path) {
26   struct stat St;
27   if (stat(Path.c_str(), &St))
28     return false;
29   return S_ISREG(St.st_mode);
30 }
31
32 static long GetEpoch(const std::string &Path) {
33   struct stat St;
34   if (stat(Path.c_str(), &St))
35     return 0;  // Can't stat, be conservative.
36   return St.st_mtime;
37 }
38
39 static void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
40                                     std::vector<std::string> *V, bool TopDir) {
41   auto E = GetEpoch(Dir);
42   if (Epoch)
43     if (E && *Epoch >= E) return;
44
45   DIR *D = opendir(Dir.c_str());
46   if (!D) {
47     Printf("No such directory: %s; exiting\n", Dir.c_str());
48     exit(1);
49   }
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)
53       V->push_back(Path);
54     else if (E->d_type == DT_DIR && *E->d_name != '.')
55       ListFilesInDirRecursive(Path, Epoch, V, false);
56   }
57   closedir(D);
58   if (Epoch && TopDir)
59     *Epoch = E;
60 }
61
62 Unit FileToVector(const std::string &Path, size_t MaxSize) {
63   std::ifstream T(Path);
64   if (!T) {
65     Printf("No such directory: %s; exiting\n", Path.c_str());
66     exit(1);
67   }
68
69   T.seekg(0, T.end);
70   size_t FileLen = T.tellg();
71   if (MaxSize)
72     FileLen = std::min(FileLen, MaxSize);
73
74   T.seekg(0, T.beg);
75   Unit Res(FileLen);
76   T.read(reinterpret_cast<char *>(Res.data()), FileLen);
77   return Res;
78 }
79
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>());
84 }
85
86 void CopyFileToErr(const std::string &Path) {
87   Printf("%s", FileToString(Path).c_str());
88 }
89
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");
93   if (!Out) return;
94   fwrite(U.data(), sizeof(U[0]), U.size(), Out);
95   fclose(Out);
96 }
97
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++) {
105     auto &X = Files[i];
106     if (Epoch && GetEpoch(X) < E) continue;
107     NumLoaded++;
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));
111   }
112 }
113
114 std::string DirPlusFile(const std::string &DirPath,
115                         const std::string &FileName) {
116   return DirPath + "/" + FileName;
117 }
118
119 void DupAndCloseStderr() {
120   int OutputFd = dup(2);
121   if (OutputFd > 0) {
122     FILE *NewOutputFile = fdopen(OutputFd, "w");
123     if (NewOutputFile) {
124       OutputFile = NewOutputFile;
125       close(2);
126     }
127   }
128 }
129
130 void CloseStdout() { close(1); }
131
132 void Printf(const char *Fmt, ...) {
133   va_list ap;
134   va_start(ap, Fmt);
135   vfprintf(OutputFile, Fmt, ap);
136   va_end(ap);
137   fflush(OutputFile);
138 }
139
140 }  // namespace fuzzer