LLVM API Documentation

Windows/Path.inc
Go to the documentation of this file.
00001 //===- llvm/Support/Windows/Path.inc - Windows Path Impl --------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the Windows specific implementation of the Path API.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 //===----------------------------------------------------------------------===//
00015 //=== WARNING: Implementation here must contain only generic Windows code that
00016 //===          is guaranteed to work on *all* Windows variants.
00017 //===----------------------------------------------------------------------===//
00018 
00019 #include "llvm/ADT/STLExtras.h"
00020 #include "llvm/Support/WindowsError.h"
00021 #include <fcntl.h>
00022 #include <io.h>
00023 #include <sys/stat.h>
00024 #include <sys/types.h>
00025 
00026 // These two headers must be included last, and make sure shlobj is required
00027 // after Windows.h to make sure it picks up our definition of _WIN32_WINNT
00028 #include "WindowsSupport.h"
00029 #include <shlobj.h>
00030 
00031 #undef max
00032 
00033 // MinGW doesn't define this.
00034 #ifndef _ERRNO_T_DEFINED
00035 #define _ERRNO_T_DEFINED
00036 typedef int errno_t;
00037 #endif
00038 
00039 #ifdef _MSC_VER
00040 # pragma comment(lib, "advapi32.lib")  // This provides CryptAcquireContextW.
00041 #endif
00042 
00043 using namespace llvm;
00044 
00045 using llvm::sys::windows::UTF8ToUTF16;
00046 using llvm::sys::windows::UTF16ToUTF8;
00047 
00048 static std::error_code windows_error(DWORD E) {
00049   return mapWindowsError(E);
00050 }
00051 
00052 static bool is_separator(const wchar_t value) {
00053   switch (value) {
00054   case L'\\':
00055   case L'/':
00056     return true;
00057   default:
00058     return false;
00059   }
00060 }
00061 
00062 namespace llvm {
00063 namespace sys  {
00064 namespace fs {
00065 
00066 std::string getMainExecutable(const char *argv0, void *MainExecAddr) {
00067   SmallVector<wchar_t, MAX_PATH> PathName;
00068   DWORD Size = ::GetModuleFileNameW(NULL, PathName.data(), PathName.capacity());
00069 
00070   // A zero return value indicates a failure other than insufficient space.
00071   if (Size == 0)
00072     return "";
00073 
00074   // Insufficient space is determined by a return value equal to the size of
00075   // the buffer passed in.
00076   if (Size == PathName.capacity())
00077     return "";
00078 
00079   // On success, GetModuleFileNameW returns the number of characters written to
00080   // the buffer not including the NULL terminator.
00081   PathName.set_size(Size);
00082 
00083   // Convert the result from UTF-16 to UTF-8.
00084   SmallVector<char, MAX_PATH> PathNameUTF8;
00085   if (UTF16ToUTF8(PathName.data(), PathName.size(), PathNameUTF8))
00086     return "";
00087 
00088   return std::string(PathNameUTF8.data());
00089 }
00090 
00091 UniqueID file_status::getUniqueID() const {
00092   // The file is uniquely identified by the volume serial number along
00093   // with the 64-bit file identifier.
00094   uint64_t FileID = (static_cast<uint64_t>(FileIndexHigh) << 32ULL) |
00095                     static_cast<uint64_t>(FileIndexLow);
00096 
00097   return UniqueID(VolumeSerialNumber, FileID);
00098 }
00099 
00100 TimeValue file_status::getLastModificationTime() const {
00101   ULARGE_INTEGER UI;
00102   UI.LowPart = LastWriteTimeLow;
00103   UI.HighPart = LastWriteTimeHigh;
00104 
00105   TimeValue Ret;
00106   Ret.fromWin32Time(UI.QuadPart);
00107   return Ret;
00108 }
00109 
00110 std::error_code current_path(SmallVectorImpl<char> &result) {
00111   SmallVector<wchar_t, MAX_PATH> cur_path;
00112   DWORD len = MAX_PATH;
00113 
00114   do {
00115     cur_path.reserve(len);
00116     len = ::GetCurrentDirectoryW(cur_path.capacity(), cur_path.data());
00117 
00118     // A zero return value indicates a failure other than insufficient space.
00119     if (len == 0)
00120       return windows_error(::GetLastError());
00121 
00122     // If there's insufficient space, the len returned is larger than the len
00123     // given.
00124   } while (len > cur_path.capacity());
00125 
00126   // On success, GetCurrentDirectoryW returns the number of characters not
00127   // including the null-terminator.
00128   cur_path.set_size(len);
00129   return UTF16ToUTF8(cur_path.begin(), cur_path.size(), result);
00130 }
00131 
00132 std::error_code create_directory(const Twine &path, bool IgnoreExisting) {
00133   SmallString<128> path_storage;
00134   SmallVector<wchar_t, 128> path_utf16;
00135 
00136   if (std::error_code ec =
00137           UTF8ToUTF16(path.toStringRef(path_storage), path_utf16))
00138     return ec;
00139 
00140   if (!::CreateDirectoryW(path_utf16.begin(), NULL)) {
00141     DWORD LastError = ::GetLastError();
00142     if (LastError != ERROR_ALREADY_EXISTS || !IgnoreExisting)
00143       return windows_error(LastError);
00144   }
00145 
00146   return std::error_code();
00147 }
00148 
00149 // We can't use symbolic links for windows.
00150 std::error_code create_link(const Twine &to, const Twine &from) {
00151   // Get arguments.
00152   SmallString<128> from_storage;
00153   SmallString<128> to_storage;
00154   StringRef f = from.toStringRef(from_storage);
00155   StringRef t = to.toStringRef(to_storage);
00156 
00157   // Convert to utf-16.
00158   SmallVector<wchar_t, 128> wide_from;
00159   SmallVector<wchar_t, 128> wide_to;
00160   if (std::error_code ec = UTF8ToUTF16(f, wide_from))
00161     return ec;
00162   if (std::error_code ec = UTF8ToUTF16(t, wide_to))
00163     return ec;
00164 
00165   if (!::CreateHardLinkW(wide_from.begin(), wide_to.begin(), NULL))
00166     return windows_error(::GetLastError());
00167 
00168   return std::error_code();
00169 }
00170 
00171 std::error_code remove(const Twine &path, bool IgnoreNonExisting) {
00172   SmallString<128> path_storage;
00173   SmallVector<wchar_t, 128> path_utf16;
00174 
00175   file_status ST;
00176   if (std::error_code EC = status(path, ST)) {
00177     if (EC != errc::no_such_file_or_directory || !IgnoreNonExisting)
00178       return EC;
00179     return std::error_code();
00180   }
00181 
00182   if (std::error_code ec =
00183           UTF8ToUTF16(path.toStringRef(path_storage), path_utf16))
00184     return ec;
00185 
00186   if (ST.type() == file_type::directory_file) {
00187     if (!::RemoveDirectoryW(c_str(path_utf16))) {
00188       std::error_code EC = windows_error(::GetLastError());
00189       if (EC != errc::no_such_file_or_directory || !IgnoreNonExisting)
00190         return EC;
00191     }
00192     return std::error_code();
00193   }
00194   if (!::DeleteFileW(c_str(path_utf16))) {
00195     std::error_code EC = windows_error(::GetLastError());
00196     if (EC != errc::no_such_file_or_directory || !IgnoreNonExisting)
00197       return EC;
00198   }
00199   return std::error_code();
00200 }
00201 
00202 std::error_code rename(const Twine &from, const Twine &to) {
00203   // Get arguments.
00204   SmallString<128> from_storage;
00205   SmallString<128> to_storage;
00206   StringRef f = from.toStringRef(from_storage);
00207   StringRef t = to.toStringRef(to_storage);
00208 
00209   // Convert to utf-16.
00210   SmallVector<wchar_t, 128> wide_from;
00211   SmallVector<wchar_t, 128> wide_to;
00212   if (std::error_code ec = UTF8ToUTF16(f, wide_from))
00213     return ec;
00214   if (std::error_code ec = UTF8ToUTF16(t, wide_to))
00215     return ec;
00216 
00217   std::error_code ec = std::error_code();
00218   for (int i = 0; i < 2000; i++) {
00219     if (::MoveFileExW(wide_from.begin(), wide_to.begin(),
00220                       MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING))
00221       return std::error_code();
00222     DWORD LastError = ::GetLastError();
00223     if (LastError != ERROR_ACCESS_DENIED)
00224       break;
00225     // Retry MoveFile() at ACCESS_DENIED.
00226     // System scanners (eg. indexer) might open the source file when
00227     // It is written and closed.
00228     ::Sleep(1);
00229   }
00230 
00231   return ec;
00232 }
00233 
00234 std::error_code resize_file(const Twine &path, uint64_t size) {
00235   SmallString<128> path_storage;
00236   SmallVector<wchar_t, 128> path_utf16;
00237 
00238   if (std::error_code ec =
00239           UTF8ToUTF16(path.toStringRef(path_storage), path_utf16))
00240     return ec;
00241 
00242   int fd = ::_wopen(path_utf16.begin(), O_BINARY | _O_RDWR, S_IWRITE);
00243   if (fd == -1)
00244     return std::error_code(errno, std::generic_category());
00245 #ifdef HAVE__CHSIZE_S
00246   errno_t error = ::_chsize_s(fd, size);
00247 #else
00248   errno_t error = ::_chsize(fd, size);
00249 #endif
00250   ::close(fd);
00251   return std::error_code(error, std::generic_category());
00252 }
00253 
00254 std::error_code access(const Twine &Path, AccessMode Mode) {
00255   SmallString<128> PathStorage;
00256   SmallVector<wchar_t, 128> PathUtf16;
00257 
00258   if (std::error_code EC =
00259           UTF8ToUTF16(Path.toStringRef(PathStorage), PathUtf16))
00260     return EC;
00261 
00262   DWORD Attributes = ::GetFileAttributesW(PathUtf16.begin());
00263 
00264   if (Attributes == INVALID_FILE_ATTRIBUTES) {
00265     // See if the file didn't actually exist.
00266     DWORD LastError = ::GetLastError();
00267     if (LastError != ERROR_FILE_NOT_FOUND &&
00268         LastError != ERROR_PATH_NOT_FOUND)
00269       return windows_error(LastError);
00270     return errc::no_such_file_or_directory;
00271   }
00272 
00273   if (Mode == AccessMode::Write && (Attributes & FILE_ATTRIBUTE_READONLY))
00274     return errc::permission_denied;
00275 
00276   return std::error_code();
00277 }
00278 
00279 bool equivalent(file_status A, file_status B) {
00280   assert(status_known(A) && status_known(B));
00281   return A.FileIndexHigh      == B.FileIndexHigh &&
00282          A.FileIndexLow       == B.FileIndexLow &&
00283          A.FileSizeHigh       == B.FileSizeHigh &&
00284          A.FileSizeLow        == B.FileSizeLow &&
00285          A.LastWriteTimeHigh  == B.LastWriteTimeHigh &&
00286          A.LastWriteTimeLow   == B.LastWriteTimeLow &&
00287          A.VolumeSerialNumber == B.VolumeSerialNumber;
00288 }
00289 
00290 std::error_code equivalent(const Twine &A, const Twine &B, bool &result) {
00291   file_status fsA, fsB;
00292   if (std::error_code ec = status(A, fsA))
00293     return ec;
00294   if (std::error_code ec = status(B, fsB))
00295     return ec;
00296   result = equivalent(fsA, fsB);
00297   return std::error_code();
00298 }
00299 
00300 static bool isReservedName(StringRef path) {
00301   // This list of reserved names comes from MSDN, at:
00302   // http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx
00303   static const char *sReservedNames[] = { "nul", "con", "prn", "aux",
00304                               "com1", "com2", "com3", "com4", "com5", "com6",
00305                               "com7", "com8", "com9", "lpt1", "lpt2", "lpt3",
00306                               "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9" };
00307 
00308   // First, check to see if this is a device namespace, which always
00309   // starts with \\.\, since device namespaces are not legal file paths.
00310   if (path.startswith("\\\\.\\"))
00311     return true;
00312 
00313   // Then compare against the list of ancient reserved names
00314   for (size_t i = 0; i < array_lengthof(sReservedNames); ++i) {
00315     if (path.equals_lower(sReservedNames[i]))
00316       return true;
00317   }
00318 
00319   // The path isn't what we consider reserved.
00320   return false;
00321 }
00322 
00323 static std::error_code getStatus(HANDLE FileHandle, file_status &Result) {
00324   if (FileHandle == INVALID_HANDLE_VALUE)
00325     goto handle_status_error;
00326 
00327   switch (::GetFileType(FileHandle)) {
00328   default:
00329     llvm_unreachable("Don't know anything about this file type");
00330   case FILE_TYPE_UNKNOWN: {
00331     DWORD Err = ::GetLastError();
00332     if (Err != NO_ERROR)
00333       return windows_error(Err);
00334     Result = file_status(file_type::type_unknown);
00335     return std::error_code();
00336   }
00337   case FILE_TYPE_DISK:
00338     break;
00339   case FILE_TYPE_CHAR:
00340     Result = file_status(file_type::character_file);
00341     return std::error_code();
00342   case FILE_TYPE_PIPE:
00343     Result = file_status(file_type::fifo_file);
00344     return std::error_code();
00345   }
00346 
00347   BY_HANDLE_FILE_INFORMATION Info;
00348   if (!::GetFileInformationByHandle(FileHandle, &Info))
00349     goto handle_status_error;
00350 
00351   {
00352     file_type Type = (Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
00353                          ? file_type::directory_file
00354                          : file_type::regular_file;
00355     Result =
00356         file_status(Type, Info.ftLastWriteTime.dwHighDateTime,
00357                     Info.ftLastWriteTime.dwLowDateTime,
00358                     Info.dwVolumeSerialNumber, Info.nFileSizeHigh,
00359                     Info.nFileSizeLow, Info.nFileIndexHigh, Info.nFileIndexLow);
00360     return std::error_code();
00361   }
00362 
00363 handle_status_error:
00364   DWORD LastError = ::GetLastError();
00365   if (LastError == ERROR_FILE_NOT_FOUND ||
00366       LastError == ERROR_PATH_NOT_FOUND)
00367     Result = file_status(file_type::file_not_found);
00368   else if (LastError == ERROR_SHARING_VIOLATION)
00369     Result = file_status(file_type::type_unknown);
00370   else
00371     Result = file_status(file_type::status_error);
00372   return windows_error(LastError);
00373 }
00374 
00375 std::error_code status(const Twine &path, file_status &result) {
00376   SmallString<128> path_storage;
00377   SmallVector<wchar_t, 128> path_utf16;
00378 
00379   StringRef path8 = path.toStringRef(path_storage);
00380   if (isReservedName(path8)) {
00381     result = file_status(file_type::character_file);
00382     return std::error_code();
00383   }
00384 
00385   if (std::error_code ec = UTF8ToUTF16(path8, path_utf16))
00386     return ec;
00387 
00388   DWORD attr = ::GetFileAttributesW(path_utf16.begin());
00389   if (attr == INVALID_FILE_ATTRIBUTES)
00390     return getStatus(INVALID_HANDLE_VALUE, result);
00391 
00392   // Handle reparse points.
00393   if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
00394     ScopedFileHandle h(
00395       ::CreateFileW(path_utf16.begin(),
00396                     0, // Attributes only.
00397                     FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
00398                     NULL,
00399                     OPEN_EXISTING,
00400                     FILE_FLAG_BACKUP_SEMANTICS,
00401                     0));
00402     if (!h)
00403       return getStatus(INVALID_HANDLE_VALUE, result);
00404   }
00405 
00406   ScopedFileHandle h(
00407       ::CreateFileW(path_utf16.begin(), 0, // Attributes only.
00408                     FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
00409                     NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0));
00410     if (!h)
00411       return getStatus(INVALID_HANDLE_VALUE, result);
00412 
00413     return getStatus(h, result);
00414 }
00415 
00416 std::error_code status(int FD, file_status &Result) {
00417   HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
00418   return getStatus(FileHandle, Result);
00419 }
00420 
00421 std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time) {
00422   ULARGE_INTEGER UI;
00423   UI.QuadPart = Time.toWin32Time();
00424   FILETIME FT;
00425   FT.dwLowDateTime = UI.LowPart;
00426   FT.dwHighDateTime = UI.HighPart;
00427   HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
00428   if (!SetFileTime(FileHandle, NULL, &FT, &FT))
00429     return windows_error(::GetLastError());
00430   return std::error_code();
00431 }
00432 
00433 std::error_code mapped_file_region::init(int FD, bool CloseFD, uint64_t Offset) {
00434   FileDescriptor = FD;
00435   // Make sure that the requested size fits within SIZE_T.
00436   if (Size > std::numeric_limits<SIZE_T>::max()) {
00437     if (FileDescriptor) {
00438       if (CloseFD)
00439         _close(FileDescriptor);
00440     } else
00441       ::CloseHandle(FileHandle);
00442     return make_error_code(errc::invalid_argument);
00443   }
00444 
00445   DWORD flprotect;
00446   switch (Mode) {
00447   case readonly:  flprotect = PAGE_READONLY; break;
00448   case readwrite: flprotect = PAGE_READWRITE; break;
00449   case priv:      flprotect = PAGE_WRITECOPY; break;
00450   }
00451 
00452   FileMappingHandle =
00453       ::CreateFileMappingW(FileHandle, 0, flprotect,
00454                            (Offset + Size) >> 32,
00455                            (Offset + Size) & 0xffffffff,
00456                            0);
00457   if (FileMappingHandle == NULL) {
00458     std::error_code ec = windows_error(GetLastError());
00459     if (FileDescriptor) {
00460       if (CloseFD)
00461         _close(FileDescriptor);
00462     } else
00463       ::CloseHandle(FileHandle);
00464     return ec;
00465   }
00466 
00467   DWORD dwDesiredAccess;
00468   switch (Mode) {
00469   case readonly:  dwDesiredAccess = FILE_MAP_READ; break;
00470   case readwrite: dwDesiredAccess = FILE_MAP_WRITE; break;
00471   case priv:      dwDesiredAccess = FILE_MAP_COPY; break;
00472   }
00473   Mapping = ::MapViewOfFile(FileMappingHandle,
00474                             dwDesiredAccess,
00475                             Offset >> 32,
00476                             Offset & 0xffffffff,
00477                             Size);
00478   if (Mapping == NULL) {
00479     std::error_code ec = windows_error(GetLastError());
00480     ::CloseHandle(FileMappingHandle);
00481     if (FileDescriptor) {
00482       if (CloseFD)
00483         _close(FileDescriptor);
00484     } else
00485       ::CloseHandle(FileHandle);
00486     return ec;
00487   }
00488 
00489   if (Size == 0) {
00490     MEMORY_BASIC_INFORMATION mbi;
00491     SIZE_T Result = VirtualQuery(Mapping, &mbi, sizeof(mbi));
00492     if (Result == 0) {
00493       std::error_code ec = windows_error(GetLastError());
00494       ::UnmapViewOfFile(Mapping);
00495       ::CloseHandle(FileMappingHandle);
00496       if (FileDescriptor) {
00497         if (CloseFD)
00498           _close(FileDescriptor);
00499       } else
00500         ::CloseHandle(FileHandle);
00501       return ec;
00502     }
00503     Size = mbi.RegionSize;
00504   }
00505 
00506   // Close all the handles except for the view. It will keep the other handles
00507   // alive.
00508   ::CloseHandle(FileMappingHandle);
00509   if (FileDescriptor) {
00510     if (CloseFD)
00511       _close(FileDescriptor); // Also closes FileHandle.
00512   } else
00513     ::CloseHandle(FileHandle);
00514   return std::error_code();
00515 }
00516 
00517 mapped_file_region::mapped_file_region(const Twine &path,
00518                                        mapmode mode,
00519                                        uint64_t length,
00520                                        uint64_t offset,
00521                                        std::error_code &ec)
00522   : Mode(mode)
00523   , Size(length)
00524   , Mapping()
00525   , FileDescriptor()
00526   , FileHandle(INVALID_HANDLE_VALUE)
00527   , FileMappingHandle() {
00528   SmallString<128> path_storage;
00529   SmallVector<wchar_t, 128> path_utf16;
00530 
00531   // Convert path to UTF-16.
00532   if ((ec = UTF8ToUTF16(path.toStringRef(path_storage), path_utf16)))
00533     return;
00534 
00535   // Get file handle for creating a file mapping.
00536   FileHandle = ::CreateFileW(c_str(path_utf16),
00537                              Mode == readonly ? GENERIC_READ
00538                                               : GENERIC_READ | GENERIC_WRITE,
00539                              Mode == readonly ? FILE_SHARE_READ
00540                                               : 0,
00541                              0,
00542                              Mode == readonly ? OPEN_EXISTING
00543                                               : OPEN_ALWAYS,
00544                              Mode == readonly ? FILE_ATTRIBUTE_READONLY
00545                                               : FILE_ATTRIBUTE_NORMAL,
00546                              0);
00547   if (FileHandle == INVALID_HANDLE_VALUE) {
00548     ec = windows_error(::GetLastError());
00549     return;
00550   }
00551 
00552   FileDescriptor = 0;
00553   ec = init(FileDescriptor, true, offset);
00554   if (ec) {
00555     Mapping = FileMappingHandle = 0;
00556     FileHandle = INVALID_HANDLE_VALUE;
00557     FileDescriptor = 0;
00558   }
00559 }
00560 
00561 mapped_file_region::mapped_file_region(int fd,
00562                                        bool closefd,
00563                                        mapmode mode,
00564                                        uint64_t length,
00565                                        uint64_t offset,
00566                                        std::error_code &ec)
00567   : Mode(mode)
00568   , Size(length)
00569   , Mapping()
00570   , FileDescriptor(fd)
00571   , FileHandle(INVALID_HANDLE_VALUE)
00572   , FileMappingHandle() {
00573   FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
00574   if (FileHandle == INVALID_HANDLE_VALUE) {
00575     if (closefd)
00576       _close(FileDescriptor);
00577     FileDescriptor = 0;
00578     ec = make_error_code(errc::bad_file_descriptor);
00579     return;
00580   }
00581 
00582   ec = init(FileDescriptor, closefd, offset);
00583   if (ec) {
00584     Mapping = FileMappingHandle = 0;
00585     FileHandle = INVALID_HANDLE_VALUE;
00586     FileDescriptor = 0;
00587   }
00588 }
00589 
00590 mapped_file_region::~mapped_file_region() {
00591   if (Mapping)
00592     ::UnmapViewOfFile(Mapping);
00593 }
00594 
00595 mapped_file_region::mapped_file_region(mapped_file_region &&other)
00596   : Mode(other.Mode)
00597   , Size(other.Size)
00598   , Mapping(other.Mapping)
00599   , FileDescriptor(other.FileDescriptor)
00600   , FileHandle(other.FileHandle)
00601   , FileMappingHandle(other.FileMappingHandle) {
00602   other.Mapping = other.FileMappingHandle = 0;
00603   other.FileHandle = INVALID_HANDLE_VALUE;
00604   other.FileDescriptor = 0;
00605 }
00606 
00607 mapped_file_region::mapmode mapped_file_region::flags() const {
00608   assert(Mapping && "Mapping failed but used anyway!");
00609   return Mode;
00610 }
00611 
00612 uint64_t mapped_file_region::size() const {
00613   assert(Mapping && "Mapping failed but used anyway!");
00614   return Size;
00615 }
00616 
00617 char *mapped_file_region::data() const {
00618   assert(Mode != readonly && "Cannot get non-const data for readonly mapping!");
00619   assert(Mapping && "Mapping failed but used anyway!");
00620   return reinterpret_cast<char*>(Mapping);
00621 }
00622 
00623 const char *mapped_file_region::const_data() const {
00624   assert(Mapping && "Mapping failed but used anyway!");
00625   return reinterpret_cast<const char*>(Mapping);
00626 }
00627 
00628 int mapped_file_region::alignment() {
00629   SYSTEM_INFO SysInfo;
00630   ::GetSystemInfo(&SysInfo);
00631   return SysInfo.dwAllocationGranularity;
00632 }
00633 
00634 std::error_code detail::directory_iterator_construct(detail::DirIterState &it,
00635                                                 StringRef path){
00636   SmallVector<wchar_t, 128> path_utf16;
00637 
00638   if (std::error_code ec = UTF8ToUTF16(path, path_utf16))
00639     return ec;
00640 
00641   // Convert path to the format that Windows is happy with.
00642   if (path_utf16.size() > 0 &&
00643       !is_separator(path_utf16[path.size() - 1]) &&
00644       path_utf16[path.size() - 1] != L':') {
00645     path_utf16.push_back(L'\\');
00646     path_utf16.push_back(L'*');
00647   } else {
00648     path_utf16.push_back(L'*');
00649   }
00650 
00651   //  Get the first directory entry.
00652   WIN32_FIND_DATAW FirstFind;
00653   ScopedFindHandle FindHandle(::FindFirstFileW(c_str(path_utf16), &FirstFind));
00654   if (!FindHandle)
00655     return windows_error(::GetLastError());
00656 
00657   size_t FilenameLen = ::wcslen(FirstFind.cFileName);
00658   while ((FilenameLen == 1 && FirstFind.cFileName[0] == L'.') ||
00659          (FilenameLen == 2 && FirstFind.cFileName[0] == L'.' &&
00660                               FirstFind.cFileName[1] == L'.'))
00661     if (!::FindNextFileW(FindHandle, &FirstFind)) {
00662       DWORD LastError = ::GetLastError();
00663       // Check for end.
00664       if (LastError == ERROR_NO_MORE_FILES)
00665         return detail::directory_iterator_destruct(it);
00666       return windows_error(LastError);
00667     } else
00668       FilenameLen = ::wcslen(FirstFind.cFileName);
00669 
00670   // Construct the current directory entry.
00671   SmallString<128> directory_entry_name_utf8;
00672   if (std::error_code ec =
00673           UTF16ToUTF8(FirstFind.cFileName, ::wcslen(FirstFind.cFileName),
00674                       directory_entry_name_utf8))
00675     return ec;
00676 
00677   it.IterationHandle = intptr_t(FindHandle.take());
00678   SmallString<128> directory_entry_path(path);
00679   path::append(directory_entry_path, directory_entry_name_utf8.str());
00680   it.CurrentEntry = directory_entry(directory_entry_path.str());
00681 
00682   return std::error_code();
00683 }
00684 
00685 std::error_code detail::directory_iterator_destruct(detail::DirIterState &it) {
00686   if (it.IterationHandle != 0)
00687     // Closes the handle if it's valid.
00688     ScopedFindHandle close(HANDLE(it.IterationHandle));
00689   it.IterationHandle = 0;
00690   it.CurrentEntry = directory_entry();
00691   return std::error_code();
00692 }
00693 
00694 std::error_code detail::directory_iterator_increment(detail::DirIterState &it) {
00695   WIN32_FIND_DATAW FindData;
00696   if (!::FindNextFileW(HANDLE(it.IterationHandle), &FindData)) {
00697     DWORD LastError = ::GetLastError();
00698     // Check for end.
00699     if (LastError == ERROR_NO_MORE_FILES)
00700       return detail::directory_iterator_destruct(it);
00701     return windows_error(LastError);
00702   }
00703 
00704   size_t FilenameLen = ::wcslen(FindData.cFileName);
00705   if ((FilenameLen == 1 && FindData.cFileName[0] == L'.') ||
00706       (FilenameLen == 2 && FindData.cFileName[0] == L'.' &&
00707                            FindData.cFileName[1] == L'.'))
00708     return directory_iterator_increment(it);
00709 
00710   SmallString<128> directory_entry_path_utf8;
00711   if (std::error_code ec =
00712           UTF16ToUTF8(FindData.cFileName, ::wcslen(FindData.cFileName),
00713                       directory_entry_path_utf8))
00714     return ec;
00715 
00716   it.CurrentEntry.replace_filename(Twine(directory_entry_path_utf8));
00717   return std::error_code();
00718 }
00719 
00720 std::error_code openFileForRead(const Twine &Name, int &ResultFD) {
00721   SmallString<128> PathStorage;
00722   SmallVector<wchar_t, 128> PathUTF16;
00723 
00724   if (std::error_code EC =
00725           UTF8ToUTF16(Name.toStringRef(PathStorage), PathUTF16))
00726     return EC;
00727 
00728   HANDLE H = ::CreateFileW(PathUTF16.begin(), GENERIC_READ,
00729                            FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
00730                            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
00731   if (H == INVALID_HANDLE_VALUE) {
00732     DWORD LastError = ::GetLastError();
00733     std::error_code EC = windows_error(LastError);
00734     // Provide a better error message when trying to open directories.
00735     // This only runs if we failed to open the file, so there is probably
00736     // no performances issues.
00737     if (LastError != ERROR_ACCESS_DENIED)
00738       return EC;
00739     if (is_directory(Name))
00740       return make_error_code(errc::is_a_directory);
00741     return EC;
00742   }
00743 
00744   int FD = ::_open_osfhandle(intptr_t(H), 0);
00745   if (FD == -1) {
00746     ::CloseHandle(H);
00747     return windows_error(ERROR_INVALID_HANDLE);
00748   }
00749 
00750   ResultFD = FD;
00751   return std::error_code();
00752 }
00753 
00754 std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
00755                             sys::fs::OpenFlags Flags, unsigned Mode) {
00756   // Verify that we don't have both "append" and "excl".
00757   assert((!(Flags & sys::fs::F_Excl) || !(Flags & sys::fs::F_Append)) &&
00758          "Cannot specify both 'excl' and 'append' file creation flags!");
00759 
00760   SmallString<128> PathStorage;
00761   SmallVector<wchar_t, 128> PathUTF16;
00762 
00763   if (std::error_code EC =
00764           UTF8ToUTF16(Name.toStringRef(PathStorage), PathUTF16))
00765     return EC;
00766 
00767   DWORD CreationDisposition;
00768   if (Flags & F_Excl)
00769     CreationDisposition = CREATE_NEW;
00770   else if (Flags & F_Append)
00771     CreationDisposition = OPEN_ALWAYS;
00772   else
00773     CreationDisposition = CREATE_ALWAYS;
00774 
00775   DWORD Access = GENERIC_WRITE;
00776   if (Flags & F_RW)
00777     Access |= GENERIC_READ;
00778 
00779   HANDLE H = ::CreateFileW(PathUTF16.begin(), Access,
00780                            FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
00781                            CreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
00782 
00783   if (H == INVALID_HANDLE_VALUE) {
00784     DWORD LastError = ::GetLastError();
00785     std::error_code EC = windows_error(LastError);
00786     // Provide a better error message when trying to open directories.
00787     // This only runs if we failed to open the file, so there is probably
00788     // no performances issues.
00789     if (LastError != ERROR_ACCESS_DENIED)
00790       return EC;
00791     if (is_directory(Name))
00792       return make_error_code(errc::is_a_directory);
00793     return EC;
00794   }
00795 
00796   int OpenFlags = 0;
00797   if (Flags & F_Append)
00798     OpenFlags |= _O_APPEND;
00799 
00800   if (Flags & F_Text)
00801     OpenFlags |= _O_TEXT;
00802 
00803   int FD = ::_open_osfhandle(intptr_t(H), OpenFlags);
00804   if (FD == -1) {
00805     ::CloseHandle(H);
00806     return windows_error(ERROR_INVALID_HANDLE);
00807   }
00808 
00809   ResultFD = FD;
00810   return std::error_code();
00811 }
00812 } // end namespace fs
00813 
00814 namespace path {
00815 
00816 bool home_directory(SmallVectorImpl<char> &result) {
00817   wchar_t Path[MAX_PATH];
00818   if (::SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0,
00819                          /*SHGFP_TYPE_CURRENT*/0, Path) != S_OK)
00820     return false;
00821 
00822   if (UTF16ToUTF8(Path, ::wcslen(Path), result))
00823     return false;
00824 
00825   return true;
00826 }
00827 
00828 static bool getTempDirEnvVar(const char *Var, SmallVectorImpl<char> &Res) {
00829   SmallVector<wchar_t, 128> NameUTF16;
00830   if (windows::UTF8ToUTF16(Var, NameUTF16))
00831     return false;
00832 
00833   SmallVector<wchar_t, 1024> Buf;
00834   size_t Size = 1024;
00835   do {
00836     Buf.reserve(Size);
00837     Size =
00838         GetEnvironmentVariableW(NameUTF16.data(), Buf.data(), Buf.capacity());
00839     if (Size == 0)
00840       return false;
00841 
00842     // Try again with larger buffer.
00843   } while (Size > Buf.capacity());
00844   Buf.set_size(Size);
00845 
00846   if (windows::UTF16ToUTF8(Buf.data(), Size, Res))
00847     return false;
00848   return true;
00849 }
00850 
00851 static bool getTempDirEnvVar(SmallVectorImpl<char> &Res) {
00852   const char *EnvironmentVariables[] = {"TMP", "TEMP", "USERPROFILE"};
00853   for (const char *Env : EnvironmentVariables) {
00854     if (getTempDirEnvVar(Env, Res))
00855       return true;
00856   }
00857   return false;
00858 }
00859 
00860 void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) {
00861   (void)ErasedOnReboot;
00862   Result.clear();
00863 
00864   // Check whether the temporary directory is specified by an environment
00865   // variable.
00866   if (getTempDirEnvVar(Result))
00867     return;
00868 
00869   // Fall back to a system default.
00870   const char *DefaultResult = "C:\\TEMP";
00871   Result.append(DefaultResult, DefaultResult + strlen(DefaultResult));
00872 }
00873 } // end namespace path
00874 
00875 namespace windows {
00876 std::error_code UTF8ToUTF16(llvm::StringRef utf8,
00877                             llvm::SmallVectorImpl<wchar_t> &utf16) {
00878   if (!utf8.empty()) {
00879     int len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8.begin(),
00880                                     utf8.size(), utf16.begin(), 0);
00881 
00882     if (len == 0)
00883       return windows_error(::GetLastError());
00884 
00885     utf16.reserve(len + 1);
00886     utf16.set_size(len);
00887 
00888     len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8.begin(),
00889                                 utf8.size(), utf16.begin(), utf16.size());
00890 
00891     if (len == 0)
00892       return windows_error(::GetLastError());
00893   }
00894 
00895   // Make utf16 null terminated.
00896   utf16.push_back(0);
00897   utf16.pop_back();
00898 
00899   return std::error_code();
00900 }
00901 
00902 static
00903 std::error_code UTF16ToCodePage(unsigned codepage, const wchar_t *utf16,
00904                                 size_t utf16_len,
00905                                 llvm::SmallVectorImpl<char> &utf8) {
00906   if (utf16_len) {
00907     // Get length.
00908     int len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, utf8.begin(),
00909                                     0, NULL, NULL);
00910 
00911     if (len == 0)
00912       return windows_error(::GetLastError());
00913 
00914     utf8.reserve(len);
00915     utf8.set_size(len);
00916 
00917     // Now do the actual conversion.
00918     len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, utf8.data(),
00919                                 utf8.size(), NULL, NULL);
00920 
00921     if (len == 0)
00922       return windows_error(::GetLastError());
00923   }
00924 
00925   // Make utf8 null terminated.
00926   utf8.push_back(0);
00927   utf8.pop_back();
00928 
00929   return std::error_code();
00930 }
00931 
00932 std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len,
00933                             llvm::SmallVectorImpl<char> &utf8) {
00934   return UTF16ToCodePage(CP_UTF8, utf16, utf16_len, utf8);
00935 }
00936 
00937 std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len,
00938                              llvm::SmallVectorImpl<char> &utf8) {
00939   return UTF16ToCodePage(CP_ACP, utf16, utf16_len, utf8);
00940 }
00941 } // end namespace windows
00942 } // end namespace sys
00943 } // end namespace llvm