diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
commit | d8e91e46262bc44006913e6796843909f1ac7bcd (patch) | |
tree | 7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/Support/Windows/Path.inc | |
parent | b7eb8e35e481a74962664b63dfb09483b200209a (diff) | |
download | src-d8e91e46262bc44006913e6796843909f1ac7bcd.tar.gz src-d8e91e46262bc44006913e6796843909f1ac7bcd.zip |
Vendor import of llvm trunk r351319 (just before the release_80 branchvendor/llvm/llvm-trunk-r351319
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=343171
svn path=/vendor/llvm/llvm-trunk-r351319/; revision=343172; tag=vendor/llvm/llvm-trunk-r351319
Diffstat (limited to 'lib/Support/Windows/Path.inc')
-rw-r--r-- | lib/Support/Windows/Path.inc | 130 |
1 files changed, 82 insertions, 48 deletions
diff --git a/lib/Support/Windows/Path.inc b/lib/Support/Windows/Path.inc index b64b013d7407..d34aa763124c 100644 --- a/lib/Support/Windows/Path.inc +++ b/lib/Support/Windows/Path.inc @@ -416,7 +416,7 @@ static std::error_code rename_internal(HANDLE FromHandle, const Twine &To, *reinterpret_cast<FILE_RENAME_INFO *>(RenameInfoBuf.data()); RenameInfo.ReplaceIfExists = ReplaceIfExists; RenameInfo.RootDirectory = 0; - RenameInfo.FileNameLength = ToWide.size(); + RenameInfo.FileNameLength = ToWide.size() * sizeof(wchar_t); std::copy(ToWide.begin(), ToWide.end(), &RenameInfo.FileName[0]); SetLastError(ERROR_SUCCESS); @@ -450,7 +450,7 @@ static std::error_code rename_handle(HANDLE FromHandle, const Twine &To) { if (std::error_code EC2 = realPathFromHandle(FromHandle, WideFrom)) return EC2; if (::MoveFileExW(WideFrom.begin(), WideTo.begin(), - MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED)) + MOVEFILE_REPLACE_EXISTING)) return std::error_code(); return mapWindowsError(GetLastError()); } @@ -766,10 +766,12 @@ std::error_code setPermissions(const Twine &Path, perms Permissions) { return std::error_code(); } -std::error_code setLastModificationAndAccessTime(int FD, TimePoint<> Time) { - FILETIME FT = toFILETIME(Time); +std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime, + TimePoint<> ModificationTime) { + FILETIME AccessFT = toFILETIME(AccessTime); + FILETIME ModifyFT = toFILETIME(ModificationTime); HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD)); - if (!SetFileTime(FileHandle, NULL, &FT, &FT)) + if (!SetFileTime(FileHandle, NULL, &AccessFT, &ModifyFT)) return mapWindowsError(::GetLastError()); return std::error_code(); } @@ -852,16 +854,37 @@ mapped_file_region::mapped_file_region(int fd, mapmode mode, size_t length, Mapping = 0; } +static bool hasFlushBufferKernelBug() { + static bool Ret{GetWindowsOSVersion() < llvm::VersionTuple(10, 0, 0, 17763)}; + return Ret; +} + +static bool isEXE(StringRef Magic) { + static const char PEMagic[] = {'P', 'E', '\0', '\0'}; + if (Magic.startswith(StringRef("MZ")) && Magic.size() >= 0x3c + 4) { + uint32_t off = read32le(Magic.data() + 0x3c); + // PE/COFF file, either EXE or DLL. + if (Magic.substr(off).startswith(StringRef(PEMagic, sizeof(PEMagic)))) + return true; + } + return false; +} + mapped_file_region::~mapped_file_region() { if (Mapping) { + + bool Exe = isEXE(StringRef((char *)Mapping, Size)); + ::UnmapViewOfFile(Mapping); - if (Mode == mapmode::readwrite) { + if (Mode == mapmode::readwrite && Exe && hasFlushBufferKernelBug()) { // There is a Windows kernel bug, the exact trigger conditions of which // are not well understood. When triggered, dirty pages are not properly // flushed and subsequent process's attempts to read a file can return // invalid data. Calling FlushFileBuffers on the write handle is // sufficient to ensure that this bug is not triggered. + // The bug only occurs when writing an executable and executing it right + // after, under high I/O pressure. ::FlushFileBuffers(FileHandle); } @@ -900,28 +923,28 @@ static basic_file_status status_from_find_data(WIN32_FIND_DATAW *FindData) { FindData->nFileSizeHigh, FindData->nFileSizeLow); } -std::error_code detail::directory_iterator_construct(detail::DirIterState &it, - StringRef path, - bool follow_symlinks) { - SmallVector<wchar_t, 128> path_utf16; +std::error_code detail::directory_iterator_construct(detail::DirIterState &IT, + StringRef Path, + bool FollowSymlinks) { + SmallVector<wchar_t, 128> PathUTF16; - if (std::error_code ec = widenPath(path, path_utf16)) - return ec; + if (std::error_code EC = widenPath(Path, PathUTF16)) + return EC; // Convert path to the format that Windows is happy with. - if (path_utf16.size() > 0 && - !is_separator(path_utf16[path.size() - 1]) && - path_utf16[path.size() - 1] != L':') { - path_utf16.push_back(L'\\'); - path_utf16.push_back(L'*'); + if (PathUTF16.size() > 0 && + !is_separator(PathUTF16[Path.size() - 1]) && + PathUTF16[Path.size() - 1] != L':') { + PathUTF16.push_back(L'\\'); + PathUTF16.push_back(L'*'); } else { - path_utf16.push_back(L'*'); + PathUTF16.push_back(L'*'); } // Get the first directory entry. WIN32_FIND_DATAW FirstFind; ScopedFindHandle FindHandle(::FindFirstFileExW( - c_str(path_utf16), FindExInfoBasic, &FirstFind, FindExSearchNameMatch, + c_str(PathUTF16), FindExInfoBasic, &FirstFind, FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH)); if (!FindHandle) return mapWindowsError(::GetLastError()); @@ -934,43 +957,45 @@ std::error_code detail::directory_iterator_construct(detail::DirIterState &it, DWORD LastError = ::GetLastError(); // Check for end. if (LastError == ERROR_NO_MORE_FILES) - return detail::directory_iterator_destruct(it); + return detail::directory_iterator_destruct(IT); return mapWindowsError(LastError); } else FilenameLen = ::wcslen(FirstFind.cFileName); // Construct the current directory entry. - SmallString<128> directory_entry_name_utf8; - if (std::error_code ec = + SmallString<128> DirectoryEntryNameUTF8; + if (std::error_code EC = UTF16ToUTF8(FirstFind.cFileName, ::wcslen(FirstFind.cFileName), - directory_entry_name_utf8)) - return ec; + DirectoryEntryNameUTF8)) + return EC; - it.IterationHandle = intptr_t(FindHandle.take()); - SmallString<128> directory_entry_path(path); - path::append(directory_entry_path, directory_entry_name_utf8); - it.CurrentEntry = directory_entry(directory_entry_path, follow_symlinks, - status_from_find_data(&FirstFind)); + IT.IterationHandle = intptr_t(FindHandle.take()); + SmallString<128> DirectoryEntryPath(Path); + path::append(DirectoryEntryPath, DirectoryEntryNameUTF8); + IT.CurrentEntry = + directory_entry(DirectoryEntryPath, FollowSymlinks, + file_type_from_attrs(FirstFind.dwFileAttributes), + status_from_find_data(&FirstFind)); return std::error_code(); } -std::error_code detail::directory_iterator_destruct(detail::DirIterState &it) { - if (it.IterationHandle != 0) +std::error_code detail::directory_iterator_destruct(detail::DirIterState &IT) { + if (IT.IterationHandle != 0) // Closes the handle if it's valid. - ScopedFindHandle close(HANDLE(it.IterationHandle)); - it.IterationHandle = 0; - it.CurrentEntry = directory_entry(); + ScopedFindHandle close(HANDLE(IT.IterationHandle)); + IT.IterationHandle = 0; + IT.CurrentEntry = directory_entry(); return std::error_code(); } -std::error_code detail::directory_iterator_increment(detail::DirIterState &it) { +std::error_code detail::directory_iterator_increment(detail::DirIterState &IT) { WIN32_FIND_DATAW FindData; - if (!::FindNextFileW(HANDLE(it.IterationHandle), &FindData)) { + if (!::FindNextFileW(HANDLE(IT.IterationHandle), &FindData)) { DWORD LastError = ::GetLastError(); // Check for end. if (LastError == ERROR_NO_MORE_FILES) - return detail::directory_iterator_destruct(it); + return detail::directory_iterator_destruct(IT); return mapWindowsError(LastError); } @@ -978,16 +1003,18 @@ std::error_code detail::directory_iterator_increment(detail::DirIterState &it) { if ((FilenameLen == 1 && FindData.cFileName[0] == L'.') || (FilenameLen == 2 && FindData.cFileName[0] == L'.' && FindData.cFileName[1] == L'.')) - return directory_iterator_increment(it); + return directory_iterator_increment(IT); - SmallString<128> directory_entry_path_utf8; - if (std::error_code ec = + SmallString<128> DirectoryEntryPathUTF8; + if (std::error_code EC = UTF16ToUTF8(FindData.cFileName, ::wcslen(FindData.cFileName), - directory_entry_path_utf8)) - return ec; + DirectoryEntryPathUTF8)) + return EC; - it.CurrentEntry.replace_filename(Twine(directory_entry_path_utf8), - status_from_find_data(&FindData)); + IT.CurrentEntry.replace_filename( + Twine(DirectoryEntryPathUTF8), + file_type_from_attrs(FindData.dwFileAttributes), + status_from_find_data(&FindData)); return std::error_code(); } @@ -1226,6 +1253,17 @@ static void expandTildeExpr(SmallVectorImpl<char> &Path) { Path.insert(Path.begin() + 1, HomeDir.begin() + 1, HomeDir.end()); } +void expand_tilde(const Twine &path, SmallVectorImpl<char> &dest) { + dest.clear(); + if (path.isTriviallyEmpty()) + return; + + path.toVector(dest); + expandTildeExpr(dest); + + return; +} + std::error_code real_path(const Twine &path, SmallVectorImpl<char> &dest, bool expand_tilde) { dest.clear(); @@ -1264,10 +1302,6 @@ static bool getKnownFolderPath(KNOWNFOLDERID folderId, return ok; } -bool getUserCacheDir(SmallVectorImpl<char> &Result) { - return getKnownFolderPath(FOLDERID_LocalAppData, Result); -} - bool home_directory(SmallVectorImpl<char> &result) { return getKnownFolderPath(FOLDERID_Profile, result); } |