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