summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Support/Windows
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2018-06-04 19:38:11 +0000
committerZachary Turner <zturner@google.com>2018-06-04 19:38:11 +0000
commit63db25ba0d5eaba5fb18816a970750e23420fd03 (patch)
tree99f4c7b7ab1f96bde8e1f83c773d5eab0b0c7ad6 /llvm/lib/Support/Windows
parent95ed88a1a93cdc15cf02e25849a6b5a8c2be3bb8 (diff)
downloadbcm5719-llvm-63db25ba0d5eaba5fb18816a970750e23420fd03.tar.gz
bcm5719-llvm-63db25ba0d5eaba5fb18816a970750e23420fd03.zip
[Support] Add functions that operate on native file handles on Windows.
Windows' CRT has a limit of 512 open file descriptors, and fds which are generated by converting a HANDLE via _get_osfhandle count towards this limit as well. Regardless, often you find yourself marshalling back and forth between native HANDLE objects and fds anyway. If we know from the getgo that we're going to need to work directly with the handle, we can cut out the marshalling layer while also not contributing to filling up the CRT's very limited handle table. On Unix these functions just delegate directly to the existing set of functions since an fd *is* the native file type. It would be nice, very long term, if we could convert most uses of fds to file_t. Differential Revision: https://reviews.llvm.org/D47688 llvm-svn: 333945
Diffstat (limited to 'llvm/lib/Support/Windows')
-rw-r--r--llvm/lib/Support/Windows/Path.inc79
1 files changed, 49 insertions, 30 deletions
diff --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc
index 0d1631d6bb0..3f6aa114505 100644
--- a/llvm/lib/Support/Windows/Path.inc
+++ b/llvm/lib/Support/Windows/Path.inc
@@ -123,6 +123,8 @@ std::error_code widenPath(const Twine &Path8,
namespace fs {
+const file_t kInvalidFile = INVALID_HANDLE_VALUE;
+
std::string getMainExecutable(const char *argv0, void *MainExecAddr) {
SmallVector<wchar_t, MAX_PATH> PathName;
DWORD Size = ::GetModuleFileNameW(NULL, PathName.data(), PathName.capacity());
@@ -1051,13 +1053,32 @@ static std::error_code directoryRealPath(const Twine &Name,
return EC;
}
+static std::error_code nativeFileToFd(Expected<HANDLE> H, int &ResultFD,
+ int OpenFlags) {
+ ResultFD = -1;
+ if (!H)
+ return errorToErrorCode(H.takeError());
+
+ ResultFD = ::_open_osfhandle(intptr_t(*H), OpenFlags);
+ if (ResultFD == -1) {
+ ::CloseHandle(*H);
+ return mapWindowsError(ERROR_INVALID_HANDLE);
+ }
+ return std::error_code();
+}
+
std::error_code openFileForRead(const Twine &Name, int &ResultFD,
SmallVectorImpl<char> *RealPath) {
- ResultFD = -1;
+ Expected<HANDLE> NativeFile = openNativeFileForRead(Name, RealPath);
+ return nativeFileToFd(std::move(NativeFile), ResultFD, 0);
+}
+
+Expected<file_t> openNativeFileForRead(const Twine &Name,
+ SmallVectorImpl<char> *RealPath) {
SmallVector<wchar_t, 128> PathUTF16;
if (std::error_code EC = widenPath(Name, PathUTF16))
- return EC;
+ return errorCodeToError(EC);
HANDLE H =
::CreateFileW(PathUTF16.begin(), GENERIC_READ,
@@ -1070,36 +1091,42 @@ std::error_code openFileForRead(const Twine &Name, int &ResultFD,
// This only runs if we failed to open the file, so there is probably
// no performances issues.
if (LastError != ERROR_ACCESS_DENIED)
- return EC;
+ return errorCodeToError(EC);
if (is_directory(Name))
- return make_error_code(errc::is_a_directory);
- return EC;
- }
-
- ResultFD = ::_open_osfhandle(intptr_t(H), 0);
- if (ResultFD == -1) {
- ::CloseHandle(H);
- return mapWindowsError(ERROR_INVALID_HANDLE);
+ return errorCodeToError(make_error_code(errc::is_a_directory));
+ return errorCodeToError(EC);
}
// Fetch the real name of the file, if the user asked
if (RealPath)
realPathFromHandle(H, *RealPath);
- return std::error_code();
+ return H;
}
std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
sys::fs::OpenFlags Flags, unsigned Mode) {
+ int OpenFlags = 0;
+ if (Flags & F_Append)
+ OpenFlags |= _O_APPEND;
+
+ if (Flags & F_Text)
+ OpenFlags |= _O_TEXT;
+
+ Expected<HANDLE> NativeFile = openNativeFileForWrite(Name, Flags, Mode);
+ return nativeFileToFd(std::move(NativeFile), ResultFD, OpenFlags);
+}
+
+Expected<file_t> openNativeFileForWrite(const Twine &Name, OpenFlags Flags,
+ unsigned Mode) {
// Verify that we don't have both "append" and "excl".
assert((!(Flags & sys::fs::F_Excl) || !(Flags & sys::fs::F_Append)) &&
"Cannot specify both 'excl' and 'append' file creation flags!");
- ResultFD = -1;
SmallVector<wchar_t, 128> PathUTF16;
if (std::error_code EC = widenPath(Name, PathUTF16))
- return EC;
+ return errorCodeToError(EC);
DWORD CreationDisposition;
if (Flags & F_Excl)
@@ -1130,26 +1157,18 @@ std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
// This only runs if we failed to open the file, so there is probably
// no performances issues.
if (LastError != ERROR_ACCESS_DENIED)
- return EC;
+ return errorCodeToError(EC);
if (is_directory(Name))
- return make_error_code(errc::is_a_directory);
- return EC;
+ return errorCodeToError(make_error_code(errc::is_a_directory));
+ return errorCodeToError(EC);
}
- int OpenFlags = 0;
- if (Flags & F_Append)
- OpenFlags |= _O_APPEND;
-
- if (Flags & F_Text)
- OpenFlags |= _O_TEXT;
-
- ResultFD = ::_open_osfhandle(intptr_t(H), OpenFlags);
- if (ResultFD == -1) {
- ::CloseHandle(H);
- return mapWindowsError(ERROR_INVALID_HANDLE);
- }
+ return H;
+}
- return std::error_code();
+void closeFile(file_t &F) {
+ ::CloseHandle(F);
+ F = kInvalidFile;
}
std::error_code remove_directories(const Twine &path, bool IgnoreErrors) {
OpenPOWER on IntegriCloud