]> git.saurik.com Git - apple/libpthread.git/blame - tests/pthread_cwd.c
libpthread-218.60.3.tar.gz
[apple/libpthread.git] / tests / pthread_cwd.c
CommitLineData
2546420a
A
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.h>
13
14#include "../src/pthread_cwd.c"
15
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"
20
21/*
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.
24 */
25static char *
26pthread_getcwd_np(char *buf, size_t size)
27{
28 int fd_cwd;
29
30 if (buf == NULL)
31 return (NULL);
32
33 /*
34 * Open the "current working directory"; if we are running on a per
35 * thread working directory, that's the one we will get.
36 */
37 if ((fd_cwd = open(".", O_RDONLY)) == -1)
38 return (NULL);
39
40 /*
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.
43 */
44 if (pthread_fchdir_np( -1) == -1) {
45 /* We aren't runniing with one... alll done. */
46 close (fd_cwd);
47 return (NULL);
48 }
49
50 /*
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..
55 */
56 if (pthread_fchdir_np(fd_cwd) == -1) {
57 close(fd_cwd);
58 errno = EBADF; /* sigil for catastrophic failure */
59 return (NULL);
60 }
61
62 /* Close our directory handle */
63 close(fd_cwd);
64
65 /*
66 * And call the regular getcwd(), which will return the per thread
67 * current working directory instead of the process one.
68 */
69 return getcwd(buf, size);
70}
71
72T_DECL(pthread_cwd, "per-thread working directory")
73{
74 char buf[MAXPATHLEN];
75
76 T_SETUPBEGIN;
77
78 T_ASSERT_EQ(pthread_fchdir_np(-1), -1, "test should not start with per-thread cwd");
79
80 /* Blow the umask to avoid shooting our foot */
81 umask(0); /* "always successful" */
82
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);
87
88 T_SETUPEND;
89
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);
94
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);
99
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);
104}