//===- FuzzerIOPosix.cpp - IO utils for Posix. ----------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // IO functions implementation using Posix API. //===----------------------------------------------------------------------===// #include "mozilla/Unused.h" #include "FuzzerPlatform.h" #if LIBFUZZER_POSIX || LIBFUZZER_FUCHSIA #include "FuzzerExtFunctions.h" #include "FuzzerIO.h" #include #include #include #include #include #include #include #include #include namespace fuzzer { bool IsFile(const std::string &Path) { struct stat St; if (stat(Path.c_str(), &St)) return false; return S_ISREG(St.st_mode); } static bool IsDirectory(const std::string &Path) { struct stat St; if (stat(Path.c_str(), &St)) return false; return S_ISDIR(St.st_mode); } size_t FileSize(const std::string &Path) { struct stat St; if (stat(Path.c_str(), &St)) return 0; return St.st_size; } std::string Basename(const std::string &Path) { size_t Pos = Path.rfind(GetSeparator()); if (Pos == std::string::npos) return Path; assert(Pos < Path.size()); return Path.substr(Pos + 1); } int ListFilesInDirRecursive(const std::string &Dir, long *Epoch, Vector *V, bool TopDir) { auto E = GetEpoch(Dir); if (Epoch) if (E && *Epoch >= E) return 0; DIR *D = opendir(Dir.c_str()); if (!D) { Printf("%s: %s; exiting\n", strerror(errno), Dir.c_str()); return 1; } while (auto E = readdir(D)) { std::string Path = DirPlusFile(Dir, E->d_name); if (E->d_type == DT_REG || E->d_type == DT_LNK || (E->d_type == DT_UNKNOWN && IsFile(Path))) V->push_back(Path); else if ((E->d_type == DT_DIR || (E->d_type == DT_UNKNOWN && IsDirectory(Path))) && *E->d_name != '.') { int Res = ListFilesInDirRecursive(Path, Epoch, V, false); if (Res != 0) return Res; } } closedir(D); if (Epoch && TopDir) *Epoch = E; return 0; } void IterateDirRecursive(const std::string &Dir, void (*DirPreCallback)(const std::string &Dir), void (*DirPostCallback)(const std::string &Dir), void (*FileCallback)(const std::string &Dir)) { DirPreCallback(Dir); DIR *D = opendir(Dir.c_str()); if (!D) return; while (auto E = readdir(D)) { std::string Path = DirPlusFile(Dir, E->d_name); if (E->d_type == DT_REG || E->d_type == DT_LNK || (E->d_type == DT_UNKNOWN && IsFile(Path))) FileCallback(Path); else if ((E->d_type == DT_DIR || (E->d_type == DT_UNKNOWN && IsDirectory(Path))) && *E->d_name != '.') IterateDirRecursive(Path, DirPreCallback, DirPostCallback, FileCallback); } closedir(D); DirPostCallback(Dir); } char GetSeparator() { return '/'; } FILE* OpenFile(int Fd, const char* Mode) { return fdopen(Fd, Mode); } int CloseFile(int fd) { return close(fd); } int DuplicateFile(int Fd) { return dup(Fd); } void RemoveFile(const std::string &Path) { unlink(Path.c_str()); } void RenameFile(const std::string &OldPath, const std::string &NewPath) { rename(OldPath.c_str(), NewPath.c_str()); } intptr_t GetHandleFromFd(int fd) { return static_cast(fd); } std::string DirName(const std::string &FileName) { char *Tmp = new char[FileName.size() + 1]; memcpy(Tmp, FileName.c_str(), FileName.size() + 1); std::string Res = dirname(Tmp); delete [] Tmp; return Res; } std::string TmpDir() { if (auto Env = getenv("TMPDIR")) return Env; return "/tmp"; } bool IsInterestingCoverageFile(const std::string &FileName) { if (FileName.find("compiler-rt/lib/") != std::string::npos) return false; // sanitizer internal. if (FileName.find("/usr/lib/") != std::string::npos) return false; if (FileName.find("/usr/include/") != std::string::npos) return false; if (FileName == "") return false; return true; } void RawPrint(const char *Str) { mozilla::Unused << write(2, Str, strlen(Str)); } void MkDir(const std::string &Path) { mkdir(Path.c_str(), 0700); } void RmDir(const std::string &Path) { rmdir(Path.c_str()); } const std::string &getDevNull() { static const std::string devNull = "/dev/null"; return devNull; } } // namespace fuzzer #endif // LIBFUZZER_POSIX