1 //===- FuzzerIOPosix.cpp - IO utils for Posix. ----------------------------===// 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 implementation using Posix API. 10 //===----------------------------------------------------------------------===// 11 #include "FuzzerDefs.h" 12 #if LIBFUZZER_POSIX || LIBFUZZER_FUCHSIA 13 14 #include "FuzzerExtFunctions.h" 15 #include "FuzzerIO.h" 16 #include <cstdarg> 17 #include <cstdio> 18 #include <dirent.h> 19 #include <fstream> 20 #include <iterator> 21 #include <libgen.h> 22 #include <sys/stat.h> 23 #include <sys/types.h> 24 #include <unistd.h> 25 26 namespace fuzzer { 27 28 bool IsFile(const std::string &Path) { 29 struct stat St; 30 if (stat(Path.c_str(), &St)) 31 return false; 32 return S_ISREG(St.st_mode); 33 } 34 35 static bool IsDirectory(const std::string &Path) { 36 struct stat St; 37 if (stat(Path.c_str(), &St)) 38 return false; 39 return S_ISDIR(St.st_mode); 40 } 41 42 size_t FileSize(const std::string &Path) { 43 struct stat St; 44 if (stat(Path.c_str(), &St)) 45 return 0; 46 return St.st_size; 47 } 48 49 std::string Basename(const std::string &Path) { 50 size_t Pos = Path.rfind(GetSeparator()); 51 if (Pos == std::string::npos) return Path; 52 assert(Pos < Path.size()); 53 return Path.substr(Pos + 1); 54 } 55 56 void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, 57 Vector<std::string> *V, bool TopDir) { 58 auto E = GetEpoch(Dir); 59 if (Epoch) 60 if (E && *Epoch >= E) return; 61 62 DIR *D = opendir(Dir.c_str()); 63 if (!D) { 64 Printf("%s: %s; exiting\n", strerror(errno), Dir.c_str()); 65 exit(1); 66 } 67 while (auto E = readdir(D)) { 68 std::string Path = DirPlusFile(Dir, E->d_name); 69 if (E->d_type == DT_REG || E->d_type == DT_LNK || 70 (E->d_type == DT_UNKNOWN && IsFile(Path))) 71 V->push_back(Path); 72 else if ((E->d_type == DT_DIR || 73 (E->d_type == DT_UNKNOWN && IsDirectory(Path))) && 74 *E->d_name != '.') 75 ListFilesInDirRecursive(Path, Epoch, V, false); 76 } 77 closedir(D); 78 if (Epoch && TopDir) 79 *Epoch = E; 80 } 81 82 char GetSeparator() { 83 return '/'; 84 } 85 86 FILE* OpenFile(int Fd, const char* Mode) { 87 return fdopen(Fd, Mode); 88 } 89 90 int CloseFile(int fd) { 91 return close(fd); 92 } 93 94 int DuplicateFile(int Fd) { 95 return dup(Fd); 96 } 97 98 void RemoveFile(const std::string &Path) { 99 unlink(Path.c_str()); 100 } 101 102 void DiscardOutput(int Fd) { 103 FILE* Temp = fopen("/dev/null", "w"); 104 if (!Temp) 105 return; 106 dup2(fileno(Temp), Fd); 107 fclose(Temp); 108 } 109 110 intptr_t GetHandleFromFd(int fd) { 111 return static_cast<intptr_t>(fd); 112 } 113 114 std::string DirName(const std::string &FileName) { 115 char *Tmp = new char[FileName.size() + 1]; 116 memcpy(Tmp, FileName.c_str(), FileName.size() + 1); 117 std::string Res = dirname(Tmp); 118 delete [] Tmp; 119 return Res; 120 } 121 122 std::string TmpDir() { 123 if (auto Env = getenv("TMPDIR")) 124 return Env; 125 return "/tmp"; 126 } 127 128 bool IsInterestingCoverageFile(const std::string &FileName) { 129 if (FileName.find("compiler-rt/lib/") != std::string::npos) 130 return false; // sanitizer internal. 131 if (FileName.find("/usr/lib/") != std::string::npos) 132 return false; 133 if (FileName.find("/usr/include/") != std::string::npos) 134 return false; 135 if (FileName == "<null>") 136 return false; 137 return true; 138 } 139 140 141 void RawPrint(const char *Str) { 142 write(2, Str, strlen(Str)); 143 } 144 145 } // namespace fuzzer 146 147 #endif // LIBFUZZER_POSIX 148