24 #include <sys/types.h>
34 #ifndef _ERRNO_T_DEFINED
35 #define _ERRNO_T_DEFINED
40 # pragma comment(lib, "advapi32.lib") // This provides CryptAcquireContextW.
68 const size_t MaxDirLen = MAX_PATH - 12;
80 CurPathLen = ::GetCurrentDirectoryW(0, NULL);
86 if ((Path8Str.
size() + CurPathLen) >= MaxDirLen &&
102 if (
I->size() == 1 && *
I ==
".")
104 if (
I->size() == 2 && *
I ==
"..")
121 DWORD Size = ::GetModuleFileNameW(NULL, PathName.
data(), PathName.
capacity());
141 return std::string(PathNameUTF8.
data());
147 uint64_t FileID = (
static_cast<uint64_t
>(FileIndexHigh) << 32ULL) |
148 static_cast<uint64_t
>(FileIndexLow);
150 return UniqueID(VolumeSerialNumber, FileID);
155 UI.LowPart = LastWriteTimeLow;
156 UI.HighPart = LastWriteTimeHigh;
159 Ret.fromWin32Time(UI.QuadPart);
165 DWORD len = MAX_PATH;
169 len = ::GetCurrentDirectoryW(cur_path.
capacity(), cur_path.
data());
177 }
while (len > cur_path.
capacity());
188 if (std::error_code ec =
widenPath(path, path_utf16))
191 if (!::CreateDirectoryW(path_utf16.
begin(), NULL)) {
192 DWORD LastError = ::GetLastError();
193 if (LastError != ERROR_ALREADY_EXISTS || !IgnoreExisting)
197 return std::error_code();
205 if (std::error_code ec =
widenPath(from, wide_from))
207 if (std::error_code ec =
widenPath(to, wide_to))
210 if (!::CreateHardLinkW(wide_from.
begin(), wide_to.
begin(), NULL))
213 return std::error_code();
216 std::error_code
remove(
const Twine &path,
bool IgnoreNonExisting) {
220 if (std::error_code EC =
status(path, ST)) {
223 return std::error_code();
226 if (std::error_code ec =
widenPath(path, path_utf16))
230 if (!::RemoveDirectoryW(
c_str(path_utf16))) {
235 return std::error_code();
237 if (!::DeleteFileW(
c_str(path_utf16))) {
242 return std::error_code();
249 if (std::error_code ec =
widenPath(from, wide_from))
251 if (std::error_code ec =
widenPath(to, wide_to))
254 std::error_code ec = std::error_code();
255 for (
int i = 0; i < 2000; i++) {
256 if (::MoveFileExW(wide_from.
begin(), wide_to.
begin(),
257 MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING))
258 return std::error_code();
259 DWORD LastError = ::GetLastError();
261 if (LastError != ERROR_ACCESS_DENIED)
272 std::error_code
resize_file(
int FD, uint64_t Size) {
273 #ifdef HAVE__CHSIZE_S
274 errno_t
error = ::_chsize_s(FD, Size);
276 errno_t error = ::_chsize(FD, Size);
278 return std::error_code(error, std::generic_category());
284 if (std::error_code EC =
widenPath(Path, PathUtf16))
287 DWORD Attributes = ::GetFileAttributesW(PathUtf16.
begin());
289 if (Attributes == INVALID_FILE_ATTRIBUTES) {
291 DWORD LastError = ::GetLastError();
292 if (LastError != ERROR_FILE_NOT_FOUND &&
293 LastError != ERROR_PATH_NOT_FOUND)
301 return std::error_code();
306 return A.FileIndexHigh == B.FileIndexHigh &&
307 A.FileIndexLow == B.FileIndexLow &&
308 A.FileSizeHigh == B.FileSizeHigh &&
309 A.FileSizeLow == B.FileSizeLow &&
310 A.LastWriteTimeHigh == B.LastWriteTimeHigh &&
311 A.LastWriteTimeLow == B.LastWriteTimeLow &&
312 A.VolumeSerialNumber == B.VolumeSerialNumber;
316 file_status fsA, fsB;
317 if (std::error_code ec =
status(A, fsA))
319 if (std::error_code ec =
status(B, fsB))
322 return std::error_code();
325 static bool isReservedName(
StringRef path) {
328 static const char *sReservedNames[] = {
"nul",
"con",
"prn",
"aux",
329 "com1",
"com2",
"com3",
"com4",
"com5",
"com6",
330 "com7",
"com8",
"com9",
"lpt1",
"lpt2",
"lpt3",
331 "lpt4",
"lpt5",
"lpt6",
"lpt7",
"lpt8",
"lpt9" };
348 static std::error_code getStatus(HANDLE FileHandle, file_status &Result) {
349 if (FileHandle == INVALID_HANDLE_VALUE)
350 goto handle_status_error;
352 switch (::GetFileType(FileHandle)) {
355 case FILE_TYPE_UNKNOWN: {
356 DWORD Err = ::GetLastError();
360 return std::error_code();
366 return std::error_code();
369 return std::error_code();
372 BY_HANDLE_FILE_INFORMATION Info;
373 if (!::GetFileInformationByHandle(FileHandle, &Info))
374 goto handle_status_error;
377 file_type Type = (Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
381 file_status(Type, Info.ftLastWriteTime.dwHighDateTime,
382 Info.ftLastWriteTime.dwLowDateTime,
383 Info.dwVolumeSerialNumber, Info.nFileSizeHigh,
384 Info.nFileSizeLow, Info.nFileIndexHigh, Info.nFileIndexLow);
385 return std::error_code();
389 DWORD LastError = ::GetLastError();
390 if (LastError == ERROR_FILE_NOT_FOUND ||
391 LastError == ERROR_PATH_NOT_FOUND)
393 else if (LastError == ERROR_SHARING_VIOLATION)
400 std::error_code
status(
const Twine &path, file_status &result) {
405 if (isReservedName(path8)) {
407 return std::error_code();
410 if (std::error_code ec =
widenPath(path8, path_utf16))
413 DWORD attr = ::GetFileAttributesW(path_utf16.
begin());
414 if (attr == INVALID_FILE_ATTRIBUTES)
415 return getStatus(INVALID_HANDLE_VALUE, result);
418 if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
420 ::CreateFileW(path_utf16.
begin(),
422 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
425 FILE_FLAG_BACKUP_SEMANTICS,
428 return getStatus(INVALID_HANDLE_VALUE, result);
432 ::CreateFileW(path_utf16.
begin(), 0,
433 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
434 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0));
436 return getStatus(INVALID_HANDLE_VALUE, result);
438 return getStatus(h, result);
441 std::error_code
status(
int FD, file_status &Result) {
442 HANDLE FileHandle =
reinterpret_cast<HANDLE
>(_get_osfhandle(FD));
443 return getStatus(FileHandle, Result);
448 UI.QuadPart = Time.toWin32Time();
450 FT.dwLowDateTime = UI.LowPart;
451 FT.dwHighDateTime = UI.HighPart;
452 HANDLE FileHandle =
reinterpret_cast<HANDLE
>(_get_osfhandle(FD));
453 if (!SetFileTime(FileHandle, NULL, &FT, &FT))
455 return std::error_code();
458 std::error_code mapped_file_region::init(
int FD, uint64_t Offset,
461 if (Size > std::numeric_limits<SIZE_T>::max())
464 HANDLE FileHandle =
reinterpret_cast<HANDLE
>(_get_osfhandle(FD));
465 if (FileHandle == INVALID_HANDLE_VALUE)
470 case readonly: flprotect = PAGE_READONLY;
break;
471 case readwrite: flprotect = PAGE_READWRITE;
break;
472 case priv: flprotect = PAGE_WRITECOPY;
break;
475 HANDLE FileMappingHandle =
476 ::CreateFileMappingW(FileHandle, 0, flprotect,
477 (Offset + Size) >> 32,
478 (Offset + Size) & 0xffffffff,
480 if (FileMappingHandle == NULL) {
485 DWORD dwDesiredAccess;
487 case readonly: dwDesiredAccess = FILE_MAP_READ;
break;
488 case readwrite: dwDesiredAccess = FILE_MAP_WRITE;
break;
489 case priv: dwDesiredAccess = FILE_MAP_COPY;
break;
491 Mapping = ::MapViewOfFile(FileMappingHandle,
496 if (Mapping == NULL) {
498 ::CloseHandle(FileMappingHandle);
503 MEMORY_BASIC_INFORMATION mbi;
504 SIZE_T Result = VirtualQuery(Mapping, &mbi,
sizeof(mbi));
507 ::UnmapViewOfFile(Mapping);
508 ::CloseHandle(FileMappingHandle);
511 Size = mbi.RegionSize;
516 ::CloseHandle(FileMappingHandle);
517 return std::error_code();
520 mapped_file_region::mapped_file_region(
int fd, mapmode mode, uint64_t length,
521 uint64_t offset, std::error_code &ec)
522 : Size(length), Mapping() {
523 ec =
init(fd, offset, mode);
528 mapped_file_region::~mapped_file_region() {
530 ::UnmapViewOfFile(Mapping);
534 assert(Mapping &&
"Mapping failed but used anyway!");
538 char *mapped_file_region::data()
const {
539 assert(Mapping &&
"Mapping failed but used anyway!");
540 return reinterpret_cast<char*
>(Mapping);
543 const char *mapped_file_region::const_data()
const {
544 assert(Mapping &&
"Mapping failed but used anyway!");
545 return reinterpret_cast<const char*
>(Mapping);
548 int mapped_file_region::alignment() {
550 ::GetSystemInfo(&SysInfo);
551 return SysInfo.dwAllocationGranularity;
558 if (std::error_code ec =
widenPath(path, path_utf16))
562 if (path_utf16.
size() > 0 &&
564 path_utf16[path.
size() - 1] != L
':') {
572 WIN32_FIND_DATAW FirstFind;
577 size_t FilenameLen = ::wcslen(FirstFind.cFileName);
578 while ((FilenameLen == 1 && FirstFind.cFileName[0] == L
'.') ||
579 (FilenameLen == 2 && FirstFind.cFileName[0] == L
'.' &&
580 FirstFind.cFileName[1] == L
'.'))
581 if (!::FindNextFileW(FindHandle, &FirstFind)) {
582 DWORD LastError = ::GetLastError();
584 if (LastError == ERROR_NO_MORE_FILES)
588 FilenameLen = ::wcslen(FirstFind.cFileName);
592 if (std::error_code ec =
593 UTF16ToUTF8(FirstFind.cFileName, ::wcslen(FirstFind.cFileName),
594 directory_entry_name_utf8))
597 it.IterationHandle =
intptr_t(FindHandle.take());
599 path::append(directory_entry_path, directory_entry_name_utf8);
600 it.CurrentEntry = directory_entry(directory_entry_path);
602 return std::error_code();
606 if (it.IterationHandle != 0)
609 it.IterationHandle = 0;
610 it.CurrentEntry = directory_entry();
611 return std::error_code();
615 WIN32_FIND_DATAW FindData;
616 if (!::FindNextFileW(HANDLE(it.IterationHandle), &FindData)) {
617 DWORD LastError = ::GetLastError();
619 if (LastError == ERROR_NO_MORE_FILES)
624 size_t FilenameLen = ::wcslen(FindData.cFileName);
625 if ((FilenameLen == 1 && FindData.cFileName[0] == L
'.') ||
626 (FilenameLen == 2 && FindData.cFileName[0] == L
'.' &&
627 FindData.cFileName[1] == L
'.'))
631 if (std::error_code ec =
632 UTF16ToUTF8(FindData.cFileName, ::wcslen(FindData.cFileName),
633 directory_entry_path_utf8))
636 it.CurrentEntry.replace_filename(
Twine(directory_entry_path_utf8));
637 return std::error_code();
643 if (std::error_code EC =
widenPath(Name, PathUTF16))
646 HANDLE
H = ::CreateFileW(PathUTF16.
begin(), GENERIC_READ,
647 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
648 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
649 if (H == INVALID_HANDLE_VALUE) {
650 DWORD LastError = ::GetLastError();
655 if (LastError != ERROR_ACCESS_DENIED)
662 int FD = ::_open_osfhandle(
intptr_t(H), 0);
669 return std::error_code();
676 "Cannot specify both 'excl' and 'append' file creation flags!");
680 if (std::error_code EC =
widenPath(Name, PathUTF16))
683 DWORD CreationDisposition;
685 CreationDisposition = CREATE_NEW;
687 CreationDisposition = OPEN_ALWAYS;
689 CreationDisposition = CREATE_ALWAYS;
691 DWORD Access = GENERIC_WRITE;
693 Access |= GENERIC_READ;
695 HANDLE H = ::CreateFileW(PathUTF16.
begin(), Access,
696 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
697 CreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
699 if (H == INVALID_HANDLE_VALUE) {
700 DWORD LastError = ::GetLastError();
705 if (LastError != ERROR_ACCESS_DENIED)
713 if (Flags & F_Append)
714 OpenFlags |= _O_APPEND;
717 OpenFlags |= _O_TEXT;
719 int FD = ::_open_osfhandle(
intptr_t(H), OpenFlags);
726 return std::error_code();
733 wchar_t Path[MAX_PATH];
734 if (::SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0,
768 const char *EnvironmentVariables[] = {
"TMP",
"TEMP",
"USERPROFILE"};
769 for (
const char *Env : EnvironmentVariables) {
770 if (getTempDirEnvVar(Env, Res))
777 (void)ErasedOnReboot;
782 if (getTempDirEnvVar(Result))
786 const char *DefaultResult =
"C:\\TEMP";
787 Result.
append(DefaultResult, DefaultResult + strlen(DefaultResult));
795 int len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8.
begin(),
804 len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8.
begin(),
815 return std::error_code();
819 std::error_code UTF16ToCodePage(
unsigned codepage,
const wchar_t *utf16,
824 int len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, utf8.
begin(),
834 len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, utf8.
data(),
835 utf8.
size(), NULL, NULL);
845 return std::error_code();
848 std::error_code
UTF16ToUTF8(
const wchar_t *utf16,
size_t utf16_len,
850 return UTF16ToCodePage(CP_UTF8, utf16, utf16_len, utf8);
853 std::error_code
UTF16ToCurCP(
const wchar_t *utf16,
size_t utf16_len,
855 return UTF16ToCodePage(CP_ACP, utf16, utf16_len, utf8);
void toVector(SmallVectorImpl< char > &Out) const
Append the concatenated string into the given SmallString or SmallVector.
void push_back(const T &Elt)
const_iterator end(StringRef path)
Get end iterator over path.
F_Append - When opening a file, if it already exists append to the existing file instead of returning...
size_t capacity() const
Return the total number of elements in the currently allocated buffer.
size_t size() const
size - Get the string size.
F_Excl - When opening a file, this flag makes raw_fd_ostream report an error if the file already exis...
UniqueID getUniqueID() const
std::error_code current_path(SmallVectorImpl< char > &result)
Get the current path.
const_iterator begin(StringRef path)
Get begin iterator over path.
void reserve(size_type N)
bool status_known(file_status s)
Is status available?
std::error_code directory_iterator_increment(DirIterState &)
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
void remove_filename(SmallVectorImpl< char > &path)
Remove the last component from path unless it is the root dir.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
std::error_code make_error_code(BitcodeError E)
bool is_absolute(const Twine &path)
Is path absolute?
May access map via data and modify it. Written to path.
May only access map via const_data as read only.
bool is_separator(char value)
Check whether the given char is a path separator on the host OS.
std::error_code create_directory(const Twine &path, bool IgnoreExisting=true)
Create the directory in path.
std::error_code create_link(const Twine &to, const Twine &from)
Create a link from from to to.
Open the file for read and write.
static std::error_code error(DiagnosticHandlerFunction DiagnosticHandler, std::error_code EC, const Twine &Message)
std::string getMainExecutable(const char *argv0, void *MainExecAddr)
Return the path to the main executable, given the value of argv[0] from program startup and the addre...
LLVM_CONSTEXPR size_t array_lengthof(T(&)[N])
Find the length of an array.
void append(in_iter S, in_iter E)
Append from an iterator pair.
initializer< Ty > init(const Ty &Val)
The instances of the Type class are immutable: once they are created, they are never changed...
std::error_code directory_iterator_construct(DirIterState &, StringRef)
std::error_code mapWindowsError(unsigned EV)
std::error_code UTF8ToUTF16(StringRef utf8, SmallVectorImpl< wchar_t > &utf16)
std::error_code resize_file(int FD, uint64_t Size)
Resize path to size.
bool startswith(StringRef Prefix) const
startswith - Check if this string starts with the given Prefix.
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time)
Set the file modification and access time.
bool is_directory(file_status status)
Does status represent a directory?
std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, SmallVectorImpl< char > &utf8)
std::error_code rename(const Twine &from, const Twine &to)
Rename from to to.
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
This returns the twine as a single StringRef if it can be represented as such.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len, SmallVectorImpl< char > &utf8)
Convert from UTF16 to the current code page used in the system.
The file should be opened in text mode on platforms that make this distinction.
May modify via data, but changes are lost on destruction.
void set_size(size_type N)
Set the array size to N, which the current array must have enough capacity for.
std::error_code directory_iterator_destruct(DirIterState &)
pointer data()
Return a pointer to the vector's buffer, even if empty().
file_type
An enumeration for the file system's view of the type.
std::error_code openFileForRead(const Twine &Name, int &ResultFD)
bool equals_lower(StringRef RHS) const
equals_lower - Check for string equality, ignoring case.
void system_temp_directory(bool erasedOnReboot, SmallVectorImpl< char > &result)
Get the typical temporary directory for the system, e.g., "/var/tmp" or "C:/TEMP".
bool equivalent(file_status A, file_status B)
Do file_status's represent the same thing?
TimeValue getLastModificationTime() const
bool home_directory(SmallVectorImpl< char > &result)
Get the user's home directory.
std::error_code access(const Twine &Path, AccessMode Mode)
Can the file be accessed?
StringRef - Represent a constant reference to a string, i.e.
std::error_code status(const Twine &path, file_status &result)
Get file status as if by POSIX stat().
std::error_code widenPath(const Twine &Path8, SmallVectorImpl< wchar_t > &Path16)
bool empty() const
empty - Check if the string is empty.
std::error_code openFileForWrite(const Twine &Name, int &ResultFD, OpenFlags Flags, unsigned Mode=0666)