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 25namespace fuzzer { 26 27bool 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 34static 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 41size_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 48std::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 55void 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 82void 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 103char GetSeparator() { 104 return '/'; 105} 106 107FILE* OpenFile(int Fd, const char* Mode) { 108 return fdopen(Fd, Mode); 109} 110 111int CloseFile(int fd) { 112 return close(fd); 113} 114 115int DuplicateFile(int Fd) { 116 return dup(Fd); 117} 118 119void RemoveFile(const std::string &Path) { 120 unlink(Path.c_str()); 121} 122 123void RenameFile(const std::string &OldPath, const std::string &NewPath) { 124 rename(OldPath.c_str(), NewPath.c_str()); 125} 126 127intptr_t GetHandleFromFd(int fd) { 128 return static_cast<intptr_t>(fd); 129} 130 131std::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 139std::string TmpDir() { 140 if (auto Env = getenv("TMPDIR")) 141 return Env; 142 return "/tmp"; 143} 144 145bool 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 157void RawPrint(const char *Str) { 158 write(2, Str, strlen(Str)); 159} 160 161void MkDir(const std::string &Path) { 162 mkdir(Path.c_str(), 0700); 163} 164 165void RmDir(const std::string &Path) { 166 rmdir(Path.c_str()); 167} 168 169const 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