mirror of
https://github.com/google/googletest.git
synced 2025-12-06 16:57:00 +08:00
Fix race condition when creating unique filename
Because the file is not opened with O_EXCL, there is no guarantee that multiple threads calling this function simultaneously across different processes will not generate the same filename. Instead make sure to use O_EXCL for the kernel to decide whether a filename already exists.
This commit is contained in:
parent
9d43b27f7a
commit
73245c3baf
@ -302,6 +302,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
// #include <condition_variable> // Guarded by GTEST_IS_THREADSAFE below
|
// #include <condition_variable> // Guarded by GTEST_IS_THREADSAFE below
|
||||||
@ -2112,6 +2113,24 @@ GTEST_DISABLE_MSC_DEPRECATED_PUSH_()
|
|||||||
!defined(GTEST_OS_XTENSA) && !defined(GTEST_OS_QURT)
|
!defined(GTEST_OS_XTENSA) && !defined(GTEST_OS_QURT)
|
||||||
inline int ChDir(const char* dir) { return chdir(dir); }
|
inline int ChDir(const char* dir) { return chdir(dir); }
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MINGW)
|
||||||
|
const int CREAT = _O_CREAT;
|
||||||
|
const int EXCL = _O_EXCL;
|
||||||
|
const int WRONLY = _O_WRONLY;
|
||||||
|
#else // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW
|
||||||
|
const int CREAT = O_CREAT;
|
||||||
|
const int EXCL = O_EXCL;
|
||||||
|
const int WRONLY = O_WRONLY;
|
||||||
|
#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW
|
||||||
|
inline int Open(const char* path, int flags, int mode) {
|
||||||
|
#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MINGW)
|
||||||
|
std::wstring_convert<wchar_codecvt> converter;
|
||||||
|
std::wstring wide_path = converter.from_bytes(path);
|
||||||
|
return _wopen(wide_path.c_str(), flags, mode);
|
||||||
|
#else // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW
|
||||||
|
return open(path, flags, mode);
|
||||||
|
#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW
|
||||||
|
}
|
||||||
inline FILE* FOpen(const char* path, const char* mode) {
|
inline FILE* FOpen(const char* path, const char* mode) {
|
||||||
#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MINGW)
|
#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MINGW)
|
||||||
struct wchar_codecvt : public std::codecvt<wchar_t, char, std::mbstate_t> {};
|
struct wchar_codecvt : public std::codecvt<wchar_t, char, std::mbstate_t> {};
|
||||||
|
|||||||
@ -312,12 +312,20 @@ bool FilePath::IsAbsolutePath() const { return CalculateRootLength() > 0; }
|
|||||||
FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
|
FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
|
||||||
const FilePath& base_name,
|
const FilePath& base_name,
|
||||||
const char* extension) {
|
const char* extension) {
|
||||||
|
// Make sure the directory does exist
|
||||||
|
directory.CreateDirectoriesRecursively();
|
||||||
|
|
||||||
FilePath full_pathname;
|
FilePath full_pathname;
|
||||||
int number = 0;
|
int number = 0;
|
||||||
do {
|
for (;;) {
|
||||||
full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
|
full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
|
||||||
} while (full_pathname.FileOrDirectoryExists());
|
int fd = posix::Open(full_pathname.c_str(),
|
||||||
return full_pathname;
|
posix::CREAT | posix::EXCL | posix::WRONLY, 0644);
|
||||||
|
if (fd != -1) {
|
||||||
|
posix::Close(fd);
|
||||||
|
return full_pathname;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if FilePath ends with a path separator, which indicates that
|
// Returns true if FilePath ends with a path separator, which indicates that
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user