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 void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, 50 Vector<std::string> *V, bool TopDir) { 51 auto E = GetEpoch(Dir); 52 if (Epoch) 53 if (E && *Epoch >= E) return; 54 55 DIR *D = opendir(Dir.c_str()); 56 if (!D) { 57 Printf("%s: %s; exiting\n", strerror(errno), Dir.c_str()); 58 exit(1); 59 } 60 while (auto E = readdir(D)) { 61 std::string Path = DirPlusFile(Dir, E->d_name); 62 if (E->d_type == DT_REG || E->d_type == DT_LNK || 63 (E->d_type == DT_UNKNOWN && IsFile(Path))) 64 V->push_back(Path); 65 else if ((E->d_type == DT_DIR || 66 (E->d_type == DT_UNKNOWN && IsDirectory(Path))) && 67 *E->d_name != '.') 68 ListFilesInDirRecursive(Path, Epoch, V, false); 69 } 70 closedir(D); 71 if (Epoch && TopDir) 72 *Epoch = E; 73 } 74 75 char GetSeparator() { 76 return '/'; 77 } 78 79 FILE* OpenFile(int Fd, const char* Mode) { 80 return fdopen(Fd, Mode); 81 } 82 83 int CloseFile(int fd) { 84 return close(fd); 85 } 86 87 int DuplicateFile(int Fd) { 88 return dup(Fd); 89 } 90 91 void RemoveFile(const std::string &Path) { 92 unlink(Path.c_str()); 93 } 94 95 void DiscardOutput(int Fd) { 96 FILE* Temp = fopen("/dev/null", "w"); 97 if (!Temp) 98 return; 99 dup2(fileno(Temp), Fd); 100 fclose(Temp); 101 } 102 103 intptr_t GetHandleFromFd(int fd) { 104 return static_cast<intptr_t>(fd); 105 } 106 107 std::string DirName(const std::string &FileName) { 108 char *Tmp = new char[FileName.size() + 1]; 109 memcpy(Tmp, FileName.c_str(), FileName.size() + 1); 110 std::string Res = dirname(Tmp); 111 delete [] Tmp; 112 return Res; 113 } 114 115 std::string TmpDir() { 116 if (auto Env = getenv("TMPDIR")) 117 return Env; 118 return "/tmp"; 119 } 120 121 bool IsInterestingCoverageFile(const std::string &FileName) { 122 if (FileName.find("compiler-rt/lib/") != std::string::npos) 123 return false; // sanitizer internal. 124 if (FileName.find("/usr/lib/") != std::string::npos) 125 return false; 126 if (FileName.find("/usr/include/") != std::string::npos) 127 return false; 128 if (FileName == "<null>") 129 return false; 130 return true; 131 } 132 133 134 void RawPrint(const char *Str) { 135 write(2, Str, strlen(Str)); 136 } 137 138 } // namespace fuzzer 139 140 #endif // LIBFUZZER_POSIX 141