1*9880d681SAndroid Build Coastguard Worker//===- llvm/Support/Windows/Path.inc - Windows Path Impl --------*- C++ -*-===// 2*9880d681SAndroid Build Coastguard Worker// 3*9880d681SAndroid Build Coastguard Worker// The LLVM Compiler Infrastructure 4*9880d681SAndroid Build Coastguard Worker// 5*9880d681SAndroid Build Coastguard Worker// This file is distributed under the University of Illinois Open Source 6*9880d681SAndroid Build Coastguard Worker// License. See LICENSE.TXT for details. 7*9880d681SAndroid Build Coastguard Worker// 8*9880d681SAndroid Build Coastguard Worker//===----------------------------------------------------------------------===// 9*9880d681SAndroid Build Coastguard Worker// 10*9880d681SAndroid Build Coastguard Worker// This file implements the Windows specific implementation of the Path API. 11*9880d681SAndroid Build Coastguard Worker// 12*9880d681SAndroid Build Coastguard Worker//===----------------------------------------------------------------------===// 13*9880d681SAndroid Build Coastguard Worker 14*9880d681SAndroid Build Coastguard Worker//===----------------------------------------------------------------------===// 15*9880d681SAndroid Build Coastguard Worker//=== WARNING: Implementation here must contain only generic Windows code that 16*9880d681SAndroid Build Coastguard Worker//=== is guaranteed to work on *all* Windows variants. 17*9880d681SAndroid Build Coastguard Worker//===----------------------------------------------------------------------===// 18*9880d681SAndroid Build Coastguard Worker 19*9880d681SAndroid Build Coastguard Worker#include "llvm/ADT/STLExtras.h" 20*9880d681SAndroid Build Coastguard Worker#include "llvm/Support/WindowsError.h" 21*9880d681SAndroid Build Coastguard Worker#include <fcntl.h> 22*9880d681SAndroid Build Coastguard Worker#include <io.h> 23*9880d681SAndroid Build Coastguard Worker#include <sys/stat.h> 24*9880d681SAndroid Build Coastguard Worker#include <sys/types.h> 25*9880d681SAndroid Build Coastguard Worker 26*9880d681SAndroid Build Coastguard Worker// These two headers must be included last, and make sure shlobj is required 27*9880d681SAndroid Build Coastguard Worker// after Windows.h to make sure it picks up our definition of _WIN32_WINNT 28*9880d681SAndroid Build Coastguard Worker#include "WindowsSupport.h" 29*9880d681SAndroid Build Coastguard Worker#include <shlobj.h> 30*9880d681SAndroid Build Coastguard Worker 31*9880d681SAndroid Build Coastguard Worker#undef max 32*9880d681SAndroid Build Coastguard Worker 33*9880d681SAndroid Build Coastguard Worker// MinGW doesn't define this. 34*9880d681SAndroid Build Coastguard Worker#ifndef _ERRNO_T_DEFINED 35*9880d681SAndroid Build Coastguard Worker#define _ERRNO_T_DEFINED 36*9880d681SAndroid Build Coastguard Workertypedef int errno_t; 37*9880d681SAndroid Build Coastguard Worker#endif 38*9880d681SAndroid Build Coastguard Worker 39*9880d681SAndroid Build Coastguard Worker#ifdef _MSC_VER 40*9880d681SAndroid Build Coastguard Worker# pragma comment(lib, "advapi32.lib") // This provides CryptAcquireContextW. 41*9880d681SAndroid Build Coastguard Worker# pragma comment(lib, "ole32.lib") // This provides CoTaskMemFree 42*9880d681SAndroid Build Coastguard Worker#endif 43*9880d681SAndroid Build Coastguard Worker 44*9880d681SAndroid Build Coastguard Workerusing namespace llvm; 45*9880d681SAndroid Build Coastguard Worker 46*9880d681SAndroid Build Coastguard Workerusing llvm::sys::windows::UTF8ToUTF16; 47*9880d681SAndroid Build Coastguard Workerusing llvm::sys::windows::UTF16ToUTF8; 48*9880d681SAndroid Build Coastguard Workerusing llvm::sys::path::widenPath; 49*9880d681SAndroid Build Coastguard Worker 50*9880d681SAndroid Build Coastguard Workerstatic bool is_separator(const wchar_t value) { 51*9880d681SAndroid Build Coastguard Worker switch (value) { 52*9880d681SAndroid Build Coastguard Worker case L'\\': 53*9880d681SAndroid Build Coastguard Worker case L'/': 54*9880d681SAndroid Build Coastguard Worker return true; 55*9880d681SAndroid Build Coastguard Worker default: 56*9880d681SAndroid Build Coastguard Worker return false; 57*9880d681SAndroid Build Coastguard Worker } 58*9880d681SAndroid Build Coastguard Worker} 59*9880d681SAndroid Build Coastguard Worker 60*9880d681SAndroid Build Coastguard Workernamespace llvm { 61*9880d681SAndroid Build Coastguard Workernamespace sys { 62*9880d681SAndroid Build Coastguard Workernamespace path { 63*9880d681SAndroid Build Coastguard Worker 64*9880d681SAndroid Build Coastguard Worker// Convert a UTF-8 path to UTF-16. Also, if the absolute equivalent of the 65*9880d681SAndroid Build Coastguard Worker// path is longer than CreateDirectory can tolerate, make it absolute and 66*9880d681SAndroid Build Coastguard Worker// prefixed by '\\?\'. 67*9880d681SAndroid Build Coastguard Workerstd::error_code widenPath(const Twine &Path8, 68*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<wchar_t> &Path16) { 69*9880d681SAndroid Build Coastguard Worker const size_t MaxDirLen = MAX_PATH - 12; // Must leave room for 8.3 filename. 70*9880d681SAndroid Build Coastguard Worker 71*9880d681SAndroid Build Coastguard Worker // Several operations would convert Path8 to SmallString; more efficient to 72*9880d681SAndroid Build Coastguard Worker // do it once up front. 73*9880d681SAndroid Build Coastguard Worker SmallString<128> Path8Str; 74*9880d681SAndroid Build Coastguard Worker Path8.toVector(Path8Str); 75*9880d681SAndroid Build Coastguard Worker 76*9880d681SAndroid Build Coastguard Worker // If we made this path absolute, how much longer would it get? 77*9880d681SAndroid Build Coastguard Worker size_t CurPathLen; 78*9880d681SAndroid Build Coastguard Worker if (llvm::sys::path::is_absolute(Twine(Path8Str))) 79*9880d681SAndroid Build Coastguard Worker CurPathLen = 0; // No contribution from current_path needed. 80*9880d681SAndroid Build Coastguard Worker else { 81*9880d681SAndroid Build Coastguard Worker CurPathLen = ::GetCurrentDirectoryW(0, NULL); 82*9880d681SAndroid Build Coastguard Worker if (CurPathLen == 0) 83*9880d681SAndroid Build Coastguard Worker return mapWindowsError(::GetLastError()); 84*9880d681SAndroid Build Coastguard Worker } 85*9880d681SAndroid Build Coastguard Worker 86*9880d681SAndroid Build Coastguard Worker // Would the absolute path be longer than our limit? 87*9880d681SAndroid Build Coastguard Worker if ((Path8Str.size() + CurPathLen) >= MaxDirLen && 88*9880d681SAndroid Build Coastguard Worker !Path8Str.startswith("\\\\?\\")) { 89*9880d681SAndroid Build Coastguard Worker SmallString<2*MAX_PATH> FullPath("\\\\?\\"); 90*9880d681SAndroid Build Coastguard Worker if (CurPathLen) { 91*9880d681SAndroid Build Coastguard Worker SmallString<80> CurPath; 92*9880d681SAndroid Build Coastguard Worker if (std::error_code EC = llvm::sys::fs::current_path(CurPath)) 93*9880d681SAndroid Build Coastguard Worker return EC; 94*9880d681SAndroid Build Coastguard Worker FullPath.append(CurPath); 95*9880d681SAndroid Build Coastguard Worker } 96*9880d681SAndroid Build Coastguard Worker // Traverse the requested path, canonicalizing . and .. as we go (because 97*9880d681SAndroid Build Coastguard Worker // the \\?\ prefix is documented to treat them as real components). 98*9880d681SAndroid Build Coastguard Worker // The iterators don't report separators and append() always attaches 99*9880d681SAndroid Build Coastguard Worker // preferred_separator so we don't need to call native() on the result. 100*9880d681SAndroid Build Coastguard Worker for (llvm::sys::path::const_iterator I = llvm::sys::path::begin(Path8Str), 101*9880d681SAndroid Build Coastguard Worker E = llvm::sys::path::end(Path8Str); 102*9880d681SAndroid Build Coastguard Worker I != E; ++I) { 103*9880d681SAndroid Build Coastguard Worker if (I->size() == 1 && *I == ".") 104*9880d681SAndroid Build Coastguard Worker continue; 105*9880d681SAndroid Build Coastguard Worker if (I->size() == 2 && *I == "..") 106*9880d681SAndroid Build Coastguard Worker llvm::sys::path::remove_filename(FullPath); 107*9880d681SAndroid Build Coastguard Worker else 108*9880d681SAndroid Build Coastguard Worker llvm::sys::path::append(FullPath, *I); 109*9880d681SAndroid Build Coastguard Worker } 110*9880d681SAndroid Build Coastguard Worker return UTF8ToUTF16(FullPath, Path16); 111*9880d681SAndroid Build Coastguard Worker } 112*9880d681SAndroid Build Coastguard Worker 113*9880d681SAndroid Build Coastguard Worker // Just use the caller's original path. 114*9880d681SAndroid Build Coastguard Worker return UTF8ToUTF16(Path8Str, Path16); 115*9880d681SAndroid Build Coastguard Worker} 116*9880d681SAndroid Build Coastguard Worker} // end namespace path 117*9880d681SAndroid Build Coastguard Worker 118*9880d681SAndroid Build Coastguard Workernamespace fs { 119*9880d681SAndroid Build Coastguard Worker 120*9880d681SAndroid Build Coastguard Workerstd::string getMainExecutable(const char *argv0, void *MainExecAddr) { 121*9880d681SAndroid Build Coastguard Worker SmallVector<wchar_t, MAX_PATH> PathName; 122*9880d681SAndroid Build Coastguard Worker DWORD Size = ::GetModuleFileNameW(NULL, PathName.data(), PathName.capacity()); 123*9880d681SAndroid Build Coastguard Worker 124*9880d681SAndroid Build Coastguard Worker // A zero return value indicates a failure other than insufficient space. 125*9880d681SAndroid Build Coastguard Worker if (Size == 0) 126*9880d681SAndroid Build Coastguard Worker return ""; 127*9880d681SAndroid Build Coastguard Worker 128*9880d681SAndroid Build Coastguard Worker // Insufficient space is determined by a return value equal to the size of 129*9880d681SAndroid Build Coastguard Worker // the buffer passed in. 130*9880d681SAndroid Build Coastguard Worker if (Size == PathName.capacity()) 131*9880d681SAndroid Build Coastguard Worker return ""; 132*9880d681SAndroid Build Coastguard Worker 133*9880d681SAndroid Build Coastguard Worker // On success, GetModuleFileNameW returns the number of characters written to 134*9880d681SAndroid Build Coastguard Worker // the buffer not including the NULL terminator. 135*9880d681SAndroid Build Coastguard Worker PathName.set_size(Size); 136*9880d681SAndroid Build Coastguard Worker 137*9880d681SAndroid Build Coastguard Worker // Convert the result from UTF-16 to UTF-8. 138*9880d681SAndroid Build Coastguard Worker SmallVector<char, MAX_PATH> PathNameUTF8; 139*9880d681SAndroid Build Coastguard Worker if (UTF16ToUTF8(PathName.data(), PathName.size(), PathNameUTF8)) 140*9880d681SAndroid Build Coastguard Worker return ""; 141*9880d681SAndroid Build Coastguard Worker 142*9880d681SAndroid Build Coastguard Worker return std::string(PathNameUTF8.data()); 143*9880d681SAndroid Build Coastguard Worker} 144*9880d681SAndroid Build Coastguard Worker 145*9880d681SAndroid Build Coastguard WorkerUniqueID file_status::getUniqueID() const { 146*9880d681SAndroid Build Coastguard Worker // The file is uniquely identified by the volume serial number along 147*9880d681SAndroid Build Coastguard Worker // with the 64-bit file identifier. 148*9880d681SAndroid Build Coastguard Worker uint64_t FileID = (static_cast<uint64_t>(FileIndexHigh) << 32ULL) | 149*9880d681SAndroid Build Coastguard Worker static_cast<uint64_t>(FileIndexLow); 150*9880d681SAndroid Build Coastguard Worker 151*9880d681SAndroid Build Coastguard Worker return UniqueID(VolumeSerialNumber, FileID); 152*9880d681SAndroid Build Coastguard Worker} 153*9880d681SAndroid Build Coastguard Worker 154*9880d681SAndroid Build Coastguard WorkerErrorOr<space_info> disk_space(const Twine &Path) { 155*9880d681SAndroid Build Coastguard Worker ULARGE_INTEGER Avail, Total, Free; 156*9880d681SAndroid Build Coastguard Worker if (!::GetDiskFreeSpaceExA(Path.str().c_str(), &Avail, &Total, &Free)) 157*9880d681SAndroid Build Coastguard Worker return mapWindowsError(::GetLastError()); 158*9880d681SAndroid Build Coastguard Worker space_info SpaceInfo; 159*9880d681SAndroid Build Coastguard Worker SpaceInfo.capacity = 160*9880d681SAndroid Build Coastguard Worker (static_cast<uint64_t>(Total.HighPart) << 32) + Total.LowPart; 161*9880d681SAndroid Build Coastguard Worker SpaceInfo.free = (static_cast<uint64_t>(Free.HighPart) << 32) + Free.LowPart; 162*9880d681SAndroid Build Coastguard Worker SpaceInfo.available = 163*9880d681SAndroid Build Coastguard Worker (static_cast<uint64_t>(Avail.HighPart) << 32) + Avail.LowPart; 164*9880d681SAndroid Build Coastguard Worker return SpaceInfo; 165*9880d681SAndroid Build Coastguard Worker} 166*9880d681SAndroid Build Coastguard Worker 167*9880d681SAndroid Build Coastguard WorkerTimeValue file_status::getLastAccessedTime() const { 168*9880d681SAndroid Build Coastguard Worker ULARGE_INTEGER UI; 169*9880d681SAndroid Build Coastguard Worker UI.LowPart = LastAccessedTimeLow; 170*9880d681SAndroid Build Coastguard Worker UI.HighPart = LastAccessedTimeHigh; 171*9880d681SAndroid Build Coastguard Worker 172*9880d681SAndroid Build Coastguard Worker TimeValue Ret; 173*9880d681SAndroid Build Coastguard Worker Ret.fromWin32Time(UI.QuadPart); 174*9880d681SAndroid Build Coastguard Worker return Ret; 175*9880d681SAndroid Build Coastguard Worker} 176*9880d681SAndroid Build Coastguard Worker 177*9880d681SAndroid Build Coastguard WorkerTimeValue file_status::getLastModificationTime() const { 178*9880d681SAndroid Build Coastguard Worker ULARGE_INTEGER UI; 179*9880d681SAndroid Build Coastguard Worker UI.LowPart = LastWriteTimeLow; 180*9880d681SAndroid Build Coastguard Worker UI.HighPart = LastWriteTimeHigh; 181*9880d681SAndroid Build Coastguard Worker 182*9880d681SAndroid Build Coastguard Worker TimeValue Ret; 183*9880d681SAndroid Build Coastguard Worker Ret.fromWin32Time(UI.QuadPart); 184*9880d681SAndroid Build Coastguard Worker return Ret; 185*9880d681SAndroid Build Coastguard Worker} 186*9880d681SAndroid Build Coastguard Worker 187*9880d681SAndroid Build Coastguard Workerstd::error_code current_path(SmallVectorImpl<char> &result) { 188*9880d681SAndroid Build Coastguard Worker SmallVector<wchar_t, MAX_PATH> cur_path; 189*9880d681SAndroid Build Coastguard Worker DWORD len = MAX_PATH; 190*9880d681SAndroid Build Coastguard Worker 191*9880d681SAndroid Build Coastguard Worker do { 192*9880d681SAndroid Build Coastguard Worker cur_path.reserve(len); 193*9880d681SAndroid Build Coastguard Worker len = ::GetCurrentDirectoryW(cur_path.capacity(), cur_path.data()); 194*9880d681SAndroid Build Coastguard Worker 195*9880d681SAndroid Build Coastguard Worker // A zero return value indicates a failure other than insufficient space. 196*9880d681SAndroid Build Coastguard Worker if (len == 0) 197*9880d681SAndroid Build Coastguard Worker return mapWindowsError(::GetLastError()); 198*9880d681SAndroid Build Coastguard Worker 199*9880d681SAndroid Build Coastguard Worker // If there's insufficient space, the len returned is larger than the len 200*9880d681SAndroid Build Coastguard Worker // given. 201*9880d681SAndroid Build Coastguard Worker } while (len > cur_path.capacity()); 202*9880d681SAndroid Build Coastguard Worker 203*9880d681SAndroid Build Coastguard Worker // On success, GetCurrentDirectoryW returns the number of characters not 204*9880d681SAndroid Build Coastguard Worker // including the null-terminator. 205*9880d681SAndroid Build Coastguard Worker cur_path.set_size(len); 206*9880d681SAndroid Build Coastguard Worker return UTF16ToUTF8(cur_path.begin(), cur_path.size(), result); 207*9880d681SAndroid Build Coastguard Worker} 208*9880d681SAndroid Build Coastguard Worker 209*9880d681SAndroid Build Coastguard Workerstd::error_code create_directory(const Twine &path, bool IgnoreExisting, 210*9880d681SAndroid Build Coastguard Worker perms Perms) { 211*9880d681SAndroid Build Coastguard Worker SmallVector<wchar_t, 128> path_utf16; 212*9880d681SAndroid Build Coastguard Worker 213*9880d681SAndroid Build Coastguard Worker if (std::error_code ec = widenPath(path, path_utf16)) 214*9880d681SAndroid Build Coastguard Worker return ec; 215*9880d681SAndroid Build Coastguard Worker 216*9880d681SAndroid Build Coastguard Worker if (!::CreateDirectoryW(path_utf16.begin(), NULL)) { 217*9880d681SAndroid Build Coastguard Worker DWORD LastError = ::GetLastError(); 218*9880d681SAndroid Build Coastguard Worker if (LastError != ERROR_ALREADY_EXISTS || !IgnoreExisting) 219*9880d681SAndroid Build Coastguard Worker return mapWindowsError(LastError); 220*9880d681SAndroid Build Coastguard Worker } 221*9880d681SAndroid Build Coastguard Worker 222*9880d681SAndroid Build Coastguard Worker return std::error_code(); 223*9880d681SAndroid Build Coastguard Worker} 224*9880d681SAndroid Build Coastguard Worker 225*9880d681SAndroid Build Coastguard Worker// We can't use symbolic links for windows. 226*9880d681SAndroid Build Coastguard Workerstd::error_code create_link(const Twine &to, const Twine &from) { 227*9880d681SAndroid Build Coastguard Worker // Convert to utf-16. 228*9880d681SAndroid Build Coastguard Worker SmallVector<wchar_t, 128> wide_from; 229*9880d681SAndroid Build Coastguard Worker SmallVector<wchar_t, 128> wide_to; 230*9880d681SAndroid Build Coastguard Worker if (std::error_code ec = widenPath(from, wide_from)) 231*9880d681SAndroid Build Coastguard Worker return ec; 232*9880d681SAndroid Build Coastguard Worker if (std::error_code ec = widenPath(to, wide_to)) 233*9880d681SAndroid Build Coastguard Worker return ec; 234*9880d681SAndroid Build Coastguard Worker 235*9880d681SAndroid Build Coastguard Worker if (!::CreateHardLinkW(wide_from.begin(), wide_to.begin(), NULL)) 236*9880d681SAndroid Build Coastguard Worker return mapWindowsError(::GetLastError()); 237*9880d681SAndroid Build Coastguard Worker 238*9880d681SAndroid Build Coastguard Worker return std::error_code(); 239*9880d681SAndroid Build Coastguard Worker} 240*9880d681SAndroid Build Coastguard Worker 241*9880d681SAndroid Build Coastguard Workerstd::error_code remove(const Twine &path, bool IgnoreNonExisting) { 242*9880d681SAndroid Build Coastguard Worker SmallVector<wchar_t, 128> path_utf16; 243*9880d681SAndroid Build Coastguard Worker 244*9880d681SAndroid Build Coastguard Worker file_status ST; 245*9880d681SAndroid Build Coastguard Worker if (std::error_code EC = status(path, ST)) { 246*9880d681SAndroid Build Coastguard Worker if (EC != errc::no_such_file_or_directory || !IgnoreNonExisting) 247*9880d681SAndroid Build Coastguard Worker return EC; 248*9880d681SAndroid Build Coastguard Worker return std::error_code(); 249*9880d681SAndroid Build Coastguard Worker } 250*9880d681SAndroid Build Coastguard Worker 251*9880d681SAndroid Build Coastguard Worker if (std::error_code ec = widenPath(path, path_utf16)) 252*9880d681SAndroid Build Coastguard Worker return ec; 253*9880d681SAndroid Build Coastguard Worker 254*9880d681SAndroid Build Coastguard Worker if (ST.type() == file_type::directory_file) { 255*9880d681SAndroid Build Coastguard Worker if (!::RemoveDirectoryW(c_str(path_utf16))) { 256*9880d681SAndroid Build Coastguard Worker std::error_code EC = mapWindowsError(::GetLastError()); 257*9880d681SAndroid Build Coastguard Worker if (EC != errc::no_such_file_or_directory || !IgnoreNonExisting) 258*9880d681SAndroid Build Coastguard Worker return EC; 259*9880d681SAndroid Build Coastguard Worker } 260*9880d681SAndroid Build Coastguard Worker return std::error_code(); 261*9880d681SAndroid Build Coastguard Worker } 262*9880d681SAndroid Build Coastguard Worker if (!::DeleteFileW(c_str(path_utf16))) { 263*9880d681SAndroid Build Coastguard Worker std::error_code EC = mapWindowsError(::GetLastError()); 264*9880d681SAndroid Build Coastguard Worker if (EC != errc::no_such_file_or_directory || !IgnoreNonExisting) 265*9880d681SAndroid Build Coastguard Worker return EC; 266*9880d681SAndroid Build Coastguard Worker } 267*9880d681SAndroid Build Coastguard Worker return std::error_code(); 268*9880d681SAndroid Build Coastguard Worker} 269*9880d681SAndroid Build Coastguard Worker 270*9880d681SAndroid Build Coastguard Workerstd::error_code rename(const Twine &from, const Twine &to) { 271*9880d681SAndroid Build Coastguard Worker // Convert to utf-16. 272*9880d681SAndroid Build Coastguard Worker SmallVector<wchar_t, 128> wide_from; 273*9880d681SAndroid Build Coastguard Worker SmallVector<wchar_t, 128> wide_to; 274*9880d681SAndroid Build Coastguard Worker if (std::error_code ec = widenPath(from, wide_from)) 275*9880d681SAndroid Build Coastguard Worker return ec; 276*9880d681SAndroid Build Coastguard Worker if (std::error_code ec = widenPath(to, wide_to)) 277*9880d681SAndroid Build Coastguard Worker return ec; 278*9880d681SAndroid Build Coastguard Worker 279*9880d681SAndroid Build Coastguard Worker std::error_code ec = std::error_code(); 280*9880d681SAndroid Build Coastguard Worker 281*9880d681SAndroid Build Coastguard Worker // Retry while we see recoverable errors. 282*9880d681SAndroid Build Coastguard Worker // System scanners (eg. indexer) might open the source file when it is written 283*9880d681SAndroid Build Coastguard Worker // and closed. 284*9880d681SAndroid Build Coastguard Worker 285*9880d681SAndroid Build Coastguard Worker bool TryReplace = true; 286*9880d681SAndroid Build Coastguard Worker 287*9880d681SAndroid Build Coastguard Worker for (int i = 0; i < 2000; i++) { 288*9880d681SAndroid Build Coastguard Worker if (i > 0) 289*9880d681SAndroid Build Coastguard Worker ::Sleep(1); 290*9880d681SAndroid Build Coastguard Worker 291*9880d681SAndroid Build Coastguard Worker if (TryReplace) { 292*9880d681SAndroid Build Coastguard Worker // Try ReplaceFile first, as it is able to associate a new data stream 293*9880d681SAndroid Build Coastguard Worker // with the destination even if the destination file is currently open. 294*9880d681SAndroid Build Coastguard Worker if (::ReplaceFileW(wide_to.data(), wide_from.data(), NULL, 0, NULL, NULL)) 295*9880d681SAndroid Build Coastguard Worker return std::error_code(); 296*9880d681SAndroid Build Coastguard Worker 297*9880d681SAndroid Build Coastguard Worker DWORD ReplaceError = ::GetLastError(); 298*9880d681SAndroid Build Coastguard Worker ec = mapWindowsError(ReplaceError); 299*9880d681SAndroid Build Coastguard Worker 300*9880d681SAndroid Build Coastguard Worker // If ReplaceFileW returned ERROR_UNABLE_TO_MOVE_REPLACEMENT or 301*9880d681SAndroid Build Coastguard Worker // ERROR_UNABLE_TO_MOVE_REPLACEMENT_2, retry but only use MoveFileExW(). 302*9880d681SAndroid Build Coastguard Worker if (ReplaceError == ERROR_UNABLE_TO_MOVE_REPLACEMENT || 303*9880d681SAndroid Build Coastguard Worker ReplaceError == ERROR_UNABLE_TO_MOVE_REPLACEMENT_2) { 304*9880d681SAndroid Build Coastguard Worker TryReplace = false; 305*9880d681SAndroid Build Coastguard Worker continue; 306*9880d681SAndroid Build Coastguard Worker } 307*9880d681SAndroid Build Coastguard Worker // If ReplaceFileW returned ERROR_UNABLE_TO_REMOVE_REPLACED, retry 308*9880d681SAndroid Build Coastguard Worker // using ReplaceFileW(). 309*9880d681SAndroid Build Coastguard Worker if (ReplaceError == ERROR_UNABLE_TO_REMOVE_REPLACED) 310*9880d681SAndroid Build Coastguard Worker continue; 311*9880d681SAndroid Build Coastguard Worker // We get ERROR_FILE_NOT_FOUND if the destination file is missing. 312*9880d681SAndroid Build Coastguard Worker // MoveFileEx can handle this case. 313*9880d681SAndroid Build Coastguard Worker if (ReplaceError != ERROR_ACCESS_DENIED && 314*9880d681SAndroid Build Coastguard Worker ReplaceError != ERROR_FILE_NOT_FOUND && 315*9880d681SAndroid Build Coastguard Worker ReplaceError != ERROR_SHARING_VIOLATION) 316*9880d681SAndroid Build Coastguard Worker break; 317*9880d681SAndroid Build Coastguard Worker } 318*9880d681SAndroid Build Coastguard Worker 319*9880d681SAndroid Build Coastguard Worker if (::MoveFileExW(wide_from.begin(), wide_to.begin(), 320*9880d681SAndroid Build Coastguard Worker MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING)) 321*9880d681SAndroid Build Coastguard Worker return std::error_code(); 322*9880d681SAndroid Build Coastguard Worker 323*9880d681SAndroid Build Coastguard Worker DWORD MoveError = ::GetLastError(); 324*9880d681SAndroid Build Coastguard Worker ec = mapWindowsError(MoveError); 325*9880d681SAndroid Build Coastguard Worker if (MoveError != ERROR_ACCESS_DENIED) break; 326*9880d681SAndroid Build Coastguard Worker } 327*9880d681SAndroid Build Coastguard Worker 328*9880d681SAndroid Build Coastguard Worker return ec; 329*9880d681SAndroid Build Coastguard Worker} 330*9880d681SAndroid Build Coastguard Worker 331*9880d681SAndroid Build Coastguard Workerstd::error_code resize_file(int FD, uint64_t Size) { 332*9880d681SAndroid Build Coastguard Worker#ifdef HAVE__CHSIZE_S 333*9880d681SAndroid Build Coastguard Worker errno_t error = ::_chsize_s(FD, Size); 334*9880d681SAndroid Build Coastguard Worker#else 335*9880d681SAndroid Build Coastguard Worker errno_t error = ::_chsize(FD, Size); 336*9880d681SAndroid Build Coastguard Worker#endif 337*9880d681SAndroid Build Coastguard Worker return std::error_code(error, std::generic_category()); 338*9880d681SAndroid Build Coastguard Worker} 339*9880d681SAndroid Build Coastguard Worker 340*9880d681SAndroid Build Coastguard Workerstd::error_code access(const Twine &Path, AccessMode Mode) { 341*9880d681SAndroid Build Coastguard Worker SmallVector<wchar_t, 128> PathUtf16; 342*9880d681SAndroid Build Coastguard Worker 343*9880d681SAndroid Build Coastguard Worker if (std::error_code EC = widenPath(Path, PathUtf16)) 344*9880d681SAndroid Build Coastguard Worker return EC; 345*9880d681SAndroid Build Coastguard Worker 346*9880d681SAndroid Build Coastguard Worker DWORD Attributes = ::GetFileAttributesW(PathUtf16.begin()); 347*9880d681SAndroid Build Coastguard Worker 348*9880d681SAndroid Build Coastguard Worker if (Attributes == INVALID_FILE_ATTRIBUTES) { 349*9880d681SAndroid Build Coastguard Worker // See if the file didn't actually exist. 350*9880d681SAndroid Build Coastguard Worker DWORD LastError = ::GetLastError(); 351*9880d681SAndroid Build Coastguard Worker if (LastError != ERROR_FILE_NOT_FOUND && 352*9880d681SAndroid Build Coastguard Worker LastError != ERROR_PATH_NOT_FOUND) 353*9880d681SAndroid Build Coastguard Worker return mapWindowsError(LastError); 354*9880d681SAndroid Build Coastguard Worker return errc::no_such_file_or_directory; 355*9880d681SAndroid Build Coastguard Worker } 356*9880d681SAndroid Build Coastguard Worker 357*9880d681SAndroid Build Coastguard Worker if (Mode == AccessMode::Write && (Attributes & FILE_ATTRIBUTE_READONLY)) 358*9880d681SAndroid Build Coastguard Worker return errc::permission_denied; 359*9880d681SAndroid Build Coastguard Worker 360*9880d681SAndroid Build Coastguard Worker return std::error_code(); 361*9880d681SAndroid Build Coastguard Worker} 362*9880d681SAndroid Build Coastguard Worker 363*9880d681SAndroid Build Coastguard Workerbool can_execute(const Twine &Path) { 364*9880d681SAndroid Build Coastguard Worker return !access(Path, AccessMode::Execute) || 365*9880d681SAndroid Build Coastguard Worker !access(Path + ".exe", AccessMode::Execute); 366*9880d681SAndroid Build Coastguard Worker} 367*9880d681SAndroid Build Coastguard Worker 368*9880d681SAndroid Build Coastguard Workerbool equivalent(file_status A, file_status B) { 369*9880d681SAndroid Build Coastguard Worker assert(status_known(A) && status_known(B)); 370*9880d681SAndroid Build Coastguard Worker return A.FileIndexHigh == B.FileIndexHigh && 371*9880d681SAndroid Build Coastguard Worker A.FileIndexLow == B.FileIndexLow && 372*9880d681SAndroid Build Coastguard Worker A.FileSizeHigh == B.FileSizeHigh && 373*9880d681SAndroid Build Coastguard Worker A.FileSizeLow == B.FileSizeLow && 374*9880d681SAndroid Build Coastguard Worker A.LastAccessedTimeHigh == B.LastAccessedTimeHigh && 375*9880d681SAndroid Build Coastguard Worker A.LastAccessedTimeLow == B.LastAccessedTimeLow && 376*9880d681SAndroid Build Coastguard Worker A.LastWriteTimeHigh == B.LastWriteTimeHigh && 377*9880d681SAndroid Build Coastguard Worker A.LastWriteTimeLow == B.LastWriteTimeLow && 378*9880d681SAndroid Build Coastguard Worker A.VolumeSerialNumber == B.VolumeSerialNumber; 379*9880d681SAndroid Build Coastguard Worker} 380*9880d681SAndroid Build Coastguard Worker 381*9880d681SAndroid Build Coastguard Workerstd::error_code equivalent(const Twine &A, const Twine &B, bool &result) { 382*9880d681SAndroid Build Coastguard Worker file_status fsA, fsB; 383*9880d681SAndroid Build Coastguard Worker if (std::error_code ec = status(A, fsA)) 384*9880d681SAndroid Build Coastguard Worker return ec; 385*9880d681SAndroid Build Coastguard Worker if (std::error_code ec = status(B, fsB)) 386*9880d681SAndroid Build Coastguard Worker return ec; 387*9880d681SAndroid Build Coastguard Worker result = equivalent(fsA, fsB); 388*9880d681SAndroid Build Coastguard Worker return std::error_code(); 389*9880d681SAndroid Build Coastguard Worker} 390*9880d681SAndroid Build Coastguard Worker 391*9880d681SAndroid Build Coastguard Workerstatic bool isReservedName(StringRef path) { 392*9880d681SAndroid Build Coastguard Worker // This list of reserved names comes from MSDN, at: 393*9880d681SAndroid Build Coastguard Worker // http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx 394*9880d681SAndroid Build Coastguard Worker static const char *const sReservedNames[] = { "nul", "con", "prn", "aux", 395*9880d681SAndroid Build Coastguard Worker "com1", "com2", "com3", "com4", 396*9880d681SAndroid Build Coastguard Worker "com5", "com6", "com7", "com8", 397*9880d681SAndroid Build Coastguard Worker "com9", "lpt1", "lpt2", "lpt3", 398*9880d681SAndroid Build Coastguard Worker "lpt4", "lpt5", "lpt6", "lpt7", 399*9880d681SAndroid Build Coastguard Worker "lpt8", "lpt9" }; 400*9880d681SAndroid Build Coastguard Worker 401*9880d681SAndroid Build Coastguard Worker // First, check to see if this is a device namespace, which always 402*9880d681SAndroid Build Coastguard Worker // starts with \\.\, since device namespaces are not legal file paths. 403*9880d681SAndroid Build Coastguard Worker if (path.startswith("\\\\.\\")) 404*9880d681SAndroid Build Coastguard Worker return true; 405*9880d681SAndroid Build Coastguard Worker 406*9880d681SAndroid Build Coastguard Worker // Then compare against the list of ancient reserved names. 407*9880d681SAndroid Build Coastguard Worker for (size_t i = 0; i < array_lengthof(sReservedNames); ++i) { 408*9880d681SAndroid Build Coastguard Worker if (path.equals_lower(sReservedNames[i])) 409*9880d681SAndroid Build Coastguard Worker return true; 410*9880d681SAndroid Build Coastguard Worker } 411*9880d681SAndroid Build Coastguard Worker 412*9880d681SAndroid Build Coastguard Worker // The path isn't what we consider reserved. 413*9880d681SAndroid Build Coastguard Worker return false; 414*9880d681SAndroid Build Coastguard Worker} 415*9880d681SAndroid Build Coastguard Worker 416*9880d681SAndroid Build Coastguard Workerstatic std::error_code getStatus(HANDLE FileHandle, file_status &Result) { 417*9880d681SAndroid Build Coastguard Worker if (FileHandle == INVALID_HANDLE_VALUE) 418*9880d681SAndroid Build Coastguard Worker goto handle_status_error; 419*9880d681SAndroid Build Coastguard Worker 420*9880d681SAndroid Build Coastguard Worker switch (::GetFileType(FileHandle)) { 421*9880d681SAndroid Build Coastguard Worker default: 422*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Don't know anything about this file type"); 423*9880d681SAndroid Build Coastguard Worker case FILE_TYPE_UNKNOWN: { 424*9880d681SAndroid Build Coastguard Worker DWORD Err = ::GetLastError(); 425*9880d681SAndroid Build Coastguard Worker if (Err != NO_ERROR) 426*9880d681SAndroid Build Coastguard Worker return mapWindowsError(Err); 427*9880d681SAndroid Build Coastguard Worker Result = file_status(file_type::type_unknown); 428*9880d681SAndroid Build Coastguard Worker return std::error_code(); 429*9880d681SAndroid Build Coastguard Worker } 430*9880d681SAndroid Build Coastguard Worker case FILE_TYPE_DISK: 431*9880d681SAndroid Build Coastguard Worker break; 432*9880d681SAndroid Build Coastguard Worker case FILE_TYPE_CHAR: 433*9880d681SAndroid Build Coastguard Worker Result = file_status(file_type::character_file); 434*9880d681SAndroid Build Coastguard Worker return std::error_code(); 435*9880d681SAndroid Build Coastguard Worker case FILE_TYPE_PIPE: 436*9880d681SAndroid Build Coastguard Worker Result = file_status(file_type::fifo_file); 437*9880d681SAndroid Build Coastguard Worker return std::error_code(); 438*9880d681SAndroid Build Coastguard Worker } 439*9880d681SAndroid Build Coastguard Worker 440*9880d681SAndroid Build Coastguard Worker BY_HANDLE_FILE_INFORMATION Info; 441*9880d681SAndroid Build Coastguard Worker if (!::GetFileInformationByHandle(FileHandle, &Info)) 442*9880d681SAndroid Build Coastguard Worker goto handle_status_error; 443*9880d681SAndroid Build Coastguard Worker 444*9880d681SAndroid Build Coastguard Worker { 445*9880d681SAndroid Build Coastguard Worker file_type Type = (Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 446*9880d681SAndroid Build Coastguard Worker ? file_type::directory_file 447*9880d681SAndroid Build Coastguard Worker : file_type::regular_file; 448*9880d681SAndroid Build Coastguard Worker Result = 449*9880d681SAndroid Build Coastguard Worker file_status(Type, Info.ftLastAccessTime.dwHighDateTime, 450*9880d681SAndroid Build Coastguard Worker Info.ftLastAccessTime.dwLowDateTime, 451*9880d681SAndroid Build Coastguard Worker Info.ftLastWriteTime.dwHighDateTime, 452*9880d681SAndroid Build Coastguard Worker Info.ftLastWriteTime.dwLowDateTime, 453*9880d681SAndroid Build Coastguard Worker Info.dwVolumeSerialNumber, Info.nFileSizeHigh, 454*9880d681SAndroid Build Coastguard Worker Info.nFileSizeLow, Info.nFileIndexHigh, Info.nFileIndexLow); 455*9880d681SAndroid Build Coastguard Worker return std::error_code(); 456*9880d681SAndroid Build Coastguard Worker } 457*9880d681SAndroid Build Coastguard Worker 458*9880d681SAndroid Build Coastguard Workerhandle_status_error: 459*9880d681SAndroid Build Coastguard Worker DWORD LastError = ::GetLastError(); 460*9880d681SAndroid Build Coastguard Worker if (LastError == ERROR_FILE_NOT_FOUND || 461*9880d681SAndroid Build Coastguard Worker LastError == ERROR_PATH_NOT_FOUND) 462*9880d681SAndroid Build Coastguard Worker Result = file_status(file_type::file_not_found); 463*9880d681SAndroid Build Coastguard Worker else if (LastError == ERROR_SHARING_VIOLATION) 464*9880d681SAndroid Build Coastguard Worker Result = file_status(file_type::type_unknown); 465*9880d681SAndroid Build Coastguard Worker else 466*9880d681SAndroid Build Coastguard Worker Result = file_status(file_type::status_error); 467*9880d681SAndroid Build Coastguard Worker return mapWindowsError(LastError); 468*9880d681SAndroid Build Coastguard Worker} 469*9880d681SAndroid Build Coastguard Worker 470*9880d681SAndroid Build Coastguard Workerstd::error_code status(const Twine &path, file_status &result) { 471*9880d681SAndroid Build Coastguard Worker SmallString<128> path_storage; 472*9880d681SAndroid Build Coastguard Worker SmallVector<wchar_t, 128> path_utf16; 473*9880d681SAndroid Build Coastguard Worker 474*9880d681SAndroid Build Coastguard Worker StringRef path8 = path.toStringRef(path_storage); 475*9880d681SAndroid Build Coastguard Worker if (isReservedName(path8)) { 476*9880d681SAndroid Build Coastguard Worker result = file_status(file_type::character_file); 477*9880d681SAndroid Build Coastguard Worker return std::error_code(); 478*9880d681SAndroid Build Coastguard Worker } 479*9880d681SAndroid Build Coastguard Worker 480*9880d681SAndroid Build Coastguard Worker if (std::error_code ec = widenPath(path8, path_utf16)) 481*9880d681SAndroid Build Coastguard Worker return ec; 482*9880d681SAndroid Build Coastguard Worker 483*9880d681SAndroid Build Coastguard Worker DWORD attr = ::GetFileAttributesW(path_utf16.begin()); 484*9880d681SAndroid Build Coastguard Worker if (attr == INVALID_FILE_ATTRIBUTES) 485*9880d681SAndroid Build Coastguard Worker return getStatus(INVALID_HANDLE_VALUE, result); 486*9880d681SAndroid Build Coastguard Worker 487*9880d681SAndroid Build Coastguard Worker // Handle reparse points. 488*9880d681SAndroid Build Coastguard Worker if (attr & FILE_ATTRIBUTE_REPARSE_POINT) { 489*9880d681SAndroid Build Coastguard Worker ScopedFileHandle h( 490*9880d681SAndroid Build Coastguard Worker ::CreateFileW(path_utf16.begin(), 491*9880d681SAndroid Build Coastguard Worker 0, // Attributes only. 492*9880d681SAndroid Build Coastguard Worker FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 493*9880d681SAndroid Build Coastguard Worker NULL, 494*9880d681SAndroid Build Coastguard Worker OPEN_EXISTING, 495*9880d681SAndroid Build Coastguard Worker FILE_FLAG_BACKUP_SEMANTICS, 496*9880d681SAndroid Build Coastguard Worker 0)); 497*9880d681SAndroid Build Coastguard Worker if (!h) 498*9880d681SAndroid Build Coastguard Worker return getStatus(INVALID_HANDLE_VALUE, result); 499*9880d681SAndroid Build Coastguard Worker } 500*9880d681SAndroid Build Coastguard Worker 501*9880d681SAndroid Build Coastguard Worker ScopedFileHandle h( 502*9880d681SAndroid Build Coastguard Worker ::CreateFileW(path_utf16.begin(), 0, // Attributes only. 503*9880d681SAndroid Build Coastguard Worker FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 504*9880d681SAndroid Build Coastguard Worker NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)); 505*9880d681SAndroid Build Coastguard Worker if (!h) 506*9880d681SAndroid Build Coastguard Worker return getStatus(INVALID_HANDLE_VALUE, result); 507*9880d681SAndroid Build Coastguard Worker 508*9880d681SAndroid Build Coastguard Worker return getStatus(h, result); 509*9880d681SAndroid Build Coastguard Worker} 510*9880d681SAndroid Build Coastguard Worker 511*9880d681SAndroid Build Coastguard Workerstd::error_code status(int FD, file_status &Result) { 512*9880d681SAndroid Build Coastguard Worker HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD)); 513*9880d681SAndroid Build Coastguard Worker return getStatus(FileHandle, Result); 514*9880d681SAndroid Build Coastguard Worker} 515*9880d681SAndroid Build Coastguard Worker 516*9880d681SAndroid Build Coastguard Workerstd::error_code setLastModificationAndAccessTime(int FD, TimeValue Time) { 517*9880d681SAndroid Build Coastguard Worker ULARGE_INTEGER UI; 518*9880d681SAndroid Build Coastguard Worker UI.QuadPart = Time.toWin32Time(); 519*9880d681SAndroid Build Coastguard Worker FILETIME FT; 520*9880d681SAndroid Build Coastguard Worker FT.dwLowDateTime = UI.LowPart; 521*9880d681SAndroid Build Coastguard Worker FT.dwHighDateTime = UI.HighPart; 522*9880d681SAndroid Build Coastguard Worker HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD)); 523*9880d681SAndroid Build Coastguard Worker if (!SetFileTime(FileHandle, NULL, &FT, &FT)) 524*9880d681SAndroid Build Coastguard Worker return mapWindowsError(::GetLastError()); 525*9880d681SAndroid Build Coastguard Worker return std::error_code(); 526*9880d681SAndroid Build Coastguard Worker} 527*9880d681SAndroid Build Coastguard Worker 528*9880d681SAndroid Build Coastguard Workerstd::error_code mapped_file_region::init(int FD, uint64_t Offset, 529*9880d681SAndroid Build Coastguard Worker mapmode Mode) { 530*9880d681SAndroid Build Coastguard Worker // Make sure that the requested size fits within SIZE_T. 531*9880d681SAndroid Build Coastguard Worker if (Size > std::numeric_limits<SIZE_T>::max()) 532*9880d681SAndroid Build Coastguard Worker return make_error_code(errc::invalid_argument); 533*9880d681SAndroid Build Coastguard Worker 534*9880d681SAndroid Build Coastguard Worker HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD)); 535*9880d681SAndroid Build Coastguard Worker if (FileHandle == INVALID_HANDLE_VALUE) 536*9880d681SAndroid Build Coastguard Worker return make_error_code(errc::bad_file_descriptor); 537*9880d681SAndroid Build Coastguard Worker 538*9880d681SAndroid Build Coastguard Worker DWORD flprotect; 539*9880d681SAndroid Build Coastguard Worker switch (Mode) { 540*9880d681SAndroid Build Coastguard Worker case readonly: flprotect = PAGE_READONLY; break; 541*9880d681SAndroid Build Coastguard Worker case readwrite: flprotect = PAGE_READWRITE; break; 542*9880d681SAndroid Build Coastguard Worker case priv: flprotect = PAGE_WRITECOPY; break; 543*9880d681SAndroid Build Coastguard Worker } 544*9880d681SAndroid Build Coastguard Worker 545*9880d681SAndroid Build Coastguard Worker HANDLE FileMappingHandle = 546*9880d681SAndroid Build Coastguard Worker ::CreateFileMappingW(FileHandle, 0, flprotect, 547*9880d681SAndroid Build Coastguard Worker (Offset + Size) >> 32, 548*9880d681SAndroid Build Coastguard Worker (Offset + Size) & 0xffffffff, 549*9880d681SAndroid Build Coastguard Worker 0); 550*9880d681SAndroid Build Coastguard Worker if (FileMappingHandle == NULL) { 551*9880d681SAndroid Build Coastguard Worker std::error_code ec = mapWindowsError(GetLastError()); 552*9880d681SAndroid Build Coastguard Worker return ec; 553*9880d681SAndroid Build Coastguard Worker } 554*9880d681SAndroid Build Coastguard Worker 555*9880d681SAndroid Build Coastguard Worker DWORD dwDesiredAccess; 556*9880d681SAndroid Build Coastguard Worker switch (Mode) { 557*9880d681SAndroid Build Coastguard Worker case readonly: dwDesiredAccess = FILE_MAP_READ; break; 558*9880d681SAndroid Build Coastguard Worker case readwrite: dwDesiredAccess = FILE_MAP_WRITE; break; 559*9880d681SAndroid Build Coastguard Worker case priv: dwDesiredAccess = FILE_MAP_COPY; break; 560*9880d681SAndroid Build Coastguard Worker } 561*9880d681SAndroid Build Coastguard Worker Mapping = ::MapViewOfFile(FileMappingHandle, 562*9880d681SAndroid Build Coastguard Worker dwDesiredAccess, 563*9880d681SAndroid Build Coastguard Worker Offset >> 32, 564*9880d681SAndroid Build Coastguard Worker Offset & 0xffffffff, 565*9880d681SAndroid Build Coastguard Worker Size); 566*9880d681SAndroid Build Coastguard Worker if (Mapping == NULL) { 567*9880d681SAndroid Build Coastguard Worker std::error_code ec = mapWindowsError(GetLastError()); 568*9880d681SAndroid Build Coastguard Worker ::CloseHandle(FileMappingHandle); 569*9880d681SAndroid Build Coastguard Worker return ec; 570*9880d681SAndroid Build Coastguard Worker } 571*9880d681SAndroid Build Coastguard Worker 572*9880d681SAndroid Build Coastguard Worker if (Size == 0) { 573*9880d681SAndroid Build Coastguard Worker MEMORY_BASIC_INFORMATION mbi; 574*9880d681SAndroid Build Coastguard Worker SIZE_T Result = VirtualQuery(Mapping, &mbi, sizeof(mbi)); 575*9880d681SAndroid Build Coastguard Worker if (Result == 0) { 576*9880d681SAndroid Build Coastguard Worker std::error_code ec = mapWindowsError(GetLastError()); 577*9880d681SAndroid Build Coastguard Worker ::UnmapViewOfFile(Mapping); 578*9880d681SAndroid Build Coastguard Worker ::CloseHandle(FileMappingHandle); 579*9880d681SAndroid Build Coastguard Worker return ec; 580*9880d681SAndroid Build Coastguard Worker } 581*9880d681SAndroid Build Coastguard Worker Size = mbi.RegionSize; 582*9880d681SAndroid Build Coastguard Worker } 583*9880d681SAndroid Build Coastguard Worker 584*9880d681SAndroid Build Coastguard Worker // Close all the handles except for the view. It will keep the other handles 585*9880d681SAndroid Build Coastguard Worker // alive. 586*9880d681SAndroid Build Coastguard Worker ::CloseHandle(FileMappingHandle); 587*9880d681SAndroid Build Coastguard Worker return std::error_code(); 588*9880d681SAndroid Build Coastguard Worker} 589*9880d681SAndroid Build Coastguard Worker 590*9880d681SAndroid Build Coastguard Workermapped_file_region::mapped_file_region(int fd, mapmode mode, uint64_t length, 591*9880d681SAndroid Build Coastguard Worker uint64_t offset, std::error_code &ec) 592*9880d681SAndroid Build Coastguard Worker : Size(length), Mapping() { 593*9880d681SAndroid Build Coastguard Worker ec = init(fd, offset, mode); 594*9880d681SAndroid Build Coastguard Worker if (ec) 595*9880d681SAndroid Build Coastguard Worker Mapping = 0; 596*9880d681SAndroid Build Coastguard Worker} 597*9880d681SAndroid Build Coastguard Worker 598*9880d681SAndroid Build Coastguard Workermapped_file_region::~mapped_file_region() { 599*9880d681SAndroid Build Coastguard Worker if (Mapping) 600*9880d681SAndroid Build Coastguard Worker ::UnmapViewOfFile(Mapping); 601*9880d681SAndroid Build Coastguard Worker} 602*9880d681SAndroid Build Coastguard Worker 603*9880d681SAndroid Build Coastguard Workeruint64_t mapped_file_region::size() const { 604*9880d681SAndroid Build Coastguard Worker assert(Mapping && "Mapping failed but used anyway!"); 605*9880d681SAndroid Build Coastguard Worker return Size; 606*9880d681SAndroid Build Coastguard Worker} 607*9880d681SAndroid Build Coastguard Worker 608*9880d681SAndroid Build Coastguard Workerchar *mapped_file_region::data() const { 609*9880d681SAndroid Build Coastguard Worker assert(Mapping && "Mapping failed but used anyway!"); 610*9880d681SAndroid Build Coastguard Worker return reinterpret_cast<char*>(Mapping); 611*9880d681SAndroid Build Coastguard Worker} 612*9880d681SAndroid Build Coastguard Worker 613*9880d681SAndroid Build Coastguard Workerconst char *mapped_file_region::const_data() const { 614*9880d681SAndroid Build Coastguard Worker assert(Mapping && "Mapping failed but used anyway!"); 615*9880d681SAndroid Build Coastguard Worker return reinterpret_cast<const char*>(Mapping); 616*9880d681SAndroid Build Coastguard Worker} 617*9880d681SAndroid Build Coastguard Worker 618*9880d681SAndroid Build Coastguard Workerint mapped_file_region::alignment() { 619*9880d681SAndroid Build Coastguard Worker SYSTEM_INFO SysInfo; 620*9880d681SAndroid Build Coastguard Worker ::GetSystemInfo(&SysInfo); 621*9880d681SAndroid Build Coastguard Worker return SysInfo.dwAllocationGranularity; 622*9880d681SAndroid Build Coastguard Worker} 623*9880d681SAndroid Build Coastguard Worker 624*9880d681SAndroid Build Coastguard Workerstd::error_code detail::directory_iterator_construct(detail::DirIterState &it, 625*9880d681SAndroid Build Coastguard Worker StringRef path){ 626*9880d681SAndroid Build Coastguard Worker SmallVector<wchar_t, 128> path_utf16; 627*9880d681SAndroid Build Coastguard Worker 628*9880d681SAndroid Build Coastguard Worker if (std::error_code ec = widenPath(path, path_utf16)) 629*9880d681SAndroid Build Coastguard Worker return ec; 630*9880d681SAndroid Build Coastguard Worker 631*9880d681SAndroid Build Coastguard Worker // Convert path to the format that Windows is happy with. 632*9880d681SAndroid Build Coastguard Worker if (path_utf16.size() > 0 && 633*9880d681SAndroid Build Coastguard Worker !is_separator(path_utf16[path.size() - 1]) && 634*9880d681SAndroid Build Coastguard Worker path_utf16[path.size() - 1] != L':') { 635*9880d681SAndroid Build Coastguard Worker path_utf16.push_back(L'\\'); 636*9880d681SAndroid Build Coastguard Worker path_utf16.push_back(L'*'); 637*9880d681SAndroid Build Coastguard Worker } else { 638*9880d681SAndroid Build Coastguard Worker path_utf16.push_back(L'*'); 639*9880d681SAndroid Build Coastguard Worker } 640*9880d681SAndroid Build Coastguard Worker 641*9880d681SAndroid Build Coastguard Worker // Get the first directory entry. 642*9880d681SAndroid Build Coastguard Worker WIN32_FIND_DATAW FirstFind; 643*9880d681SAndroid Build Coastguard Worker ScopedFindHandle FindHandle(::FindFirstFileW(c_str(path_utf16), &FirstFind)); 644*9880d681SAndroid Build Coastguard Worker if (!FindHandle) 645*9880d681SAndroid Build Coastguard Worker return mapWindowsError(::GetLastError()); 646*9880d681SAndroid Build Coastguard Worker 647*9880d681SAndroid Build Coastguard Worker size_t FilenameLen = ::wcslen(FirstFind.cFileName); 648*9880d681SAndroid Build Coastguard Worker while ((FilenameLen == 1 && FirstFind.cFileName[0] == L'.') || 649*9880d681SAndroid Build Coastguard Worker (FilenameLen == 2 && FirstFind.cFileName[0] == L'.' && 650*9880d681SAndroid Build Coastguard Worker FirstFind.cFileName[1] == L'.')) 651*9880d681SAndroid Build Coastguard Worker if (!::FindNextFileW(FindHandle, &FirstFind)) { 652*9880d681SAndroid Build Coastguard Worker DWORD LastError = ::GetLastError(); 653*9880d681SAndroid Build Coastguard Worker // Check for end. 654*9880d681SAndroid Build Coastguard Worker if (LastError == ERROR_NO_MORE_FILES) 655*9880d681SAndroid Build Coastguard Worker return detail::directory_iterator_destruct(it); 656*9880d681SAndroid Build Coastguard Worker return mapWindowsError(LastError); 657*9880d681SAndroid Build Coastguard Worker } else 658*9880d681SAndroid Build Coastguard Worker FilenameLen = ::wcslen(FirstFind.cFileName); 659*9880d681SAndroid Build Coastguard Worker 660*9880d681SAndroid Build Coastguard Worker // Construct the current directory entry. 661*9880d681SAndroid Build Coastguard Worker SmallString<128> directory_entry_name_utf8; 662*9880d681SAndroid Build Coastguard Worker if (std::error_code ec = 663*9880d681SAndroid Build Coastguard Worker UTF16ToUTF8(FirstFind.cFileName, ::wcslen(FirstFind.cFileName), 664*9880d681SAndroid Build Coastguard Worker directory_entry_name_utf8)) 665*9880d681SAndroid Build Coastguard Worker return ec; 666*9880d681SAndroid Build Coastguard Worker 667*9880d681SAndroid Build Coastguard Worker it.IterationHandle = intptr_t(FindHandle.take()); 668*9880d681SAndroid Build Coastguard Worker SmallString<128> directory_entry_path(path); 669*9880d681SAndroid Build Coastguard Worker path::append(directory_entry_path, directory_entry_name_utf8); 670*9880d681SAndroid Build Coastguard Worker it.CurrentEntry = directory_entry(directory_entry_path); 671*9880d681SAndroid Build Coastguard Worker 672*9880d681SAndroid Build Coastguard Worker return std::error_code(); 673*9880d681SAndroid Build Coastguard Worker} 674*9880d681SAndroid Build Coastguard Worker 675*9880d681SAndroid Build Coastguard Workerstd::error_code detail::directory_iterator_destruct(detail::DirIterState &it) { 676*9880d681SAndroid Build Coastguard Worker if (it.IterationHandle != 0) 677*9880d681SAndroid Build Coastguard Worker // Closes the handle if it's valid. 678*9880d681SAndroid Build Coastguard Worker ScopedFindHandle close(HANDLE(it.IterationHandle)); 679*9880d681SAndroid Build Coastguard Worker it.IterationHandle = 0; 680*9880d681SAndroid Build Coastguard Worker it.CurrentEntry = directory_entry(); 681*9880d681SAndroid Build Coastguard Worker return std::error_code(); 682*9880d681SAndroid Build Coastguard Worker} 683*9880d681SAndroid Build Coastguard Worker 684*9880d681SAndroid Build Coastguard Workerstd::error_code detail::directory_iterator_increment(detail::DirIterState &it) { 685*9880d681SAndroid Build Coastguard Worker WIN32_FIND_DATAW FindData; 686*9880d681SAndroid Build Coastguard Worker if (!::FindNextFileW(HANDLE(it.IterationHandle), &FindData)) { 687*9880d681SAndroid Build Coastguard Worker DWORD LastError = ::GetLastError(); 688*9880d681SAndroid Build Coastguard Worker // Check for end. 689*9880d681SAndroid Build Coastguard Worker if (LastError == ERROR_NO_MORE_FILES) 690*9880d681SAndroid Build Coastguard Worker return detail::directory_iterator_destruct(it); 691*9880d681SAndroid Build Coastguard Worker return mapWindowsError(LastError); 692*9880d681SAndroid Build Coastguard Worker } 693*9880d681SAndroid Build Coastguard Worker 694*9880d681SAndroid Build Coastguard Worker size_t FilenameLen = ::wcslen(FindData.cFileName); 695*9880d681SAndroid Build Coastguard Worker if ((FilenameLen == 1 && FindData.cFileName[0] == L'.') || 696*9880d681SAndroid Build Coastguard Worker (FilenameLen == 2 && FindData.cFileName[0] == L'.' && 697*9880d681SAndroid Build Coastguard Worker FindData.cFileName[1] == L'.')) 698*9880d681SAndroid Build Coastguard Worker return directory_iterator_increment(it); 699*9880d681SAndroid Build Coastguard Worker 700*9880d681SAndroid Build Coastguard Worker SmallString<128> directory_entry_path_utf8; 701*9880d681SAndroid Build Coastguard Worker if (std::error_code ec = 702*9880d681SAndroid Build Coastguard Worker UTF16ToUTF8(FindData.cFileName, ::wcslen(FindData.cFileName), 703*9880d681SAndroid Build Coastguard Worker directory_entry_path_utf8)) 704*9880d681SAndroid Build Coastguard Worker return ec; 705*9880d681SAndroid Build Coastguard Worker 706*9880d681SAndroid Build Coastguard Worker it.CurrentEntry.replace_filename(Twine(directory_entry_path_utf8)); 707*9880d681SAndroid Build Coastguard Worker return std::error_code(); 708*9880d681SAndroid Build Coastguard Worker} 709*9880d681SAndroid Build Coastguard Worker 710*9880d681SAndroid Build Coastguard Workerstd::error_code openFileForRead(const Twine &Name, int &ResultFD, 711*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<char> *RealPath) { 712*9880d681SAndroid Build Coastguard Worker SmallVector<wchar_t, 128> PathUTF16; 713*9880d681SAndroid Build Coastguard Worker 714*9880d681SAndroid Build Coastguard Worker if (std::error_code EC = widenPath(Name, PathUTF16)) 715*9880d681SAndroid Build Coastguard Worker return EC; 716*9880d681SAndroid Build Coastguard Worker 717*9880d681SAndroid Build Coastguard Worker HANDLE H = 718*9880d681SAndroid Build Coastguard Worker ::CreateFileW(PathUTF16.begin(), GENERIC_READ, 719*9880d681SAndroid Build Coastguard Worker FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 720*9880d681SAndroid Build Coastguard Worker NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 721*9880d681SAndroid Build Coastguard Worker if (H == INVALID_HANDLE_VALUE) { 722*9880d681SAndroid Build Coastguard Worker DWORD LastError = ::GetLastError(); 723*9880d681SAndroid Build Coastguard Worker std::error_code EC = mapWindowsError(LastError); 724*9880d681SAndroid Build Coastguard Worker // Provide a better error message when trying to open directories. 725*9880d681SAndroid Build Coastguard Worker // This only runs if we failed to open the file, so there is probably 726*9880d681SAndroid Build Coastguard Worker // no performances issues. 727*9880d681SAndroid Build Coastguard Worker if (LastError != ERROR_ACCESS_DENIED) 728*9880d681SAndroid Build Coastguard Worker return EC; 729*9880d681SAndroid Build Coastguard Worker if (is_directory(Name)) 730*9880d681SAndroid Build Coastguard Worker return make_error_code(errc::is_a_directory); 731*9880d681SAndroid Build Coastguard Worker return EC; 732*9880d681SAndroid Build Coastguard Worker } 733*9880d681SAndroid Build Coastguard Worker 734*9880d681SAndroid Build Coastguard Worker int FD = ::_open_osfhandle(intptr_t(H), 0); 735*9880d681SAndroid Build Coastguard Worker if (FD == -1) { 736*9880d681SAndroid Build Coastguard Worker ::CloseHandle(H); 737*9880d681SAndroid Build Coastguard Worker return mapWindowsError(ERROR_INVALID_HANDLE); 738*9880d681SAndroid Build Coastguard Worker } 739*9880d681SAndroid Build Coastguard Worker 740*9880d681SAndroid Build Coastguard Worker // Fetch the real name of the file, if the user asked 741*9880d681SAndroid Build Coastguard Worker if (RealPath) { 742*9880d681SAndroid Build Coastguard Worker RealPath->clear(); 743*9880d681SAndroid Build Coastguard Worker wchar_t RealPathUTF16[MAX_PATH]; 744*9880d681SAndroid Build Coastguard Worker DWORD CountChars = 745*9880d681SAndroid Build Coastguard Worker ::GetFinalPathNameByHandleW(H, RealPathUTF16, MAX_PATH, 746*9880d681SAndroid Build Coastguard Worker FILE_NAME_NORMALIZED); 747*9880d681SAndroid Build Coastguard Worker if (CountChars > 0 && CountChars < MAX_PATH) { 748*9880d681SAndroid Build Coastguard Worker // Convert the result from UTF-16 to UTF-8. 749*9880d681SAndroid Build Coastguard Worker SmallString<MAX_PATH> RealPathUTF8; 750*9880d681SAndroid Build Coastguard Worker if (!UTF16ToUTF8(RealPathUTF16, CountChars, RealPathUTF8)) 751*9880d681SAndroid Build Coastguard Worker RealPath->append(RealPathUTF8.data(), 752*9880d681SAndroid Build Coastguard Worker RealPathUTF8.data() + strlen(RealPathUTF8.data())); 753*9880d681SAndroid Build Coastguard Worker } 754*9880d681SAndroid Build Coastguard Worker } 755*9880d681SAndroid Build Coastguard Worker 756*9880d681SAndroid Build Coastguard Worker ResultFD = FD; 757*9880d681SAndroid Build Coastguard Worker return std::error_code(); 758*9880d681SAndroid Build Coastguard Worker} 759*9880d681SAndroid Build Coastguard Worker 760*9880d681SAndroid Build Coastguard Workerstd::error_code openFileForWrite(const Twine &Name, int &ResultFD, 761*9880d681SAndroid Build Coastguard Worker sys::fs::OpenFlags Flags, unsigned Mode) { 762*9880d681SAndroid Build Coastguard Worker // Verify that we don't have both "append" and "excl". 763*9880d681SAndroid Build Coastguard Worker assert((!(Flags & sys::fs::F_Excl) || !(Flags & sys::fs::F_Append)) && 764*9880d681SAndroid Build Coastguard Worker "Cannot specify both 'excl' and 'append' file creation flags!"); 765*9880d681SAndroid Build Coastguard Worker 766*9880d681SAndroid Build Coastguard Worker SmallVector<wchar_t, 128> PathUTF16; 767*9880d681SAndroid Build Coastguard Worker 768*9880d681SAndroid Build Coastguard Worker if (std::error_code EC = widenPath(Name, PathUTF16)) 769*9880d681SAndroid Build Coastguard Worker return EC; 770*9880d681SAndroid Build Coastguard Worker 771*9880d681SAndroid Build Coastguard Worker DWORD CreationDisposition; 772*9880d681SAndroid Build Coastguard Worker if (Flags & F_Excl) 773*9880d681SAndroid Build Coastguard Worker CreationDisposition = CREATE_NEW; 774*9880d681SAndroid Build Coastguard Worker else if (Flags & F_Append) 775*9880d681SAndroid Build Coastguard Worker CreationDisposition = OPEN_ALWAYS; 776*9880d681SAndroid Build Coastguard Worker else 777*9880d681SAndroid Build Coastguard Worker CreationDisposition = CREATE_ALWAYS; 778*9880d681SAndroid Build Coastguard Worker 779*9880d681SAndroid Build Coastguard Worker DWORD Access = GENERIC_WRITE; 780*9880d681SAndroid Build Coastguard Worker if (Flags & F_RW) 781*9880d681SAndroid Build Coastguard Worker Access |= GENERIC_READ; 782*9880d681SAndroid Build Coastguard Worker 783*9880d681SAndroid Build Coastguard Worker HANDLE H = ::CreateFileW(PathUTF16.begin(), Access, 784*9880d681SAndroid Build Coastguard Worker FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 785*9880d681SAndroid Build Coastguard Worker CreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL); 786*9880d681SAndroid Build Coastguard Worker 787*9880d681SAndroid Build Coastguard Worker if (H == INVALID_HANDLE_VALUE) { 788*9880d681SAndroid Build Coastguard Worker DWORD LastError = ::GetLastError(); 789*9880d681SAndroid Build Coastguard Worker std::error_code EC = mapWindowsError(LastError); 790*9880d681SAndroid Build Coastguard Worker // Provide a better error message when trying to open directories. 791*9880d681SAndroid Build Coastguard Worker // This only runs if we failed to open the file, so there is probably 792*9880d681SAndroid Build Coastguard Worker // no performances issues. 793*9880d681SAndroid Build Coastguard Worker if (LastError != ERROR_ACCESS_DENIED) 794*9880d681SAndroid Build Coastguard Worker return EC; 795*9880d681SAndroid Build Coastguard Worker if (is_directory(Name)) 796*9880d681SAndroid Build Coastguard Worker return make_error_code(errc::is_a_directory); 797*9880d681SAndroid Build Coastguard Worker return EC; 798*9880d681SAndroid Build Coastguard Worker } 799*9880d681SAndroid Build Coastguard Worker 800*9880d681SAndroid Build Coastguard Worker int OpenFlags = 0; 801*9880d681SAndroid Build Coastguard Worker if (Flags & F_Append) 802*9880d681SAndroid Build Coastguard Worker OpenFlags |= _O_APPEND; 803*9880d681SAndroid Build Coastguard Worker 804*9880d681SAndroid Build Coastguard Worker if (Flags & F_Text) 805*9880d681SAndroid Build Coastguard Worker OpenFlags |= _O_TEXT; 806*9880d681SAndroid Build Coastguard Worker 807*9880d681SAndroid Build Coastguard Worker int FD = ::_open_osfhandle(intptr_t(H), OpenFlags); 808*9880d681SAndroid Build Coastguard Worker if (FD == -1) { 809*9880d681SAndroid Build Coastguard Worker ::CloseHandle(H); 810*9880d681SAndroid Build Coastguard Worker return mapWindowsError(ERROR_INVALID_HANDLE); 811*9880d681SAndroid Build Coastguard Worker } 812*9880d681SAndroid Build Coastguard Worker 813*9880d681SAndroid Build Coastguard Worker ResultFD = FD; 814*9880d681SAndroid Build Coastguard Worker return std::error_code(); 815*9880d681SAndroid Build Coastguard Worker} 816*9880d681SAndroid Build Coastguard Worker 817*9880d681SAndroid Build Coastguard Workerstd::error_code getPathFromOpenFD(int FD, SmallVectorImpl<char> &ResultPath) { 818*9880d681SAndroid Build Coastguard Worker HANDLE FileHandle = reinterpret_cast<HANDLE>(::_get_osfhandle(FD)); 819*9880d681SAndroid Build Coastguard Worker if (FileHandle == INVALID_HANDLE_VALUE) 820*9880d681SAndroid Build Coastguard Worker return make_error_code(errc::bad_file_descriptor); 821*9880d681SAndroid Build Coastguard Worker 822*9880d681SAndroid Build Coastguard Worker DWORD CharCount; 823*9880d681SAndroid Build Coastguard Worker SmallVector<wchar_t, 1024> TempPath; 824*9880d681SAndroid Build Coastguard Worker do { 825*9880d681SAndroid Build Coastguard Worker CharCount = ::GetFinalPathNameByHandleW(FileHandle, TempPath.begin(), 826*9880d681SAndroid Build Coastguard Worker TempPath.capacity(), 827*9880d681SAndroid Build Coastguard Worker FILE_NAME_NORMALIZED); 828*9880d681SAndroid Build Coastguard Worker if (CharCount < TempPath.capacity()) 829*9880d681SAndroid Build Coastguard Worker break; 830*9880d681SAndroid Build Coastguard Worker 831*9880d681SAndroid Build Coastguard Worker // Reserve sufficient space for the path as well as the null character. Even 832*9880d681SAndroid Build Coastguard Worker // though the API does not document that it is required, if we reserve just 833*9880d681SAndroid Build Coastguard Worker // CharCount space, the function call will not store the resulting path and 834*9880d681SAndroid Build Coastguard Worker // still report success. 835*9880d681SAndroid Build Coastguard Worker TempPath.reserve(CharCount + 1); 836*9880d681SAndroid Build Coastguard Worker } while (true); 837*9880d681SAndroid Build Coastguard Worker 838*9880d681SAndroid Build Coastguard Worker if (CharCount == 0) 839*9880d681SAndroid Build Coastguard Worker return mapWindowsError(::GetLastError()); 840*9880d681SAndroid Build Coastguard Worker 841*9880d681SAndroid Build Coastguard Worker TempPath.set_size(CharCount); 842*9880d681SAndroid Build Coastguard Worker 843*9880d681SAndroid Build Coastguard Worker // On earlier Windows releases, the character count includes the terminating 844*9880d681SAndroid Build Coastguard Worker // null. 845*9880d681SAndroid Build Coastguard Worker if (TempPath.back() == L'\0') { 846*9880d681SAndroid Build Coastguard Worker --CharCount; 847*9880d681SAndroid Build Coastguard Worker TempPath.pop_back(); 848*9880d681SAndroid Build Coastguard Worker } 849*9880d681SAndroid Build Coastguard Worker 850*9880d681SAndroid Build Coastguard Worker return windows::UTF16ToUTF8(TempPath.data(), CharCount, ResultPath); 851*9880d681SAndroid Build Coastguard Worker} 852*9880d681SAndroid Build Coastguard Worker} // end namespace fs 853*9880d681SAndroid Build Coastguard Worker 854*9880d681SAndroid Build Coastguard Workernamespace path { 855*9880d681SAndroid Build Coastguard Workerstatic bool getKnownFolderPath(KNOWNFOLDERID folderId, 856*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<char> &result) { 857*9880d681SAndroid Build Coastguard Worker#if 0 858*9880d681SAndroid Build Coastguard Worker wchar_t *path = nullptr; 859*9880d681SAndroid Build Coastguard Worker if (::SHGetKnownFolderPath(folderId, KF_FLAG_CREATE, nullptr, &path) != S_OK) 860*9880d681SAndroid Build Coastguard Worker return false; 861*9880d681SAndroid Build Coastguard Worker 862*9880d681SAndroid Build Coastguard Worker bool ok = !UTF16ToUTF8(path, ::wcslen(path), result); 863*9880d681SAndroid Build Coastguard Worker ::CoTaskMemFree(path); 864*9880d681SAndroid Build Coastguard Worker return ok; 865*9880d681SAndroid Build Coastguard Worker#else 866*9880d681SAndroid Build Coastguard Worker // ANDROID needs updated mingw to build this. 867*9880d681SAndroid Build Coastguard Worker // BUG: http://b/26523949 868*9880d681SAndroid Build Coastguard Worker return false; 869*9880d681SAndroid Build Coastguard Worker#endif 870*9880d681SAndroid Build Coastguard Worker} 871*9880d681SAndroid Build Coastguard Worker 872*9880d681SAndroid Build Coastguard Workerbool getUserCacheDir(SmallVectorImpl<char> &Result) { 873*9880d681SAndroid Build Coastguard Worker#if 0 874*9880d681SAndroid Build Coastguard Worker return getKnownFolderPath(FOLDERID_LocalAppData, Result); 875*9880d681SAndroid Build Coastguard Worker#else 876*9880d681SAndroid Build Coastguard Worker // ANDROID needs updated mingw to build this. 877*9880d681SAndroid Build Coastguard Worker // BUG: http://b/26523949 878*9880d681SAndroid Build Coastguard Worker return false; 879*9880d681SAndroid Build Coastguard Worker#endif 880*9880d681SAndroid Build Coastguard Worker} 881*9880d681SAndroid Build Coastguard Worker 882*9880d681SAndroid Build Coastguard Workerbool home_directory(SmallVectorImpl<char> &result) { 883*9880d681SAndroid Build Coastguard Worker return getKnownFolderPath(FOLDERID_Profile, result); 884*9880d681SAndroid Build Coastguard Worker} 885*9880d681SAndroid Build Coastguard Worker 886*9880d681SAndroid Build Coastguard Workerstatic bool getTempDirEnvVar(const wchar_t *Var, SmallVectorImpl<char> &Res) { 887*9880d681SAndroid Build Coastguard Worker SmallVector<wchar_t, 1024> Buf; 888*9880d681SAndroid Build Coastguard Worker size_t Size = 1024; 889*9880d681SAndroid Build Coastguard Worker do { 890*9880d681SAndroid Build Coastguard Worker Buf.reserve(Size); 891*9880d681SAndroid Build Coastguard Worker Size = GetEnvironmentVariableW(Var, Buf.data(), Buf.capacity()); 892*9880d681SAndroid Build Coastguard Worker if (Size == 0) 893*9880d681SAndroid Build Coastguard Worker return false; 894*9880d681SAndroid Build Coastguard Worker 895*9880d681SAndroid Build Coastguard Worker // Try again with larger buffer. 896*9880d681SAndroid Build Coastguard Worker } while (Size > Buf.capacity()); 897*9880d681SAndroid Build Coastguard Worker Buf.set_size(Size); 898*9880d681SAndroid Build Coastguard Worker 899*9880d681SAndroid Build Coastguard Worker return !windows::UTF16ToUTF8(Buf.data(), Size, Res); 900*9880d681SAndroid Build Coastguard Worker} 901*9880d681SAndroid Build Coastguard Worker 902*9880d681SAndroid Build Coastguard Workerstatic bool getTempDirEnvVar(SmallVectorImpl<char> &Res) { 903*9880d681SAndroid Build Coastguard Worker const wchar_t *EnvironmentVariables[] = {L"TMP", L"TEMP", L"USERPROFILE"}; 904*9880d681SAndroid Build Coastguard Worker for (auto *Env : EnvironmentVariables) { 905*9880d681SAndroid Build Coastguard Worker if (getTempDirEnvVar(Env, Res)) 906*9880d681SAndroid Build Coastguard Worker return true; 907*9880d681SAndroid Build Coastguard Worker } 908*9880d681SAndroid Build Coastguard Worker return false; 909*9880d681SAndroid Build Coastguard Worker} 910*9880d681SAndroid Build Coastguard Worker 911*9880d681SAndroid Build Coastguard Workervoid system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) { 912*9880d681SAndroid Build Coastguard Worker (void)ErasedOnReboot; 913*9880d681SAndroid Build Coastguard Worker Result.clear(); 914*9880d681SAndroid Build Coastguard Worker 915*9880d681SAndroid Build Coastguard Worker // Check whether the temporary directory is specified by an environment var. 916*9880d681SAndroid Build Coastguard Worker // This matches GetTempPath logic to some degree. GetTempPath is not used 917*9880d681SAndroid Build Coastguard Worker // directly as it cannot handle evn var longer than 130 chars on Windows 7 918*9880d681SAndroid Build Coastguard Worker // (fixed on Windows 8). 919*9880d681SAndroid Build Coastguard Worker if (getTempDirEnvVar(Result)) { 920*9880d681SAndroid Build Coastguard Worker assert(!Result.empty() && "Unexpected empty path"); 921*9880d681SAndroid Build Coastguard Worker native(Result); // Some Unix-like shells use Unix path separator in $TMP. 922*9880d681SAndroid Build Coastguard Worker fs::make_absolute(Result); // Make it absolute if not already. 923*9880d681SAndroid Build Coastguard Worker return; 924*9880d681SAndroid Build Coastguard Worker } 925*9880d681SAndroid Build Coastguard Worker 926*9880d681SAndroid Build Coastguard Worker // Fall back to a system default. 927*9880d681SAndroid Build Coastguard Worker const char *DefaultResult = "C:\\Temp"; 928*9880d681SAndroid Build Coastguard Worker Result.append(DefaultResult, DefaultResult + strlen(DefaultResult)); 929*9880d681SAndroid Build Coastguard Worker} 930*9880d681SAndroid Build Coastguard Worker} // end namespace path 931*9880d681SAndroid Build Coastguard Worker 932*9880d681SAndroid Build Coastguard Workernamespace windows { 933*9880d681SAndroid Build Coastguard Workerstd::error_code UTF8ToUTF16(llvm::StringRef utf8, 934*9880d681SAndroid Build Coastguard Worker llvm::SmallVectorImpl<wchar_t> &utf16) { 935*9880d681SAndroid Build Coastguard Worker if (!utf8.empty()) { 936*9880d681SAndroid Build Coastguard Worker int len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8.begin(), 937*9880d681SAndroid Build Coastguard Worker utf8.size(), utf16.begin(), 0); 938*9880d681SAndroid Build Coastguard Worker 939*9880d681SAndroid Build Coastguard Worker if (len == 0) 940*9880d681SAndroid Build Coastguard Worker return mapWindowsError(::GetLastError()); 941*9880d681SAndroid Build Coastguard Worker 942*9880d681SAndroid Build Coastguard Worker utf16.reserve(len + 1); 943*9880d681SAndroid Build Coastguard Worker utf16.set_size(len); 944*9880d681SAndroid Build Coastguard Worker 945*9880d681SAndroid Build Coastguard Worker len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8.begin(), 946*9880d681SAndroid Build Coastguard Worker utf8.size(), utf16.begin(), utf16.size()); 947*9880d681SAndroid Build Coastguard Worker 948*9880d681SAndroid Build Coastguard Worker if (len == 0) 949*9880d681SAndroid Build Coastguard Worker return mapWindowsError(::GetLastError()); 950*9880d681SAndroid Build Coastguard Worker } 951*9880d681SAndroid Build Coastguard Worker 952*9880d681SAndroid Build Coastguard Worker // Make utf16 null terminated. 953*9880d681SAndroid Build Coastguard Worker utf16.push_back(0); 954*9880d681SAndroid Build Coastguard Worker utf16.pop_back(); 955*9880d681SAndroid Build Coastguard Worker 956*9880d681SAndroid Build Coastguard Worker return std::error_code(); 957*9880d681SAndroid Build Coastguard Worker} 958*9880d681SAndroid Build Coastguard Worker 959*9880d681SAndroid Build Coastguard Workerstatic 960*9880d681SAndroid Build Coastguard Workerstd::error_code UTF16ToCodePage(unsigned codepage, const wchar_t *utf16, 961*9880d681SAndroid Build Coastguard Worker size_t utf16_len, 962*9880d681SAndroid Build Coastguard Worker llvm::SmallVectorImpl<char> &utf8) { 963*9880d681SAndroid Build Coastguard Worker if (utf16_len) { 964*9880d681SAndroid Build Coastguard Worker // Get length. 965*9880d681SAndroid Build Coastguard Worker int len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, utf8.begin(), 966*9880d681SAndroid Build Coastguard Worker 0, NULL, NULL); 967*9880d681SAndroid Build Coastguard Worker 968*9880d681SAndroid Build Coastguard Worker if (len == 0) 969*9880d681SAndroid Build Coastguard Worker return mapWindowsError(::GetLastError()); 970*9880d681SAndroid Build Coastguard Worker 971*9880d681SAndroid Build Coastguard Worker utf8.reserve(len); 972*9880d681SAndroid Build Coastguard Worker utf8.set_size(len); 973*9880d681SAndroid Build Coastguard Worker 974*9880d681SAndroid Build Coastguard Worker // Now do the actual conversion. 975*9880d681SAndroid Build Coastguard Worker len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, utf8.data(), 976*9880d681SAndroid Build Coastguard Worker utf8.size(), NULL, NULL); 977*9880d681SAndroid Build Coastguard Worker 978*9880d681SAndroid Build Coastguard Worker if (len == 0) 979*9880d681SAndroid Build Coastguard Worker return mapWindowsError(::GetLastError()); 980*9880d681SAndroid Build Coastguard Worker } 981*9880d681SAndroid Build Coastguard Worker 982*9880d681SAndroid Build Coastguard Worker // Make utf8 null terminated. 983*9880d681SAndroid Build Coastguard Worker utf8.push_back(0); 984*9880d681SAndroid Build Coastguard Worker utf8.pop_back(); 985*9880d681SAndroid Build Coastguard Worker 986*9880d681SAndroid Build Coastguard Worker return std::error_code(); 987*9880d681SAndroid Build Coastguard Worker} 988*9880d681SAndroid Build Coastguard Worker 989*9880d681SAndroid Build Coastguard Workerstd::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, 990*9880d681SAndroid Build Coastguard Worker llvm::SmallVectorImpl<char> &utf8) { 991*9880d681SAndroid Build Coastguard Worker return UTF16ToCodePage(CP_UTF8, utf16, utf16_len, utf8); 992*9880d681SAndroid Build Coastguard Worker} 993*9880d681SAndroid Build Coastguard Worker 994*9880d681SAndroid Build Coastguard Workerstd::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len, 995*9880d681SAndroid Build Coastguard Worker llvm::SmallVectorImpl<char> &utf8) { 996*9880d681SAndroid Build Coastguard Worker return UTF16ToCodePage(CP_ACP, utf16, utf16_len, utf8); 997*9880d681SAndroid Build Coastguard Worker} 998*9880d681SAndroid Build Coastguard Worker 999*9880d681SAndroid Build Coastguard Worker} // end namespace windows 1000*9880d681SAndroid Build Coastguard Worker} // end namespace sys 1001*9880d681SAndroid Build Coastguard Worker} // end namespace llvm 1002