in tools/common/file_system.cc [94:141]
bool MakeDirs(const std::string &path, int mode) {
// If we got an empty string, we've recursed past the first segment in the
// path. Assume it exists (if it doesn't, we'll fail when we try to create a
// directory inside it).
if (path.empty()) {
return true;
}
struct stat dir_stats;
if (stat(path.c_str(), &dir_stats) == 0) {
// Return true if the directory already exists.
if (S_ISDIR(dir_stats.st_mode)) {
return true;
}
std::cerr << "error: path already exists but is not a directory: "
<< path << "\n";
return false;
}
// Recurse to create the parent directory.
if (!MakeDirs(Dirname(path).c_str(), mode)) {
return false;
}
// Create the directory that was requested.
if (mkdir(path.c_str(), mode) == 0) {
return true;
}
// Race condition: The above call to `mkdir` could fail if there are multiple
// calls to `MakeDirs` running at the same time with overlapping paths, so
// check again to see if the directory exists despite the call failing. If it
// does, that's ok.
if (errno == EEXIST && stat(path.c_str(), &dir_stats) == 0) {
if (S_ISDIR(dir_stats.st_mode)) {
return true;
}
std::cerr << "error: path already exists but is not a directory: "
<< path << "\n";
return false;
}
std::cerr << "error: could not create directory: " << path
<< " (" << strerror(errno) << ")\n";
return false;
}