X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FSupport%2FWindows%2FPath.inc;h=49910af55a79490e43f3b72fcc64b224fa5d9354;hp=3033149980c1e1dd7eac9f5bc7633dc987097002;hb=6bd362c2d9d3e3284708ba5e55d8f3ccf7493313;hpb=9a7f4507abf0d46f07d2bfb4b5c652e519eea7e6 diff --git a/lib/Support/Windows/Path.inc b/lib/Support/Windows/Path.inc index 3033149980c..49910af55a7 100644 --- a/lib/Support/Windows/Path.inc +++ b/lib/Support/Windows/Path.inc @@ -253,17 +253,34 @@ std::error_code rename(const Twine &from, const Twine &to) { return ec; std::error_code ec = std::error_code(); + + // Retry while we see ERROR_ACCESS_DENIED. + // System scanners (eg. indexer) might open the source file when it is written + // and closed. + for (int i = 0; i < 2000; i++) { + // Try ReplaceFile first, as it is able to associate a new data stream with + // the destination even if the destination file is currently open. + if (::ReplaceFileW(wide_to.begin(), wide_from.begin(), NULL, 0, NULL, NULL)) + return std::error_code(); + + // We get ERROR_FILE_NOT_FOUND if the destination file is missing. + // MoveFileEx can handle this case. + DWORD ReplaceError = ::GetLastError(); + ec = mapWindowsError(ReplaceError); + if (ReplaceError != ERROR_ACCESS_DENIED && + ReplaceError != ERROR_FILE_NOT_FOUND && + ReplaceError != ERROR_SHARING_VIOLATION) + break; + if (::MoveFileExW(wide_from.begin(), wide_to.begin(), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING)) return std::error_code(); - DWORD LastError = ::GetLastError(); - ec = mapWindowsError(LastError); - if (LastError != ERROR_ACCESS_DENIED) - break; - // Retry MoveFile() at ACCESS_DENIED. - // System scanners (eg. indexer) might open the source file when - // It is written and closed. + + DWORD MoveError = ::GetLastError(); + ec = mapWindowsError(MoveError); + if (MoveError != ERROR_ACCESS_DENIED) break; + ::Sleep(1); } @@ -302,6 +319,11 @@ std::error_code access(const Twine &Path, AccessMode Mode) { return std::error_code(); } +bool can_execute(const Twine &Path) { + return !access(Path, AccessMode::Execute) || + !access(Path + ".exe", AccessMode::Execute); +} + bool equivalent(file_status A, file_status B) { assert(status_known(A) && status_known(B)); return A.FileIndexHigh == B.FileIndexHigh && @@ -326,10 +348,12 @@ std::error_code equivalent(const Twine &A, const Twine &B, bool &result) { static bool isReservedName(StringRef path) { // This list of reserved names comes from MSDN, at: // http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx - static const char *sReservedNames[] = { "nul", "con", "prn", "aux", - "com1", "com2", "com3", "com4", "com5", "com6", - "com7", "com8", "com9", "lpt1", "lpt2", "lpt3", - "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9" }; + static const char *const sReservedNames[] = { "nul", "con", "prn", "aux", + "com1", "com2", "com3", "com4", + "com5", "com6", "com7", "com8", + "com9", "lpt1", "lpt2", "lpt3", + "lpt4", "lpt5", "lpt6", "lpt7", + "lpt8", "lpt9" }; // First, check to see if this is a device namespace, which always // starts with \\.\, since device namespaces are not legal file paths. @@ -644,9 +668,10 @@ std::error_code openFileForRead(const Twine &Name, int &ResultFD) { if (std::error_code EC = widenPath(Name, PathUTF16)) return EC; - HANDLE H = ::CreateFileW(PathUTF16.begin(), GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + HANDLE H = + ::CreateFileW(PathUTF16.begin(), GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (H == INVALID_HANDLE_VALUE) { DWORD LastError = ::GetLastError(); std::error_code EC = mapWindowsError(LastError); @@ -729,17 +754,23 @@ std::error_code openFileForWrite(const Twine &Name, int &ResultFD, } // end namespace fs namespace path { - -bool home_directory(SmallVectorImpl &result) { - wchar_t Path[MAX_PATH]; - if (::SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, - /*SHGFP_TYPE_CURRENT*/0, Path) != S_OK) +static bool getKnownFolderPath(KNOWNFOLDERID folderId, + SmallVectorImpl &result) { + wchar_t *path = nullptr; + if (::SHGetKnownFolderPath(folderId, KF_FLAG_CREATE, nullptr, &path) != S_OK) return false; - if (UTF16ToUTF8(Path, ::wcslen(Path), result)) - return false; + bool ok = !UTF16ToUTF8(path, ::wcslen(path), result); + ::CoTaskMemFree(path); + return ok; +} - return true; +bool getUserCacheDir(SmallVectorImpl &Result) { + return getKnownFolderPath(FOLDERID_LocalAppData, Result); +} + +bool home_directory(SmallVectorImpl &result) { + return getKnownFolderPath(FOLDERID_Profile, result); } static bool getTempDirEnvVar(const char *Var, SmallVectorImpl &Res) {