1 //===- FuzzerIOPosix.cpp - IO utils for Posix. ----------------------------===//
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
7 //===----------------------------------------------------------------------===//
8 // IO functions implementation using Posix API.
9 //===----------------------------------------------------------------------===//
10 #include "FuzzerPlatform.h"
11 #if LIBFUZZER_POSIX || LIBFUZZER_FUCHSIA
13 #include "FuzzerExtFunctions.h"
22 #include <sys/types.h>
27 bool IsFile(const std::string
&Path
) {
29 if (stat(Path
.c_str(), &St
))
31 return S_ISREG(St
.st_mode
);
34 bool IsDirectory(const std::string
&Path
) {
36 if (stat(Path
.c_str(), &St
))
38 return S_ISDIR(St
.st_mode
);
41 size_t FileSize(const std::string
&Path
) {
43 if (stat(Path
.c_str(), &St
))
48 std::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);
55 void ListFilesInDirRecursive(const std::string
&Dir
, long *Epoch
,
56 std::vector
<std::string
> *V
, bool TopDir
) {
57 auto E
= GetEpoch(Dir
);
59 if (E
&& *Epoch
>= E
) return;
61 DIR *D
= opendir(Dir
.c_str());
63 Printf("%s: %s; exiting\n", strerror(errno
), Dir
.c_str());
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
)))
71 else if ((E
->d_type
== DT_DIR
||
72 (E
->d_type
== DT_UNKNOWN
&& IsDirectory(Path
))) &&
74 ListFilesInDirRecursive(Path
, Epoch
, V
, false);
81 void IterateDirRecursive(const std::string
&Dir
,
82 void (*DirPreCallback
)(const std::string
&Dir
),
83 void (*DirPostCallback
)(const std::string
&Dir
),
84 void (*FileCallback
)(const std::string
&Dir
)) {
86 DIR *D
= opendir(Dir
.c_str());
88 while (auto E
= readdir(D
)) {
89 std::string Path
= DirPlusFile(Dir
, E
->d_name
);
90 if (E
->d_type
== DT_REG
|| E
->d_type
== DT_LNK
||
91 (E
->d_type
== DT_UNKNOWN
&& IsFile(Path
)))
93 else if ((E
->d_type
== DT_DIR
||
94 (E
->d_type
== DT_UNKNOWN
&& IsDirectory(Path
))) &&
96 IterateDirRecursive(Path
, DirPreCallback
, DirPostCallback
, FileCallback
);
102 char GetSeparator() {
106 bool IsSeparator(char C
) {
110 FILE* OpenFile(int Fd
, const char* Mode
) {
111 return fdopen(Fd
, Mode
);
114 int CloseFile(int fd
) {
118 int DuplicateFile(int Fd
) {
122 void RemoveFile(const std::string
&Path
) {
123 unlink(Path
.c_str());
126 void RenameFile(const std::string
&OldPath
, const std::string
&NewPath
) {
127 rename(OldPath
.c_str(), NewPath
.c_str());
130 intptr_t GetHandleFromFd(int fd
) {
131 return static_cast<intptr_t>(fd
);
134 std::string
DirName(const std::string
&FileName
) {
135 char *Tmp
= new char[FileName
.size() + 1];
136 memcpy(Tmp
, FileName
.c_str(), FileName
.size() + 1);
137 std::string Res
= dirname(Tmp
);
142 std::string
TmpDir() {
143 if (auto Env
= getenv("TMPDIR"))
148 bool IsInterestingCoverageFile(const std::string
&FileName
) {
149 if (FileName
.find("compiler-rt/lib/") != std::string::npos
)
150 return false; // sanitizer internal.
151 if (FileName
.find("/usr/lib/") != std::string::npos
)
153 if (FileName
.find("/usr/include/") != std::string::npos
)
155 if (FileName
== "<null>")
160 void RawPrint(const char *Str
) {
161 (void)write(2, Str
, strlen(Str
));
164 void MkDir(const std::string
&Path
) {
165 mkdir(Path
.c_str(), 0700);
168 void RmDir(const std::string
&Path
) {
172 const std::string
&getDevNull() {
173 static const std::string devNull
= "/dev/null";
177 } // namespace fuzzer
179 #endif // LIBFUZZER_POSIX