blob: 38fc105d7a7399f038ff1dc722c18b2cf237e4a2 [file] [log] [blame] [edit]
//===- 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 <fcntl.h>
#ifdef _WIN32
#include <io.h>
#else
#include <sys/types.h>
#include <unistd.h>
#endif
#include <errno.h>
#include <new>
#include <stdint.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "dxc/Support/WinIncludes.h"
#include "dxc/WinAdapter.h"
#include "llvm/Support/MSFileSystem.h"
////////////////////////////////////////////////////////////////////////////////
// Externally visible functions.
HRESULT
CreateMSFileSystemForDisk(::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(HANDLE hFindFile,
LPWIN32_FIND_DATAW lpFindFileData) throw() override;
virtual HANDLE
FindFirstFileW(LPCWSTR lpFileName,
LPWIN32_FIND_DATAW lpFindFileData) throw() override;
virtual void FindClose(HANDLE findHandle) throw() override;
virtual HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess,
DWORD dwShareMode, DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes) throw() override;
virtual BOOL SetFileTime(HANDLE hFile, const FILETIME *lpCreationTime,
const FILETIME *lpLastAccessTime,
const FILETIME *lpLastWriteTime) throw() override;
virtual BOOL GetFileInformationByHandle(
HANDLE hFile,
LPBY_HANDLE_FILE_INFORMATION lpFileInformation) throw() override;
virtual DWORD GetFileType(HANDLE hFile) throw() override;
virtual BOOL CreateHardLinkW(LPCWSTR lpFileName,
LPCWSTR lpExistingFileName) throw() override;
virtual BOOL MoveFileExW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName,
DWORD dwFlags) throw() override;
virtual DWORD GetFileAttributesW(LPCWSTR lpFileName) throw() override;
virtual BOOL CloseHandle(HANDLE hObject) throw() override;
virtual BOOL DeleteFileW(LPCWSTR lpFileName) throw() override;
virtual BOOL RemoveDirectoryW(LPCWSTR lpFileName) throw() override;
virtual BOOL CreateDirectoryW(LPCWSTR lpPathName) throw() override;
virtual DWORD GetCurrentDirectoryW(DWORD nBufferLength,
LPWSTR lpBuffer) throw() override;
virtual DWORD GetMainModuleFileNameW(LPWSTR lpFilename,
DWORD nSize) throw() override;
virtual DWORD GetTempPathW(DWORD nBufferLength,
LPWSTR lpBuffer) throw() override;
virtual BOOLEAN CreateSymbolicLinkW(LPCWSTR lpSymlinkFileName,
LPCWSTR lpTargetFileName,
DWORD dwFlags) throw() override;
virtual bool SupportsCreateSymbolicLink() throw() override;
virtual BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead) throw() override;
virtual HANDLE CreateFileMappingW(HANDLE hFile, DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow) throw() override;
virtual LPVOID MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow,
SIZE_T dwNumberOfBytesToMap) throw() override;
virtual BOOL UnmapViewOfFile(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(LPCWSTR path, uint64_t size) throw() override;
virtual int Read(int fd, void *buffer, unsigned int count) throw() override;
virtual int Write(int fd, 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
}
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
}
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
}
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
}
BOOL MSFileSystemForDisk::SetFileTime(HANDLE hFile,
const FILETIME *lpCreationTime,
const FILETIME *lpLastAccessTime,
const FILETIME *lpLastWriteTime) throw() {
#ifdef _WIN32
return ::SetFileTime(hFile, lpCreationTime, lpLastAccessTime,
lpLastWriteTime);
#else
assert(false && "Not implemented for Unix");
return false;
#endif
}
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
}
DWORD
MSFileSystemForDisk::GetFileType(HANDLE hFile) throw() {
#ifdef _WIN32
return ::GetFileType(hFile);
#else
assert(false && "Not implemented for Unix");
return 0;
#endif
}
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
}
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
}
DWORD
MSFileSystemForDisk::GetFileAttributesW(LPCWSTR lpFileName) throw() {
#ifdef _WIN32
return ::GetFileAttributesW(lpFileName);
#else
assert(false && "Not implemented for Unix");
return 0;
#endif
}
BOOL MSFileSystemForDisk::CloseHandle(HANDLE hObject) throw() {
#ifdef _WIN32
return ::CloseHandle(hObject);
#else
assert(false && "Not implemented for Unix");
return false;
#endif
}
BOOL MSFileSystemForDisk::DeleteFileW(LPCWSTR lpFileName) throw() {
#ifdef _WIN32
return ::DeleteFileW(lpFileName);
#else
assert(false && "Not implemented for Unix");
return false;
#endif
}
BOOL MSFileSystemForDisk::RemoveDirectoryW(LPCWSTR lpFileName) throw() {
#ifdef _WIN32
return ::RemoveDirectoryW(lpFileName);
#else
assert(false && "Not implemented for Unix");
return false;
#endif
}
BOOL MSFileSystemForDisk::CreateDirectoryW(LPCWSTR lpPathName) throw() {
#ifdef _WIN32
return ::CreateDirectoryW(lpPathName, nullptr);
#else
assert(false && "Not implemented for Unix");
return false;
#endif
}
DWORD MSFileSystemForDisk::GetCurrentDirectoryW(DWORD nBufferLength,
LPWSTR lpBuffer) throw() {
#ifdef _WIN32
return ::GetCurrentDirectoryW(nBufferLength, lpBuffer);
#else
assert(false && "Not implemented for Unix");
return 0;
#endif
}
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
}
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"));
} // namespace
#endif
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
}
BOOL MSFileSystemForDisk::ReadFile(HANDLE hFile, LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead) throw() {
#ifdef _WIN32
return ::ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead,
nullptr);
#else
assert(false && "Not implemented for Unix");
return false;
#endif
}
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
}
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
}
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
}
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
}
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
}
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(::llvm::sys::fs::MSFileSystem **pResult) throw() {
*pResult = new (std::nothrow)::llvm::sys::fs::MSFileSystemForDisk();
return (*pResult != nullptr) ? S_OK : E_OUTOFMEMORY;
}