summaryrefslogtreecommitdiffstats
path: root/native_client_sdk
diff options
context:
space:
mode:
Diffstat (limited to 'native_client_sdk')
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_object.cc31
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_object.h13
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc42
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/kernel_object_test.cc9
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/kernel_proxy_test.cc56
5 files changed, 131 insertions, 20 deletions
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_object.cc b/native_client_sdk/src/libraries/nacl_io/kernel_object.cc
index fccc5c85..5ff8902 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_object.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_object.cc
@@ -179,11 +179,30 @@ Error KernelObject::AcquireHandle(int fd, ScopedKernelHandle* out_handle) {
return EBADF;
}
-int KernelObject::AllocateFD(const ScopedKernelHandle& handle) {
+Error KernelObject::AcquireHandleAndPath(int fd, ScopedKernelHandle* out_handle,
+ std::string* out_path){
+ out_handle->reset(NULL);
+
+ AUTO_LOCK(handle_lock_);
+ if (fd < 0 || fd >= static_cast<int>(handle_map_.size()))
+ return EBADF;
+
+ *out_handle = handle_map_[fd].handle;
+ if (!out_handle)
+ return EBADF;
+
+ *out_path = handle_map_[fd].path;
+
+ return 0;
+}
+
+int KernelObject::AllocateFD(const ScopedKernelHandle& handle,
+ const std::string& path) {
AUTO_LOCK(handle_lock_);
int id;
- Descriptor_t descriptor(handle);
+ std::string abs_path = GetAbsParts(path).Join();
+ Descriptor_t descriptor(handle, abs_path);
// If we can recycle and FD, use that first
if (free_fds_.size()) {
@@ -196,10 +215,12 @@ int KernelObject::AllocateFD(const ScopedKernelHandle& handle) {
id = handle_map_.size();
handle_map_.push_back(descriptor);
}
+
return id;
}
-void KernelObject::FreeAndReassignFD(int fd, const ScopedKernelHandle& handle) {
+void KernelObject::FreeAndReassignFD(int fd, const ScopedKernelHandle& handle,
+ const std::string& path) {
if (NULL == handle) {
FreeFD(fd);
} else {
@@ -209,7 +230,8 @@ void KernelObject::FreeAndReassignFD(int fd, const ScopedKernelHandle& handle) {
if (fd >= (int)handle_map_.size())
handle_map_.resize(fd + 1);
- handle_map_[fd] = Descriptor_t(handle);
+ // This path will be from an existing handle, and absolute.
+ handle_map_[fd] = Descriptor_t(handle, path);
}
}
@@ -221,6 +243,7 @@ void KernelObject::FreeFD(int fd) {
// Force lower numbered FD to be available first.
std::push_heap(free_fds_.begin(), free_fds_.end(), std::greater<int>());
+ //
}
} // namespace nacl_io
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_object.h b/native_client_sdk/src/libraries/nacl_io/kernel_object.h
index 70ffb2f..ca6be9d 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_object.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_object.h
@@ -31,10 +31,13 @@ class KernelObject {
public:
struct Descriptor_t {
Descriptor_t() : flags(0) {}
- explicit Descriptor_t(const ScopedKernelHandle& h) : handle(h), flags(0) {}
+ explicit Descriptor_t(const ScopedKernelHandle& h,
+ const std::string& open_path)
+ : handle(h), flags(0), path(open_path) {}
ScopedKernelHandle handle;
int flags;
+ std::string path;
};
typedef std::vector<Descriptor_t> HandleMap_t;
typedef std::map<std::string, ScopedFilesystem> FsMap_t;
@@ -71,14 +74,18 @@ class KernelObject {
// Convert from FD to KernelHandle, and acquire the handle.
// Assumes |out_handle| is non-NULL.
Error AcquireHandle(int fd, ScopedKernelHandle* out_handle);
+ Error AcquireHandleAndPath(int fd, ScopedKernelHandle *out_handle,
+ std::string* out_path);
// Allocate a new fd and assign the handle to it, while
// ref counting the handle and associated filesystem.
// Assumes |handle| is non-NULL;
- int AllocateFD(const ScopedKernelHandle& handle);
+ int AllocateFD(const ScopedKernelHandle& handle,
+ const std::string& path=std::string());
// Assumes |handle| is non-NULL;
- void FreeAndReassignFD(int fd, const ScopedKernelHandle& handle);
+ void FreeAndReassignFD(int fd, const ScopedKernelHandle& handle,
+ const std::string& path);
void FreeFD(int fd);
// Returns or sets CWD
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
index 3ddca20..5451120 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
@@ -172,7 +172,7 @@ int KernelProxy::open_resource(const char* path) {
return -1;
}
- return AllocateFD(handle);
+ return AllocateFD(handle, path);
}
int KernelProxy::open(const char* path, int open_flags) {
@@ -192,7 +192,7 @@ int KernelProxy::open(const char* path, int open_flags) {
return -1;
}
- return AllocateFD(handle);
+ return AllocateFD(handle, path);
}
int KernelProxy::pipe(int pipefds[2]) {
@@ -233,13 +233,13 @@ int KernelProxy::close(int fd) {
int KernelProxy::dup(int oldfd) {
ScopedKernelHandle handle;
- Error error = AcquireHandle(oldfd, &handle);
+ std::string path;
+ Error error = AcquireHandleAndPath(oldfd, &handle, &path);
if (error) {
errno = error;
return -1;
}
-
- return AllocateFD(handle);
+ return AllocateFD(handle, path);
}
int KernelProxy::dup2(int oldfd, int newfd) {
@@ -248,13 +248,14 @@ int KernelProxy::dup2(int oldfd, int newfd) {
return newfd;
ScopedKernelHandle old_handle;
- Error error = AcquireHandle(oldfd, &old_handle);
+ std::string old_path;
+ Error error = AcquireHandleAndPath(oldfd, &old_handle, &old_path);
if (error) {
errno = error;
return -1;
}
- FreeAndReassignFD(newfd, old_handle);
+ FreeAndReassignFD(newfd, old_handle, old_path);
return newfd;
}
@@ -509,8 +510,31 @@ int KernelProxy::getdents(int fd, void* buf, unsigned int count) {
}
int KernelProxy::fchdir(int fd) {
- errno = ENOSYS;
- return -1;
+ ScopedKernelHandle handle;
+ std::string path;
+ Error error = AcquireHandleAndPath(fd, &handle, &path);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+
+ if (!handle->node()->IsaDir()) {
+ errno = ENOTDIR;
+ return -1;
+ }
+
+ if (path.empty()) {
+ errno = EBADF;
+ return -1;
+ }
+
+ error = SetCWD(path);
+ if (error) {
+ // errno is return value from SetCWD
+ errno = error;
+ return -1;
+ }
+ return 0;
}
int KernelProxy::ftruncate(int fd, off_t length) {
diff --git a/native_client_sdk/src/tests/nacl_io_test/kernel_object_test.cc b/native_client_sdk/src/tests/nacl_io_test/kernel_object_test.cc
index cfa1ca4..4350aae 100644
--- a/native_client_sdk/src/tests/nacl_io_test/kernel_object_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/kernel_object_test.cc
@@ -95,13 +95,13 @@ TEST_F(KernelObjectTest, Referencing) {
// Allocating an FD should cause the KernelProxy to ref the handle and
// the node and filesystem should be unchanged.
- int fd1 = proxy.AllocateFD(handle_a);
+ int fd1 = proxy.AllocateFD(handle_a, "/example");
EXPECT_EQ(3, handle_a->RefCount());
EXPECT_EQ(2, fs->RefCount());
EXPECT_EQ(2, node->RefCount());
// If we "dup" the handle, we should bump the ref count on the handle
- int fd2 = proxy.AllocateFD(handle_b);
+ int fd2 = proxy.AllocateFD(handle_b, "");
EXPECT_EQ(4, handle_a->RefCount());
EXPECT_EQ(2, fs->RefCount());
EXPECT_EQ(2, node->RefCount());
@@ -165,16 +165,17 @@ TEST_F(KernelObjectTest, FreeAndReassignFD) {
EXPECT_EQ(2, node->RefCount());
EXPECT_EQ(1, raw_handle->RefCount());
- proxy.AllocateFD(handle);
+ proxy.AllocateFD(handle, "/example");
EXPECT_EQ(2, fs->RefCount());
EXPECT_EQ(2, node->RefCount());
EXPECT_EQ(2, raw_handle->RefCount());
- proxy.FreeAndReassignFD(5, handle);
+ proxy.FreeAndReassignFD(5, handle, "/example");
EXPECT_EQ(2, fs->RefCount());
EXPECT_EQ(2, node->RefCount());
EXPECT_EQ(3, raw_handle->RefCount());
+
handle.reset();
EXPECT_EQ(2, raw_handle->RefCount());
diff --git a/native_client_sdk/src/tests/nacl_io_test/kernel_proxy_test.cc b/native_client_sdk/src/tests/nacl_io_test/kernel_proxy_test.cc
index 08e690e..183ba3b 100644
--- a/native_client_sdk/src/tests/nacl_io_test/kernel_proxy_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/kernel_proxy_test.cc
@@ -282,6 +282,62 @@ TEST_F(KernelProxyTest, WorkingDirectory) {
EXPECT_STREQ("/foo", text);
}
+TEST_F(KernelProxyTest, FDPathMapping) {
+ char text[1024];
+
+ int fd1, fd2, fd3, fd4, fd5;
+
+ EXPECT_EQ(0, ki_mkdir("/foo", S_IREAD | S_IWRITE));
+ EXPECT_EQ(0, ki_mkdir("/foo/bar", S_IREAD | S_IWRITE));
+ EXPECT_EQ(0, ki_mkdir("/example", S_IREAD | S_IWRITE));
+ ki_chdir("/foo");
+
+ fd1 = ki_open("/example", O_RDONLY);
+ EXPECT_NE(-1, fd1);
+ EXPECT_EQ(ki_fchdir(fd1), 0);
+ EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
+ EXPECT_STREQ("/example", text);
+
+ EXPECT_EQ(0, ki_chdir("/foo"));
+ fd2 = ki_open("../example", O_RDONLY);
+ EXPECT_NE(-1, fd2);
+ EXPECT_EQ(0, ki_fchdir(fd2));
+ EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
+ EXPECT_STREQ("/example", text);
+
+ EXPECT_EQ(0, ki_chdir("/foo"));
+ fd3 = ki_open("../test", O_CREAT | O_RDWR);
+ EXPECT_NE(-1, fd3);
+ EXPECT_EQ(-1, ki_fchdir(fd3));
+ EXPECT_EQ(ENOTDIR, errno);
+
+ EXPECT_EQ(0, ki_chdir("/foo"));
+ fd4 = ki_open("bar", O_RDONLY);
+ EXPECT_EQ(0, ki_fchdir(fd4));
+ EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
+ EXPECT_STREQ("/foo/bar", text);
+ EXPECT_EQ(0, ki_chdir("/example"));
+ EXPECT_EQ(0, ki_fchdir(fd4));
+ EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
+ EXPECT_STREQ("/foo/bar", text);
+
+ EXPECT_EQ(0, ki_chdir("/example"));
+ fd5 = ki_dup(fd4);
+ ASSERT_GT(fd5, -1);
+ ASSERT_NE(fd4, fd5);
+ EXPECT_EQ(0, ki_fchdir(fd5));
+ EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
+ EXPECT_STREQ("/foo/bar", text);
+
+ fd5 = 123;
+
+ EXPECT_EQ(0, ki_chdir("/example"));
+ EXPECT_EQ(fd5, ki_dup2(fd4, fd5));
+ EXPECT_EQ(0, ki_fchdir(fd5));
+ EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
+ EXPECT_STREQ("/foo/bar", text);
+}
+
TEST_F(KernelProxyTest, MemMountIO) {
char text[1024];
int fd1, fd2, fd3;