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