diff options
Diffstat (limited to 'contrib/llvm/lib/Support/Windows/PathV2.inc')
-rw-r--r-- | contrib/llvm/lib/Support/Windows/PathV2.inc | 265 |
1 files changed, 261 insertions, 4 deletions
diff --git a/contrib/llvm/lib/Support/Windows/PathV2.inc b/contrib/llvm/lib/Support/Windows/PathV2.inc index 3ac983a..696768b 100644 --- a/contrib/llvm/lib/Support/Windows/PathV2.inc +++ b/contrib/llvm/lib/Support/Windows/PathV2.inc @@ -22,6 +22,8 @@ #include <sys/stat.h> #include <sys/types.h> +#undef max + // MinGW doesn't define this. #ifndef _ERRNO_T_DEFINED #define _ERRNO_T_DEFINED @@ -301,11 +303,21 @@ error_code rename(const Twine &from, const Twine &to) { if (error_code ec = UTF8ToUTF16(f, wide_from)) return ec; if (error_code ec = UTF8ToUTF16(t, wide_to)) return ec; - if (!::MoveFileExW(wide_from.begin(), wide_to.begin(), - MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING)) - return windows_error(::GetLastError()); + error_code ec = error_code::success(); + for (int i = 0; i < 2000; i++) { + if (::MoveFileExW(wide_from.begin(), wide_to.begin(), + MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING)) + return error_code::success(); + ec = windows_error(::GetLastError()); + if (ec != windows_error::access_denied) + break; + // Retry MoveFile() at ACCESS_DENIED. + // System scanners (eg. indexer) might open the source file when + // It is written and closed. + ::Sleep(1); + } - return error_code::success(); + return ec; } error_code resize_file(const Twine &path, uint64_t size) { @@ -487,6 +499,41 @@ handle_status_error: return error_code::success(); } + +// Modifies permissions on a file. +error_code permissions(const Twine &path, perms prms) { +#if 0 // verify code below before enabling: + // If the permissions bits are not trying to modify + // "write" permissions, there is nothing to do. + if (!(prms & (owner_write|group_write|others_write))) + return error_code::success(); + + SmallString<128> path_storage; + SmallVector<wchar_t, 128> path_utf16; + + if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage), + path_utf16)) + return ec; + + DWORD attributes = ::GetFileAttributesW(path_utf16.begin()); + + if (prms & add_perms) { + attributes &= ~FILE_ATTRIBUTE_READONLY; + } + else if (prms & remove_perms) { + attributes |= FILE_ATTRIBUTE_READONLY; + } + else { + assert(0 && "neither add_perms or remove_perms is set"); + } + + if ( ! ::SetFileAttributesW(path_utf16.begin(), attributes)) + return windows_error(::GetLastError()); +#endif + return error_code::success(); +} + + // FIXME: mode should be used here and default to user r/w only, // it currently comes in as a UNIX mode. error_code unique_file(const Twine &model, int &result_fd, @@ -658,6 +705,203 @@ error_code get_magic(const Twine &path, uint32_t len, return error_code::success(); } +error_code mapped_file_region::init(int FD, uint64_t Offset) { + FileDescriptor = FD; + // Make sure that the requested size fits within SIZE_T. + if (Size > std::numeric_limits<SIZE_T>::max()) { + if (FileDescriptor) + _close(FileDescriptor); + else + ::CloseHandle(FileHandle); + return make_error_code(errc::invalid_argument); + } + + DWORD flprotect; + switch (Mode) { + case readonly: flprotect = PAGE_READONLY; break; + case readwrite: flprotect = PAGE_READWRITE; break; + case priv: flprotect = PAGE_WRITECOPY; break; + default: llvm_unreachable("invalid mapping mode"); + } + + FileMappingHandle = ::CreateFileMapping(FileHandle, + 0, + flprotect, + Size >> 32, + Size & 0xffffffff, + 0); + if (FileMappingHandle == NULL) { + error_code ec = windows_error(GetLastError()); + if (FileDescriptor) + _close(FileDescriptor); + else + ::CloseHandle(FileHandle); + return ec; + } + + DWORD dwDesiredAccess; + switch (Mode) { + case readonly: dwDesiredAccess = FILE_MAP_READ; break; + case readwrite: dwDesiredAccess = FILE_MAP_WRITE; break; + case priv: dwDesiredAccess = FILE_MAP_COPY; break; + default: llvm_unreachable("invalid mapping mode"); + } + Mapping = ::MapViewOfFile(FileMappingHandle, + dwDesiredAccess, + Offset >> 32, + Offset & 0xffffffff, + Size); + if (Mapping == NULL) { + error_code ec = windows_error(GetLastError()); + ::CloseHandle(FileMappingHandle); + if (FileDescriptor) + _close(FileDescriptor); + else + ::CloseHandle(FileHandle); + return ec; + } + + if (Size == 0) { + MEMORY_BASIC_INFORMATION mbi; + SIZE_T Result = VirtualQuery(Mapping, &mbi, sizeof(mbi)); + if (Result == 0) { + error_code ec = windows_error(GetLastError()); + ::UnmapViewOfFile(Mapping); + ::CloseHandle(FileMappingHandle); + if (FileDescriptor) + _close(FileDescriptor); + else + ::CloseHandle(FileHandle); + return ec; + } + Size = mbi.RegionSize; + } + return error_code::success(); +} + +mapped_file_region::mapped_file_region(const Twine &path, + mapmode mode, + uint64_t length, + uint64_t offset, + error_code &ec) + : Mode(mode) + , Size(length) + , Mapping() + , 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)) + return; + + // Get file handle for creating a file mapping. + FileHandle = ::CreateFileW(c_str(path_utf16), + Mode == readonly ? GENERIC_READ + : GENERIC_READ | GENERIC_WRITE, + Mode == readonly ? FILE_SHARE_READ + : 0, + 0, + Mode == readonly ? OPEN_EXISTING + : OPEN_ALWAYS, + Mode == readonly ? FILE_ATTRIBUTE_READONLY + : FILE_ATTRIBUTE_NORMAL, + 0); + if (FileHandle == INVALID_HANDLE_VALUE) { + ec = windows_error(::GetLastError()); + return; + } + + FileDescriptor = 0; + ec = init(FileDescriptor, offset); + if (ec) { + Mapping = FileMappingHandle = 0; + FileHandle = INVALID_HANDLE_VALUE; + FileDescriptor = 0; + } +} + +mapped_file_region::mapped_file_region(int fd, + mapmode mode, + uint64_t length, + uint64_t offset, + error_code &ec) + : Mode(mode) + , Size(length) + , Mapping() + , FileDescriptor(fd) + , FileHandle(INVALID_HANDLE_VALUE) + , FileMappingHandle() { + FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); + if (FileHandle == INVALID_HANDLE_VALUE) { + _close(FileDescriptor); + FileDescriptor = 0; + ec = make_error_code(errc::bad_file_descriptor); + return; + } + + ec = init(FileDescriptor, offset); + if (ec) { + Mapping = FileMappingHandle = 0; + FileHandle = INVALID_HANDLE_VALUE; + FileDescriptor = 0; + } +} + +mapped_file_region::~mapped_file_region() { + if (Mapping) + ::UnmapViewOfFile(Mapping); + if (FileMappingHandle) + ::CloseHandle(FileMappingHandle); + if (FileDescriptor) + _close(FileDescriptor); + else if (FileHandle != INVALID_HANDLE_VALUE) + ::CloseHandle(FileHandle); +} + +#if LLVM_USE_RVALUE_REFERENCES +mapped_file_region::mapped_file_region(mapped_file_region &&other) + : Mode(other.Mode) + , Size(other.Size) + , Mapping(other.Mapping) + , FileDescriptor(other.FileDescriptor) + , FileHandle(other.FileHandle) + , FileMappingHandle(other.FileMappingHandle) { + other.Mapping = other.FileMappingHandle = 0; + 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!"); + return Mode; +} + +uint64_t mapped_file_region::size() const { + assert(Mapping && "Mapping failed but used anyway!"); + return Size; +} + +char *mapped_file_region::data() const { + assert(Mode != readonly && "Cannot get non const data for readonly mapping!"); + assert(Mapping && "Mapping failed but used anyway!"); + return reinterpret_cast<char*>(Mapping); +} + +const char *mapped_file_region::const_data() const { + assert(Mapping && "Mapping failed but used anyway!"); + return reinterpret_cast<const char*>(Mapping); +} + +int mapped_file_region::alignment() { + SYSTEM_INFO SysInfo; + ::GetSystemInfo(&SysInfo); + return SysInfo.dwAllocationGranularity; +} + error_code detail::directory_iterator_construct(detail::DirIterState &it, StringRef path){ SmallVector<wchar_t, 128> path_utf16; @@ -745,6 +989,19 @@ error_code detail::directory_iterator_increment(detail::DirIterState &it) { return error_code::success(); } +error_code map_file_pages(const Twine &path, off_t file_offset, size_t size, + bool map_writable, void *&result) { + assert(0 && "NOT IMPLEMENTED"); + return windows_error::invalid_function; +} + +error_code unmap_file_pages(void *base, size_t size) { + assert(0 && "NOT IMPLEMENTED"); + return windows_error::invalid_function; +} + + + } // end namespace fs } // end namespace sys } // end namespace llvm |