]> git.saurik.com Git - apple/libpthread.git/blob - tests/pthread_cwd.c
libpthread-454.40.3.tar.gz
[apple/libpthread.git] / tests / pthread_cwd.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <fcntl.h>
5 #include <string.h>
6 #include <sys/syscall.h>
7 #include <sys/errno.h>
8 #include <sys/stat.h>
9 #include <sys/param.h>
10 #include <pthread/private.h>
11
12 #include "darwintest_defaults.h"
13
14 // /tmp is a symlink, so use full path for strict compare
15 #define WORKDIR "/private/var/tmp/ptwork"
16 #define WORKDIR1 WORKDIR "/one"
17 #define WORKDIR2 WORKDIR "/two"
18
19 /*
20 * This is a slow routine, just like getcwd(); people should remember that
21 * they set something, instead of asking us what they told us.
22 */
23 static char *
24 pthread_getcwd_np(char *buf, size_t size)
25 {
26 int fd_cwd;
27
28 if (buf == NULL)
29 return (NULL);
30
31 /*
32 * Open the "current working directory"; if we are running on a per
33 * thread working directory, that's the one we will get.
34 */
35 if ((fd_cwd = open(".", O_RDONLY)) == -1)
36 return (NULL);
37
38 /*
39 * Switch off the per thread current working directory, in case we
40 * were on one; this fails if we aren't running with one.
41 */
42 if (pthread_fchdir_np( -1) == -1) {
43 /* We aren't runniing with one... alll done. */
44 close (fd_cwd);
45 return (NULL);
46 }
47
48 /*
49 * If we successfully switched off, then we switch back...
50 * this may fail catastrophically, if we no longer have rights;
51 * this should never happen, but threads may clobber our fd out
52 * from under us, etc..
53 */
54 if (pthread_fchdir_np(fd_cwd) == -1) {
55 close(fd_cwd);
56 errno = EBADF; /* sigil for catastrophic failure */
57 return (NULL);
58 }
59
60 /* Close our directory handle */
61 close(fd_cwd);
62
63 /*
64 * And call the regular getcwd(), which will return the per thread
65 * current working directory instead of the process one.
66 */
67 return getcwd(buf, size);
68 }
69
70 T_DECL(pthread_cwd, "per-thread working directory")
71 {
72 char buf[MAXPATHLEN];
73
74 T_SETUPBEGIN;
75
76 T_ASSERT_EQ(pthread_fchdir_np(-1), -1, "test should not start with per-thread cwd");
77
78 /* Blow the umask to avoid shooting our foot */
79 umask(0); /* "always successful" */
80
81 /* Now set us up the test directories... */
82 T_WITH_ERRNO; T_ASSERT_TRUE(mkdir(WORKDIR, 0777) != -1 || errno == EEXIST, NULL);
83 T_WITH_ERRNO; T_ASSERT_TRUE(mkdir(WORKDIR1, 0777) != -1 || errno == EEXIST, NULL);
84 T_WITH_ERRNO; T_ASSERT_TRUE(mkdir(WORKDIR2, 0777) != -1 || errno == EEXIST, NULL);
85
86 T_SETUPEND;
87
88 T_LOG("start in " WORKDIR1);
89 T_ASSERT_POSIX_SUCCESS(chdir(WORKDIR1), NULL);
90 T_ASSERT_EQ_STR(WORKDIR1, getcwd(buf, MAXPATHLEN), NULL);
91 T_ASSERT_NULL(pthread_getcwd_np(buf, MAXPATHLEN), "pthread_getcwd_np should return NULL without per-thread cwd, got: %s", buf);
92
93 T_LOG("move per-thread CWD to " WORKDIR2);
94 T_ASSERT_POSIX_SUCCESS(pthread_chdir_np(WORKDIR2), NULL);
95 T_ASSERT_EQ_STR(WORKDIR2, getcwd(buf, MAXPATHLEN), NULL);
96 T_ASSERT_EQ_STR(WORKDIR2, pthread_getcwd_np(buf, MAXPATHLEN), NULL);
97
98 T_LOG("unset per-thread CWD and confirm things go back");
99 T_ASSERT_POSIX_SUCCESS(pthread_fchdir_np(-1), NULL);
100 T_ASSERT_NULL(pthread_getcwd_np(buf, MAXPATHLEN), "pthread_getcwd_np should return NULL after reseting per-thread cwd, got: %s", buf);
101 T_ASSERT_EQ_STR(WORKDIR1, getcwd(buf, MAXPATHLEN), NULL);
102 }