]> git.saurik.com Git - apple/xnu.git/blob - tools/tests/unit_tests/ptcwd_test_11269991_src/ptcwd_test_11269991.c
2f58665901b91d56434d0d560fee1e7437e16c18
[apple/xnu.git] / tools / tests / unit_tests / ptcwd_test_11269991_src / ptcwd_test_11269991.c
1 /*
2 * Test program for checking the per-thread current working directories
3 * are happy.
4 */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <fcntl.h>
9 #include <string.h>
10 #include <sys/syscall.h>
11 #include <sys/errno.h>
12 #include <sys/stat.h>
13 #include <sys/param.h>
14
15 #ifndef SYS___pthread_chdir
16 #define SYS___pthread_chdir 348
17 #endif
18
19 #ifndef SYS___pthread_fchdir
20 #define SYS___pthread_fchdir 349
21 #endif
22
23 /*
24 * /tmp is a symlink, so use full path for strict compare
25 */
26 #define WORKDIR "/private/tmp/ptwork"
27 #define WORKDIR1 WORKDIR "/one"
28 #define WORKDIR2 WORKDIR "/two"
29
30
31 int
32 pthread_chdir_np(char *path)
33 {
34 return syscall(SYS___pthread_chdir, path);
35 }
36
37 int
38 pthread_fchdir_np(int fd)
39 {
40 return syscall(SYS___pthread_fchdir, fd);
41 }
42
43
44 /*
45 * This is a slow routine, just like getcwd(); people should remember that
46 * they set something, instead of asking us what they told us.
47 */
48 char *
49 pthread_getcwd_np(char *buf, size_t size)
50 {
51 int fd_cwd;
52
53 /*
54 * XXX disable compatibility hack, since we have no compatibility
55 * XXX to protect.
56 */
57 if (buf == NULL)
58 return (NULL);
59
60 /*
61 * Open the "current working directory"; if we are running on a per
62 * thread working directory, that's the one we will get.
63 */
64 if ((fd_cwd = open(".", O_RDONLY)) == -1)
65 return (NULL);
66
67 /*
68 * Switch off the per thread current working directory, in case we
69 * were on one; this fails if we aren't running with one.
70 */
71 if (pthread_fchdir_np( -1) == -1) {
72 /* We aren't runniing with one... alll done. */
73 close (fd_cwd);
74 return (NULL);
75 }
76
77 /*
78 * If we successfully switched off, then we switch back...
79 * this may fail catastrophically, if we no longer have rights;
80 * this should never happen, but threads may clobber our fd out
81 * from under us, etc..
82 */
83 if (pthread_fchdir_np(fd_cwd) == -1) {
84 close(fd_cwd);
85 errno = EBADF; /* sigil for catastrophic failure */
86 return (NULL);
87 }
88
89 /* Close our directory handle */
90 close(fd_cwd);
91
92 /*
93 * And call the regular getcwd(), which will return the per thread
94 * current working directory instead of the process one.
95 */
96 return getcwd(buf, size);
97 }
98
99
100 int
101 main(int ac, char *av[])
102 {
103 char buf[MAXPATHLEN];
104 char *p;
105
106 /*
107 * First, verify that we are NOT using a per thread current working
108 * directory...
109 */
110 if (pthread_fchdir_np( -1) != -1) {
111 fprintf(stderr, "FAIL: Started out on PT CWD\n");
112 exit(1);
113 }
114
115 /* Blow the umask to avoid shooting our foot */
116 umask(0); /* "always successful" */
117
118 /* Now set us up the test directories... */
119
120 if (mkdir(WORKDIR, 0777) == -1 && errno != EEXIST) {
121 perror("FAIL: mkdir: " WORKDIR);
122 exit(2);
123 }
124
125 printf("workdir \"" WORKDIR "\" created\n");
126
127 if (mkdir(WORKDIR1, 0777) == -1 && errno != EEXIST) {
128 perror("FAIL: mkdir: " WORKDIR1);
129 exit(2);
130 }
131
132 printf("workdir \"" WORKDIR1 "\" created\n");
133
134 if (mkdir(WORKDIR2, 0777) == -1 && errno != EEXIST) {
135 perror("FAIL: mkdir: " WORKDIR2);
136 exit(2);
137 }
138
139 printf("workdir \"" WORKDIR2 "\" created\n");
140
141 /* Change the process current working directory to WORKDIR1 */
142
143 if (chdir(WORKDIR1) == -1) {
144 perror("FAIL: chdir: \"" WORKDIR1 "\" failed\n");
145 exit(3);
146 }
147
148 printf("process current working directory changed to \"" WORKDIR1 "\"...\n");
149
150 printf("verifying; getcwd says: \"%s\"\n", getcwd(buf, MAXPATHLEN));
151 if (strcmp(WORKDIR1, buf)) {
152 fprintf(stderr, "FAIL: \"%s\" != \"%s\"\n", WORKDIR1, buf);
153 exit(3);
154 }
155 printf("verified.\n");
156
157 /* Verify that we don't get an answer for pthread_getcwd_np() */
158
159 if ((p = pthread_getcwd_np(buf, MAXPATHLEN)) != NULL) {
160 fprintf(stderr, "FAIL: pthread_getcwd_np should fail, got \"%s\" instead\n", p);
161 exit(4);
162 }
163
164 printf("Good so far: pthread_getcwd_np() got no answer (correct)\n");
165
166 if (pthread_chdir_np(WORKDIR2) == -1) {
167 perror("FAIL: pthread_chdir_np: " WORKDIR2);
168 exit(5);
169 }
170
171 printf("Set per thread current working directory to \"" WORKDIR2"\"\n");
172 printf("verifying; getcwd says: \"%s\"\n", getcwd(buf, MAXPATHLEN));
173 if (strcmp(WORKDIR2, buf)) {
174 fprintf(stderr, "FAIL: \"%s\" != \"%s\"\n", WORKDIR2, buf);
175 exit(3);
176 }
177 printf("verified.\n");
178
179 /* Now verify we get an answer for pthread_getcwd_np() */
180 if ((p = pthread_getcwd_np(buf, MAXPATHLEN)) == NULL) {
181 perror("FAIL: pthread_getcwd_np");
182 exit(6);
183 }
184
185 printf("verifying... pthread_getcwd_np says \"%s\"\n", p);
186 if (strcmp(WORKDIR2, buf)) {
187 fprintf(stderr, "FAIL: \"%s\" != \"%s\"\n", WORKDIR2, buf);
188 exit(7);
189 }
190 printf("verified.\n");
191
192 printf("verifying our old cwd still exists by going of PT CWD...\n");
193 if (pthread_fchdir_np(-1) != 0) {
194 perror("FAIL: pthread_fchdir_np");
195 exit(8);
196 }
197 printf("off... but are we really off?\n");
198
199 printf("Check by verifying that pthread_getcwd_np now fails\n");
200 if ((p = pthread_getcwd_np(buf, MAXPATHLEN)) != NULL) {
201 fprintf(stderr, "FAIL: pthread_getcwd_np should fail, got \"%s\" instead\n", p);
202 exit(9);
203 }
204
205 printf("verified.\n");
206
207 printf("One last check: see that getcwd says \"" WORKDIR1 "\" again\n");
208 printf("verifying; getcwd says: \"%s\"\n", getcwd(buf, MAXPATHLEN));
209 if (strcmp(WORKDIR1, buf)) {
210 fprintf(stderr, "FAIL: \"%s\" != \"%s\"\n", WORKDIR1, buf);
211 exit(10);
212 }
213 printf("verified.\n");
214
215
216 printf("\nPASS: testing was successful\n");
217
218 exit(0);
219 }