10b57cec5SDimitry Andric //===- FuzzerIOPosix.cpp - IO utils for Posix. ----------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric // IO functions implementation using Posix API.
90b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
105ffd83dbSDimitry Andric #include "FuzzerPlatform.h"
110b57cec5SDimitry Andric #if LIBFUZZER_POSIX || LIBFUZZER_FUCHSIA
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "FuzzerExtFunctions.h"
140b57cec5SDimitry Andric #include "FuzzerIO.h"
150b57cec5SDimitry Andric #include <cstdarg>
160b57cec5SDimitry Andric #include <cstdio>
170b57cec5SDimitry Andric #include <dirent.h>
180b57cec5SDimitry Andric #include <fstream>
190b57cec5SDimitry Andric #include <iterator>
200b57cec5SDimitry Andric #include <libgen.h>
210b57cec5SDimitry Andric #include <sys/stat.h>
220b57cec5SDimitry Andric #include <sys/types.h>
230b57cec5SDimitry Andric #include <unistd.h>
240b57cec5SDimitry Andric
250b57cec5SDimitry Andric namespace fuzzer {
260b57cec5SDimitry Andric
IsFile(const std::string & Path)270b57cec5SDimitry Andric bool IsFile(const std::string &Path) {
280b57cec5SDimitry Andric struct stat St;
290b57cec5SDimitry Andric if (stat(Path.c_str(), &St))
300b57cec5SDimitry Andric return false;
310b57cec5SDimitry Andric return S_ISREG(St.st_mode);
320b57cec5SDimitry Andric }
330b57cec5SDimitry Andric
IsDirectory(const std::string & Path)34e8d8bef9SDimitry Andric bool IsDirectory(const std::string &Path) {
350b57cec5SDimitry Andric struct stat St;
360b57cec5SDimitry Andric if (stat(Path.c_str(), &St))
370b57cec5SDimitry Andric return false;
380b57cec5SDimitry Andric return S_ISDIR(St.st_mode);
390b57cec5SDimitry Andric }
400b57cec5SDimitry Andric
FileSize(const std::string & Path)410b57cec5SDimitry Andric size_t FileSize(const std::string &Path) {
420b57cec5SDimitry Andric struct stat St;
430b57cec5SDimitry Andric if (stat(Path.c_str(), &St))
440b57cec5SDimitry Andric return 0;
450b57cec5SDimitry Andric return St.st_size;
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric
Basename(const std::string & Path)480b57cec5SDimitry Andric std::string Basename(const std::string &Path) {
490b57cec5SDimitry Andric size_t Pos = Path.rfind(GetSeparator());
500b57cec5SDimitry Andric if (Pos == std::string::npos) return Path;
510b57cec5SDimitry Andric assert(Pos < Path.size());
520b57cec5SDimitry Andric return Path.substr(Pos + 1);
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric
ListFilesInDirRecursive(const std::string & Dir,long * Epoch,std::vector<std::string> * V,bool TopDir)550b57cec5SDimitry Andric void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
56*349cc55cSDimitry Andric std::vector<std::string> *V, bool TopDir) {
570b57cec5SDimitry Andric auto E = GetEpoch(Dir);
580b57cec5SDimitry Andric if (Epoch)
590b57cec5SDimitry Andric if (E && *Epoch >= E) return;
600b57cec5SDimitry Andric
610b57cec5SDimitry Andric DIR *D = opendir(Dir.c_str());
620b57cec5SDimitry Andric if (!D) {
630b57cec5SDimitry Andric Printf("%s: %s; exiting\n", strerror(errno), Dir.c_str());
640b57cec5SDimitry Andric exit(1);
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric while (auto E = readdir(D)) {
670b57cec5SDimitry Andric std::string Path = DirPlusFile(Dir, E->d_name);
680b57cec5SDimitry Andric if (E->d_type == DT_REG || E->d_type == DT_LNK ||
690b57cec5SDimitry Andric (E->d_type == DT_UNKNOWN && IsFile(Path)))
700b57cec5SDimitry Andric V->push_back(Path);
710b57cec5SDimitry Andric else if ((E->d_type == DT_DIR ||
720b57cec5SDimitry Andric (E->d_type == DT_UNKNOWN && IsDirectory(Path))) &&
730b57cec5SDimitry Andric *E->d_name != '.')
740b57cec5SDimitry Andric ListFilesInDirRecursive(Path, Epoch, V, false);
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric closedir(D);
770b57cec5SDimitry Andric if (Epoch && TopDir)
780b57cec5SDimitry Andric *Epoch = E;
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric
IterateDirRecursive(const std::string & Dir,void (* DirPreCallback)(const std::string & Dir),void (* DirPostCallback)(const std::string & Dir),void (* FileCallback)(const std::string & Dir))810b57cec5SDimitry Andric void IterateDirRecursive(const std::string &Dir,
820b57cec5SDimitry Andric void (*DirPreCallback)(const std::string &Dir),
830b57cec5SDimitry Andric void (*DirPostCallback)(const std::string &Dir),
840b57cec5SDimitry Andric void (*FileCallback)(const std::string &Dir)) {
850b57cec5SDimitry Andric DirPreCallback(Dir);
860b57cec5SDimitry Andric DIR *D = opendir(Dir.c_str());
870b57cec5SDimitry Andric if (!D) return;
880b57cec5SDimitry Andric while (auto E = readdir(D)) {
890b57cec5SDimitry Andric std::string Path = DirPlusFile(Dir, E->d_name);
900b57cec5SDimitry Andric if (E->d_type == DT_REG || E->d_type == DT_LNK ||
910b57cec5SDimitry Andric (E->d_type == DT_UNKNOWN && IsFile(Path)))
920b57cec5SDimitry Andric FileCallback(Path);
930b57cec5SDimitry Andric else if ((E->d_type == DT_DIR ||
940b57cec5SDimitry Andric (E->d_type == DT_UNKNOWN && IsDirectory(Path))) &&
950b57cec5SDimitry Andric *E->d_name != '.')
960b57cec5SDimitry Andric IterateDirRecursive(Path, DirPreCallback, DirPostCallback, FileCallback);
970b57cec5SDimitry Andric }
980b57cec5SDimitry Andric closedir(D);
990b57cec5SDimitry Andric DirPostCallback(Dir);
1000b57cec5SDimitry Andric }
1010b57cec5SDimitry Andric
GetSeparator()1020b57cec5SDimitry Andric char GetSeparator() {
1030b57cec5SDimitry Andric return '/';
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric
IsSeparator(char C)106e8d8bef9SDimitry Andric bool IsSeparator(char C) {
107e8d8bef9SDimitry Andric return C == '/';
108e8d8bef9SDimitry Andric }
109e8d8bef9SDimitry Andric
OpenFile(int Fd,const char * Mode)1100b57cec5SDimitry Andric FILE* OpenFile(int Fd, const char* Mode) {
1110b57cec5SDimitry Andric return fdopen(Fd, Mode);
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric
CloseFile(int fd)1140b57cec5SDimitry Andric int CloseFile(int fd) {
1150b57cec5SDimitry Andric return close(fd);
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric
DuplicateFile(int Fd)1180b57cec5SDimitry Andric int DuplicateFile(int Fd) {
1190b57cec5SDimitry Andric return dup(Fd);
1200b57cec5SDimitry Andric }
1210b57cec5SDimitry Andric
RemoveFile(const std::string & Path)1220b57cec5SDimitry Andric void RemoveFile(const std::string &Path) {
1230b57cec5SDimitry Andric unlink(Path.c_str());
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric
RenameFile(const std::string & OldPath,const std::string & NewPath)1260b57cec5SDimitry Andric void RenameFile(const std::string &OldPath, const std::string &NewPath) {
1270b57cec5SDimitry Andric rename(OldPath.c_str(), NewPath.c_str());
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric
GetHandleFromFd(int fd)1300b57cec5SDimitry Andric intptr_t GetHandleFromFd(int fd) {
1310b57cec5SDimitry Andric return static_cast<intptr_t>(fd);
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric
DirName(const std::string & FileName)1340b57cec5SDimitry Andric std::string DirName(const std::string &FileName) {
1350b57cec5SDimitry Andric char *Tmp = new char[FileName.size() + 1];
1360b57cec5SDimitry Andric memcpy(Tmp, FileName.c_str(), FileName.size() + 1);
1370b57cec5SDimitry Andric std::string Res = dirname(Tmp);
1380b57cec5SDimitry Andric delete [] Tmp;
1390b57cec5SDimitry Andric return Res;
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric
TmpDir()1420b57cec5SDimitry Andric std::string TmpDir() {
1430b57cec5SDimitry Andric if (auto Env = getenv("TMPDIR"))
1440b57cec5SDimitry Andric return Env;
1450b57cec5SDimitry Andric return "/tmp";
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric
IsInterestingCoverageFile(const std::string & FileName)1480b57cec5SDimitry Andric bool IsInterestingCoverageFile(const std::string &FileName) {
1490b57cec5SDimitry Andric if (FileName.find("compiler-rt/lib/") != std::string::npos)
1500b57cec5SDimitry Andric return false; // sanitizer internal.
1510b57cec5SDimitry Andric if (FileName.find("/usr/lib/") != std::string::npos)
1520b57cec5SDimitry Andric return false;
1530b57cec5SDimitry Andric if (FileName.find("/usr/include/") != std::string::npos)
1540b57cec5SDimitry Andric return false;
1550b57cec5SDimitry Andric if (FileName == "<null>")
1560b57cec5SDimitry Andric return false;
1570b57cec5SDimitry Andric return true;
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric
RawPrint(const char * Str)1600b57cec5SDimitry Andric void RawPrint(const char *Str) {
161e8d8bef9SDimitry Andric (void)write(2, Str, strlen(Str));
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric
MkDir(const std::string & Path)1640b57cec5SDimitry Andric void MkDir(const std::string &Path) {
1650b57cec5SDimitry Andric mkdir(Path.c_str(), 0700);
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric
RmDir(const std::string & Path)1680b57cec5SDimitry Andric void RmDir(const std::string &Path) {
1690b57cec5SDimitry Andric rmdir(Path.c_str());
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric
getDevNull()1720b57cec5SDimitry Andric const std::string &getDevNull() {
1730b57cec5SDimitry Andric static const std::string devNull = "/dev/null";
1740b57cec5SDimitry Andric return devNull;
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric
1770b57cec5SDimitry Andric } // namespace fuzzer
1780b57cec5SDimitry Andric
1790b57cec5SDimitry Andric #endif // LIBFUZZER_POSIX
180