diff --git a/tools/common/file_system.cc b/tools/common/file_system.cc index 15b2c274f..081c82750 100644 --- a/tools/common/file_system.cc +++ b/tools/common/file_system.cc @@ -18,7 +18,9 @@ #include #include +#include #include +#include #ifdef __APPLE__ #include @@ -99,7 +101,13 @@ bool MakeDirs(const std::string &path, int mode) { struct stat dir_stats; if (stat(path.c_str(), &dir_stats) == 0) { // Return true if the directory already exists. - return S_ISDIR(dir_stats.st_mode); + if (!S_ISDIR(dir_stats.st_mode)) { + std::cerr << "error: path exists and isn't a directory " + << strerror(errno) << " (" << path.c_str() << ") \n"; + return false; + } else { + return true; + } } // Recurse to create the parent directory. @@ -108,5 +116,29 @@ bool MakeDirs(const std::string &path, int mode) { } // Create the directory that was requested. - return mkdir(path.c_str(), mode) == 0; + int mkdir_ret = mkdir(path.c_str(), mode); + if (mkdir_ret == 0) { + return true; + } + + // Save the mkdir errno for better reporting. + int mkdir_errno = errno; + + // Deal with a race condition when 2 `MakeDirs` are running at the same time: + // one `mkdir` invocation will fail in each recursive call at different + // points. Don't recurse here to avoid an infinite loop in failure cases. + if (errno == EEXIST && stat(path.c_str(), &dir_stats) == 0) { + if (!S_ISDIR(dir_stats.st_mode)) { + std::cerr << "error: path exists and isn't a directory " + << strerror(errno) << " (" << path.c_str() << ") \n"; + return false; + } else { + // Return true if the directory already exists. + return true; + } + } + + std::cerr << "error:" << strerror(mkdir_errno) << " (" << path.c_str() + << ") \n"; + return false; }