aboutsummaryrefslogtreecommitdiff
path: root/lib/Support/Windows/Path.inc
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
commitd8e91e46262bc44006913e6796843909f1ac7bcd (patch)
tree7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/Support/Windows/Path.inc
parentb7eb8e35e481a74962664b63dfb09483b200209a (diff)
downloadsrc-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.inc130
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);
}