diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -260,6 +260,10 @@ // Strip the directories from the module name. const char *StripModuleName(const char *module); +#if !SANITIZER_FUCHSIA +int CreateDir(const char *pathname); +#endif + // OS uptr ReadBinaryName(/*out*/char *buf, uptr buf_len); uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len); 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); } +int CreateDir(const char *pathname) { 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 @@ -75,6 +75,21 @@ 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'; + /* Some of these will fail, because the directory exists, ignore it. */ + CreateDir(path); + path[i] = save; + } +} + void ReportFile::SetReportPath(const char *path) { if (path) { uptr len = internal_strlen(path); @@ -95,6 +110,7 @@ fd = kStdoutFd; } else { internal_snprintf(path_prefix, kMaxPathLength, "%s", path); + RecursiveMkdir(path_prefix); } } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp @@ -151,6 +151,8 @@ #endif } +int CreateDir(const char *pathname) { return mkdir(pathname, 0755); } + bool SupportsColoredOutput(fd_t fd) { return isatty(fd) != 0; } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp @@ -565,7 +565,9 @@ internal__exit(3); } -#if !SANITIZER_GO +int CreateDir(const char *pathname) { return _mkdir(pathname); } + +# if !SANITIZER_GO // Read the file to extract the ImageBase field from the PE header. If ASLR is // disabled and this virtual address is available, the loader will typically // load the image at this address. Therefore, we call it the preferred base. Any 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.