LLVM API Documentation

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