| 2611 | } |
| 2612 | |
| 2613 | bool fs::pending_file::commit(bool overwrite) |
| 2614 | { |
| 2615 | if (m_path.empty()) |
| 2616 | { |
| 2617 | fs::g_tls_error = fs::error::noent; |
| 2618 | return false; |
| 2619 | } |
| 2620 | |
| 2621 | // The temporary file's contents must be on disk before rename |
| 2622 | #ifndef _WIN32 |
| 2623 | if (file) |
| 2624 | { |
| 2625 | file.sync(); |
| 2626 | } |
| 2627 | #endif |
| 2628 | |
| 2629 | #ifdef _WIN32 |
| 2630 | if (file) |
| 2631 | { |
| 2632 | // Disable auto-delete |
| 2633 | FILE_DISPOSITION_INFO disp; |
| 2634 | disp.DeleteFileW = false; |
| 2635 | ensure(SetFileInformationByHandle(file.get_handle(), FileDispositionInfo, &disp, sizeof(disp))); |
| 2636 | } |
| 2637 | |
| 2638 | std::vector<std::wstring> hardlink_paths; |
| 2639 | |
| 2640 | const auto ws1 = to_wchar(m_path); |
| 2641 | |
| 2642 | const HANDLE file_handle = !overwrite ? INVALID_HANDLE_VALUE : CreateFileW(ws1.get(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); |
| 2643 | |
| 2644 | while (file_handle != INVALID_HANDLE_VALUE) |
| 2645 | { |
| 2646 | // Get file ID (used to check for hardlinks) |
| 2647 | BY_HANDLE_FILE_INFORMATION file_info; |
| 2648 | |
| 2649 | if (!GetFileInformationByHandle(file_handle, &file_info) || file_info.nNumberOfLinks == 1) |
| 2650 | { |
| 2651 | CloseHandle(file_handle); |
| 2652 | break; |
| 2653 | } |
| 2654 | |
| 2655 | // Buffer for holding link name |
| 2656 | std::wstring link_name_buffer(MAX_PATH, wchar_t{}); |
| 2657 | DWORD buffer_size{}; |
| 2658 | HANDLE find_handle = INVALID_HANDLE_VALUE; |
| 2659 | |
| 2660 | while (true) |
| 2661 | { |
| 2662 | buffer_size = static_cast<DWORD>(link_name_buffer.size() - 1); |
| 2663 | find_handle = FindFirstFileNameW(ws1.get(), 0, &buffer_size, link_name_buffer.data()); |
| 2664 | |
| 2665 | if (find_handle != INVALID_HANDLE_VALUE || GetLastError() != ERROR_MORE_DATA) |
| 2666 | { |
| 2667 | break; |
| 2668 | } |
| 2669 | |
| 2670 | link_name_buffer.resize(buffer_size + 1); |
no test coverage detected