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