xref: /openbsd-src/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIOWindows.cpp (revision 810390e339a5425391477d5d41c78d7cab2424ac)
13cab2bb3Spatrick //===- FuzzerIOWindows.cpp - IO utils for Windows. ------------------------===//
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 for Windows.
93cab2bb3Spatrick //===----------------------------------------------------------------------===//
101f9cb04fSpatrick #include "FuzzerPlatform.h"
113cab2bb3Spatrick #if LIBFUZZER_WINDOWS
123cab2bb3Spatrick 
133cab2bb3Spatrick #include "FuzzerExtFunctions.h"
143cab2bb3Spatrick #include "FuzzerIO.h"
153cab2bb3Spatrick #include <cstdarg>
163cab2bb3Spatrick #include <cstdio>
173cab2bb3Spatrick #include <fstream>
183cab2bb3Spatrick #include <io.h>
193cab2bb3Spatrick #include <iterator>
203cab2bb3Spatrick #include <sys/stat.h>
213cab2bb3Spatrick #include <sys/types.h>
223cab2bb3Spatrick #include <windows.h>
233cab2bb3Spatrick 
243cab2bb3Spatrick namespace fuzzer {
253cab2bb3Spatrick 
IsFile(const std::string & Path,const DWORD & FileAttributes)263cab2bb3Spatrick static bool IsFile(const std::string &Path, const DWORD &FileAttributes) {
273cab2bb3Spatrick 
283cab2bb3Spatrick   if (FileAttributes & FILE_ATTRIBUTE_NORMAL)
293cab2bb3Spatrick     return true;
303cab2bb3Spatrick 
313cab2bb3Spatrick   if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
323cab2bb3Spatrick     return false;
333cab2bb3Spatrick 
343cab2bb3Spatrick   HANDLE FileHandle(
353cab2bb3Spatrick       CreateFileA(Path.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
363cab2bb3Spatrick                   FILE_FLAG_BACKUP_SEMANTICS, 0));
373cab2bb3Spatrick 
383cab2bb3Spatrick   if (FileHandle == INVALID_HANDLE_VALUE) {
393cab2bb3Spatrick     Printf("CreateFileA() failed for \"%s\" (Error code: %lu).\n", Path.c_str(),
403cab2bb3Spatrick         GetLastError());
413cab2bb3Spatrick     return false;
423cab2bb3Spatrick   }
433cab2bb3Spatrick 
443cab2bb3Spatrick   DWORD FileType = GetFileType(FileHandle);
453cab2bb3Spatrick 
463cab2bb3Spatrick   if (FileType == FILE_TYPE_UNKNOWN) {
473cab2bb3Spatrick     Printf("GetFileType() failed for \"%s\" (Error code: %lu).\n", Path.c_str(),
483cab2bb3Spatrick         GetLastError());
493cab2bb3Spatrick     CloseHandle(FileHandle);
503cab2bb3Spatrick     return false;
513cab2bb3Spatrick   }
523cab2bb3Spatrick 
533cab2bb3Spatrick   if (FileType != FILE_TYPE_DISK) {
543cab2bb3Spatrick     CloseHandle(FileHandle);
553cab2bb3Spatrick     return false;
563cab2bb3Spatrick   }
573cab2bb3Spatrick 
583cab2bb3Spatrick   CloseHandle(FileHandle);
593cab2bb3Spatrick   return true;
603cab2bb3Spatrick }
613cab2bb3Spatrick 
IsFile(const std::string & Path)623cab2bb3Spatrick bool IsFile(const std::string &Path) {
633cab2bb3Spatrick   DWORD Att = GetFileAttributesA(Path.c_str());
643cab2bb3Spatrick 
653cab2bb3Spatrick   if (Att == INVALID_FILE_ATTRIBUTES) {
663cab2bb3Spatrick     Printf("GetFileAttributesA() failed for \"%s\" (Error code: %lu).\n",
673cab2bb3Spatrick         Path.c_str(), GetLastError());
683cab2bb3Spatrick     return false;
693cab2bb3Spatrick   }
703cab2bb3Spatrick 
713cab2bb3Spatrick   return IsFile(Path, Att);
723cab2bb3Spatrick }
733cab2bb3Spatrick 
IsDir(DWORD FileAttrs)743cab2bb3Spatrick static bool IsDir(DWORD FileAttrs) {
753cab2bb3Spatrick   if (FileAttrs == INVALID_FILE_ATTRIBUTES) return false;
763cab2bb3Spatrick   return FileAttrs & FILE_ATTRIBUTE_DIRECTORY;
773cab2bb3Spatrick }
783cab2bb3Spatrick 
IsDirectory(const std::string & Path)79d89ec533Spatrick bool IsDirectory(const std::string &Path) {
80d89ec533Spatrick   DWORD Att = GetFileAttributesA(Path.c_str());
81d89ec533Spatrick 
82d89ec533Spatrick   if (Att == INVALID_FILE_ATTRIBUTES) {
83d89ec533Spatrick     Printf("GetFileAttributesA() failed for \"%s\" (Error code: %lu).\n",
84d89ec533Spatrick            Path.c_str(), GetLastError());
85d89ec533Spatrick     return false;
86d89ec533Spatrick   }
87d89ec533Spatrick 
88d89ec533Spatrick   return IsDir(Att);
89d89ec533Spatrick }
90d89ec533Spatrick 
Basename(const std::string & Path)913cab2bb3Spatrick std::string Basename(const std::string &Path) {
923cab2bb3Spatrick   size_t Pos = Path.find_last_of("/\\");
933cab2bb3Spatrick   if (Pos == std::string::npos) return Path;
943cab2bb3Spatrick   assert(Pos < Path.size());
953cab2bb3Spatrick   return Path.substr(Pos + 1);
963cab2bb3Spatrick }
973cab2bb3Spatrick 
FileSize(const std::string & Path)983cab2bb3Spatrick size_t FileSize(const std::string &Path) {
993cab2bb3Spatrick   WIN32_FILE_ATTRIBUTE_DATA attr;
1003cab2bb3Spatrick   if (!GetFileAttributesExA(Path.c_str(), GetFileExInfoStandard, &attr)) {
1013cab2bb3Spatrick     DWORD LastError = GetLastError();
1023cab2bb3Spatrick     if (LastError != ERROR_FILE_NOT_FOUND)
1033cab2bb3Spatrick       Printf("GetFileAttributesExA() failed for \"%s\" (Error code: %lu).\n",
1043cab2bb3Spatrick              Path.c_str(), LastError);
1053cab2bb3Spatrick     return 0;
1063cab2bb3Spatrick   }
1073cab2bb3Spatrick   ULARGE_INTEGER size;
1083cab2bb3Spatrick   size.HighPart = attr.nFileSizeHigh;
1093cab2bb3Spatrick   size.LowPart = attr.nFileSizeLow;
1103cab2bb3Spatrick   return size.QuadPart;
1113cab2bb3Spatrick }
1123cab2bb3Spatrick 
ListFilesInDirRecursive(const std::string & Dir,long * Epoch,std::vector<std::string> * V,bool TopDir)1133cab2bb3Spatrick void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
114*810390e3Srobert                              std::vector<std::string> *V, bool TopDir) {
1153cab2bb3Spatrick   auto E = GetEpoch(Dir);
1163cab2bb3Spatrick   if (Epoch)
1173cab2bb3Spatrick     if (E && *Epoch >= E) return;
1183cab2bb3Spatrick 
1193cab2bb3Spatrick   std::string Path(Dir);
1203cab2bb3Spatrick   assert(!Path.empty());
1213cab2bb3Spatrick   if (Path.back() != '\\')
1223cab2bb3Spatrick       Path.push_back('\\');
1233cab2bb3Spatrick   Path.push_back('*');
1243cab2bb3Spatrick 
1253cab2bb3Spatrick   // Get the first directory entry.
1263cab2bb3Spatrick   WIN32_FIND_DATAA FindInfo;
1273cab2bb3Spatrick   HANDLE FindHandle(FindFirstFileA(Path.c_str(), &FindInfo));
1283cab2bb3Spatrick   if (FindHandle == INVALID_HANDLE_VALUE)
1293cab2bb3Spatrick   {
1303cab2bb3Spatrick     if (GetLastError() == ERROR_FILE_NOT_FOUND)
1313cab2bb3Spatrick       return;
1323cab2bb3Spatrick     Printf("No such file or directory: %s; exiting\n", Dir.c_str());
1333cab2bb3Spatrick     exit(1);
1343cab2bb3Spatrick   }
1353cab2bb3Spatrick 
1363cab2bb3Spatrick   do {
1373cab2bb3Spatrick     std::string FileName = DirPlusFile(Dir, FindInfo.cFileName);
1383cab2bb3Spatrick 
1393cab2bb3Spatrick     if (FindInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1403cab2bb3Spatrick       size_t FilenameLen = strlen(FindInfo.cFileName);
1413cab2bb3Spatrick       if ((FilenameLen == 1 && FindInfo.cFileName[0] == '.') ||
1423cab2bb3Spatrick           (FilenameLen == 2 && FindInfo.cFileName[0] == '.' &&
1433cab2bb3Spatrick                                FindInfo.cFileName[1] == '.'))
1443cab2bb3Spatrick         continue;
1453cab2bb3Spatrick 
1463cab2bb3Spatrick       ListFilesInDirRecursive(FileName, Epoch, V, false);
1473cab2bb3Spatrick     }
1483cab2bb3Spatrick     else if (IsFile(FileName, FindInfo.dwFileAttributes))
1493cab2bb3Spatrick       V->push_back(FileName);
1503cab2bb3Spatrick   } while (FindNextFileA(FindHandle, &FindInfo));
1513cab2bb3Spatrick 
1523cab2bb3Spatrick   DWORD LastError = GetLastError();
1533cab2bb3Spatrick   if (LastError != ERROR_NO_MORE_FILES)
1543cab2bb3Spatrick     Printf("FindNextFileA failed (Error code: %lu).\n", LastError);
1553cab2bb3Spatrick 
1563cab2bb3Spatrick   FindClose(FindHandle);
1573cab2bb3Spatrick 
1583cab2bb3Spatrick   if (Epoch && TopDir)
1593cab2bb3Spatrick     *Epoch = E;
1603cab2bb3Spatrick }
1613cab2bb3Spatrick 
IterateDirRecursive(const std::string & Dir,void (* DirPreCallback)(const std::string & Dir),void (* DirPostCallback)(const std::string & Dir),void (* FileCallback)(const std::string & Dir))1623cab2bb3Spatrick void IterateDirRecursive(const std::string &Dir,
1633cab2bb3Spatrick                          void (*DirPreCallback)(const std::string &Dir),
1643cab2bb3Spatrick                          void (*DirPostCallback)(const std::string &Dir),
1653cab2bb3Spatrick                          void (*FileCallback)(const std::string &Dir)) {
1663cab2bb3Spatrick   // TODO(metzman): Implement ListFilesInDirRecursive via this function.
1673cab2bb3Spatrick   DirPreCallback(Dir);
1683cab2bb3Spatrick 
1693cab2bb3Spatrick   DWORD DirAttrs = GetFileAttributesA(Dir.c_str());
1703cab2bb3Spatrick   if (!IsDir(DirAttrs)) return;
1713cab2bb3Spatrick 
1723cab2bb3Spatrick   std::string TargetDir(Dir);
1733cab2bb3Spatrick   assert(!TargetDir.empty());
1743cab2bb3Spatrick   if (TargetDir.back() != '\\') TargetDir.push_back('\\');
1753cab2bb3Spatrick   TargetDir.push_back('*');
1763cab2bb3Spatrick 
1773cab2bb3Spatrick   WIN32_FIND_DATAA FindInfo;
1783cab2bb3Spatrick   // Find the directory's first file.
1793cab2bb3Spatrick   HANDLE FindHandle = FindFirstFileA(TargetDir.c_str(), &FindInfo);
1803cab2bb3Spatrick   if (FindHandle == INVALID_HANDLE_VALUE) {
1813cab2bb3Spatrick     DWORD LastError = GetLastError();
1823cab2bb3Spatrick     if (LastError != ERROR_FILE_NOT_FOUND) {
1833cab2bb3Spatrick       // If the directory isn't empty, then something abnormal is going on.
1843cab2bb3Spatrick       Printf("FindFirstFileA failed for %s (Error code: %lu).\n", Dir.c_str(),
1853cab2bb3Spatrick              LastError);
1863cab2bb3Spatrick     }
1873cab2bb3Spatrick     return;
1883cab2bb3Spatrick   }
1893cab2bb3Spatrick 
1903cab2bb3Spatrick   do {
1913cab2bb3Spatrick     std::string Path = DirPlusFile(Dir, FindInfo.cFileName);
1923cab2bb3Spatrick     DWORD PathAttrs = FindInfo.dwFileAttributes;
1933cab2bb3Spatrick     if (IsDir(PathAttrs)) {
1943cab2bb3Spatrick       // Is Path the current directory (".") or the parent ("..")?
1953cab2bb3Spatrick       if (strcmp(FindInfo.cFileName, ".") == 0 ||
1963cab2bb3Spatrick           strcmp(FindInfo.cFileName, "..") == 0)
1973cab2bb3Spatrick         continue;
1983cab2bb3Spatrick       IterateDirRecursive(Path, DirPreCallback, DirPostCallback, FileCallback);
1993cab2bb3Spatrick     } else if (PathAttrs != INVALID_FILE_ATTRIBUTES) {
2003cab2bb3Spatrick       FileCallback(Path);
2013cab2bb3Spatrick     }
2023cab2bb3Spatrick   } while (FindNextFileA(FindHandle, &FindInfo));
2033cab2bb3Spatrick 
2043cab2bb3Spatrick   DWORD LastError = GetLastError();
2053cab2bb3Spatrick   if (LastError != ERROR_NO_MORE_FILES)
2063cab2bb3Spatrick     Printf("FindNextFileA failed for %s (Error code: %lu).\n", Dir.c_str(),
2073cab2bb3Spatrick            LastError);
2083cab2bb3Spatrick 
2093cab2bb3Spatrick   FindClose(FindHandle);
2103cab2bb3Spatrick   DirPostCallback(Dir);
2113cab2bb3Spatrick }
2123cab2bb3Spatrick 
GetSeparator()2133cab2bb3Spatrick char GetSeparator() {
2143cab2bb3Spatrick   return '\\';
2153cab2bb3Spatrick }
2163cab2bb3Spatrick 
OpenFile(int Fd,const char * Mode)2173cab2bb3Spatrick FILE* OpenFile(int Fd, const char* Mode) {
2183cab2bb3Spatrick   return _fdopen(Fd, Mode);
2193cab2bb3Spatrick }
2203cab2bb3Spatrick 
CloseFile(int Fd)2213cab2bb3Spatrick int CloseFile(int Fd) {
2223cab2bb3Spatrick   return _close(Fd);
2233cab2bb3Spatrick }
2243cab2bb3Spatrick 
DuplicateFile(int Fd)2253cab2bb3Spatrick int DuplicateFile(int Fd) {
2263cab2bb3Spatrick   return _dup(Fd);
2273cab2bb3Spatrick }
2283cab2bb3Spatrick 
RemoveFile(const std::string & Path)2293cab2bb3Spatrick void RemoveFile(const std::string &Path) {
2303cab2bb3Spatrick   _unlink(Path.c_str());
2313cab2bb3Spatrick }
2323cab2bb3Spatrick 
RenameFile(const std::string & OldPath,const std::string & NewPath)2333cab2bb3Spatrick void RenameFile(const std::string &OldPath, const std::string &NewPath) {
2343cab2bb3Spatrick   rename(OldPath.c_str(), NewPath.c_str());
2353cab2bb3Spatrick }
2363cab2bb3Spatrick 
GetHandleFromFd(int fd)2373cab2bb3Spatrick intptr_t GetHandleFromFd(int fd) {
2383cab2bb3Spatrick   return _get_osfhandle(fd);
2393cab2bb3Spatrick }
2403cab2bb3Spatrick 
IsSeparator(char C)241d89ec533Spatrick bool IsSeparator(char C) {
2423cab2bb3Spatrick   return C == '\\' || C == '/';
2433cab2bb3Spatrick }
2443cab2bb3Spatrick 
2453cab2bb3Spatrick // Parse disk designators, like "C:\". If Relative == true, also accepts: "C:".
2463cab2bb3Spatrick // Returns number of characters considered if successful.
ParseDrive(const std::string & FileName,const size_t Offset,bool Relative=true)2473cab2bb3Spatrick static size_t ParseDrive(const std::string &FileName, const size_t Offset,
2483cab2bb3Spatrick                          bool Relative = true) {
2493cab2bb3Spatrick   if (Offset + 1 >= FileName.size() || FileName[Offset + 1] != ':')
2503cab2bb3Spatrick     return 0;
2513cab2bb3Spatrick   if (Offset + 2 >= FileName.size() || !IsSeparator(FileName[Offset + 2])) {
2523cab2bb3Spatrick     if (!Relative) // Accept relative path?
2533cab2bb3Spatrick       return 0;
2543cab2bb3Spatrick     else
2553cab2bb3Spatrick       return 2;
2563cab2bb3Spatrick   }
2573cab2bb3Spatrick   return 3;
2583cab2bb3Spatrick }
2593cab2bb3Spatrick 
2603cab2bb3Spatrick // Parse a file name, like: SomeFile.txt
2613cab2bb3Spatrick // Returns number of characters considered if successful.
ParseFileName(const std::string & FileName,const size_t Offset)2623cab2bb3Spatrick static size_t ParseFileName(const std::string &FileName, const size_t Offset) {
2633cab2bb3Spatrick   size_t Pos = Offset;
2643cab2bb3Spatrick   const size_t End = FileName.size();
2653cab2bb3Spatrick   for(; Pos < End && !IsSeparator(FileName[Pos]); ++Pos)
2663cab2bb3Spatrick     ;
2673cab2bb3Spatrick   return Pos - Offset;
2683cab2bb3Spatrick }
2693cab2bb3Spatrick 
2703cab2bb3Spatrick // Parse a directory ending in separator, like: `SomeDir\`
2713cab2bb3Spatrick // Returns number of characters considered if successful.
ParseDir(const std::string & FileName,const size_t Offset)2723cab2bb3Spatrick static size_t ParseDir(const std::string &FileName, const size_t Offset) {
2733cab2bb3Spatrick   size_t Pos = Offset;
2743cab2bb3Spatrick   const size_t End = FileName.size();
2753cab2bb3Spatrick   if (Pos >= End || IsSeparator(FileName[Pos]))
2763cab2bb3Spatrick     return 0;
2773cab2bb3Spatrick   for(; Pos < End && !IsSeparator(FileName[Pos]); ++Pos)
2783cab2bb3Spatrick     ;
2793cab2bb3Spatrick   if (Pos >= End)
2803cab2bb3Spatrick     return 0;
2813cab2bb3Spatrick   ++Pos; // Include separator.
2823cab2bb3Spatrick   return Pos - Offset;
2833cab2bb3Spatrick }
2843cab2bb3Spatrick 
2853cab2bb3Spatrick // Parse a servername and share, like: `SomeServer\SomeShare\`
2863cab2bb3Spatrick // Returns number of characters considered if successful.
ParseServerAndShare(const std::string & FileName,const size_t Offset)2873cab2bb3Spatrick static size_t ParseServerAndShare(const std::string &FileName,
2883cab2bb3Spatrick                                   const size_t Offset) {
2893cab2bb3Spatrick   size_t Pos = Offset, Res;
2903cab2bb3Spatrick   if (!(Res = ParseDir(FileName, Pos)))
2913cab2bb3Spatrick     return 0;
2923cab2bb3Spatrick   Pos += Res;
2933cab2bb3Spatrick   if (!(Res = ParseDir(FileName, Pos)))
2943cab2bb3Spatrick     return 0;
2953cab2bb3Spatrick   Pos += Res;
2963cab2bb3Spatrick   return Pos - Offset;
2973cab2bb3Spatrick }
2983cab2bb3Spatrick 
299*810390e3Srobert // Parse the given Ref string from the position Offset, to exactly match the
300*810390e3Srobert // given string Patt. Returns number of characters considered if successful.
ParseCustomString(const std::string & Ref,size_t Offset,const char * Patt)3013cab2bb3Spatrick static size_t ParseCustomString(const std::string &Ref, size_t Offset,
3023cab2bb3Spatrick                                 const char *Patt) {
3033cab2bb3Spatrick   size_t Len = strlen(Patt);
3043cab2bb3Spatrick   if (Offset + Len > Ref.size())
3053cab2bb3Spatrick     return 0;
3063cab2bb3Spatrick   return Ref.compare(Offset, Len, Patt) == 0 ? Len : 0;
3073cab2bb3Spatrick }
3083cab2bb3Spatrick 
3093cab2bb3Spatrick // Parse a location, like:
3103cab2bb3Spatrick // \\?\UNC\Server\Share\  \\?\C:\  \\Server\Share\  \  C:\  C:
3113cab2bb3Spatrick // Returns number of characters considered if successful.
ParseLocation(const std::string & FileName)3123cab2bb3Spatrick static size_t ParseLocation(const std::string &FileName) {
3133cab2bb3Spatrick   size_t Pos = 0, Res;
3143cab2bb3Spatrick 
3153cab2bb3Spatrick   if ((Res = ParseCustomString(FileName, Pos, R"(\\?\)"))) {
3163cab2bb3Spatrick     Pos += Res;
3173cab2bb3Spatrick     if ((Res = ParseCustomString(FileName, Pos, R"(UNC\)"))) {
3183cab2bb3Spatrick       Pos += Res;
3193cab2bb3Spatrick       if ((Res = ParseServerAndShare(FileName, Pos)))
3203cab2bb3Spatrick         return Pos + Res;
3213cab2bb3Spatrick       return 0;
3223cab2bb3Spatrick     }
3233cab2bb3Spatrick     if ((Res = ParseDrive(FileName, Pos, false)))
3243cab2bb3Spatrick       return Pos + Res;
3253cab2bb3Spatrick     return 0;
3263cab2bb3Spatrick   }
3273cab2bb3Spatrick 
3283cab2bb3Spatrick   if (Pos < FileName.size() && IsSeparator(FileName[Pos])) {
3293cab2bb3Spatrick     ++Pos;
3303cab2bb3Spatrick     if (Pos < FileName.size() && IsSeparator(FileName[Pos])) {
3313cab2bb3Spatrick       ++Pos;
3323cab2bb3Spatrick       if ((Res = ParseServerAndShare(FileName, Pos)))
3333cab2bb3Spatrick         return Pos + Res;
3343cab2bb3Spatrick       return 0;
3353cab2bb3Spatrick     }
3363cab2bb3Spatrick     return Pos;
3373cab2bb3Spatrick   }
3383cab2bb3Spatrick 
3393cab2bb3Spatrick   if ((Res = ParseDrive(FileName, Pos)))
3403cab2bb3Spatrick     return Pos + Res;
3413cab2bb3Spatrick 
3423cab2bb3Spatrick   return Pos;
3433cab2bb3Spatrick }
3443cab2bb3Spatrick 
DirName(const std::string & FileName)3453cab2bb3Spatrick std::string DirName(const std::string &FileName) {
3463cab2bb3Spatrick   size_t LocationLen = ParseLocation(FileName);
3473cab2bb3Spatrick   size_t DirLen = 0, Res;
3483cab2bb3Spatrick   while ((Res = ParseDir(FileName, LocationLen + DirLen)))
3493cab2bb3Spatrick     DirLen += Res;
3503cab2bb3Spatrick   size_t FileLen = ParseFileName(FileName, LocationLen + DirLen);
3513cab2bb3Spatrick 
3523cab2bb3Spatrick   if (LocationLen + DirLen + FileLen != FileName.size()) {
3533cab2bb3Spatrick     Printf("DirName() failed for \"%s\", invalid path.\n", FileName.c_str());
3543cab2bb3Spatrick     exit(1);
3553cab2bb3Spatrick   }
3563cab2bb3Spatrick 
3573cab2bb3Spatrick   if (DirLen) {
3583cab2bb3Spatrick     --DirLen; // Remove trailing separator.
3593cab2bb3Spatrick     if (!FileLen) { // Path ended in separator.
3603cab2bb3Spatrick       assert(DirLen);
3613cab2bb3Spatrick       // Remove file name from Dir.
3623cab2bb3Spatrick       while (DirLen && !IsSeparator(FileName[LocationLen + DirLen - 1]))
3633cab2bb3Spatrick         --DirLen;
3643cab2bb3Spatrick       if (DirLen) // Remove trailing separator.
3653cab2bb3Spatrick         --DirLen;
3663cab2bb3Spatrick     }
3673cab2bb3Spatrick   }
3683cab2bb3Spatrick 
3693cab2bb3Spatrick   if (!LocationLen) { // Relative path.
3703cab2bb3Spatrick     if (!DirLen)
3713cab2bb3Spatrick       return ".";
3723cab2bb3Spatrick     return std::string(".\\").append(FileName, 0, DirLen);
3733cab2bb3Spatrick   }
3743cab2bb3Spatrick 
3753cab2bb3Spatrick   return FileName.substr(0, LocationLen + DirLen);
3763cab2bb3Spatrick }
3773cab2bb3Spatrick 
TmpDir()3783cab2bb3Spatrick std::string TmpDir() {
3793cab2bb3Spatrick   std::string Tmp;
3803cab2bb3Spatrick   Tmp.resize(MAX_PATH + 1);
3813cab2bb3Spatrick   DWORD Size = GetTempPathA(Tmp.size(), &Tmp[0]);
3823cab2bb3Spatrick   if (Size == 0) {
3833cab2bb3Spatrick     Printf("Couldn't get Tmp path.\n");
3843cab2bb3Spatrick     exit(1);
3853cab2bb3Spatrick   }
3863cab2bb3Spatrick   Tmp.resize(Size);
3873cab2bb3Spatrick   return Tmp;
3883cab2bb3Spatrick }
3893cab2bb3Spatrick 
IsInterestingCoverageFile(const std::string & FileName)3903cab2bb3Spatrick bool IsInterestingCoverageFile(const std::string &FileName) {
3913cab2bb3Spatrick   if (FileName.find("Program Files") != std::string::npos)
3923cab2bb3Spatrick     return false;
3933cab2bb3Spatrick   if (FileName.find("compiler-rt\\lib\\") != std::string::npos)
3943cab2bb3Spatrick     return false; // sanitizer internal.
3953cab2bb3Spatrick   if (FileName == "<null>")
3963cab2bb3Spatrick     return false;
3973cab2bb3Spatrick   return true;
3983cab2bb3Spatrick }
3993cab2bb3Spatrick 
RawPrint(const char * Str)4003cab2bb3Spatrick void RawPrint(const char *Str) {
4013cab2bb3Spatrick   _write(2, Str, strlen(Str));
4023cab2bb3Spatrick }
4033cab2bb3Spatrick 
MkDir(const std::string & Path)4043cab2bb3Spatrick void MkDir(const std::string &Path) {
4053cab2bb3Spatrick   if (CreateDirectoryA(Path.c_str(), nullptr)) return;
4063cab2bb3Spatrick   Printf("CreateDirectoryA failed for %s (Error code: %lu).\n", Path.c_str(),
4073cab2bb3Spatrick          GetLastError());
4083cab2bb3Spatrick }
4093cab2bb3Spatrick 
RmDir(const std::string & Path)4103cab2bb3Spatrick void RmDir(const std::string &Path) {
4113cab2bb3Spatrick   if (RemoveDirectoryA(Path.c_str())) return;
4123cab2bb3Spatrick   Printf("RemoveDirectoryA failed for %s (Error code: %lu).\n", Path.c_str(),
4133cab2bb3Spatrick          GetLastError());
4143cab2bb3Spatrick }
4153cab2bb3Spatrick 
getDevNull()4163cab2bb3Spatrick const std::string &getDevNull() {
4173cab2bb3Spatrick   static const std::string devNull = "NUL";
4183cab2bb3Spatrick   return devNull;
4193cab2bb3Spatrick }
4203cab2bb3Spatrick 
4213cab2bb3Spatrick }  // namespace fuzzer
4223cab2bb3Spatrick 
4233cab2bb3Spatrick #endif // LIBFUZZER_WINDOWS
424