24 #include <sys/types.h>
29 #ifndef _ERRNO_T_DEFINED
30 #define _ERRNO_T_DEFINED
35 # pragma comment(lib, "advapi32.lib") // This provides CryptAcquireContextW.
44 typedef BOOLEAN (WINAPI *PtrCreateSymbolicLinkW)(
45 LPCWSTR lpSymlinkFileName,
46 LPCWSTR lpTargetFileName,
49 PtrCreateSymbolicLinkW create_symbolic_link_api =
50 PtrCreateSymbolicLinkW(::GetProcAddress(
51 ::GetModuleHandleW(L
"Kernel32.dll"),
"CreateSymbolicLinkW"));
55 DWORD len = ::GetTempPathW(result.
capacity(), result.
begin());
84 bool makeAbsolute,
unsigned mode,
99 if (
error_code ec = TempDir(temp_dir))
return ec;
101 if (model_utf16.
size() > 2 && model_utf16[1] == L
':') {
114 if (!::CryptAcquireContextW(&HCPC,
118 CRYPT_VERIFYCONTEXT))
125 e = model_utf16.
end();
129 if (!::CryptGenRandom(CryptoProvider, 1, &val))
131 random_path_utf16.
push_back(L
"0123456789abcdef"[val & 15]);
140 HANDLE TempFileHandle = INVALID_HANDLE_VALUE;
146 ::CreateFileW(random_path_utf16.
begin(), GENERIC_READ | GENERIC_WRITE,
147 FILE_SHARE_READ, NULL,
150 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY, NULL);
151 if (TempFileHandle == INVALID_HANDLE_VALUE) {
155 goto retry_random_path;
161 int fd = ::_open_osfhandle(
intptr_t(TempFileHandle), 0);
163 ::CloseHandle(TempFileHandle);
164 ::DeleteFileW(random_path_utf16.
begin());
176 if (attributes != INVALID_FILE_ATTRIBUTES)
177 goto retry_random_path;
186 if (!::CreateDirectoryW(random_path_utf16.
begin(), NULL)) {
190 goto retry_random_path;
197 random_path_utf16.
size(), result_path)) {
200 ::CloseHandle(TempFileHandle);
201 ::DeleteFileW(random_path_utf16.
begin());
205 ::RemoveDirectoryW(random_path_utf16.
begin());
220 DWORD Size = ::GetModuleFileNameW(NULL, PathName.
data(), PathName.
capacity());
240 return std::string(PathNameUTF8.
data());
246 uint64_t FileID = (
static_cast<uint64_t
>(FileIndexHigh) << 32ULL) |
247 static_cast<uint64_t
>(FileIndexLow);
249 return UniqueID(VolumeSerialNumber, FileID);
254 UI.LowPart = LastWriteTimeLow;
255 UI.HighPart = LastWriteTimeHigh;
258 Ret.fromWin32Time(UI.QuadPart);
264 DWORD len = MAX_PATH;
268 len = ::GetCurrentDirectoryW(cur_path.
capacity(), cur_path.
data());
276 }
while (len > cur_path.
capacity());
292 if (!::CreateDirectoryW(path_utf16.
begin(), NULL)) {
317 if (!::CreateHardLinkW(wide_from.
begin(), wide_to.
begin(), NULL))
325 if (!create_symbolic_link_api)
340 if (!create_symbolic_link_api(wide_from.
begin(), wide_to.
begin(), 0))
366 if (!::RemoveDirectoryW(
c_str(path_utf16))) {
374 if (!::DeleteFileW(
c_str(path_utf16))) {
400 for (
int i = 0; i < 2000; i++) {
401 if (::MoveFileExW(wide_from.
begin(), wide_to.
begin(),
402 MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING))
424 int fd = ::_wopen(path_utf16.
begin(), O_BINARY | _O_RDWR, S_IWRITE);
427 #ifdef HAVE__CHSIZE_S
428 errno_t error = ::_chsize_s(fd, size);
430 errno_t error = ::_chsize(fd, size);
444 DWORD attributes = ::GetFileAttributesW(path_utf16.
begin());
446 if (attributes == INVALID_FILE_ATTRIBUTES) {
466 DWORD Attr = ::GetFileAttributesW(PathUtf16.
begin());
467 return (Attr != INVALID_FILE_ATTRIBUTES) && !(Attr & FILE_ATTRIBUTE_READONLY);
477 DWORD Attr = ::GetFileAttributesW(PathUtf16.
begin());
478 return Attr != INVALID_FILE_ATTRIBUTES;
483 return A.FileIndexHigh == B.FileIndexHigh &&
484 A.FileIndexLow == B.FileIndexLow &&
485 A.FileSizeHigh == B.FileSizeHigh &&
486 A.FileSizeLow == B.FileSizeLow &&
487 A.LastWriteTimeHigh == B.LastWriteTimeHigh &&
488 A.LastWriteTimeLow == B.LastWriteTimeLow &&
489 A.VolumeSerialNumber == B.VolumeSerialNumber;
493 file_status fsA, fsB;
500 static bool isReservedName(
StringRef path) {
503 static const char *sReservedNames[] = {
"nul",
"con",
"prn",
"aux",
504 "com1",
"com2",
"com3",
"com4",
"com5",
"com6",
505 "com7",
"com8",
"com9",
"lpt1",
"lpt2",
"lpt3",
506 "lpt4",
"lpt5",
"lpt6",
"lpt7",
"lpt8",
"lpt9" };
523 static error_code getStatus(HANDLE FileHandle, file_status &Result) {
524 if (FileHandle == INVALID_HANDLE_VALUE)
525 goto handle_status_error;
527 switch (::GetFileType(FileHandle)) {
530 case FILE_TYPE_UNKNOWN: {
531 DWORD Err = ::GetLastError();
547 BY_HANDLE_FILE_INFORMATION Info;
548 if (!::GetFileInformationByHandle(FileHandle, &Info))
549 goto handle_status_error;
552 file_type Type = (Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
556 file_status(Type, Info.ftLastWriteTime.dwHighDateTime,
557 Info.ftLastWriteTime.dwLowDateTime,
558 Info.dwVolumeSerialNumber, Info.nFileSizeHigh,
559 Info.nFileSizeLow, Info.nFileIndexHigh, Info.nFileIndexLow);
580 if (isReservedName(path8)) {
588 DWORD attr = ::GetFileAttributesW(path_utf16.
begin());
589 if (attr == INVALID_FILE_ATTRIBUTES)
590 return getStatus(INVALID_HANDLE_VALUE, result);
593 if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
595 ::CreateFileW(path_utf16.
begin(),
597 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
600 FILE_FLAG_BACKUP_SEMANTICS,
603 return getStatus(INVALID_HANDLE_VALUE, result);
607 ::CreateFileW(path_utf16.
begin(), 0,
608 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
609 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0));
611 return getStatus(INVALID_HANDLE_VALUE, result);
613 return getStatus(h, result);
617 HANDLE FileHandle =
reinterpret_cast<HANDLE
>(_get_osfhandle(FD));
618 return getStatus(FileHandle, Result);
623 UI.QuadPart = Time.toWin32Time();
625 FT.dwLowDateTime = UI.LowPart;
626 FT.dwHighDateTime = UI.HighPart;
627 HANDLE FileHandle =
reinterpret_cast<HANDLE
>(_get_osfhandle(FD));
628 if (!SetFileTime(FileHandle, NULL, &FT, &FT))
645 HANDLE file = ::CreateFileW(
c_str(path_utf16),
650 FILE_ATTRIBUTE_READONLY,
652 if (file == INVALID_HANDLE_VALUE)
659 DWORD bytes_read = 0;
660 BOOL read_success = ::ReadFile(file, result.
data(), len, &bytes_read, NULL);
663 if (!read_success || (bytes_read != len)) {
665 if (bytes_read <= len)
675 error_code mapped_file_region::init(
int FD,
bool CloseFD, uint64_t Offset) {
678 if (Size > std::numeric_limits<SIZE_T>::max()) {
679 if (FileDescriptor) {
681 _close(FileDescriptor);
683 ::CloseHandle(FileHandle);
689 case readonly: flprotect = PAGE_READONLY;
break;
690 case readwrite: flprotect = PAGE_READWRITE;
break;
691 case priv: flprotect = PAGE_WRITECOPY;
break;
695 ::CreateFileMappingW(FileHandle, 0, flprotect,
696 (Offset + Size) >> 32,
697 (Offset + Size) & 0xffffffff,
699 if (FileMappingHandle == NULL) {
701 if (FileDescriptor) {
703 _close(FileDescriptor);
705 ::CloseHandle(FileHandle);
709 DWORD dwDesiredAccess;
711 case readonly: dwDesiredAccess = FILE_MAP_READ;
break;
712 case readwrite: dwDesiredAccess = FILE_MAP_WRITE;
break;
713 case priv: dwDesiredAccess = FILE_MAP_COPY;
break;
715 Mapping = ::MapViewOfFile(FileMappingHandle,
720 if (Mapping == NULL) {
722 ::CloseHandle(FileMappingHandle);
723 if (FileDescriptor) {
725 _close(FileDescriptor);
727 ::CloseHandle(FileHandle);
732 MEMORY_BASIC_INFORMATION mbi;
733 SIZE_T Result = VirtualQuery(Mapping, &mbi,
sizeof(mbi));
736 ::UnmapViewOfFile(Mapping);
737 ::CloseHandle(FileMappingHandle);
738 if (FileDescriptor) {
740 _close(FileDescriptor);
742 ::CloseHandle(FileHandle);
745 Size = mbi.RegionSize;
750 ::CloseHandle(FileMappingHandle);
751 if (FileDescriptor) {
753 _close(FileDescriptor);
755 ::CloseHandle(FileHandle);
759 mapped_file_region::mapped_file_region(
const Twine &path,
768 , FileHandle(INVALID_HANDLE_VALUE)
769 , FileMappingHandle() {
778 FileHandle = ::CreateFileW(
c_str(path_utf16),
779 Mode == readonly ? GENERIC_READ
780 : GENERIC_READ | GENERIC_WRITE,
781 Mode == readonly ? FILE_SHARE_READ
784 Mode == readonly ? OPEN_EXISTING
786 Mode == readonly ? FILE_ATTRIBUTE_READONLY
787 : FILE_ATTRIBUTE_NORMAL,
789 if (FileHandle == INVALID_HANDLE_VALUE) {
795 ec =
init(FileDescriptor,
true, offset);
797 Mapping = FileMappingHandle = 0;
798 FileHandle = INVALID_HANDLE_VALUE;
803 mapped_file_region::mapped_file_region(
int fd,
813 , FileHandle(INVALID_HANDLE_VALUE)
814 , FileMappingHandle() {
815 FileHandle =
reinterpret_cast<HANDLE
>(_get_osfhandle(fd));
816 if (FileHandle == INVALID_HANDLE_VALUE) {
818 _close(FileDescriptor);
824 ec =
init(FileDescriptor, closefd, offset);
826 Mapping = FileMappingHandle = 0;
827 FileHandle = INVALID_HANDLE_VALUE;
832 mapped_file_region::~mapped_file_region() {
834 ::UnmapViewOfFile(Mapping);
837 #if LLVM_HAS_RVALUE_REFERENCES
838 mapped_file_region::mapped_file_region(mapped_file_region &&other)
841 , Mapping(other.Mapping)
842 , FileDescriptor(other.FileDescriptor)
843 , FileHandle(other.FileHandle)
844 , FileMappingHandle(other.FileMappingHandle) {
845 other.Mapping = other.FileMappingHandle = 0;
846 other.FileHandle = INVALID_HANDLE_VALUE;
847 other.FileDescriptor = 0;
851 mapped_file_region::mapmode mapped_file_region::flags()
const {
852 assert(Mapping &&
"Mapping failed but used anyway!");
856 uint64_t mapped_file_region::size()
const {
857 assert(Mapping &&
"Mapping failed but used anyway!");
861 char *mapped_file_region::data()
const {
862 assert(Mode != readonly &&
"Cannot get non const data for readonly mapping!");
863 assert(Mapping &&
"Mapping failed but used anyway!");
864 return reinterpret_cast<char*
>(Mapping);
867 const char *mapped_file_region::const_data()
const {
868 assert(Mapping &&
"Mapping failed but used anyway!");
869 return reinterpret_cast<const char*
>(Mapping);
872 int mapped_file_region::alignment() {
874 ::GetSystemInfo(&SysInfo);
875 return SysInfo.dwAllocationGranularity;
887 if (path_utf16.
size() > 0 &&
889 path_utf16[path.
size() - 1] != L
':') {
897 WIN32_FIND_DATAW FirstFind;
902 size_t FilenameLen = ::wcslen(FirstFind.cFileName);
903 while ((FilenameLen == 1 && FirstFind.cFileName[0] == L
'.') ||
904 (FilenameLen == 2 && FirstFind.cFileName[0] == L
'.' &&
905 FirstFind.cFileName[1] == L
'.'))
906 if (!::FindNextFileW(FindHandle, &FirstFind)) {
913 FilenameLen = ::wcslen(FirstFind.cFileName);
918 ::wcslen(FirstFind.cFileName),
919 directory_entry_name_utf8))
922 it.IterationHandle =
intptr_t(FindHandle.take());
925 it.CurrentEntry = directory_entry(directory_entry_path.str());
931 if (it.IterationHandle != 0)
934 it.IterationHandle = 0;
935 it.CurrentEntry = directory_entry();
940 WIN32_FIND_DATAW FindData;
941 if (!::FindNextFileW(HANDLE(it.IterationHandle), &FindData)) {
949 size_t FilenameLen = ::wcslen(FindData.cFileName);
950 if ((FilenameLen == 1 && FindData.cFileName[0] == L
'.') ||
951 (FilenameLen == 2 && FindData.cFileName[0] == L
'.' &&
952 FindData.cFileName[1] == L
'.'))
957 ::wcslen(FindData.cFileName),
958 directory_entry_path_utf8))
961 it.CurrentEntry.replace_filename(
Twine(directory_entry_path_utf8));
966 bool map_writable,
void *&result) {
967 assert(0 &&
"NOT IMPLEMENTED");
972 assert(0 &&
"NOT IMPLEMENTED");
984 HANDLE
H = ::CreateFileW(PathUTF16.
begin(), GENERIC_READ,
985 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
986 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
987 if (H == INVALID_HANDLE_VALUE) {
999 int FD = ::_open_osfhandle(
intptr_t(H), 0);
1013 "Cannot specify both 'excl' and 'append' file creation flags!");
1022 DWORD CreationDisposition;
1024 CreationDisposition = CREATE_NEW;
1026 CreationDisposition = OPEN_ALWAYS;
1028 CreationDisposition = CREATE_ALWAYS;
1030 HANDLE H = ::CreateFileW(PathUTF16.
begin(), GENERIC_WRITE,
1031 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1032 CreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
1034 if (H == INVALID_HANDLE_VALUE) {
1047 if (Flags & F_Append)
1048 OpenFlags |= _O_APPEND;
1051 OpenFlags |= _O_TEXT;
1053 int FD = ::_open_osfhandle(
intptr_t(H), OpenFlags);
1067 int len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
1077 len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
1094 int len = ::WideCharToMultiByte(CP_UTF8, 0,
1106 len = ::WideCharToMultiByte(CP_UTF8, 0,
void set_size(unsigned N)
void push_back(const T &Elt)
bool can_execute(const Twine &Path)
Can we execute this file?
size_t size() const
size - Get the string size.
error_code directory_iterator_construct(DirIterState &, StringRef)
error_code openFileForWrite(const Twine &Name, int &ResultFD, OpenFlags Flags, unsigned Mode=0666)
error_code resize_file(const Twine &path, uint64_t size)
Resize path to size. File is resized as if by POSIX truncate().
error_code setLastModificationAndAccessTime(int FD, TimeValue Time)
UniqueID getUniqueID() const
iterator insert(iterator I, const T &Elt)
error_code current_path(SmallVectorImpl< char > &result)
Get the current path.
error_code unmap_file_pages(void *base, size_t size)
Memory unmaps the contents of a file.
error_code openFileForRead(const Twine &Name, int &ResultFD)
bool status_known(file_status s)
Is status available?
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, SmallVectorImpl< char > &utf8)
error_code UTF8ToUTF16(StringRef utf8, SmallVectorImpl< wchar_t > &utf16)
#define llvm_unreachable(msg)
bool is_absolute(const Twine &path)
Is path absolute?
May access map via data and modify it. Written to path.
error_code directory_iterator_destruct(DirIterState &)
error_code map_file_pages(const Twine &path, off_t file_offset, size_t size, bool map_writable, void *&result)
Memory maps the contents of a file.
bool can_write(const Twine &Path)
Can we write this file?
const error_category & posix_category()
error_code directory_iterator_increment(DirIterState &)
May only access map via const_data as read only.
size_t array_lengthof(T(&)[N])
Find the length of an array.
bool is_separator(char value)
Check whether the given char is a path separator on the host OS.
error_code create_hard_link(const Twine &to, const Twine &from)
Create a hard link from from to to.
std::string getMainExecutable(const char *argv0, void *MainExecAddr)
static llvm::error_code createUniqueEntity(const llvm::Twine &Model, int &ResultFD, llvm::SmallVectorImpl< char > &ResultPath, bool MakeAbsolute, unsigned Mode, FSEntity Type)
initializer< Ty > init(const Ty &Val)
error_code status(const Twine &path, file_status &result)
Get file status as if by POSIX stat().
iterator erase(iterator I)
bool is_directory(file_status status)
Does status represent a directory?
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
StringRef toStringRef(SmallVectorImpl< char > &Out) const
StringRef str() const
Explicit conversion to StringRef.
May modify via data, but changes are lost on destruction.
pointer data()
data - Return a pointer to the vector's buffer, even if empty().
error_code create_directory(const Twine &path, bool &existed)
Create the directory in path.
bool equals_lower(StringRef RHS) const
equals_lower - Check for string equality, ignoring case.
error_code create_symlink(const Twine &to, const Twine &from)
Create a symbolic link from from to to.
static error_code success()
Deduce function attributes
const error_category & generic_category()
bool equivalent(file_status A, file_status B)
Do file_status's represent the same thing?
TimeValue getLastModificationTime() const
error_code rename(const Twine &from, const Twine &to)
Rename from to to. Files are renamed as if by POSIX rename().
bool exists(file_status status)
Does file exist?
error_code get_magic(const Twine &path, uint32_t len, SmallVectorImpl< char > &result)
Get path's first len bytes.
error_code make_error_code(errc _e)