13cab2bb3Spatrick //===- FuzzerIOPosix.cpp - IO utils for Posix. ----------------------------===// 23cab2bb3Spatrick // 33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information. 53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63cab2bb3Spatrick // 73cab2bb3Spatrick //===----------------------------------------------------------------------===// 83cab2bb3Spatrick // IO functions implementation using Posix API. 93cab2bb3Spatrick //===----------------------------------------------------------------------===// 101f9cb04fSpatrick #include "FuzzerPlatform.h" 113cab2bb3Spatrick #if LIBFUZZER_POSIX || LIBFUZZER_FUCHSIA 123cab2bb3Spatrick 133cab2bb3Spatrick #include "FuzzerExtFunctions.h" 143cab2bb3Spatrick #include "FuzzerIO.h" 153cab2bb3Spatrick #include <cstdarg> 163cab2bb3Spatrick #include <cstdio> 173cab2bb3Spatrick #include <dirent.h> 183cab2bb3Spatrick #include <fstream> 193cab2bb3Spatrick #include <iterator> 203cab2bb3Spatrick #include <libgen.h> 213cab2bb3Spatrick #include <sys/stat.h> 223cab2bb3Spatrick #include <sys/types.h> 233cab2bb3Spatrick #include <unistd.h> 243cab2bb3Spatrick 253cab2bb3Spatrick namespace fuzzer { 263cab2bb3Spatrick 273cab2bb3Spatrick bool IsFile(const std::string &Path) { 283cab2bb3Spatrick struct stat St; 293cab2bb3Spatrick if (stat(Path.c_str(), &St)) 303cab2bb3Spatrick return false; 313cab2bb3Spatrick return S_ISREG(St.st_mode); 323cab2bb3Spatrick } 333cab2bb3Spatrick 34*d89ec533Spatrick bool IsDirectory(const std::string &Path) { 353cab2bb3Spatrick struct stat St; 363cab2bb3Spatrick if (stat(Path.c_str(), &St)) 373cab2bb3Spatrick return false; 383cab2bb3Spatrick return S_ISDIR(St.st_mode); 393cab2bb3Spatrick } 403cab2bb3Spatrick 413cab2bb3Spatrick size_t FileSize(const std::string &Path) { 423cab2bb3Spatrick struct stat St; 433cab2bb3Spatrick if (stat(Path.c_str(), &St)) 443cab2bb3Spatrick return 0; 453cab2bb3Spatrick return St.st_size; 463cab2bb3Spatrick } 473cab2bb3Spatrick 483cab2bb3Spatrick std::string Basename(const std::string &Path) { 493cab2bb3Spatrick size_t Pos = Path.rfind(GetSeparator()); 503cab2bb3Spatrick if (Pos == std::string::npos) return Path; 513cab2bb3Spatrick assert(Pos < Path.size()); 523cab2bb3Spatrick return Path.substr(Pos + 1); 533cab2bb3Spatrick } 543cab2bb3Spatrick 553cab2bb3Spatrick void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, 563cab2bb3Spatrick Vector<std::string> *V, bool TopDir) { 573cab2bb3Spatrick auto E = GetEpoch(Dir); 583cab2bb3Spatrick if (Epoch) 593cab2bb3Spatrick if (E && *Epoch >= E) return; 603cab2bb3Spatrick 613cab2bb3Spatrick DIR *D = opendir(Dir.c_str()); 623cab2bb3Spatrick if (!D) { 633cab2bb3Spatrick Printf("%s: %s; exiting\n", strerror(errno), Dir.c_str()); 643cab2bb3Spatrick exit(1); 653cab2bb3Spatrick } 663cab2bb3Spatrick while (auto E = readdir(D)) { 673cab2bb3Spatrick std::string Path = DirPlusFile(Dir, E->d_name); 683cab2bb3Spatrick if (E->d_type == DT_REG || E->d_type == DT_LNK || 693cab2bb3Spatrick (E->d_type == DT_UNKNOWN && IsFile(Path))) 703cab2bb3Spatrick V->push_back(Path); 713cab2bb3Spatrick else if ((E->d_type == DT_DIR || 723cab2bb3Spatrick (E->d_type == DT_UNKNOWN && IsDirectory(Path))) && 733cab2bb3Spatrick *E->d_name != '.') 743cab2bb3Spatrick ListFilesInDirRecursive(Path, Epoch, V, false); 753cab2bb3Spatrick } 763cab2bb3Spatrick closedir(D); 773cab2bb3Spatrick if (Epoch && TopDir) 783cab2bb3Spatrick *Epoch = E; 793cab2bb3Spatrick } 803cab2bb3Spatrick 813cab2bb3Spatrick 823cab2bb3Spatrick void IterateDirRecursive(const std::string &Dir, 833cab2bb3Spatrick void (*DirPreCallback)(const std::string &Dir), 843cab2bb3Spatrick void (*DirPostCallback)(const std::string &Dir), 853cab2bb3Spatrick void (*FileCallback)(const std::string &Dir)) { 863cab2bb3Spatrick DirPreCallback(Dir); 873cab2bb3Spatrick DIR *D = opendir(Dir.c_str()); 883cab2bb3Spatrick if (!D) return; 893cab2bb3Spatrick while (auto E = readdir(D)) { 903cab2bb3Spatrick std::string Path = DirPlusFile(Dir, E->d_name); 913cab2bb3Spatrick if (E->d_type == DT_REG || E->d_type == DT_LNK || 923cab2bb3Spatrick (E->d_type == DT_UNKNOWN && IsFile(Path))) 933cab2bb3Spatrick FileCallback(Path); 943cab2bb3Spatrick else if ((E->d_type == DT_DIR || 953cab2bb3Spatrick (E->d_type == DT_UNKNOWN && IsDirectory(Path))) && 963cab2bb3Spatrick *E->d_name != '.') 973cab2bb3Spatrick IterateDirRecursive(Path, DirPreCallback, DirPostCallback, FileCallback); 983cab2bb3Spatrick } 993cab2bb3Spatrick closedir(D); 1003cab2bb3Spatrick DirPostCallback(Dir); 1013cab2bb3Spatrick } 1023cab2bb3Spatrick 1033cab2bb3Spatrick char GetSeparator() { 1043cab2bb3Spatrick return '/'; 1053cab2bb3Spatrick } 1063cab2bb3Spatrick 107*d89ec533Spatrick bool IsSeparator(char C) { 108*d89ec533Spatrick return C == '/'; 109*d89ec533Spatrick } 110*d89ec533Spatrick 1113cab2bb3Spatrick FILE* OpenFile(int Fd, const char* Mode) { 1123cab2bb3Spatrick return fdopen(Fd, Mode); 1133cab2bb3Spatrick } 1143cab2bb3Spatrick 1153cab2bb3Spatrick int CloseFile(int fd) { 1163cab2bb3Spatrick return close(fd); 1173cab2bb3Spatrick } 1183cab2bb3Spatrick 1193cab2bb3Spatrick int DuplicateFile(int Fd) { 1203cab2bb3Spatrick return dup(Fd); 1213cab2bb3Spatrick } 1223cab2bb3Spatrick 1233cab2bb3Spatrick void RemoveFile(const std::string &Path) { 1243cab2bb3Spatrick unlink(Path.c_str()); 1253cab2bb3Spatrick } 1263cab2bb3Spatrick 1273cab2bb3Spatrick void RenameFile(const std::string &OldPath, const std::string &NewPath) { 1283cab2bb3Spatrick rename(OldPath.c_str(), NewPath.c_str()); 1293cab2bb3Spatrick } 1303cab2bb3Spatrick 1313cab2bb3Spatrick intptr_t GetHandleFromFd(int fd) { 1323cab2bb3Spatrick return static_cast<intptr_t>(fd); 1333cab2bb3Spatrick } 1343cab2bb3Spatrick 1353cab2bb3Spatrick std::string DirName(const std::string &FileName) { 1363cab2bb3Spatrick char *Tmp = new char[FileName.size() + 1]; 1373cab2bb3Spatrick memcpy(Tmp, FileName.c_str(), FileName.size() + 1); 1383cab2bb3Spatrick std::string Res = dirname(Tmp); 1393cab2bb3Spatrick delete [] Tmp; 1403cab2bb3Spatrick return Res; 1413cab2bb3Spatrick } 1423cab2bb3Spatrick 1433cab2bb3Spatrick std::string TmpDir() { 1443cab2bb3Spatrick if (auto Env = getenv("TMPDIR")) 1453cab2bb3Spatrick return Env; 1463cab2bb3Spatrick return "/tmp"; 1473cab2bb3Spatrick } 1483cab2bb3Spatrick 1493cab2bb3Spatrick bool IsInterestingCoverageFile(const std::string &FileName) { 1503cab2bb3Spatrick if (FileName.find("compiler-rt/lib/") != std::string::npos) 1513cab2bb3Spatrick return false; // sanitizer internal. 1523cab2bb3Spatrick if (FileName.find("/usr/lib/") != std::string::npos) 1533cab2bb3Spatrick return false; 1543cab2bb3Spatrick if (FileName.find("/usr/include/") != std::string::npos) 1553cab2bb3Spatrick return false; 1563cab2bb3Spatrick if (FileName == "<null>") 1573cab2bb3Spatrick return false; 1583cab2bb3Spatrick return true; 1593cab2bb3Spatrick } 1603cab2bb3Spatrick 1613cab2bb3Spatrick void RawPrint(const char *Str) { 162*d89ec533Spatrick (void)write(2, Str, strlen(Str)); 1633cab2bb3Spatrick } 1643cab2bb3Spatrick 1653cab2bb3Spatrick void MkDir(const std::string &Path) { 1663cab2bb3Spatrick mkdir(Path.c_str(), 0700); 1673cab2bb3Spatrick } 1683cab2bb3Spatrick 1693cab2bb3Spatrick void RmDir(const std::string &Path) { 1703cab2bb3Spatrick rmdir(Path.c_str()); 1713cab2bb3Spatrick } 1723cab2bb3Spatrick 1733cab2bb3Spatrick const std::string &getDevNull() { 1743cab2bb3Spatrick static const std::string devNull = "/dev/null"; 1753cab2bb3Spatrick return devNull; 1763cab2bb3Spatrick } 1773cab2bb3Spatrick 1783cab2bb3Spatrick } // namespace fuzzer 1793cab2bb3Spatrick 1803cab2bb3Spatrick #endif // LIBFUZZER_POSIX 181