Index: lib/profile/InstrProfilingUtil.h =================================================================== --- lib/profile/InstrProfilingUtil.h +++ lib/profile/InstrProfilingUtil.h @@ -16,6 +16,12 @@ /*! \brief Create a directory tree. */ void __llvm_profile_recursive_mkdir(char *Pathname); +/*! Set the mode used when creating profile directories. */ +void __llvm_profile_set_dir_mode(unsigned Mode); + +/*! Return the directory creation mode. */ +unsigned __llvm_profile_get_dir_mode(void); + int lprofLockFd(int fd); int lprofUnlockFd(int fd); Index: lib/profile/InstrProfilingUtil.c =================================================================== --- lib/profile/InstrProfilingUtil.c +++ lib/profile/InstrProfilingUtil.c @@ -35,6 +35,8 @@ #include "InstrProfiling.h" #include "InstrProfilingUtil.h" +COMPILER_RT_WEAK unsigned lprofDirMode = 0755; + COMPILER_RT_VISIBILITY void __llvm_profile_recursive_mkdir(char *path) { int i; @@ -47,12 +49,19 @@ #ifdef _WIN32 _mkdir(path); #else - mkdir(path, 0755); /* Some of these will fail, ignore it. */ + /* Some of these will fail, ignore it. */ + mkdir(path, __llvm_profile_get_dir_mode()); #endif path[i] = save; } } +COMPILER_RT_VISIBILITY +void __llvm_profile_set_dir_mode(unsigned Mode) { lprofDirMode = Mode; } + +COMPILER_RT_VISIBILITY +unsigned __llvm_profile_get_dir_mode(void) { return lprofDirMode; } + #if COMPILER_RT_HAS_ATOMICS != 1 COMPILER_RT_VISIBILITY uint32_t lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV) { Index: test/profile/instrprof-set-dir-mode.c =================================================================== --- test/profile/instrprof-set-dir-mode.c +++ test/profile/instrprof-set-dir-mode.c @@ -0,0 +1,48 @@ +// UNSUPPORTED: windows +// RUN: %clang_pgogen -o %t.bin %s -DTESTPATH=\"%t.dir\" +// RUN: rm -rf %t.dir +// RUN: %run %t.bin + +#include +#include +#include +#include + +void __llvm_profile_set_dir_mode(unsigned Mode); +unsigned __llvm_profile_get_dir_mode(void); +void __llvm_profile_recursive_mkdir(char *Path); + +static int test(unsigned Mode, const char *TestDir) { + int Ret = 0; + + /* Create a dir and set the mode accordingly. */ + char *Dir = strdup(TestDir); + if (!Dir) + return -1; + __llvm_profile_set_dir_mode(Mode); + __llvm_profile_recursive_mkdir(Dir); + + if (Mode != __llvm_profile_get_dir_mode()) + Ret = -1; + else { + const unsigned Expected = ~umask(0) & Mode; + struct stat DirSt; + if (stat(Dir, &DirSt) == -1) + Ret = -1; + else if (DirSt.st_mode != Expected) { + printf("Modes do not match: Expected %o but found %o (%s)\n", Expected, + DirSt.st_mode, Dir); + Ret = -1; + } + } + + free(Dir); + return Ret; +} + +int main(void) { + if (test(S_IFDIR | 0777, TESTPATH "/foo/bar/baz/") || + test(S_IFDIR | 0666, TESTPATH "/foo/bar/qux/")) + return -1; + return 0; +}