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