diff options
author | Stephen Hines <srhines@google.com> | 2014-12-01 14:51:49 -0800 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-12-02 16:08:10 -0800 |
commit | 37ed9c199ca639565f6ce88105f9e39e898d82d0 (patch) | |
tree | 8fb36d3910e3ee4c4e1b7422f4f017108efc52f5 /lib/Support/Windows/Path.inc | |
parent | d2327b22152ced7bc46dc629fc908959e8a52d03 (diff) | |
download | external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.zip external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.tar.gz external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.tar.bz2 |
Update aosp/master LLVM for rebase to r222494.
Change-Id: Ic787f5e0124df789bd26f3f24680f45e678eef2d
Diffstat (limited to 'lib/Support/Windows/Path.inc')
-rw-r--r-- | lib/Support/Windows/Path.inc | 231 |
1 files changed, 137 insertions, 94 deletions
diff --git a/lib/Support/Windows/Path.inc b/lib/Support/Windows/Path.inc index 7a1bc04..365031c 100644 --- a/lib/Support/Windows/Path.inc +++ b/lib/Support/Windows/Path.inc @@ -49,23 +49,6 @@ static std::error_code windows_error(DWORD E) { return mapWindowsError(E); } -static std::error_code TempDir(SmallVectorImpl<char> &Result) { - SmallVector<wchar_t, 64> Res; -retry_temp_dir: - DWORD Len = ::GetTempPathW(Res.capacity(), Res.begin()); - - if (Len == 0) - return windows_error(::GetLastError()); - - if (Len > Res.capacity()) { - Res.reserve(Len); - goto retry_temp_dir; - } - - Res.set_size(Len); - return UTF16ToUTF8(Res.begin(), Res.size(), Result); -} - static bool is_separator(const wchar_t value) { switch (value) { case L'\\': @@ -76,6 +59,59 @@ static bool is_separator(const wchar_t value) { } } +// Convert a UTF-8 path to UTF-16. Also, if the absolute equivalent of the +// path is longer than CreateDirectory can tolerate, make it absolute and +// prefixed by '\\?\'. +static std::error_code widenPath(const Twine &Path8, + SmallVectorImpl<wchar_t> &Path16) { + const size_t MaxDirLen = MAX_PATH - 12; // Must leave room for 8.3 filename. + + // Several operations would convert Path8 to SmallString; more efficient to + // do it once up front. + SmallString<128> Path8Str; + Path8.toVector(Path8Str); + + // If we made this path absolute, how much longer would it get? + size_t CurPathLen; + if (llvm::sys::path::is_absolute(Twine(Path8Str))) + CurPathLen = 0; // No contribution from current_path needed. + else { + CurPathLen = ::GetCurrentDirectoryW(0, NULL); + if (CurPathLen == 0) + return windows_error(::GetLastError()); + } + + // Would the absolute path be longer than our limit? + if ((Path8Str.size() + CurPathLen) >= MaxDirLen && + !Path8Str.startswith("\\\\?\\")) { + SmallString<2*MAX_PATH> FullPath("\\\\?\\"); + if (CurPathLen) { + SmallString<80> CurPath; + if (std::error_code EC = llvm::sys::fs::current_path(CurPath)) + return EC; + FullPath.append(CurPath); + } + // Traverse the requested path, canonicalizing . and .. as we go (because + // the \\?\ prefix is documented to treat them as real components). + // The iterators don't report separators and append() always attaches + // preferred_separator so we don't need to call native() on the result. + for (llvm::sys::path::const_iterator I = llvm::sys::path::begin(Path8Str), + E = llvm::sys::path::end(Path8Str); + I != E; ++I) { + if (I->size() == 1 && *I == ".") + continue; + if (I->size() == 2 && *I == "..") + llvm::sys::path::remove_filename(FullPath); + else + llvm::sys::path::append(FullPath, *I); + } + return UTF8ToUTF16(FullPath, Path16); + } + + // Just use the caller's original path. + return UTF8ToUTF16(Path8Str, Path16); +} + namespace llvm { namespace sys { namespace fs { @@ -147,11 +183,9 @@ std::error_code current_path(SmallVectorImpl<char> &result) { } std::error_code create_directory(const Twine &path, bool IgnoreExisting) { - SmallString<128> path_storage; SmallVector<wchar_t, 128> path_utf16; - if (std::error_code ec = - UTF8ToUTF16(path.toStringRef(path_storage), path_utf16)) + if (std::error_code ec = widenPath(path, path_utf16)) return ec; if (!::CreateDirectoryW(path_utf16.begin(), NULL)) { @@ -163,25 +197,14 @@ std::error_code create_directory(const Twine &path, bool IgnoreExisting) { return std::error_code(); } -std::error_code normalize_separators(SmallVectorImpl<char> &Path) { - (void) Path; - return std::error_code(); -} - // We can't use symbolic links for windows. std::error_code create_link(const Twine &to, const Twine &from) { - // Get arguments. - SmallString<128> from_storage; - SmallString<128> to_storage; - StringRef f = from.toStringRef(from_storage); - StringRef t = to.toStringRef(to_storage); - // Convert to utf-16. SmallVector<wchar_t, 128> wide_from; SmallVector<wchar_t, 128> wide_to; - if (std::error_code ec = UTF8ToUTF16(f, wide_from)) + if (std::error_code ec = widenPath(from, wide_from)) return ec; - if (std::error_code ec = UTF8ToUTF16(t, wide_to)) + if (std::error_code ec = widenPath(to, wide_to)) return ec; if (!::CreateHardLinkW(wide_from.begin(), wide_to.begin(), NULL)) @@ -191,7 +214,6 @@ std::error_code create_link(const Twine &to, const Twine &from) { } std::error_code remove(const Twine &path, bool IgnoreNonExisting) { - SmallString<128> path_storage; SmallVector<wchar_t, 128> path_utf16; file_status ST; @@ -201,8 +223,7 @@ std::error_code remove(const Twine &path, bool IgnoreNonExisting) { return std::error_code(); } - if (std::error_code ec = - UTF8ToUTF16(path.toStringRef(path_storage), path_utf16)) + if (std::error_code ec = widenPath(path, path_utf16)) return ec; if (ST.type() == file_type::directory_file) { @@ -222,18 +243,12 @@ std::error_code remove(const Twine &path, bool IgnoreNonExisting) { } std::error_code rename(const Twine &from, const Twine &to) { - // Get arguments. - SmallString<128> from_storage; - SmallString<128> to_storage; - StringRef f = from.toStringRef(from_storage); - StringRef t = to.toStringRef(to_storage); - // Convert to utf-16. SmallVector<wchar_t, 128> wide_from; SmallVector<wchar_t, 128> wide_to; - if (std::error_code ec = UTF8ToUTF16(f, wide_from)) + if (std::error_code ec = widenPath(from, wide_from)) return ec; - if (std::error_code ec = UTF8ToUTF16(t, wide_to)) + if (std::error_code ec = widenPath(to, wide_to)) return ec; std::error_code ec = std::error_code(); @@ -254,11 +269,9 @@ std::error_code rename(const Twine &from, const Twine &to) { } std::error_code resize_file(const Twine &path, uint64_t size) { - SmallString<128> path_storage; SmallVector<wchar_t, 128> path_utf16; - if (std::error_code ec = - UTF8ToUTF16(path.toStringRef(path_storage), path_utf16)) + if (std::error_code ec = widenPath(path, path_utf16)) return ec; int fd = ::_wopen(path_utf16.begin(), O_BINARY | _O_RDWR, S_IWRITE); @@ -273,49 +286,27 @@ std::error_code resize_file(const Twine &path, uint64_t size) { return std::error_code(error, std::generic_category()); } -std::error_code exists(const Twine &path, bool &result) { - SmallString<128> path_storage; - SmallVector<wchar_t, 128> path_utf16; +std::error_code access(const Twine &Path, AccessMode Mode) { + SmallVector<wchar_t, 128> PathUtf16; - if (std::error_code ec = - UTF8ToUTF16(path.toStringRef(path_storage), path_utf16)) - return ec; + if (std::error_code EC = widenPath(Path, PathUtf16)) + return EC; - DWORD attributes = ::GetFileAttributesW(path_utf16.begin()); + DWORD Attributes = ::GetFileAttributesW(PathUtf16.begin()); - if (attributes == INVALID_FILE_ATTRIBUTES) { + if (Attributes == INVALID_FILE_ATTRIBUTES) { // See if the file didn't actually exist. DWORD LastError = ::GetLastError(); if (LastError != ERROR_FILE_NOT_FOUND && LastError != ERROR_PATH_NOT_FOUND) return windows_error(LastError); - result = false; - } else - result = true; - return std::error_code(); -} - -bool can_write(const Twine &Path) { - // FIXME: take security attributes into account. - SmallString<128> PathStorage; - SmallVector<wchar_t, 128> PathUtf16; - - if (UTF8ToUTF16(Path.toStringRef(PathStorage), PathUtf16)) - return false; - - DWORD Attr = ::GetFileAttributesW(PathUtf16.begin()); - return (Attr != INVALID_FILE_ATTRIBUTES) && !(Attr & FILE_ATTRIBUTE_READONLY); -} + return errc::no_such_file_or_directory; + } -bool can_execute(const Twine &Path) { - SmallString<128> PathStorage; - SmallVector<wchar_t, 128> PathUtf16; + if (Mode == AccessMode::Write && (Attributes & FILE_ATTRIBUTE_READONLY)) + return errc::permission_denied; - if (UTF8ToUTF16(Path.toStringRef(PathStorage), PathUtf16)) - return false; - - DWORD Attr = ::GetFileAttributesW(PathUtf16.begin()); - return Attr != INVALID_FILE_ATTRIBUTES; + return std::error_code(); } bool equivalent(file_status A, file_status B) { @@ -424,7 +415,7 @@ std::error_code status(const Twine &path, file_status &result) { return std::error_code(); } - if (std::error_code ec = UTF8ToUTF16(path8, path_utf16)) + if (std::error_code ec = widenPath(path8, path_utf16)) return ec; DWORD attr = ::GetFileAttributesW(path_utf16.begin()); @@ -567,11 +558,10 @@ mapped_file_region::mapped_file_region(const Twine &path, , FileDescriptor() , FileHandle(INVALID_HANDLE_VALUE) , FileMappingHandle() { - SmallString<128> path_storage; SmallVector<wchar_t, 128> path_utf16; // Convert path to UTF-16. - if ((ec = UTF8ToUTF16(path.toStringRef(path_storage), path_utf16))) + if ((ec = widenPath(path, path_utf16))) return; // Get file handle for creating a file mapping. @@ -677,7 +667,7 @@ std::error_code detail::directory_iterator_construct(detail::DirIterState &it, StringRef path){ SmallVector<wchar_t, 128> path_utf16; - if (std::error_code ec = UTF8ToUTF16(path, path_utf16)) + if (std::error_code ec = widenPath(path, path_utf16)) return ec; // Convert path to the format that Windows is happy with. @@ -760,11 +750,9 @@ std::error_code detail::directory_iterator_increment(detail::DirIterState &it) { } std::error_code openFileForRead(const Twine &Name, int &ResultFD) { - SmallString<128> PathStorage; SmallVector<wchar_t, 128> PathUTF16; - if (std::error_code EC = - UTF8ToUTF16(Name.toStringRef(PathStorage), PathUTF16)) + if (std::error_code EC = widenPath(Name, PathUTF16)) return EC; HANDLE H = ::CreateFileW(PathUTF16.begin(), GENERIC_READ, @@ -799,11 +787,9 @@ std::error_code openFileForWrite(const Twine &Name, int &ResultFD, assert((!(Flags & sys::fs::F_Excl) || !(Flags & sys::fs::F_Append)) && "Cannot specify both 'excl' and 'append' file creation flags!"); - SmallString<128> PathStorage; SmallVector<wchar_t, 128> PathUTF16; - if (std::error_code EC = - UTF8ToUTF16(Name.toStringRef(PathStorage), PathUTF16)) + if (std::error_code EC = widenPath(Name, PathUTF16)) return EC; DWORD CreationDisposition; @@ -867,6 +853,51 @@ bool home_directory(SmallVectorImpl<char> &result) { return true; } +static bool getTempDirEnvVar(const char *Var, SmallVectorImpl<char> &Res) { + SmallVector<wchar_t, 128> NameUTF16; + if (windows::UTF8ToUTF16(Var, NameUTF16)) + return false; + + SmallVector<wchar_t, 1024> Buf; + size_t Size = 1024; + do { + Buf.reserve(Size); + Size = + GetEnvironmentVariableW(NameUTF16.data(), Buf.data(), Buf.capacity()); + if (Size == 0) + return false; + + // Try again with larger buffer. + } while (Size > Buf.capacity()); + Buf.set_size(Size); + + if (windows::UTF16ToUTF8(Buf.data(), Size, Res)) + return false; + return true; +} + +static bool getTempDirEnvVar(SmallVectorImpl<char> &Res) { + const char *EnvironmentVariables[] = {"TMP", "TEMP", "USERPROFILE"}; + for (const char *Env : EnvironmentVariables) { + if (getTempDirEnvVar(Env, Res)) + return true; + } + return false; +} + +void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) { + (void)ErasedOnReboot; + Result.clear(); + + // Check whether the temporary directory is specified by an environment + // variable. + if (getTempDirEnvVar(Result)) + return; + + // Fall back to a system default. + const char *DefaultResult = "C:\\TEMP"; + Result.append(DefaultResult, DefaultResult + strlen(DefaultResult)); +} } // end namespace path namespace windows { @@ -896,11 +927,13 @@ std::error_code UTF8ToUTF16(llvm::StringRef utf8, return std::error_code(); } -std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, - llvm::SmallVectorImpl<char> &utf8) { +static +std::error_code UTF16ToCodePage(unsigned codepage, const wchar_t *utf16, + size_t utf16_len, + llvm::SmallVectorImpl<char> &utf8) { if (utf16_len) { // Get length. - int len = ::WideCharToMultiByte(CP_UTF8, 0, utf16, utf16_len, utf8.begin(), + int len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, utf8.begin(), 0, NULL, NULL); if (len == 0) @@ -910,7 +943,7 @@ std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, utf8.set_size(len); // Now do the actual conversion. - len = ::WideCharToMultiByte(CP_UTF8, 0, utf16, utf16_len, utf8.data(), + len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, utf8.data(), utf8.size(), NULL, NULL); if (len == 0) @@ -923,6 +956,16 @@ std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, return std::error_code(); } + +std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, + llvm::SmallVectorImpl<char> &utf8) { + return UTF16ToCodePage(CP_UTF8, utf16, utf16_len, utf8); +} + +std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len, + llvm::SmallVectorImpl<char> &utf8) { + return UTF16ToCodePage(CP_ACP, utf16, utf16_len, utf8); +} } // end namespace windows } // end namespace sys } // end namespace llvm |