Home | History | Annotate | Download | only in Windows
      1 //===- llvm/Support/Windows/PathV2.inc - Windows Path Impl ------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file implements the Windows specific implementation of the PathV2 API.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 //===----------------------------------------------------------------------===//
     15 //=== WARNING: Implementation here must contain only generic Windows code that
     16 //===          is guaranteed to work on *all* Windows variants.
     17 //===----------------------------------------------------------------------===//
     18 
     19 #include "Windows.h"
     20 #include <fcntl.h>
     21 #include <io.h>
     22 #include <sys/stat.h>
     23 #include <sys/types.h>
     24 
     25 #undef max
     26 
     27 // MinGW doesn't define this.
     28 #ifndef _ERRNO_T_DEFINED
     29 #define _ERRNO_T_DEFINED
     30 typedef int errno_t;
     31 #endif
     32 
     33 using namespace llvm;
     34 
     35 namespace {
     36   typedef BOOLEAN (WINAPI *PtrCreateSymbolicLinkW)(
     37     /*__in*/ LPCWSTR lpSymlinkFileName,
     38     /*__in*/ LPCWSTR lpTargetFileName,
     39     /*__in*/ DWORD dwFlags);
     40 
     41   PtrCreateSymbolicLinkW create_symbolic_link_api = PtrCreateSymbolicLinkW(
     42     ::GetProcAddress(::GetModuleHandleA("kernel32.dll"),
     43                      "CreateSymbolicLinkW"));
     44 
     45   error_code UTF8ToUTF16(StringRef utf8, SmallVectorImpl<wchar_t> &utf16) {
     46     int len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
     47                                     utf8.begin(), utf8.size(),
     48                                     utf16.begin(), 0);
     49 
     50     if (len == 0)
     51       return windows_error(::GetLastError());
     52 
     53     utf16.reserve(len + 1);
     54     utf16.set_size(len);
     55 
     56     len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
     57                                     utf8.begin(), utf8.size(),
     58                                     utf16.begin(), utf16.size());
     59 
     60     if (len == 0)
     61       return windows_error(::GetLastError());
     62 
     63     // Make utf16 null terminated.
     64     utf16.push_back(0);
     65     utf16.pop_back();
     66 
     67     return error_code::success();
     68   }
     69 
     70   error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len,
     71                                SmallVectorImpl<char> &utf8) {
     72     // Get length.
     73     int len = ::WideCharToMultiByte(CP_UTF8, 0,
     74                                     utf16, utf16_len,
     75                                     utf8.begin(), 0,
     76                                     NULL, NULL);
     77 
     78     if (len == 0)
     79       return windows_error(::GetLastError());
     80 
     81     utf8.reserve(len);
     82     utf8.set_size(len);
     83 
     84     // Now do the actual conversion.
     85     len = ::WideCharToMultiByte(CP_UTF8, 0,
     86                                 utf16, utf16_len,
     87                                 utf8.data(), utf8.size(),
     88                                 NULL, NULL);
     89 
     90     if (len == 0)
     91       return windows_error(::GetLastError());
     92 
     93     // Make utf8 null terminated.
     94     utf8.push_back(0);
     95     utf8.pop_back();
     96 
     97     return error_code::success();
     98   }
     99 
    100   error_code TempDir(SmallVectorImpl<wchar_t> &result) {
    101   retry_temp_dir:
    102     DWORD len = ::GetTempPathW(result.capacity(), result.begin());
    103 
    104     if (len == 0)
    105       return windows_error(::GetLastError());
    106 
    107     if (len > result.capacity()) {
    108       result.reserve(len);
    109       goto retry_temp_dir;
    110     }
    111 
    112     result.set_size(len);
    113     return error_code::success();
    114   }
    115 
    116   bool is_separator(const wchar_t value) {
    117     switch (value) {
    118     case L'\\':
    119     case L'/':
    120       return true;
    121     default:
    122       return false;
    123     }
    124   }
    125 }
    126 
    127 namespace llvm {
    128 namespace sys  {
    129 namespace fs {
    130 
    131 error_code current_path(SmallVectorImpl<char> &result) {
    132   SmallVector<wchar_t, 128> cur_path;
    133   cur_path.reserve(128);
    134 retry_cur_dir:
    135   DWORD len = ::GetCurrentDirectoryW(cur_path.capacity(), cur_path.data());
    136 
    137   // A zero return value indicates a failure other than insufficient space.
    138   if (len == 0)
    139     return windows_error(::GetLastError());
    140 
    141   // If there's insufficient space, the len returned is larger than the len
    142   // given.
    143   if (len > cur_path.capacity()) {
    144     cur_path.reserve(len);
    145     goto retry_cur_dir;
    146   }
    147 
    148   cur_path.set_size(len);
    149   // cur_path now holds the current directory in utf-16. Convert to utf-8.
    150 
    151   // Find out how much space we need. Sadly, this function doesn't return the
    152   // size needed unless you tell it the result size is 0, which means you
    153   // _always_ have to call it twice.
    154   len = ::WideCharToMultiByte(CP_UTF8, 0,
    155                               cur_path.data(), cur_path.size(),
    156                               result.data(), 0,
    157                               NULL, NULL);
    158 
    159   if (len == 0)
    160     return make_error_code(windows_error(::GetLastError()));
    161 
    162   result.reserve(len);
    163   result.set_size(len);
    164   // Now do the actual conversion.
    165   len = ::WideCharToMultiByte(CP_UTF8, 0,
    166                               cur_path.data(), cur_path.size(),
    167                               result.data(), result.size(),
    168                               NULL, NULL);
    169   if (len == 0)
    170     return windows_error(::GetLastError());
    171 
    172   return error_code::success();
    173 }
    174 
    175 error_code copy_file(const Twine &from, const Twine &to, copy_option copt) {
    176   // Get arguments.
    177   SmallString<128> from_storage;
    178   SmallString<128> to_storage;
    179   StringRef f = from.toStringRef(from_storage);
    180   StringRef t = to.toStringRef(to_storage);
    181 
    182   // Convert to utf-16.
    183   SmallVector<wchar_t, 128> wide_from;
    184   SmallVector<wchar_t, 128> wide_to;
    185   if (error_code ec = UTF8ToUTF16(f, wide_from)) return ec;
    186   if (error_code ec = UTF8ToUTF16(t, wide_to)) return ec;
    187 
    188   // Copy the file.
    189   BOOL res = ::CopyFileW(wide_from.begin(), wide_to.begin(),
    190                          copt != copy_option::overwrite_if_exists);
    191 
    192   if (res == 0)
    193     return windows_error(::GetLastError());
    194 
    195   return error_code::success();
    196 }
    197 
    198 error_code create_directory(const Twine &path, bool &existed) {
    199   SmallString<128> path_storage;
    200   SmallVector<wchar_t, 128> path_utf16;
    201 
    202   if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage),
    203                                   path_utf16))
    204     return ec;
    205 
    206   if (!::CreateDirectoryW(path_utf16.begin(), NULL)) {
    207     error_code ec = windows_error(::GetLastError());
    208     if (ec == windows_error::already_exists)
    209       existed = true;
    210     else
    211       return ec;
    212   } else
    213     existed = false;
    214 
    215   return error_code::success();
    216 }
    217 
    218 error_code create_hard_link(const Twine &to, const Twine &from) {
    219   // Get arguments.
    220   SmallString<128> from_storage;
    221   SmallString<128> to_storage;
    222   StringRef f = from.toStringRef(from_storage);
    223   StringRef t = to.toStringRef(to_storage);
    224 
    225   // Convert to utf-16.
    226   SmallVector<wchar_t, 128> wide_from;
    227   SmallVector<wchar_t, 128> wide_to;
    228   if (error_code ec = UTF8ToUTF16(f, wide_from)) return ec;
    229   if (error_code ec = UTF8ToUTF16(t, wide_to)) return ec;
    230 
    231   if (!::CreateHardLinkW(wide_from.begin(), wide_to.begin(), NULL))
    232     return windows_error(::GetLastError());
    233 
    234   return error_code::success();
    235 }
    236 
    237 error_code create_symlink(const Twine &to, const Twine &from) {
    238   // Only do it if the function is available at runtime.
    239   if (!create_symbolic_link_api)
    240     return make_error_code(errc::function_not_supported);
    241 
    242   // Get arguments.
    243   SmallString<128> from_storage;
    244   SmallString<128> to_storage;
    245   StringRef f = from.toStringRef(from_storage);
    246   StringRef t = to.toStringRef(to_storage);
    247 
    248   // Convert to utf-16.
    249   SmallVector<wchar_t, 128> wide_from;
    250   SmallVector<wchar_t, 128> wide_to;
    251   if (error_code ec = UTF8ToUTF16(f, wide_from)) return ec;
    252   if (error_code ec = UTF8ToUTF16(t, wide_to)) return ec;
    253 
    254   if (!create_symbolic_link_api(wide_from.begin(), wide_to.begin(), 0))
    255     return windows_error(::GetLastError());
    256 
    257   return error_code::success();
    258 }
    259 
    260 error_code remove(const Twine &path, bool &existed) {
    261   SmallString<128> path_storage;
    262   SmallVector<wchar_t, 128> path_utf16;
    263 
    264   file_status st;
    265   if (error_code ec = status(path, st))
    266     return ec;
    267 
    268   if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage),
    269                                   path_utf16))
    270     return ec;
    271 
    272   if (st.type() == file_type::directory_file) {
    273     if (!::RemoveDirectoryW(c_str(path_utf16))) {
    274       error_code ec = windows_error(::GetLastError());
    275       if (ec != windows_error::file_not_found)
    276         return ec;
    277       existed = false;
    278     } else
    279       existed = true;
    280   } else {
    281     if (!::DeleteFileW(c_str(path_utf16))) {
    282       error_code ec = windows_error(::GetLastError());
    283       if (ec != windows_error::file_not_found)
    284         return ec;
    285       existed = false;
    286     } else
    287       existed = true;
    288   }
    289 
    290   return error_code::success();
    291 }
    292 
    293 error_code rename(const Twine &from, const Twine &to) {
    294   // Get arguments.
    295   SmallString<128> from_storage;
    296   SmallString<128> to_storage;
    297   StringRef f = from.toStringRef(from_storage);
    298   StringRef t = to.toStringRef(to_storage);
    299 
    300   // Convert to utf-16.
    301   SmallVector<wchar_t, 128> wide_from;
    302   SmallVector<wchar_t, 128> wide_to;
    303   if (error_code ec = UTF8ToUTF16(f, wide_from)) return ec;
    304   if (error_code ec = UTF8ToUTF16(t, wide_to)) return ec;
    305 
    306   error_code ec = error_code::success();
    307   for (int i = 0; i < 2000; i++) {
    308     if (::MoveFileExW(wide_from.begin(), wide_to.begin(),
    309                       MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING))
    310       return error_code::success();
    311     ec = windows_error(::GetLastError());
    312     if (ec != windows_error::access_denied)
    313       break;
    314     // Retry MoveFile() at ACCESS_DENIED.
    315     // System scanners (eg. indexer) might open the source file when
    316     // It is written and closed.
    317     ::Sleep(1);
    318   }
    319 
    320   return ec;
    321 }
    322 
    323 error_code resize_file(const Twine &path, uint64_t size) {
    324   SmallString<128> path_storage;
    325   SmallVector<wchar_t, 128> path_utf16;
    326 
    327   if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage),
    328                                   path_utf16))
    329     return ec;
    330 
    331   int fd = ::_wopen(path_utf16.begin(), O_BINARY | _O_RDWR, S_IWRITE);
    332   if (fd == -1)
    333     return error_code(errno, generic_category());
    334 #ifdef HAVE__CHSIZE_S
    335   errno_t error = ::_chsize_s(fd, size);
    336 #else
    337   errno_t error = ::_chsize(fd, size);
    338 #endif
    339   ::close(fd);
    340   return error_code(error, generic_category());
    341 }
    342 
    343 error_code exists(const Twine &path, bool &result) {
    344   SmallString<128> path_storage;
    345   SmallVector<wchar_t, 128> path_utf16;
    346 
    347   if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage),
    348                                   path_utf16))
    349     return ec;
    350 
    351   DWORD attributes = ::GetFileAttributesW(path_utf16.begin());
    352 
    353   if (attributes == INVALID_FILE_ATTRIBUTES) {
    354     // See if the file didn't actually exist.
    355     error_code ec = make_error_code(windows_error(::GetLastError()));
    356     if (ec != windows_error::file_not_found &&
    357         ec != windows_error::path_not_found)
    358       return ec;
    359     result = false;
    360   } else
    361     result = true;
    362   return error_code::success();
    363 }
    364 
    365 bool equivalent(file_status A, file_status B) {
    366   assert(status_known(A) && status_known(B));
    367   return A.FileIndexHigh      == B.FileIndexHigh &&
    368          A.FileIndexLow       == B.FileIndexLow &&
    369          A.FileSizeHigh       == B.FileSizeHigh &&
    370          A.FileSizeLow        == B.FileSizeLow &&
    371          A.LastWriteTimeHigh  == B.LastWriteTimeHigh &&
    372          A.LastWriteTimeLow   == B.LastWriteTimeLow &&
    373          A.VolumeSerialNumber == B.VolumeSerialNumber;
    374 }
    375 
    376 error_code equivalent(const Twine &A, const Twine &B, bool &result) {
    377   file_status fsA, fsB;
    378   if (error_code ec = status(A, fsA)) return ec;
    379   if (error_code ec = status(B, fsB)) return ec;
    380   result = equivalent(fsA, fsB);
    381   return error_code::success();
    382 }
    383 
    384 error_code file_size(const Twine &path, uint64_t &result) {
    385   SmallString<128> path_storage;
    386   SmallVector<wchar_t, 128> path_utf16;
    387 
    388   if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage),
    389                                   path_utf16))
    390     return ec;
    391 
    392   WIN32_FILE_ATTRIBUTE_DATA FileData;
    393   if (!::GetFileAttributesExW(path_utf16.begin(),
    394                               ::GetFileExInfoStandard,
    395                               &FileData))
    396     return windows_error(::GetLastError());
    397 
    398   result =
    399     (uint64_t(FileData.nFileSizeHigh) << (sizeof(FileData.nFileSizeLow) * 8))
    400     + FileData.nFileSizeLow;
    401 
    402   return error_code::success();
    403 }
    404 
    405 static bool isReservedName(StringRef path) {
    406   // This list of reserved names comes from MSDN, at:
    407   // http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx
    408   static const char *sReservedNames[] = { "nul", "con", "prn", "aux",
    409                               "com1", "com2", "com3", "com4", "com5", "com6",
    410                               "com7", "com8", "com9", "lpt1", "lpt2", "lpt3",
    411                               "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9" };
    412 
    413   // First, check to see if this is a device namespace, which always
    414   // starts with \\.\, since device namespaces are not legal file paths.
    415   if (path.startswith("\\\\.\\"))
    416     return true;
    417 
    418   // Then compare against the list of ancient reserved names
    419   for (size_t i = 0; i < sizeof(sReservedNames) / sizeof(const char *); ++i) {
    420     if (path.equals_lower(sReservedNames[i]))
    421       return true;
    422   }
    423 
    424   // The path isn't what we consider reserved.
    425   return false;
    426 }
    427 
    428 error_code status(const Twine &path, file_status &result) {
    429   SmallString<128> path_storage;
    430   SmallVector<wchar_t, 128> path_utf16;
    431 
    432   StringRef path8 = path.toStringRef(path_storage);
    433   if (isReservedName(path8)) {
    434     result = file_status(file_type::character_file);
    435     return error_code::success();
    436   }
    437 
    438   if (error_code ec = UTF8ToUTF16(path8, path_utf16))
    439     return ec;
    440 
    441   DWORD attr = ::GetFileAttributesW(path_utf16.begin());
    442   if (attr == INVALID_FILE_ATTRIBUTES)
    443     goto handle_status_error;
    444 
    445   // Handle reparse points.
    446   if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
    447     ScopedFileHandle h(
    448       ::CreateFileW(path_utf16.begin(),
    449                     0, // Attributes only.
    450                     FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
    451                     NULL,
    452                     OPEN_EXISTING,
    453                     FILE_FLAG_BACKUP_SEMANTICS,
    454                     0));
    455     if (!h)
    456       goto handle_status_error;
    457   }
    458 
    459   if (attr & FILE_ATTRIBUTE_DIRECTORY)
    460     result = file_status(file_type::directory_file);
    461   else {
    462     result = file_status(file_type::regular_file);
    463     ScopedFileHandle h(
    464       ::CreateFileW(path_utf16.begin(),
    465                     0, // Attributes only.
    466                     FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
    467                     NULL,
    468                     OPEN_EXISTING,
    469                     FILE_FLAG_BACKUP_SEMANTICS,
    470                     0));
    471     if (!h)
    472       goto handle_status_error;
    473     BY_HANDLE_FILE_INFORMATION Info;
    474     if (!::GetFileInformationByHandle(h, &Info))
    475       goto handle_status_error;
    476     result.FileIndexHigh      = Info.nFileIndexHigh;
    477     result.FileIndexLow       = Info.nFileIndexLow;
    478     result.FileSizeHigh       = Info.nFileSizeHigh;
    479     result.FileSizeLow        = Info.nFileSizeLow;
    480     result.LastWriteTimeHigh  = Info.ftLastWriteTime.dwHighDateTime;
    481     result.LastWriteTimeLow   = Info.ftLastWriteTime.dwLowDateTime;
    482     result.VolumeSerialNumber = Info.dwVolumeSerialNumber;
    483   }
    484 
    485   return error_code::success();
    486 
    487 handle_status_error:
    488   error_code ec = windows_error(::GetLastError());
    489   if (ec == windows_error::file_not_found ||
    490       ec == windows_error::path_not_found)
    491     result = file_status(file_type::file_not_found);
    492   else if (ec == windows_error::sharing_violation)
    493     result = file_status(file_type::type_unknown);
    494   else {
    495     result = file_status(file_type::status_error);
    496     return ec;
    497   }
    498 
    499   return error_code::success();
    500 }
    501 
    502 
    503 // Modifies permissions on a file.
    504 error_code permissions(const Twine &path, perms prms) {
    505 #if 0 // verify code below before enabling:
    506   // If the permissions bits are not trying to modify
    507   // "write" permissions, there is nothing to do.
    508   if (!(prms & (owner_write|group_write|others_write)))
    509     return error_code::success();
    510   
    511   SmallString<128> path_storage;
    512   SmallVector<wchar_t, 128> path_utf16;
    513 
    514   if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage),
    515                                   path_utf16))
    516     return ec;
    517 
    518   DWORD attributes = ::GetFileAttributesW(path_utf16.begin());
    519 
    520   if (prms & add_perms) {
    521     attributes &= ~FILE_ATTRIBUTE_READONLY;
    522   }
    523   else if (prms & remove_perms) {
    524     attributes |= FILE_ATTRIBUTE_READONLY;
    525   }
    526   else {
    527     assert(0 && "neither add_perms or remove_perms is set");
    528   }
    529 
    530   if ( ! ::SetFileAttributesW(path_utf16.begin(), attributes))
    531     return windows_error(::GetLastError());
    532 #endif    
    533   return error_code::success();
    534 }
    535 
    536 
    537 // FIXME: mode should be used here and default to user r/w only,
    538 // it currently comes in as a UNIX mode.
    539 error_code unique_file(const Twine &model, int &result_fd,
    540                        SmallVectorImpl<char> &result_path,
    541                        bool makeAbsolute, unsigned mode) {
    542   // Use result_path as temp storage.
    543   result_path.set_size(0);
    544   StringRef m = model.toStringRef(result_path);
    545 
    546   SmallVector<wchar_t, 128> model_utf16;
    547   if (error_code ec = UTF8ToUTF16(m, model_utf16)) return ec;
    548 
    549   if (makeAbsolute) {
    550     // Make model absolute by prepending a temp directory if it's not already.
    551     bool absolute = path::is_absolute(m);
    552 
    553     if (!absolute) {
    554       SmallVector<wchar_t, 64> temp_dir;
    555       if (error_code ec = TempDir(temp_dir)) return ec;
    556       // Handle c: by removing it.
    557       if (model_utf16.size() > 2 && model_utf16[1] == L':') {
    558         model_utf16.erase(model_utf16.begin(), model_utf16.begin() + 2);
    559       }
    560       model_utf16.insert(model_utf16.begin(), temp_dir.begin(), temp_dir.end());
    561     }
    562   }
    563 
    564   // Replace '%' with random chars. From here on, DO NOT modify model. It may be
    565   // needed if the randomly chosen path already exists.
    566   SmallVector<wchar_t, 128> random_path_utf16;
    567 
    568   // Get a Crypto Provider for CryptGenRandom.
    569   HCRYPTPROV HCPC;
    570   if (!::CryptAcquireContextW(&HCPC,
    571                               NULL,
    572                               NULL,
    573                               PROV_RSA_FULL,
    574                               CRYPT_VERIFYCONTEXT))
    575     return windows_error(::GetLastError());
    576   ScopedCryptContext CryptoProvider(HCPC);
    577 
    578 retry_random_path:
    579   random_path_utf16.set_size(0);
    580   for (SmallVectorImpl<wchar_t>::const_iterator i = model_utf16.begin(),
    581                                                 e = model_utf16.end();
    582                                                 i != e; ++i) {
    583     if (*i == L'%') {
    584       BYTE val = 0;
    585       if (!::CryptGenRandom(CryptoProvider, 1, &val))
    586           return windows_error(::GetLastError());
    587       random_path_utf16.push_back("0123456789abcdef"[val & 15]);
    588     }
    589     else
    590       random_path_utf16.push_back(*i);
    591   }
    592   // Make random_path_utf16 null terminated.
    593   random_path_utf16.push_back(0);
    594   random_path_utf16.pop_back();
    595 
    596   // Make sure we don't fall into an infinite loop by constantly trying
    597   // to create the parent path.
    598   bool TriedToCreateParent = false;
    599 
    600   // Try to create + open the path.
    601 retry_create_file:
    602   HANDLE TempFileHandle = ::CreateFileW(random_path_utf16.begin(),
    603                                         GENERIC_READ | GENERIC_WRITE,
    604                                         FILE_SHARE_READ,
    605                                         NULL,
    606                                         // Return ERROR_FILE_EXISTS if the file
    607                                         // already exists.
    608                                         CREATE_NEW,
    609                                         FILE_ATTRIBUTE_TEMPORARY,
    610                                         NULL);
    611   if (TempFileHandle == INVALID_HANDLE_VALUE) {
    612     // If the file existed, try again, otherwise, error.
    613     error_code ec = windows_error(::GetLastError());
    614     if (ec == windows_error::file_exists)
    615       goto retry_random_path;
    616     // Check for non-existing parent directories.
    617     if (ec == windows_error::path_not_found && !TriedToCreateParent) {
    618       TriedToCreateParent = true;
    619 
    620       // Create the directories using result_path as temp storage.
    621       if (error_code ec = UTF16ToUTF8(random_path_utf16.begin(),
    622                                       random_path_utf16.size(), result_path))
    623         return ec;
    624       StringRef p(result_path.begin(), result_path.size());
    625       SmallString<64> dir_to_create;
    626       for (path::const_iterator i = path::begin(p),
    627                                 e = --path::end(p); i != e; ++i) {
    628         path::append(dir_to_create, *i);
    629         bool Exists;
    630         if (error_code ec = exists(Twine(dir_to_create), Exists)) return ec;
    631         if (!Exists) {
    632           // If c: doesn't exist, bail.
    633           if (i->endswith(":"))
    634             return ec;
    635 
    636           SmallVector<wchar_t, 64> dir_to_create_utf16;
    637           if (error_code ec = UTF8ToUTF16(dir_to_create, dir_to_create_utf16))
    638             return ec;
    639 
    640           // Create the directory.
    641           if (!::CreateDirectoryW(dir_to_create_utf16.begin(), NULL))
    642             return windows_error(::GetLastError());
    643         }
    644       }
    645       goto retry_create_file;
    646     }
    647     return ec;
    648   }
    649 
    650   // Set result_path to the utf-8 representation of the path.
    651   if (error_code ec = UTF16ToUTF8(random_path_utf16.begin(),
    652                                   random_path_utf16.size(), result_path)) {
    653     ::CloseHandle(TempFileHandle);
    654     ::DeleteFileW(random_path_utf16.begin());
    655     return ec;
    656   }
    657 
    658   // Convert the Windows API file handle into a C-runtime handle.
    659   int fd = ::_open_osfhandle(intptr_t(TempFileHandle), 0);
    660   if (fd == -1) {
    661     ::CloseHandle(TempFileHandle);
    662     ::DeleteFileW(random_path_utf16.begin());
    663     // MSDN doesn't say anything about _open_osfhandle setting errno or
    664     // GetLastError(), so just return invalid_handle.
    665     return windows_error::invalid_handle;
    666   }
    667 
    668   result_fd = fd;
    669   return error_code::success();
    670 }
    671 
    672 error_code get_magic(const Twine &path, uint32_t len,
    673                      SmallVectorImpl<char> &result) {
    674   SmallString<128> path_storage;
    675   SmallVector<wchar_t, 128> path_utf16;
    676   result.set_size(0);
    677 
    678   // Convert path to UTF-16.
    679   if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage),
    680                                   path_utf16))
    681     return ec;
    682 
    683   // Open file.
    684   HANDLE file = ::CreateFileW(c_str(path_utf16),
    685                               GENERIC_READ,
    686                               FILE_SHARE_READ,
    687                               NULL,
    688                               OPEN_EXISTING,
    689                               FILE_ATTRIBUTE_READONLY,
    690                               NULL);
    691   if (file == INVALID_HANDLE_VALUE)
    692     return windows_error(::GetLastError());
    693 
    694   // Allocate buffer.
    695   result.reserve(len);
    696 
    697   // Get magic!
    698   DWORD bytes_read = 0;
    699   BOOL read_success = ::ReadFile(file, result.data(), len, &bytes_read, NULL);
    700   error_code ec = windows_error(::GetLastError());
    701   ::CloseHandle(file);
    702   if (!read_success || (bytes_read != len)) {
    703     // Set result size to the number of bytes read if it's valid.
    704     if (bytes_read <= len)
    705       result.set_size(bytes_read);
    706     // ERROR_HANDLE_EOF is mapped to errc::value_too_large.
    707     return ec;
    708   }
    709 
    710   result.set_size(len);
    711   return error_code::success();
    712 }
    713 
    714 error_code mapped_file_region::init(int FD, bool CloseFD, uint64_t Offset) {
    715   FileDescriptor = FD;
    716   // Make sure that the requested size fits within SIZE_T.
    717   if (Size > std::numeric_limits<SIZE_T>::max()) {
    718     if (FileDescriptor) {
    719       if (CloseFD)
    720         _close(FileDescriptor);
    721     } else
    722       ::CloseHandle(FileHandle);
    723     return make_error_code(errc::invalid_argument);
    724   }
    725 
    726   DWORD flprotect;
    727   switch (Mode) {
    728   case readonly:  flprotect = PAGE_READONLY; break;
    729   case readwrite: flprotect = PAGE_READWRITE; break;
    730   case priv:      flprotect = PAGE_WRITECOPY; break;
    731   default: llvm_unreachable("invalid mapping mode");
    732   }
    733 
    734   FileMappingHandle = ::CreateFileMapping(FileHandle,
    735                                           0,
    736                                           flprotect,
    737                                           Size >> 32,
    738                                           Size & 0xffffffff,
    739                                           0);
    740   if (FileMappingHandle == NULL) {
    741     error_code ec = windows_error(GetLastError());
    742     if (FileDescriptor) {
    743       if (CloseFD)
    744         _close(FileDescriptor);
    745     } else
    746       ::CloseHandle(FileHandle);
    747     return ec;
    748   }
    749 
    750   DWORD dwDesiredAccess;
    751   switch (Mode) {
    752   case readonly:  dwDesiredAccess = FILE_MAP_READ; break;
    753   case readwrite: dwDesiredAccess = FILE_MAP_WRITE; break;
    754   case priv:      dwDesiredAccess = FILE_MAP_COPY; break;
    755   default: llvm_unreachable("invalid mapping mode");
    756   }
    757   Mapping = ::MapViewOfFile(FileMappingHandle,
    758                             dwDesiredAccess,
    759                             Offset >> 32,
    760                             Offset & 0xffffffff,
    761                             Size);
    762   if (Mapping == NULL) {
    763     error_code ec = windows_error(GetLastError());
    764     ::CloseHandle(FileMappingHandle);
    765     if (FileDescriptor) {
    766       if (CloseFD)
    767         _close(FileDescriptor);
    768     } else
    769       ::CloseHandle(FileHandle);
    770     return ec;
    771   }
    772 
    773   if (Size == 0) {
    774     MEMORY_BASIC_INFORMATION mbi;
    775     SIZE_T Result = VirtualQuery(Mapping, &mbi, sizeof(mbi));
    776     if (Result == 0) {
    777       error_code ec = windows_error(GetLastError());
    778       ::UnmapViewOfFile(Mapping);
    779       ::CloseHandle(FileMappingHandle);
    780       if (FileDescriptor) {
    781         if (CloseFD)
    782           _close(FileDescriptor);
    783       } else
    784         ::CloseHandle(FileHandle);
    785       return ec;
    786     }
    787     Size = mbi.RegionSize;
    788   }
    789 
    790   // Close all the handles except for the view. It will keep the other handles
    791   // alive.
    792   ::CloseHandle(FileMappingHandle);
    793   if (FileDescriptor) {
    794     if (CloseFD)
    795       _close(FileDescriptor); // Also closes FileHandle.
    796   } else
    797     ::CloseHandle(FileHandle);
    798   return error_code::success();
    799 }
    800 
    801 mapped_file_region::mapped_file_region(const Twine &path,
    802                                        mapmode mode,
    803                                        uint64_t length,
    804                                        uint64_t offset,
    805                                        error_code &ec) 
    806   : Mode(mode)
    807   , Size(length)
    808   , Mapping()
    809   , FileDescriptor()
    810   , FileHandle(INVALID_HANDLE_VALUE)
    811   , FileMappingHandle() {
    812   SmallString<128> path_storage;
    813   SmallVector<wchar_t, 128> path_utf16;
    814 
    815   // Convert path to UTF-16.
    816   if ((ec = UTF8ToUTF16(path.toStringRef(path_storage), path_utf16)))
    817     return;
    818 
    819   // Get file handle for creating a file mapping.
    820   FileHandle = ::CreateFileW(c_str(path_utf16),
    821                              Mode == readonly ? GENERIC_READ
    822                                               : GENERIC_READ | GENERIC_WRITE,
    823                              Mode == readonly ? FILE_SHARE_READ
    824                                               : 0,
    825                              0,
    826                              Mode == readonly ? OPEN_EXISTING
    827                                               : OPEN_ALWAYS,
    828                              Mode == readonly ? FILE_ATTRIBUTE_READONLY
    829                                               : FILE_ATTRIBUTE_NORMAL,
    830                              0);
    831   if (FileHandle == INVALID_HANDLE_VALUE) {
    832     ec = windows_error(::GetLastError());
    833     return;
    834   }
    835 
    836   FileDescriptor = 0;
    837   ec = init(FileDescriptor, true, offset);
    838   if (ec) {
    839     Mapping = FileMappingHandle = 0;
    840     FileHandle = INVALID_HANDLE_VALUE;
    841     FileDescriptor = 0;
    842   }
    843 }
    844 
    845 mapped_file_region::mapped_file_region(int fd,
    846                                        bool closefd,
    847                                        mapmode mode,
    848                                        uint64_t length,
    849                                        uint64_t offset,
    850                                        error_code &ec)
    851   : Mode(mode)
    852   , Size(length)
    853   , Mapping()
    854   , FileDescriptor(fd)
    855   , FileHandle(INVALID_HANDLE_VALUE)
    856   , FileMappingHandle() {
    857   FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
    858   if (FileHandle == INVALID_HANDLE_VALUE) {
    859     if (closefd)
    860       _close(FileDescriptor);
    861     FileDescriptor = 0;
    862     ec = make_error_code(errc::bad_file_descriptor);
    863     return;
    864   }
    865 
    866   ec = init(FileDescriptor, closefd, offset);
    867   if (ec) {
    868     Mapping = FileMappingHandle = 0;
    869     FileHandle = INVALID_HANDLE_VALUE;
    870     FileDescriptor = 0;
    871   }
    872 }
    873 
    874 mapped_file_region::~mapped_file_region() {
    875   if (Mapping)
    876     ::UnmapViewOfFile(Mapping);
    877 }
    878 
    879 #if LLVM_HAS_RVALUE_REFERENCES
    880 mapped_file_region::mapped_file_region(mapped_file_region &&other)
    881   : Mode(other.Mode)
    882   , Size(other.Size)
    883   , Mapping(other.Mapping)
    884   , FileDescriptor(other.FileDescriptor)
    885   , FileHandle(other.FileHandle)
    886   , FileMappingHandle(other.FileMappingHandle) {
    887   other.Mapping = other.FileMappingHandle = 0;
    888   other.FileHandle = INVALID_HANDLE_VALUE;
    889   other.FileDescriptor = 0;
    890 }
    891 #endif
    892 
    893 mapped_file_region::mapmode mapped_file_region::flags() const {
    894   assert(Mapping && "Mapping failed but used anyway!");
    895   return Mode;
    896 }
    897 
    898 uint64_t mapped_file_region::size() const {
    899   assert(Mapping && "Mapping failed but used anyway!");
    900   return Size;
    901 }
    902 
    903 char *mapped_file_region::data() const {
    904   assert(Mode != readonly && "Cannot get non const data for readonly mapping!");
    905   assert(Mapping && "Mapping failed but used anyway!");
    906   return reinterpret_cast<char*>(Mapping);
    907 }
    908 
    909 const char *mapped_file_region::const_data() const {
    910   assert(Mapping && "Mapping failed but used anyway!");
    911   return reinterpret_cast<const char*>(Mapping);
    912 }
    913 
    914 int mapped_file_region::alignment() {
    915   SYSTEM_INFO SysInfo;
    916   ::GetSystemInfo(&SysInfo);
    917   return SysInfo.dwAllocationGranularity;
    918 }
    919 
    920 error_code detail::directory_iterator_construct(detail::DirIterState &it,
    921                                                 StringRef path){
    922   SmallVector<wchar_t, 128> path_utf16;
    923 
    924   if (error_code ec = UTF8ToUTF16(path,
    925                                   path_utf16))
    926     return ec;
    927 
    928   // Convert path to the format that Windows is happy with.
    929   if (path_utf16.size() > 0 &&
    930       !is_separator(path_utf16[path.size() - 1]) &&
    931       path_utf16[path.size() - 1] != L':') {
    932     path_utf16.push_back(L'\\');
    933     path_utf16.push_back(L'*');
    934   } else {
    935     path_utf16.push_back(L'*');
    936   }
    937 
    938   //  Get the first directory entry.
    939   WIN32_FIND_DATAW FirstFind;
    940   ScopedFindHandle FindHandle(::FindFirstFileW(c_str(path_utf16), &FirstFind));
    941   if (!FindHandle)
    942     return windows_error(::GetLastError());
    943 
    944   size_t FilenameLen = ::wcslen(FirstFind.cFileName);
    945   while ((FilenameLen == 1 && FirstFind.cFileName[0] == L'.') ||
    946          (FilenameLen == 2 && FirstFind.cFileName[0] == L'.' &&
    947                               FirstFind.cFileName[1] == L'.'))
    948     if (!::FindNextFileW(FindHandle, &FirstFind)) {
    949       error_code ec = windows_error(::GetLastError());
    950       // Check for end.
    951       if (ec == windows_error::no_more_files)
    952         return detail::directory_iterator_destruct(it);
    953       return ec;
    954     } else
    955       FilenameLen = ::wcslen(FirstFind.cFileName);
    956 
    957   // Construct the current directory entry.
    958   SmallString<128> directory_entry_name_utf8;
    959   if (error_code ec = UTF16ToUTF8(FirstFind.cFileName,
    960                                   ::wcslen(FirstFind.cFileName),
    961                                   directory_entry_name_utf8))
    962     return ec;
    963 
    964   it.IterationHandle = intptr_t(FindHandle.take());
    965   SmallString<128> directory_entry_path(path);
    966   path::append(directory_entry_path, directory_entry_name_utf8.str());
    967   it.CurrentEntry = directory_entry(directory_entry_path.str());
    968 
    969   return error_code::success();
    970 }
    971 
    972 error_code detail::directory_iterator_destruct(detail::DirIterState &it) {
    973   if (it.IterationHandle != 0)
    974     // Closes the handle if it's valid.
    975     ScopedFindHandle close(HANDLE(it.IterationHandle));
    976   it.IterationHandle = 0;
    977   it.CurrentEntry = directory_entry();
    978   return error_code::success();
    979 }
    980 
    981 error_code detail::directory_iterator_increment(detail::DirIterState &it) {
    982   WIN32_FIND_DATAW FindData;
    983   if (!::FindNextFileW(HANDLE(it.IterationHandle), &FindData)) {
    984     error_code ec = windows_error(::GetLastError());
    985     // Check for end.
    986     if (ec == windows_error::no_more_files)
    987       return detail::directory_iterator_destruct(it);
    988     return ec;
    989   }
    990 
    991   size_t FilenameLen = ::wcslen(FindData.cFileName);
    992   if ((FilenameLen == 1 && FindData.cFileName[0] == L'.') ||
    993       (FilenameLen == 2 && FindData.cFileName[0] == L'.' &&
    994                            FindData.cFileName[1] == L'.'))
    995     return directory_iterator_increment(it);
    996 
    997   SmallString<128> directory_entry_path_utf8;
    998   if (error_code ec = UTF16ToUTF8(FindData.cFileName,
    999                                   ::wcslen(FindData.cFileName),
   1000                                   directory_entry_path_utf8))
   1001     return ec;
   1002 
   1003   it.CurrentEntry.replace_filename(Twine(directory_entry_path_utf8));
   1004   return error_code::success();
   1005 }
   1006 
   1007 error_code map_file_pages(const Twine &path, off_t file_offset, size_t size,  
   1008                                             bool map_writable, void *&result) {
   1009   assert(0 && "NOT IMPLEMENTED");
   1010   return windows_error::invalid_function;
   1011 }
   1012 
   1013 error_code unmap_file_pages(void *base, size_t size) {
   1014   assert(0 && "NOT IMPLEMENTED");
   1015   return windows_error::invalid_function;
   1016 }
   1017 
   1018 
   1019 
   1020 } // end namespace fs
   1021 } // end namespace sys
   1022 } // end namespace llvm
   1023