| 533 | |
| 534 | #ifdef _WIN32 |
| 535 | std::string SystemToolsStatic::GetCasePathName(std::string const& pathIn) |
| 536 | { |
| 537 | std::string casePath; |
| 538 | |
| 539 | // First check if the file is relative. We don't fix relative paths since the |
| 540 | // real case depends on the root directory and the given path fragment may |
| 541 | // have meaning elsewhere in the project. |
| 542 | if (!SystemTools::FileIsFullPath(pathIn)) { |
| 543 | // This looks unnecessary, but it allows for the return value optimization |
| 544 | // since all return paths return the same local variable. |
| 545 | casePath = pathIn; |
| 546 | return casePath; |
| 547 | } |
| 548 | |
| 549 | std::vector<std::string> path_components; |
| 550 | SystemTools::SplitPath(pathIn, path_components); |
| 551 | |
| 552 | // Start with root component. |
| 553 | std::vector<std::string>::size_type idx = 0; |
| 554 | casePath = path_components[idx++]; |
| 555 | // make sure drive letter is always upper case |
| 556 | if (casePath.size() > 1 && casePath[1] == ':') { |
| 557 | casePath[0] = kwsysString_toupper(casePath[0]); |
| 558 | } |
| 559 | char const* sep = ""; |
| 560 | |
| 561 | // If network path, fill casePath with server/share so FindFirstFile |
| 562 | // will work after that. Maybe someday call other APIs to get |
| 563 | // actual case of servers and shares. |
| 564 | if (path_components.size() > 2 && path_components[0] == "//") { |
| 565 | casePath += path_components[idx++]; |
| 566 | casePath += "/"; |
| 567 | casePath += path_components[idx++]; |
| 568 | sep = "/"; |
| 569 | } |
| 570 | |
| 571 | // Convert case of all components that exist. |
| 572 | bool converting = true; |
| 573 | for (; idx < path_components.size(); idx++) { |
| 574 | casePath += sep; |
| 575 | sep = "/"; |
| 576 | |
| 577 | if (converting) { |
| 578 | // If path component contains wildcards, we skip matching |
| 579 | // because these filenames are not allowed on windows, |
| 580 | // and we do not want to match a different file. |
| 581 | if (path_components[idx].find('*') != std::string::npos || |
| 582 | path_components[idx].find('?') != std::string::npos) { |
| 583 | converting = false; |
| 584 | } else { |
| 585 | std::string test_str = casePath; |
| 586 | test_str += path_components[idx]; |
| 587 | |
| 588 | WIN32_FIND_DATAW findData; |
| 589 | HANDLE hFind = |
| 590 | ::FindFirstFileW(Encoding::ToWide(test_str).c_str(), &findData); |
| 591 | if (INVALID_HANDLE_VALUE != hFind) { |
| 592 | auto case_file_name = Encoding::ToNarrow(findData.cFileName); |
nothing calls this directly
no test coverage detected