| 76 | } |
| 77 | |
| 78 | FILE* CreateTempFileNearUtf8(const std::string& targetFileName, |
| 79 | std::string* fileName) { |
| 80 | #ifdef _WIN32 |
| 81 | if (fileName == nullptr) { |
| 82 | return nullptr; |
| 83 | } |
| 84 | |
| 85 | const std::wstring target = internal::WideFromUtf8(targetFileName); |
| 86 | const std::wstring parent = ParentDirectory(target); |
| 87 | const DWORD processId = GetCurrentProcessId(); |
| 88 | const ULONGLONG tick = GetTickCount64(); |
| 89 | |
| 90 | for (int i = 0; i < 100; i++) { |
| 91 | const std::wstring tempFileName = |
| 92 | parent + L".opencc-" + std::to_wstring(processId) + L"-" + |
| 93 | std::to_wstring(tick) + L"-" + std::to_wstring(i) + L".tmp"; |
| 94 | const int fd = _wopen(tempFileName.c_str(), |
| 95 | _O_CREAT | _O_EXCL | _O_BINARY | _O_WRONLY, |
| 96 | _S_IREAD | _S_IWRITE); |
| 97 | if (fd == -1) { |
| 98 | continue; |
| 99 | } |
| 100 | FILE* file = _wfdopen(fd, L"wb"); |
| 101 | if (file == nullptr) { |
| 102 | _close(fd); |
| 103 | DeleteFileW(tempFileName.c_str()); |
| 104 | return nullptr; |
| 105 | } |
| 106 | *fileName = internal::Utf8FromWide(tempFileName); |
| 107 | return file; |
| 108 | } |
| 109 | return nullptr; |
| 110 | #else |
| 111 | if (fileName == nullptr) { |
| 112 | return nullptr; |
| 113 | } |
| 114 | |
| 115 | std::string tempFileName = ParentDirectory(targetFileName); |
| 116 | tempFileName += "/"; |
| 117 | tempFileName += "openccXXXXXX"; |
| 118 | |
| 119 | std::vector<char> pathBuffer(tempFileName.begin(), tempFileName.end()); |
| 120 | pathBuffer.push_back('\0'); |
| 121 | const int fd = mkstemp(pathBuffer.data()); |
| 122 | if (fd == -1) { |
| 123 | return nullptr; |
| 124 | } |
| 125 | FILE* file = fdopen(fd, "wb"); |
| 126 | if (file == nullptr) { |
| 127 | close(fd); |
| 128 | std::remove(pathBuffer.data()); |
| 129 | return nullptr; |
| 130 | } |
| 131 | *fileName = pathBuffer.data(); |
| 132 | return file; |
| 133 | #endif |
| 134 | } |
| 135 |
no test coverage detected