6 #include <sys/syscall.h>
10 #include <pthread/private.h>
12 #include "darwintest_defaults.h"
14 #include "../src/pthread_cwd.c"
16 // /tmp is a symlink, so use full path for strict compare
17 #define WORKDIR "/private/var/tmp/ptwork"
18 #define WORKDIR1 WORKDIR "/one"
19 #define WORKDIR2 WORKDIR "/two"
22 * This is a slow routine, just like getcwd(); people should remember that
23 * they set something, instead of asking us what they told us.
26 pthread_getcwd_np(char *buf
, size_t size
)
34 * Open the "current working directory"; if we are running on a per
35 * thread working directory, that's the one we will get.
37 if ((fd_cwd
= open(".", O_RDONLY
)) == -1)
41 * Switch off the per thread current working directory, in case we
42 * were on one; this fails if we aren't running with one.
44 if (pthread_fchdir_np( -1) == -1) {
45 /* We aren't runniing with one... alll done. */
51 * If we successfully switched off, then we switch back...
52 * this may fail catastrophically, if we no longer have rights;
53 * this should never happen, but threads may clobber our fd out
54 * from under us, etc..
56 if (pthread_fchdir_np(fd_cwd
) == -1) {
58 errno
= EBADF
; /* sigil for catastrophic failure */
62 /* Close our directory handle */
66 * And call the regular getcwd(), which will return the per thread
67 * current working directory instead of the process one.
69 return getcwd(buf
, size
);
72 T_DECL(pthread_cwd
, "per-thread working directory")
78 T_ASSERT_EQ(pthread_fchdir_np(-1), -1, "test should not start with per-thread cwd");
80 /* Blow the umask to avoid shooting our foot */
81 umask(0); /* "always successful" */
83 /* Now set us up the test directories... */
84 T_WITH_ERRNO
; T_ASSERT_TRUE(mkdir(WORKDIR
, 0777) != -1 || errno
== EEXIST
, NULL
);
85 T_WITH_ERRNO
; T_ASSERT_TRUE(mkdir(WORKDIR1
, 0777) != -1 || errno
== EEXIST
, NULL
);
86 T_WITH_ERRNO
; T_ASSERT_TRUE(mkdir(WORKDIR2
, 0777) != -1 || errno
== EEXIST
, NULL
);
90 T_LOG("start in " WORKDIR1
);
91 T_ASSERT_POSIX_SUCCESS(chdir(WORKDIR1
), NULL
);
92 T_ASSERT_EQ_STR(WORKDIR1
, getcwd(buf
, MAXPATHLEN
), NULL
);
93 T_ASSERT_NULL(pthread_getcwd_np(buf
, MAXPATHLEN
), "pthread_getcwd_np should return NULL without per-thread cwd, got: %s", buf
);
95 T_LOG("move per-thread CWD to " WORKDIR2
);
96 T_ASSERT_POSIX_SUCCESS(pthread_chdir_np(WORKDIR2
), NULL
);
97 T_ASSERT_EQ_STR(WORKDIR2
, getcwd(buf
, MAXPATHLEN
), NULL
);
98 T_ASSERT_EQ_STR(WORKDIR2
, pthread_getcwd_np(buf
, MAXPATHLEN
), NULL
);
100 T_LOG("unset per-thread CWD and confirm things go back");
101 T_ASSERT_POSIX_SUCCESS(pthread_fchdir_np(-1), NULL
);
102 T_ASSERT_NULL(pthread_getcwd_np(buf
, MAXPATHLEN
), "pthread_getcwd_np should return NULL after reseting per-thread cwd, got: %s", buf
);
103 T_ASSERT_EQ_STR(WORKDIR1
, getcwd(buf
, MAXPATHLEN
), NULL
);