//===- llvm/Support/Windows/MSFileSystemImpl.cpp DXComplier Impl *- C++ -*-===// /////////////////////////////////////////////////////////////////////////////// // // // MSFileSystemImpl.cpp // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // This file implements the DXCompiler specific implementation of the Path API.// // // /////////////////////////////////////////////////////////////////////////////// #include #ifdef _WIN32 #include #else #include #include #endif #include #include #include #include #include #include "dxc/Support/WinIncludes.h" #include "dxc/Support/WinAdapter.h" #include "llvm/Support/MSFileSystem.h" /////////////////////////////////////////////////////////////////////////////////////////////////// // Externally visible functions. HRESULT CreateMSFileSystemForDisk(_COM_Outptr_ ::llvm::sys::fs::MSFileSystem** pResult) throw(); /////////////////////////////////////////////////////////////////////////////////////////////////// // Win32-and-CRT-based MSFileSystem implementation with direct filesystem access. namespace llvm { namespace sys { namespace fs { class MSFileSystemForDisk : public MSFileSystem { public: unsigned _defaultAttributes; MSFileSystemForDisk(); virtual BOOL FindNextFileW(_In_ HANDLE hFindFile, _Out_ LPWIN32_FIND_DATAW lpFindFileData) throw() override; virtual HANDLE FindFirstFileW(_In_ LPCWSTR lpFileName, _Out_ LPWIN32_FIND_DATAW lpFindFileData) throw() override; virtual void FindClose(HANDLE findHandle) throw() override; virtual HANDLE CreateFileW(_In_ LPCWSTR lpFileName, _In_ DWORD dwDesiredAccess, _In_ DWORD dwShareMode, _In_ DWORD dwCreationDisposition, _In_ DWORD dwFlagsAndAttributes) throw() override; virtual BOOL SetFileTime(_In_ HANDLE hFile, _In_opt_ const FILETIME *lpCreationTime, _In_opt_ const FILETIME *lpLastAccessTime, _In_opt_ const FILETIME *lpLastWriteTime) throw() override; virtual BOOL GetFileInformationByHandle(_In_ HANDLE hFile, _Out_ LPBY_HANDLE_FILE_INFORMATION lpFileInformation) throw() override; virtual DWORD GetFileType(_In_ HANDLE hFile) throw() override; virtual BOOL CreateHardLinkW(_In_ LPCWSTR lpFileName, _In_ LPCWSTR lpExistingFileName) throw() override; virtual BOOL MoveFileExW(_In_ LPCWSTR lpExistingFileName, _In_opt_ LPCWSTR lpNewFileName, _In_ DWORD dwFlags) throw() override; virtual DWORD GetFileAttributesW(_In_ LPCWSTR lpFileName) throw() override; virtual BOOL CloseHandle(_In_ HANDLE hObject) throw() override; virtual BOOL DeleteFileW(_In_ LPCWSTR lpFileName) throw() override; virtual BOOL RemoveDirectoryW(_In_ LPCWSTR lpFileName) throw() override; virtual BOOL CreateDirectoryW(_In_ LPCWSTR lpPathName) throw() override; _Success_(return != 0 && return < nBufferLength) virtual DWORD GetCurrentDirectoryW(_In_ DWORD nBufferLength, _Out_writes_to_opt_(nBufferLength, return + 1) LPWSTR lpBuffer) throw() override; _Success_(return != 0 && return < nSize) virtual DWORD GetMainModuleFileNameW(__out_ecount_part(nSize, return + 1) LPWSTR lpFilename, DWORD nSize) throw() override; virtual DWORD GetTempPathW(DWORD nBufferLength, _Out_writes_to_opt_(nBufferLength, return + 1) LPWSTR lpBuffer) throw() override; virtual BOOLEAN CreateSymbolicLinkW(_In_ LPCWSTR lpSymlinkFileName, _In_ LPCWSTR lpTargetFileName, DWORD dwFlags) throw() override; virtual bool SupportsCreateSymbolicLink() throw() override; virtual BOOL ReadFile(_In_ HANDLE hFile, _Out_bytecap_(nNumberOfBytesToRead) LPVOID lpBuffer, _In_ DWORD nNumberOfBytesToRead, _Out_opt_ LPDWORD lpNumberOfBytesRead) throw() override; virtual HANDLE CreateFileMappingW(_In_ HANDLE hFile, _In_ DWORD flProtect, _In_ DWORD dwMaximumSizeHigh, _In_ DWORD dwMaximumSizeLow) throw() override; virtual LPVOID MapViewOfFile(_In_ HANDLE hFileMappingObject, _In_ DWORD dwDesiredAccess, _In_ DWORD dwFileOffsetHigh, _In_ DWORD dwFileOffsetLow, _In_ SIZE_T dwNumberOfBytesToMap) throw() override; virtual BOOL UnmapViewOfFile(_In_ LPCVOID lpBaseAddress) throw() override; // Console APIs. virtual bool FileDescriptorIsDisplayed(int fd) throw() override; virtual unsigned GetColumnCount(DWORD nStdHandle) throw() override; virtual unsigned GetConsoleOutputTextAttributes() throw() override; virtual void SetConsoleOutputTextAttributes(unsigned attributes) throw() override; virtual void ResetConsoleOutputTextAttributes() throw() override; // CRT APIs. virtual int open_osfhandle(intptr_t osfhandle, int flags) throw() override; virtual intptr_t get_osfhandle(int fd) throw() override; virtual int close(int fd) throw() override; virtual long lseek(int fd, long offset, int origin) throw() override; virtual int setmode(int fd, int mode) throw() override; virtual errno_t resize_file(_In_ LPCWSTR path, uint64_t size) throw() override; virtual int Read(int fd, _Out_bytecap_(count) void* buffer, unsigned int count) throw() override; virtual int Write(int fd, _In_bytecount_(count) const void* buffer, unsigned int count) throw() override; #ifndef _WIN32 virtual int Open(const char *lpFileName, int flags, mode_t mode) throw() override; virtual int Stat(const char *lpFileName, struct stat *Status) throw() override; virtual int Fstat(int FD, struct stat *Status) throw() override; #endif }; MSFileSystemForDisk::MSFileSystemForDisk() { #ifdef _WIN32 _defaultAttributes = GetConsoleOutputTextAttributes(); #endif } _Use_decl_annotations_ BOOL MSFileSystemForDisk::FindNextFileW(HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData) throw() { #ifdef _WIN32 return ::FindNextFileW(hFindFile, lpFindFileData); #else assert(false && "Not implemented for Unix"); return false; #endif } _Use_decl_annotations_ HANDLE MSFileSystemForDisk::FindFirstFileW(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData) throw() { #ifdef _WIN32 return ::FindFirstFileW(lpFileName, lpFindFileData); #else assert(false && "Not implemented for Unix"); return nullptr; #endif } void MSFileSystemForDisk::FindClose(HANDLE findHandle) throw() { #ifdef _WIN32 ::FindClose(findHandle); #else assert(false && "Not implemented for Unix"); #endif } _Use_decl_annotations_ HANDLE MSFileSystemForDisk::CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes) throw() { #ifdef _WIN32 return ::CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, nullptr, dwCreationDisposition, dwFlagsAndAttributes, nullptr); #else assert(false && "Not implemented for Unix"); return nullptr; #endif } _Use_decl_annotations_ BOOL MSFileSystemForDisk::SetFileTime(HANDLE hFile, _In_opt_ const FILETIME *lpCreationTime, _In_opt_ const FILETIME *lpLastAccessTime, _In_opt_ const FILETIME *lpLastWriteTime) throw() { #ifdef _WIN32 return ::SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime); #else assert(false && "Not implemented for Unix"); return false; #endif } _Use_decl_annotations_ BOOL MSFileSystemForDisk::GetFileInformationByHandle(HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation) throw() { #ifdef _WIN32 return ::GetFileInformationByHandle(hFile, lpFileInformation); #else assert(false && "Not implemented for Unix"); return false; #endif } _Use_decl_annotations_ DWORD MSFileSystemForDisk::GetFileType(HANDLE hFile) throw() { #ifdef _WIN32 return ::GetFileType(hFile); #else assert(false && "Not implemented for Unix"); return 0; #endif } _Use_decl_annotations_ BOOL MSFileSystemForDisk::CreateHardLinkW(LPCWSTR lpFileName, LPCWSTR lpExistingFileName) throw() { #ifdef _WIN32 return ::CreateHardLinkW(lpFileName, lpExistingFileName, nullptr); #else assert(false && "Not implemented for Unix"); return false; #endif } _Use_decl_annotations_ BOOL MSFileSystemForDisk::MoveFileExW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags) throw() { #ifdef _WIN32 return ::MoveFileExW(lpExistingFileName, lpNewFileName, dwFlags); #else assert(false && "Not implemented for Unix"); return false; #endif } _Use_decl_annotations_ DWORD MSFileSystemForDisk::GetFileAttributesW(LPCWSTR lpFileName) throw() { #ifdef _WIN32 return ::GetFileAttributesW(lpFileName); #else assert(false && "Not implemented for Unix"); return 0; #endif } _Use_decl_annotations_ BOOL MSFileSystemForDisk::CloseHandle(HANDLE hObject) throw() { #ifdef _WIN32 return ::CloseHandle(hObject); #else assert(false && "Not implemented for Unix"); return false; #endif } _Use_decl_annotations_ BOOL MSFileSystemForDisk::DeleteFileW(LPCWSTR lpFileName) throw() { #ifdef _WIN32 return ::DeleteFileW(lpFileName); #else assert(false && "Not implemented for Unix"); return false; #endif } _Use_decl_annotations_ BOOL MSFileSystemForDisk::RemoveDirectoryW(LPCWSTR lpFileName) throw() { #ifdef _WIN32 return ::RemoveDirectoryW(lpFileName); #else assert(false && "Not implemented for Unix"); return false; #endif } _Use_decl_annotations_ BOOL MSFileSystemForDisk::CreateDirectoryW(LPCWSTR lpPathName) throw() { #ifdef _WIN32 return ::CreateDirectoryW(lpPathName, nullptr); #else assert(false && "Not implemented for Unix"); return false; #endif } _Use_decl_annotations_ DWORD MSFileSystemForDisk::GetCurrentDirectoryW(DWORD nBufferLength, LPWSTR lpBuffer) throw() { #ifdef _WIN32 return ::GetCurrentDirectoryW(nBufferLength, lpBuffer); #else assert(false && "Not implemented for Unix"); return 0; #endif } _Use_decl_annotations_ DWORD MSFileSystemForDisk::GetMainModuleFileNameW(LPWSTR lpFilename, DWORD nSize) throw() { #ifdef _WIN32 // Add some code to ensure that the result is null terminated. if (nSize <= 1) { ::SetLastError(ERROR_INSUFFICIENT_BUFFER); return 0; } DWORD result = ::GetModuleFileNameW(nullptr, lpFilename, nSize - 1); if (result == 0) return result; lpFilename[result] = L'\0'; return result; #else assert(false && "Not implemented for Unix"); return 0; #endif } _Use_decl_annotations_ DWORD MSFileSystemForDisk::GetTempPathW(DWORD nBufferLength, LPWSTR lpBuffer) throw() { #ifdef _WIN32 return ::GetTempPathW(nBufferLength, lpBuffer); #else assert(false && "Not implemented for Unix"); return 0; #endif } #ifdef _WIN32 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")); } #endif _Use_decl_annotations_ BOOLEAN MSFileSystemForDisk::CreateSymbolicLinkW(LPCWSTR lpSymlinkFileName, LPCWSTR lpTargetFileName, DWORD dwFlags) throw() { #ifdef _WIN32 return create_symbolic_link_api(lpSymlinkFileName, lpTargetFileName, dwFlags); #else assert(false && "Not implemented for Unix"); return false; #endif } bool MSFileSystemForDisk::SupportsCreateSymbolicLink() throw() { #ifdef _WIN32 return create_symbolic_link_api != nullptr; #else assert(false && "Not implemented for Unix"); return false; #endif } _Use_decl_annotations_ BOOL MSFileSystemForDisk::ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, _Out_opt_ LPDWORD lpNumberOfBytesRead) throw() { #ifdef _WIN32 return ::ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, nullptr); #else assert(false && "Not implemented for Unix"); return false; #endif } _Use_decl_annotations_ HANDLE MSFileSystemForDisk::CreateFileMappingW(HANDLE hFile, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow) throw() { #ifdef _WIN32 return ::CreateFileMappingW(hFile, nullptr, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, nullptr); #else assert(false && "Not implemented for Unix"); return nullptr; #endif } _Use_decl_annotations_ LPVOID MSFileSystemForDisk::MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap) throw() { #ifdef _WIN32 return ::MapViewOfFile(hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap); #else assert(false && "Not implemented for Unix"); return nullptr; #endif } _Use_decl_annotations_ BOOL MSFileSystemForDisk::UnmapViewOfFile(LPCVOID lpBaseAddress) throw() { #ifdef _WIN32 return ::UnmapViewOfFile(lpBaseAddress); #else assert(false && "Not implemented for Unix"); return false; #endif } bool MSFileSystemForDisk::FileDescriptorIsDisplayed(int fd) throw() { #ifdef _WIN32 DWORD Mode; // Unused return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0); #else assert(false && "Not implemented for Unix"); return false; #endif } unsigned MSFileSystemForDisk::GetColumnCount(DWORD nStdHandle) throw() { #ifdef _WIN32 unsigned Columns = 0; CONSOLE_SCREEN_BUFFER_INFO csbi; if (::GetConsoleScreenBufferInfo(GetStdHandle(nStdHandle), &csbi)) Columns = csbi.dwSize.X; return Columns; #else assert(false && "Not implemented for Unix"); return 0; #endif } unsigned MSFileSystemForDisk::GetConsoleOutputTextAttributes() throw() { #ifdef _WIN32 CONSOLE_SCREEN_BUFFER_INFO csbi; if (::GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) return csbi.wAttributes; return 0; #else assert(false && "Not implemented for Unix"); return 0; #endif } void MSFileSystemForDisk::SetConsoleOutputTextAttributes(unsigned attributes) throw() { #ifdef _WIN32 ::SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), attributes); #else assert(false && "Not implemented for Unix"); #endif } void MSFileSystemForDisk::ResetConsoleOutputTextAttributes() throw() { #ifdef _WIN32 ::SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), _defaultAttributes); #else assert(false && "Not implemented for Unix"); #endif } int MSFileSystemForDisk::open_osfhandle(intptr_t osfhandle, int flags) throw() { #ifdef _WIN32 return ::_open_osfhandle(osfhandle, flags); #else assert(false && "Not implemented for Unix"); return 0; #endif } intptr_t MSFileSystemForDisk::get_osfhandle(int fd) throw() { #ifdef _WIN32 return ::_get_osfhandle(fd); #else assert(false && "Not implemented for Unix"); return 0; #endif } int MSFileSystemForDisk::close(int fd) throw() { #ifdef _WIN32 return ::_close(fd); #else return ::close(fd); #endif } long MSFileSystemForDisk::lseek(int fd, long offset, int origin) throw() { #ifdef _WIN32 return ::_lseek(fd, offset, origin); #else return ::lseek(fd, offset, origin); #endif } int MSFileSystemForDisk::setmode(int fd, int mode) throw() { #ifdef _WIN32 return ::_setmode(fd, mode); #else assert(false && "Not implemented for Unix"); return 0; #endif } _Use_decl_annotations_ errno_t MSFileSystemForDisk::resize_file(LPCWSTR path, uint64_t size) throw() { #ifdef _WIN32 int fd = ::_wopen(path, O_BINARY | _O_RDWR, S_IWRITE); if (fd == -1) return errno; #ifdef HAVE__CHSIZE_S errno_t error = ::_chsize_s(fd, size); #else errno_t error = ::_chsize(fd, size); #endif ::_close(fd); return error; #else assert(false && "Not implemented for Unix"); return 0; #endif } _Use_decl_annotations_ int MSFileSystemForDisk::Read(int fd, void* buffer, unsigned int count) throw() { #ifdef _WIN32 return ::_read(fd, buffer, count); #else return ::read(fd, buffer, count); #endif } _Use_decl_annotations_ int MSFileSystemForDisk::Write(int fd, const void* buffer, unsigned int count) throw() { #ifdef _WIN32 return ::_write(fd, buffer, count); #else return ::write(fd, buffer, count); #endif } #ifndef _WIN32 int MSFileSystemForDisk::Open(const char *lpFileName, int flags, mode_t mode) throw() { return ::open(lpFileName, flags, mode); } int MSFileSystemForDisk::Stat(const char *lpFileName, struct stat *Status) throw() { return ::stat(lpFileName, Status); } int MSFileSystemForDisk::Fstat(int FD, struct stat *Status) throw() { return ::fstat(FD, Status); } #endif } // end namespace fs } // end namespace sys } // end namespace llvm /////////////////////////////////////////////////////////////////////////////////////////////////// // Externally visible functions. HRESULT CreateMSFileSystemForDisk(_COM_Outptr_ ::llvm::sys::fs::MSFileSystem** pResult) throw() { *pResult = new (std::nothrow) ::llvm::sys::fs::MSFileSystemForDisk(); return (*pResult != nullptr) ? S_OK : E_OUTOFMEMORY; }