| 713 | #endif |
| 714 | |
| 715 | std::optional<MMKVPath_t> getUniqueFileName(const MMKVPath_t &folder, const MMKVPath_t &prefix) { |
| 716 | fs::path folderPath(folder); |
| 717 | fs::path prefixPath(prefix); |
| 718 | |
| 719 | // Ensure the directory exists |
| 720 | std::error_code ec; |
| 721 | if (!fs::exists(folderPath, ec)) { |
| 722 | // Attempt to create it or fail if preferred. |
| 723 | // GetTempFileName fails if dir doesn't exist, so we adhere to that. |
| 724 | return std::nullopt; |
| 725 | } |
| 726 | |
| 727 | // Behavior: Generate random unique filename, CREATE the file to reserve it. |
| 728 | std::random_device rd; |
| 729 | std::mt19937_64 gen(rd()); |
| 730 | std::uniform_int_distribution<uint64_t> dis; |
| 731 | |
| 732 | constexpr int maxAttempts = 64; |
| 733 | for (int i = 0; i < maxAttempts; ++i) { |
| 734 | uint64_t randomVal = dis(gen); |
| 735 | MMKVPath_t suffix = to_string(randomVal); |
| 736 | MMKVPath_t fileName = prefix + "." + suffix + ".tmp"; |
| 737 | fs::path candidatePath = folderPath / fileName; |
| 738 | |
| 739 | // Atomic check and create logic "mimic" |
| 740 | // std::filesystem::exists is not atomic, but standard C++17 <fstream> doesn't |
| 741 | // support O_EXCL (exclusive create) easily without platform headers. |
| 742 | // We check existence first to avoid clobbering existing files. |
| 743 | if (fs::exists(candidatePath, ec)) { |
| 744 | continue; // Collision found, try next |
| 745 | } |
| 746 | |
| 747 | // Try to create the file to "reserve" it |
| 748 | File file(candidatePath.native(), OpenFlag::ReadWrite | OpenFlag::Create); |
| 749 | if (file.isFileValid()) { |
| 750 | return candidatePath.native(); |
| 751 | } |
| 752 | } |
| 753 | |
| 754 | // Failed to find unique name after max attempts |
| 755 | return std::nullopt; |
| 756 | } |
| 757 | } // namespace mmkv |
| 758 | |
| 759 | #endif // !defined(MMKV_WIN32) |
no test coverage detected