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