1 // XFAIL: aix
2 // UNSUPPORTED: windows
3 // RUN: %clang_pgogen -o %t.bin %s -DTESTPATH=\"%t.dir\"
4 // RUN: rm -rf %t.dir
5 // RUN: %run %t.bin
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/stat.h>
11 
12 void __llvm_profile_set_dir_mode(unsigned Mode);
13 unsigned __llvm_profile_get_dir_mode(void);
14 void __llvm_profile_recursive_mkdir(char *Path);
15 
test(unsigned Mode,const char * TestDir)16 static int test(unsigned Mode, const char *TestDir) {
17   int Ret = 0;
18 
19   /* Create a dir and set the mode accordingly. */
20   char *Dir = strdup(TestDir);
21   if (!Dir)
22     return -1;
23   __llvm_profile_set_dir_mode(Mode);
24   __llvm_profile_recursive_mkdir(Dir);
25 
26   if (Mode != __llvm_profile_get_dir_mode())
27     Ret = -1;
28   else {
29     // From 'man mkdir':
30     // "If the parent directory has the set-group-ID bit set, then so will the
31     // newly created directory."  So we mask off S_ISGID below; this test cannot
32     // control its parent directory.
33     const unsigned Expected = ~umask(0) & Mode;
34     struct stat DirSt;
35     if (stat(Dir, &DirSt) == -1)
36       Ret = -1;
37     // AIX has some extended definition of high order bits for st_mode, avoid trying to comparing those by masking them off.
38     else if (((DirSt.st_mode & ~S_ISGID) & 0xFFFF) != Expected) {
39       printf("Modes do not match: Expected %o but found %o (%s)\n", Expected,
40              DirSt.st_mode, Dir);
41       Ret = -1;
42     }
43   }
44 
45   free(Dir);
46   return Ret;
47 }
48 
main(void)49 int main(void) {
50   if (test(S_IFDIR | 0777, TESTPATH "/foo/bar/baz/") ||
51       test(S_IFDIR | 0666, TESTPATH "/foo/bar/qux/"))
52     return -1;
53   return 0;
54 }
55