181 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8// IO functions implementation using Posix API.9//===----------------------------------------------------------------------===//10#include "FuzzerPlatform.h"11#if LIBFUZZER_POSIX || LIBFUZZER_FUCHSIA12 13#include "FuzzerExtFunctions.h"14#include "FuzzerIO.h"15#include <cerrno>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 26namespace fuzzer {27 28bool 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 35bool 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 42size_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 49std::string Basename(const std::string &Path) {50 size_t Pos = Path.rfind(GetSeparator());51 if (Pos == std::string::npos) return Path;52 assert(Pos < Path.size());53 return Path.substr(Pos + 1);54}55 56void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,57 std::vector<std::string> *V, bool TopDir) {58 auto E = GetEpoch(Dir);59 if (Epoch)60 if (E && *Epoch >= E) return;61 62 DIR *D = opendir(Dir.c_str());63 if (!D) {64 Printf("%s: %s; exiting\n", strerror(errno), Dir.c_str());65 exit(1);66 }67 while (auto E = readdir(D)) {68 std::string Path = DirPlusFile(Dir, E->d_name);69 if (E->d_type == DT_REG || E->d_type == DT_LNK ||70 (E->d_type == DT_UNKNOWN && IsFile(Path)))71 V->push_back(Path);72 else if ((E->d_type == DT_DIR ||73 (E->d_type == DT_UNKNOWN && IsDirectory(Path))) &&74 *E->d_name != '.')75 ListFilesInDirRecursive(Path, Epoch, V, false);76 }77 closedir(D);78 if (Epoch && TopDir)79 *Epoch = E;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 107bool IsSeparator(char C) {108 return C == '/';109}110 111FILE* OpenFile(int Fd, const char* Mode) {112 return fdopen(Fd, Mode);113}114 115int CloseFile(int fd) {116 return close(fd);117}118 119int DuplicateFile(int Fd) {120 return dup(Fd);121}122 123void RemoveFile(const std::string &Path) {124 unlink(Path.c_str());125}126 127void RenameFile(const std::string &OldPath, const std::string &NewPath) {128 rename(OldPath.c_str(), NewPath.c_str());129}130 131intptr_t GetHandleFromFd(int fd) {132 return static_cast<intptr_t>(fd);133}134 135std::string DirName(const std::string &FileName) {136 char *Tmp = new char[FileName.size() + 1];137 memcpy(Tmp, FileName.c_str(), FileName.size() + 1);138 std::string Res = dirname(Tmp);139 delete [] Tmp;140 return Res;141}142 143std::string TmpDir() {144 if (auto Env = getenv("TMPDIR"))145 return Env;146 return "/tmp";147}148 149bool IsInterestingCoverageFile(const std::string &FileName) {150 if (FileName.find("compiler-rt/lib/") != std::string::npos)151 return false; // sanitizer internal.152 if (FileName.find("/usr/lib/") != std::string::npos)153 return false;154 if (FileName.find("/usr/include/") != std::string::npos)155 return false;156 if (FileName == "<null>")157 return false;158 return true;159}160 161void RawPrint(const char *Str) {162 (void)write(2, Str, strlen(Str));163}164 165void MkDir(const std::string &Path) {166 mkdir(Path.c_str(), 0700);167}168 169void RmDir(const std::string &Path) {170 rmdir(Path.c_str());171}172 173const std::string &getDevNull() {174 static const std::string devNull = "/dev/null";175 return devNull;176}177 178} // namespace fuzzer179 180#endif // LIBFUZZER_POSIX181