diff options
author | Stephen Hines <srhines@google.com> | 2014-04-23 16:57:46 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-04-24 15:53:16 -0700 |
commit | 36b56886974eae4f9c5ebc96befd3e7bfe5de338 (patch) | |
tree | e6cfb69fbbd937f450eeb83bfb83b9da3b01275a /lib/Support/Windows/Path.inc | |
parent | 69a8640022b04415ae9fac62f8ab090601d8f889 (diff) | |
download | external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.zip external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.gz external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.bz2 |
Update to LLVM 3.5a.
Change-Id: Ifadecab779f128e62e430c2b4f6ddd84953ed617
Diffstat (limited to 'lib/Support/Windows/Path.inc')
-rw-r--r-- | lib/Support/Windows/Path.inc | 355 |
1 files changed, 101 insertions, 254 deletions
diff --git a/lib/Support/Windows/Path.inc b/lib/Support/Windows/Path.inc index 0b39198..e59888e 100644 --- a/lib/Support/Windows/Path.inc +++ b/lib/Support/Windows/Path.inc @@ -17,12 +17,16 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/STLExtras.h" -#include "Windows.h" #include <fcntl.h> #include <io.h> #include <sys/stat.h> #include <sys/types.h> +// These two headers must be included last, and make sure shlobj is required +// after Windows.h to make sure it picks up our definition of _WIN32_WINNT +#include "WindowsSupport.h" +#include <shlobj.h> + #undef max // MinGW doesn't define this. @@ -40,175 +44,31 @@ using namespace llvm; using llvm::sys::windows::UTF8ToUTF16; using llvm::sys::windows::UTF16ToUTF8; -namespace { - typedef BOOLEAN (WINAPI *PtrCreateSymbolicLinkW)( - /*__in*/ LPCWSTR lpSymlinkFileName, - /*__in*/ LPCWSTR lpTargetFileName, - /*__in*/ DWORD dwFlags); - - PtrCreateSymbolicLinkW create_symbolic_link_api = - PtrCreateSymbolicLinkW(::GetProcAddress( - ::GetModuleHandleW(L"Kernel32.dll"), "CreateSymbolicLinkW")); - - error_code TempDir(SmallVectorImpl<wchar_t> &result) { - retry_temp_dir: - DWORD len = ::GetTempPathW(result.capacity(), result.begin()); - - if (len == 0) - return windows_error(::GetLastError()); - - if (len > result.capacity()) { - result.reserve(len); - goto retry_temp_dir; - } - - result.set_size(len); - return error_code::success(); - } +static error_code TempDir(SmallVectorImpl<char> &Result) { + SmallVector<wchar_t, 64> Res; +retry_temp_dir: + DWORD Len = ::GetTempPathW(Res.capacity(), Res.begin()); - bool is_separator(const wchar_t value) { - switch (value) { - case L'\\': - case L'/': - return true; - default: - return false; - } - } -} - -// FIXME: mode should be used here and default to user r/w only, -// it currently comes in as a UNIX mode. -static error_code createUniqueEntity(const Twine &model, int &result_fd, - SmallVectorImpl<char> &result_path, - bool makeAbsolute, unsigned mode, - FSEntity Type) { - // Use result_path as temp storage. - result_path.set_size(0); - StringRef m = model.toStringRef(result_path); - - SmallVector<wchar_t, 128> model_utf16; - if (error_code ec = UTF8ToUTF16(m, model_utf16)) return ec; - - if (makeAbsolute) { - // Make model absolute by prepending a temp directory if it's not already. - bool absolute = sys::path::is_absolute(m); - - if (!absolute) { - SmallVector<wchar_t, 64> temp_dir; - if (error_code ec = TempDir(temp_dir)) return ec; - // Handle c: by removing it. - if (model_utf16.size() > 2 && model_utf16[1] == L':') { - model_utf16.erase(model_utf16.begin(), model_utf16.begin() + 2); - } - model_utf16.insert(model_utf16.begin(), temp_dir.begin(), temp_dir.end()); - } - } - - // Replace '%' with random chars. From here on, DO NOT modify model. It may be - // needed if the randomly chosen path already exists. - SmallVector<wchar_t, 128> random_path_utf16; - - // Get a Crypto Provider for CryptGenRandom. - HCRYPTPROV HCPC; - if (!::CryptAcquireContextW(&HCPC, - NULL, - NULL, - PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT)) + if (Len == 0) return windows_error(::GetLastError()); - ScopedCryptContext CryptoProvider(HCPC); - -retry_random_path: - random_path_utf16.set_size(0); - for (SmallVectorImpl<wchar_t>::const_iterator i = model_utf16.begin(), - e = model_utf16.end(); - i != e; ++i) { - if (*i == L'%') { - BYTE val = 0; - if (!::CryptGenRandom(CryptoProvider, 1, &val)) - return windows_error(::GetLastError()); - random_path_utf16.push_back(L"0123456789abcdef"[val & 15]); - } - else - random_path_utf16.push_back(*i); - } - // Make random_path_utf16 null terminated. - random_path_utf16.push_back(0); - random_path_utf16.pop_back(); - - HANDLE TempFileHandle = INVALID_HANDLE_VALUE; - - switch (Type) { - case FS_File: { - // Try to create + open the path. - TempFileHandle = - ::CreateFileW(random_path_utf16.begin(), GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ, NULL, - // Return ERROR_FILE_EXISTS if the file - // already exists. - CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY, NULL); - if (TempFileHandle == INVALID_HANDLE_VALUE) { - // If the file existed, try again, otherwise, error. - error_code ec = windows_error(::GetLastError()); - if (ec == windows_error::file_exists) - goto retry_random_path; - - return ec; - } - - // Convert the Windows API file handle into a C-runtime handle. - int fd = ::_open_osfhandle(intptr_t(TempFileHandle), 0); - if (fd == -1) { - ::CloseHandle(TempFileHandle); - ::DeleteFileW(random_path_utf16.begin()); - // MSDN doesn't say anything about _open_osfhandle setting errno or - // GetLastError(), so just return invalid_handle. - return windows_error::invalid_handle; - } - result_fd = fd; - break; - } - - case FS_Name: { - DWORD attributes = ::GetFileAttributesW(random_path_utf16.begin()); - if (attributes != INVALID_FILE_ATTRIBUTES) - goto retry_random_path; - error_code EC = make_error_code(windows_error(::GetLastError())); - if (EC != windows_error::file_not_found && - EC != windows_error::path_not_found) - return EC; - break; + if (Len > Res.capacity()) { + Res.reserve(Len); + goto retry_temp_dir; } - case FS_Dir: - if (!::CreateDirectoryW(random_path_utf16.begin(), NULL)) { - error_code EC = windows_error(::GetLastError()); - if (EC != windows_error::already_exists) - return EC; - goto retry_random_path; - } - break; - } + Res.set_size(Len); + return UTF16ToUTF8(Res.begin(), Res.size(), Result); +} - // Set result_path to the utf-8 representation of the path. - if (error_code ec = UTF16ToUTF8(random_path_utf16.begin(), - random_path_utf16.size(), result_path)) { - switch (Type) { - case FS_File: - ::CloseHandle(TempFileHandle); - ::DeleteFileW(random_path_utf16.begin()); - case FS_Name: - break; - case FS_Dir: - ::RemoveDirectoryW(random_path_utf16.begin()); - break; - } - return ec; +static bool is_separator(const wchar_t value) { + switch (value) { + case L'\\': + case L'/': + return true; + default: + return false; } - - return error_code::success(); } namespace llvm { @@ -281,7 +141,7 @@ error_code current_path(SmallVectorImpl<char> &result) { return UTF16ToUTF8(cur_path.begin(), cur_path.size(), result); } -error_code create_directory(const Twine &path, bool &existed) { +error_code create_directory(const Twine &path, bool IgnoreExisting) { SmallString<128> path_storage; SmallVector<wchar_t, 128> path_utf16; @@ -291,40 +151,20 @@ error_code create_directory(const Twine &path, bool &existed) { if (!::CreateDirectoryW(path_utf16.begin(), NULL)) { error_code ec = windows_error(::GetLastError()); - if (ec == windows_error::already_exists) - existed = true; - else + if (ec != windows_error::already_exists || !IgnoreExisting) return ec; - } else - existed = false; + } return error_code::success(); } -error_code create_hard_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 (error_code ec = UTF8ToUTF16(f, wide_from)) return ec; - if (error_code ec = UTF8ToUTF16(t, wide_to)) return ec; - - if (!::CreateHardLinkW(wide_from.begin(), wide_to.begin(), NULL)) - return windows_error(::GetLastError()); - +error_code normalize_separators(SmallVectorImpl<char> &Path) { + (void) Path; return error_code::success(); } -error_code create_symlink(const Twine &to, const Twine &from) { - // Only do it if the function is available at runtime. - if (!create_symbolic_link_api) - return make_error_code(errc::function_not_supported); - +// We can't use symbolic links for windows. +error_code create_link(const Twine &to, const Twine &from) { // Get arguments. SmallString<128> from_storage; SmallString<128> to_storage; @@ -337,49 +177,40 @@ error_code create_symlink(const Twine &to, const Twine &from) { if (error_code ec = UTF8ToUTF16(f, wide_from)) return ec; if (error_code ec = UTF8ToUTF16(t, wide_to)) return ec; - if (!create_symbolic_link_api(wide_from.begin(), wide_to.begin(), 0)) + if (!::CreateHardLinkW(wide_from.begin(), wide_to.begin(), NULL)) return windows_error(::GetLastError()); return error_code::success(); } -error_code remove(const Twine &path, bool &existed) { +error_code remove(const Twine &path, bool IgnoreNonExisting) { SmallString<128> path_storage; SmallVector<wchar_t, 128> path_utf16; - file_status st; - error_code EC = status(path, st); - if (EC) { - if (EC == windows_error::file_not_found || - EC == windows_error::path_not_found) { - existed = false; - return error_code::success(); - } - return EC; + file_status ST; + if (error_code EC = status(path, ST)) { + if (EC != errc::no_such_file_or_directory || !IgnoreNonExisting) + return EC; + return error_code::success(); } if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage), path_utf16)) return ec; - if (st.type() == file_type::directory_file) { + if (ST.type() == file_type::directory_file) { if (!::RemoveDirectoryW(c_str(path_utf16))) { - error_code ec = windows_error(::GetLastError()); - if (ec != windows_error::file_not_found) - return ec; - existed = false; - } else - existed = true; - } else { - if (!::DeleteFileW(c_str(path_utf16))) { - error_code ec = windows_error(::GetLastError()); - if (ec != windows_error::file_not_found) - return ec; - existed = false; - } else - existed = true; + error_code EC = windows_error(::GetLastError()); + if (EC != errc::no_such_file_or_directory || !IgnoreNonExisting) + return EC; + } + return error_code::success(); + } + if (!::DeleteFileW(c_str(path_utf16))) { + error_code EC = windows_error(::GetLastError()); + if (EC != errc::no_such_file_or_directory || !IgnoreNonExisting) + return EC; } - return error_code::success(); } @@ -834,7 +665,6 @@ mapped_file_region::~mapped_file_region() { ::UnmapViewOfFile(Mapping); } -#if LLVM_HAS_RVALUE_REFERENCES mapped_file_region::mapped_file_region(mapped_file_region &&other) : Mode(other.Mode) , Size(other.Size) @@ -846,7 +676,6 @@ mapped_file_region::mapped_file_region(mapped_file_region &&other) other.FileHandle = INVALID_HANDLE_VALUE; other.FileDescriptor = 0; } -#endif mapped_file_region::mapmode mapped_file_region::flags() const { assert(Mapping && "Mapping failed but used anyway!"); @@ -859,7 +688,7 @@ uint64_t mapped_file_region::size() const { } char *mapped_file_region::data() const { - assert(Mode != readonly && "Cannot get non const data for readonly mapping!"); + assert(Mode != readonly && "Cannot get non-const data for readonly mapping!"); assert(Mapping && "Mapping failed but used anyway!"); return reinterpret_cast<char*>(Mapping); } @@ -1027,7 +856,11 @@ error_code openFileForWrite(const Twine &Name, int &ResultFD, else CreationDisposition = CREATE_ALWAYS; - HANDLE H = ::CreateFileW(PathUTF16.begin(), GENERIC_WRITE, + DWORD Access = GENERIC_WRITE; + if (Flags & F_RW) + Access |= GENERIC_READ; + + HANDLE H = ::CreateFileW(PathUTF16.begin(), Access, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL); @@ -1047,7 +880,7 @@ error_code openFileForWrite(const Twine &Name, int &ResultFD, if (Flags & F_Append) OpenFlags |= _O_APPEND; - if (!(Flags & F_Binary)) + if (Flags & F_Text) OpenFlags |= _O_TEXT; int FD = ::_open_osfhandle(intptr_t(H), OpenFlags); @@ -1061,25 +894,41 @@ error_code openFileForWrite(const Twine &Name, int &ResultFD, } } // end namespace fs +namespace path { + +bool home_directory(SmallVectorImpl<char> &result) { + wchar_t Path[MAX_PATH]; + if (::SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, + /*SHGFP_TYPE_CURRENT*/0, Path) != S_OK) + return false; + + if (UTF16ToUTF8(Path, ::wcslen(Path), result)) + return false; + + return true; +} + +} // end namespace path + namespace windows { llvm::error_code UTF8ToUTF16(llvm::StringRef utf8, llvm::SmallVectorImpl<wchar_t> &utf16) { - int len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, - utf8.begin(), utf8.size(), - utf16.begin(), 0); + if (!utf8.empty()) { + int len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8.begin(), + utf8.size(), utf16.begin(), 0); - if (len == 0) - return llvm::windows_error(::GetLastError()); + if (len == 0) + return llvm::windows_error(::GetLastError()); - utf16.reserve(len + 1); - utf16.set_size(len); + utf16.reserve(len + 1); + utf16.set_size(len); - len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, - utf8.begin(), utf8.size(), - utf16.begin(), utf16.size()); + len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8.begin(), + utf8.size(), utf16.begin(), utf16.size()); - if (len == 0) - return llvm::windows_error(::GetLastError()); + if (len == 0) + return llvm::windows_error(::GetLastError()); + } // Make utf16 null terminated. utf16.push_back(0); @@ -1090,26 +939,24 @@ llvm::error_code UTF8ToUTF16(llvm::StringRef utf8, llvm::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, llvm::SmallVectorImpl<char> &utf8) { - // Get length. - int len = ::WideCharToMultiByte(CP_UTF8, 0, - utf16, utf16_len, - utf8.begin(), 0, - NULL, NULL); - - if (len == 0) - return llvm::windows_error(::GetLastError()); - - utf8.reserve(len); - utf8.set_size(len); - - // Now do the actual conversion. - len = ::WideCharToMultiByte(CP_UTF8, 0, - utf16, utf16_len, - utf8.data(), utf8.size(), - NULL, NULL); - - if (len == 0) - return llvm::windows_error(::GetLastError()); + if (utf16_len) { + // Get length. + int len = ::WideCharToMultiByte(CP_UTF8, 0, utf16, utf16_len, utf8.begin(), + 0, NULL, NULL); + + if (len == 0) + return llvm::windows_error(::GetLastError()); + + utf8.reserve(len); + utf8.set_size(len); + + // Now do the actual conversion. + len = ::WideCharToMultiByte(CP_UTF8, 0, utf16, utf16_len, utf8.data(), + utf8.size(), NULL, NULL); + + if (len == 0) + return llvm::windows_error(::GetLastError()); + } // Make utf8 null terminated. utf8.push_back(0); |