diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_nolibc.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_common_nolibc.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_nolibc.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_nolibc.cpp @@ -25,6 +25,7 @@ #endif void WriteToSyslog(const char *buffer) {} void Abort() { internal__exit(1); } +extern "C" int mkdir(const char *pathname, unsigned int mode) { return 0; } #endif // !SANITIZER_WINDOWS #if !SANITIZER_WINDOWS && !SANITIZER_MAC diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp @@ -19,6 +19,11 @@ #include "sanitizer_common.h" #include "sanitizer_file.h" +#if SANITIZER_WINDOWS +#include +#else +#include +#endif namespace __sanitizer { @@ -75,6 +80,25 @@ fd_pid = pid; } +static void RecursiveMkdir(char *path) { + int i; + int start = 1; + + for (i = start; path[i] != '\0'; ++i) { + char save = path[i]; + if (IsPathSeparator(path[i])) + continue; + path[i] = '\0'; +#if SANITIZER_WINDOWS + _mkdir(path); +#else + /* Some of these will fail, because the directory exists, ignore it. */ + mkdir(path, 0755); +#endif + path[i] = save; + } +} + void ReportFile::SetReportPath(const char *path) { if (path) { uptr len = internal_strlen(path); @@ -95,6 +119,7 @@ fd = kStdoutFd; } else { internal_snprintf(path_prefix, kMaxPathLength, "%s", path); + RecursiveMkdir(path_prefix); } } diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_test.cpp b/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_test.cpp --- a/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_test.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_test.cpp @@ -11,10 +11,10 @@ int main(int argc, char **argv) { char buff[1000]; - sprintf(buff, "%s.report_path", argv[0]); + sprintf(buff, "%s.report_path/report", argv[0]); __sanitizer_set_report_path(buff); assert(strncmp(buff, __sanitizer_get_report_path(), strlen(buff)) == 0); printf("Path %s\n", __sanitizer_get_report_path()); } -// CHECK: Path {{.*}}Posix/Output/sanitizer_set_report_path_test.cpp.tmp.report_path. +// CHECK: Path {{.*}}Posix/Output/sanitizer_set_report_path_test.cpp.tmp.report_path/report.