#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <pthread/private.h>
#include "darwintest_defaults.h"
#define WORKDIR "/private/var/tmp/ptwork"
#define WORKDIR1 WORKDIR "/one"
#define WORKDIR2 WORKDIR "/two"
static char *
pthread_getcwd_np(char *buf, size_t size)
{
int fd_cwd;
if (buf == NULL)
return (NULL);
if ((fd_cwd = open(".", O_RDONLY)) == -1)
return (NULL);
if (pthread_fchdir_np( -1) == -1) {
close (fd_cwd);
return (NULL);
}
if (pthread_fchdir_np(fd_cwd) == -1) {
close(fd_cwd);
errno = EBADF;
return (NULL);
}
close(fd_cwd);
return getcwd(buf, size);
}
T_DECL(pthread_cwd, "per-thread working directory")
{
char buf[MAXPATHLEN];
T_SETUPBEGIN;
T_ASSERT_EQ(pthread_fchdir_np(-1), -1, "test should not start with per-thread cwd");
umask(0);
T_WITH_ERRNO; T_ASSERT_TRUE(mkdir(WORKDIR, 0777) != -1 || errno == EEXIST, NULL);
T_WITH_ERRNO; T_ASSERT_TRUE(mkdir(WORKDIR1, 0777) != -1 || errno == EEXIST, NULL);
T_WITH_ERRNO; T_ASSERT_TRUE(mkdir(WORKDIR2, 0777) != -1 || errno == EEXIST, NULL);
T_SETUPEND;
T_LOG("start in " WORKDIR1);
T_ASSERT_POSIX_SUCCESS(chdir(WORKDIR1), NULL);
T_ASSERT_EQ_STR(WORKDIR1, getcwd(buf, MAXPATHLEN), NULL);
T_ASSERT_NULL(pthread_getcwd_np(buf, MAXPATHLEN), "pthread_getcwd_np should return NULL without per-thread cwd, got: %s", buf);
T_LOG("move per-thread CWD to " WORKDIR2);
T_ASSERT_POSIX_SUCCESS(pthread_chdir_np(WORKDIR2), NULL);
T_ASSERT_EQ_STR(WORKDIR2, getcwd(buf, MAXPATHLEN), NULL);
T_ASSERT_EQ_STR(WORKDIR2, pthread_getcwd_np(buf, MAXPATHLEN), NULL);
T_LOG("unset per-thread CWD and confirm things go back");
T_ASSERT_POSIX_SUCCESS(pthread_fchdir_np(-1), NULL);
T_ASSERT_NULL(pthread_getcwd_np(buf, MAXPATHLEN), "pthread_getcwd_np should return NULL after reseting per-thread cwd, got: %s", buf);
T_ASSERT_EQ_STR(WORKDIR1, getcwd(buf, MAXPATHLEN), NULL);
}