aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Support/Windows/Path.inc
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2014-04-23 16:57:46 -0700
committerStephen Hines <srhines@google.com>2014-04-24 15:53:16 -0700
commit36b56886974eae4f9c5ebc96befd3e7bfe5de338 (patch)
treee6cfb69fbbd937f450eeb83bfb83b9da3b01275a /lib/Support/Windows/Path.inc
parent69a8640022b04415ae9fac62f8ab090601d8f889 (diff)
downloadexternal_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.inc355
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);