summaryrefslogtreecommitdiffstats
path: root/native_client_sdk
diff options
context:
space:
mode:
authorbinji@chromium.org <binji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-29 19:41:38 +0000
committerbinji@chromium.org <binji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-29 19:41:38 +0000
commit3db8ba82c016850681ea0b8993e23e8367f6d03d (patch)
tree5942d22094b7415d3dc583efdf15635ce0a6deba /native_client_sdk
parent326995c7daabb1376a7beb2182316818a667e64d (diff)
downloadchromium_src-3db8ba82c016850681ea0b8993e23e8367f6d03d.zip
chromium_src-3db8ba82c016850681ea0b8993e23e8367f6d03d.tar.gz
chromium_src-3db8ba82c016850681ea0b8993e23e8367f6d03d.tar.bz2
[NaCl SDK] Create Filesystem nodes in /dev/fs/...
These can be used to pass data to a filesystem. I'll use this in the next CL to provide a way to pass data to a JavaScript filesystem. BUG=none R=sbc@chromium.org Review URL: https://codereview.chromium.org/304013002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@273552 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'native_client_sdk')
-rw-r--r--native_client_sdk/src/libraries/nacl_io/devfs/dev_fs.cc55
-rw-r--r--native_client_sdk/src/libraries/nacl_io/devfs/dev_fs.h4
-rw-r--r--native_client_sdk/src/libraries/nacl_io/filesystem.cc4
-rw-r--r--native_client_sdk/src/libraries/nacl_io/filesystem.h2
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_object.cc5
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_object.h2
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc164
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_proxy.h15
-rw-r--r--native_client_sdk/src/libraries/sdk_util/scoped_ref.h5
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/kernel_proxy_test.cc46
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/kernel_wrap_test.cc4
11 files changed, 235 insertions, 71 deletions
diff --git a/native_client_sdk/src/libraries/nacl_io/devfs/dev_fs.cc b/native_client_sdk/src/libraries/nacl_io/devfs/dev_fs.cc
index 3b5f44c..a88021d 100644
--- a/native_client_sdk/src/libraries/nacl_io/devfs/dev_fs.cc
+++ b/native_client_sdk/src/libraries/nacl_io/devfs/dev_fs.cc
@@ -11,6 +11,7 @@
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
+#include <stdio.h>
#include <string.h>
#include "nacl_io/devfs/jspipe_node.h"
@@ -111,6 +112,19 @@ class UrandomNode : public Node {
#endif
};
+class FsNode : public Node {
+ public:
+ FsNode(Filesystem* filesystem, Filesystem* other_fs);
+
+ virtual Error VIoctl(int request, va_list args);
+
+ private:
+ // Don't addref the filesystem. We are relying on the fact that the
+ // KernelObject will keep the filsystem around as long as we need it, and
+ // this node will be destroyed when the filesystem is destroyed.
+ Filesystem* other_fs_;
+};
+
RealNode::RealNode(Filesystem* filesystem, int fd) : Node(filesystem), fd_(fd) {
SetType(S_IFCHR);
}
@@ -261,6 +275,14 @@ Error UrandomNode::Write(const HandleAttr& attr,
return 0;
}
+FsNode::FsNode(Filesystem* filesystem, Filesystem* other_fs)
+ : Node(filesystem), other_fs_(other_fs) {
+}
+
+Error FsNode::VIoctl(int request, va_list args) {
+ return other_fs_->Filesystem_VIoctl(request, args);
+}
+
} // namespace
Error DevFs::Access(const Path& path, int a_mode) {
@@ -278,7 +300,16 @@ Error DevFs::Access(const Path& path, int a_mode) {
Error DevFs::Open(const Path& path, int open_flags, ScopedNode* out_node) {
out_node->reset(NULL);
- int error = root_->FindChild(path.Join(), out_node);
+ int error;
+ if (path.Part(1) == "fs") {
+ if (path.Size() == 3)
+ error = fs_dir_->FindChild(path.Part(2), out_node);
+ else
+ error = ENOENT;
+ } else {
+ error = root_->FindChild(path.Join(), out_node);
+ }
+
// Only return EACCES when trying to create a node that does not exist.
if ((error == ENOENT) && (open_flags & O_CREAT))
return EACCES;
@@ -296,6 +327,22 @@ Error DevFs::Remove(const Path& path) { return EPERM; }
Error DevFs::Rename(const Path& path, const Path& newpath) { return EPERM; }
+Error DevFs::CreateFsNode(Filesystem* other_fs) {
+ int dev = other_fs->dev();
+ char path[32];
+ snprintf(path, 32, "%d", dev);
+ ScopedNode new_node(new FsNode(this, other_fs));
+ return fs_dir_->AddChild(path, new_node);
+}
+
+Error DevFs::DestroyFsNode(Filesystem* other_fs) {
+ int dev = other_fs->dev();
+ char path[32];
+ snprintf(path, 32, "%d", dev);
+ return fs_dir_->RemoveChild(path);
+}
+
+
DevFs::DevFs() {}
#define INITIALIZE_DEV_NODE(path, klass) \
@@ -336,6 +383,12 @@ Error DevFs::Init(const FsInitArgs& args) {
INITIALIZE_DEV_NODE("/jspipe3", JSPipeNode);
new_node->Ioctl(NACL_IOC_PIPE_SETNAME, "jspipe3");
+ // Add a directory for "fs" nodes; they represent all currently-mounted
+ // filesystems. We can ioctl these nodes to make changes or provide input to
+ // a mounted filesystem.
+ INITIALIZE_DEV_NODE("/fs", DirNode);
+ fs_dir_ = new_node;
+
return 0;
}
diff --git a/native_client_sdk/src/libraries/nacl_io/devfs/dev_fs.h b/native_client_sdk/src/libraries/nacl_io/devfs/dev_fs.h
index ad96ae2..a17dc85 100644
--- a/native_client_sdk/src/libraries/nacl_io/devfs/dev_fs.h
+++ b/native_client_sdk/src/libraries/nacl_io/devfs/dev_fs.h
@@ -22,6 +22,9 @@ class DevFs : public Filesystem {
virtual Error Remove(const Path& path);
virtual Error Rename(const Path& path, const Path& newpath);
+ Error CreateFsNode(Filesystem* fs);
+ Error DestroyFsNode(Filesystem* fs);
+
protected:
DevFs();
@@ -29,6 +32,7 @@ class DevFs : public Filesystem {
private:
ScopedNode root_;
+ ScopedNode fs_dir_;
friend class TypedFsFactory<DevFs>;
DISALLOW_COPY_AND_ASSIGN(DevFs);
diff --git a/native_client_sdk/src/libraries/nacl_io/filesystem.cc b/native_client_sdk/src/libraries/nacl_io/filesystem.cc
index 0c5b8ca..7a2b1a0 100644
--- a/native_client_sdk/src/libraries/nacl_io/filesystem.cc
+++ b/native_client_sdk/src/libraries/nacl_io/filesystem.cc
@@ -48,4 +48,8 @@ void Filesystem::OnNodeDestroyed(Node* node) {
inode_pool_.Release(node->stat_.st_ino);
}
+Error Filesystem::Filesystem_VIoctl(int request, va_list args) {
+ return EINVAL;
+}
+
} // namespace nacl_io
diff --git a/native_client_sdk/src/libraries/nacl_io/filesystem.h b/native_client_sdk/src/libraries/nacl_io/filesystem.h
index ddec5d6..47546b9 100644
--- a/native_client_sdk/src/libraries/nacl_io/filesystem.h
+++ b/native_client_sdk/src/libraries/nacl_io/filesystem.h
@@ -58,6 +58,7 @@ class Filesystem : public sdk_util::RefObject {
public:
PepperInterface* ppapi() { return ppapi_; }
+ int dev() { return dev_; }
// All paths in functions below are expected to containing a leading "/".
@@ -84,6 +85,7 @@ class Filesystem : public sdk_util::RefObject {
virtual Error Rmdir(const Path& path) = 0;
virtual Error Remove(const Path& path) = 0;
virtual Error Rename(const Path& path, const Path& newpath) = 0;
+ virtual Error Filesystem_VIoctl(int request, va_list args);
// Assumes that |node| is non-NULL.
void OnNodeCreated(Node* node);
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 98362eb..8b64ca1 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_object.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_object.cc
@@ -40,7 +40,8 @@ Error KernelObject::AttachFsAtPath(const ScopedFilesystem& fs,
return 0;
}
-Error KernelObject::DetachFsAtPath(const std::string& path) {
+Error KernelObject::DetachFsAtPath(const std::string& path,
+ ScopedFilesystem* out_fs) {
std::string abs_path = GetAbsParts(path).Join();
AUTO_LOCK(fs_lock_);
@@ -52,6 +53,8 @@ Error KernelObject::DetachFsAtPath(const std::string& path) {
if (it->second->RefCount() != 1)
return EBUSY;
+ *out_fs = it->second;
+
filesystems_.erase(it);
return 0;
}
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 ca6be9d..cab977b 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_object.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_object.h
@@ -49,7 +49,7 @@ class KernelObject {
Error AttachFsAtPath(const ScopedFilesystem& fs, const std::string& path);
// Unmap the Filesystem object from the specified path and release it.
- Error DetachFsAtPath(const std::string& path);
+ Error DetachFsAtPath(const std::string& path, ScopedFilesystem* out_fs);
// Find the filesystem for the given path, and acquires it and return a
// path relative to the filesystem.
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 65265ba..0110bfa 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
@@ -26,6 +26,7 @@
#include "nacl_io/httpfs/http_fs.h"
#include "nacl_io/kernel_handle.h"
#include "nacl_io/kernel_wrap_real.h"
+#include "nacl_io/log.h"
#include "nacl_io/memfs/mem_fs.h"
#include "nacl_io/node.h"
#include "nacl_io/osmman.h"
@@ -49,16 +50,17 @@
namespace nacl_io {
-
-KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL),
- exit_handler_(NULL),
- signal_emitter_(new EventEmitter) {
- memset(&sigwinch_handler_, 0, sizeof(sigwinch_handler_));
- sigwinch_handler_.sa_handler = SIG_DFL;
+KernelProxy::KernelProxy()
+ : dev_(0),
+ ppapi_(NULL),
+ exit_handler_(NULL),
+ signal_emitter_(new EventEmitter) {
+ memset(&sigwinch_handler_, 0, sizeof(sigwinch_handler_));
+ sigwinch_handler_.sa_handler = SIG_DFL;
}
KernelProxy::~KernelProxy() {
- // Clean up the MountFactories.
+ // Clean up the FsFactories.
for (FsFactoryMap_t::iterator i = factories_.begin(); i != factories_.end();
++i) {
delete i->second;
@@ -76,18 +78,26 @@ Error KernelProxy::Init(PepperInterface* ppapi) {
factories_["httpfs"] = new TypedFsFactory<HttpFs>;
factories_["passthroughfs"] = new TypedFsFactory<PassthroughFs>;
- int result;
- result = mount("", "/", "passthroughfs", 0, NULL);
- if (result != 0) {
+ ScopedFilesystem root_fs;
+ rtn = MountInternal("", "/", "passthroughfs", 0, NULL, false, &root_fs);
+ if (rtn != 0)
assert(false);
- rtn = errno;
- }
- result = mount("", "/dev", "dev", 0, NULL);
- if (result != 0) {
+ ScopedFilesystem fs;
+ rtn = MountInternal("", "/dev", "dev", 0, NULL, false, &fs);
+ if (rtn != 0)
+ assert(false);
+ dev_fs_ = sdk_util::static_scoped_ref_cast<DevFs>(fs);
+
+ // Create the filesystem nodes for / and /dev afterward. They can't be
+ // created the normal way because the dev filesystem didn't exist yet.
+ rtn = CreateFsNode(root_fs);
+ if (rtn != 0)
+ assert(false);
+
+ rtn = CreateFsNode(dev_fs_);
+ if (rtn != 0)
assert(false);
- rtn = errno;
- }
// Open the first three in order to get STDIN, STDOUT, STDERR
int fd;
@@ -113,8 +123,8 @@ Error KernelProxy::Init(PepperInterface* ppapi) {
FsInitArgs args;
args.dev = dev_++;
args.ppapi = ppapi_;
- stream_mount_.reset(new StreamFs());
- result = stream_mount_->Init(args);
+ stream_fs_.reset(new StreamFs());
+ int result = stream_fs_->Init(args);
if (result != 0) {
assert(false);
rtn = result;
@@ -204,12 +214,12 @@ int KernelProxy::open(const char* path, int open_flags) {
}
int KernelProxy::pipe(int pipefds[2]) {
- PipeNode* pipe = new PipeNode(stream_mount_.get());
+ PipeNode* pipe = new PipeNode(stream_fs_.get());
ScopedNode node(pipe);
if (pipe->Init(O_RDWR) == 0) {
- ScopedKernelHandle handle0(new KernelHandle(stream_mount_, node));
- ScopedKernelHandle handle1(new KernelHandle(stream_mount_, node));
+ ScopedKernelHandle handle0(new KernelHandle(stream_fs_, node));
+ ScopedKernelHandle handle1(new KernelHandle(stream_fs_, node));
// Should never fail, but...
if (handle0->Init(O_RDONLY) || handle1->Init(O_WRONLY)) {
@@ -381,20 +391,35 @@ int KernelProxy::stat(const char* path, struct stat* buf) {
return result;
}
-
int KernelProxy::mount(const char* source,
const char* target,
const char* filesystemtype,
unsigned long mountflags,
const void* data) {
+ ScopedFilesystem fs;
+ Error error = MountInternal(
+ source, target, filesystemtype, mountflags, data, true, &fs);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+
+ return 0;
+}
+
+Error KernelProxy::MountInternal(const char* source,
+ const char* target,
+ const char* filesystemtype,
+ unsigned long mountflags,
+ const void* data,
+ bool create_fs_node,
+ ScopedFilesystem* out_filesystem) {
std::string abs_path = GetAbsParts(target).Join();
// Find a factory of that type
FsFactoryMap_t::iterator factory = factories_.find(filesystemtype);
- if (factory == factories_.end()) {
- errno = ENODEV;
- return -1;
- }
+ if (factory == factories_.end())
+ return ENODEV;
// Create a map of settings
StringMap_t smap;
@@ -406,7 +431,8 @@ int KernelProxy::mount(const char* source,
sdk_util::SplitString(static_cast<const char*>(data), ',', &elements);
for (std::vector<std::string>::const_iterator it = elements.begin();
- it != elements.end(); ++it) {
+ it != elements.end();
+ ++it) {
size_t location = it->find('=');
if (location != std::string::npos) {
std::string key = it->substr(0, location);
@@ -425,26 +451,42 @@ int KernelProxy::mount(const char* source,
ScopedFilesystem fs;
Error error = factory->second->CreateFilesystem(args, &fs);
- if (error) {
- errno = error;
- return -1;
- }
+ if (error)
+ return error;
error = AttachFsAtPath(fs, abs_path);
- if (error) {
- errno = error;
- return -1;
+ if (error)
+ return error;
+
+ if (create_fs_node) {
+ error = CreateFsNode(fs);
+ if (error)
+ return error;
}
+ *out_filesystem = fs;
return 0;
}
+Error KernelProxy::CreateFsNode(const ScopedFilesystem& fs) {
+ assert(dev_fs_);
+
+ return dev_fs_->CreateFsNode(fs.get());
+}
+
int KernelProxy::umount(const char* path) {
- Error error = DetachFsAtPath(path);
+ ScopedFilesystem fs;
+ Error error = DetachFsAtPath(path, &fs);
if (error) {
errno = error;
return -1;
}
+
+ error = dev_fs_->DestroyFsNode(fs.get());
+ if (error) {
+ // Ignore any errors here, just log.
+ LOG_ERROR("Unable to destroy FsNode: %s", strerror(error));
+ }
return 0;
}
@@ -739,8 +781,8 @@ int KernelProxy::fchmod(int fd, int mode) {
int KernelProxy::fcntl(int fd, int request, va_list args) {
Error error = 0;
- // F_GETFD and F_SETFD are descirptor specific flags that
- // are stored in the KernelObject's decriptor map unlink
+ // F_GETFD and F_SETFD are descriptor specific flags that
+ // are stored in the KernelObject's decriptor map unlike
// F_GETFL and F_SETFL which are handle specific.
switch (request) {
case F_GETFD: {
@@ -798,12 +840,12 @@ int KernelProxy::access(const char* path, int amode) {
return 0;
}
-int KernelProxy::readlink(const char *path, char *buf, size_t count) {
+int KernelProxy::readlink(const char* path, char* buf, size_t count) {
errno = EINVAL;
return -1;
}
-int KernelProxy::utimes(const char *filename, const struct timeval times[2]) {
+int KernelProxy::utimes(const char* filename, const struct timeval times[2]) {
errno = EINVAL;
return -1;
}
@@ -915,8 +957,9 @@ int KernelProxy::tcgetattr(int fd, struct termios* termios_p) {
return 0;
}
-int KernelProxy::tcsetattr(int fd, int optional_actions,
- const struct termios *termios_p) {
+int KernelProxy::tcsetattr(int fd,
+ int optional_actions,
+ const struct termios* termios_p) {
ScopedKernelHandle handle;
Error error = AcquireHandle(fd, &handle);
if (error) {
@@ -965,7 +1008,8 @@ int KernelProxy::kill(pid_t pid, int sig) {
return 0;
}
-int KernelProxy::sigaction(int signum, const struct sigaction* action,
+int KernelProxy::sigaction(int signum,
+ const struct sigaction* action,
struct sigaction* oaction) {
if (action && action->sa_flags & SA_SIGINFO) {
// We don't support SA_SIGINFO (sa_sigaction field) yet
@@ -1025,8 +1069,11 @@ int KernelProxy::sigaction(int signum, const struct sigaction* action,
#ifdef PROVIDES_SOCKET_API
-int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds,
- fd_set* exceptfds, struct timeval* timeout) {
+int KernelProxy::select(int nfds,
+ fd_set* readfds,
+ fd_set* writefds,
+ fd_set* exceptfds,
+ struct timeval* timeout) {
std::vector<pollfd> pollfds;
for (int fd = 0; fd < nfds; fd++) {
@@ -1061,8 +1108,8 @@ int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds,
// If the timeout is invalid or too long (larger than signed 32 bit).
if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) ||
- (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) ||
- (ms < 0) || (ms >= INT_MAX)) {
+ (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) || (ms < 0) ||
+ (ms >= INT_MAX)) {
errno = EINVAL;
return -1;
}
@@ -1103,7 +1150,7 @@ struct PollInfo {
typedef std::map<EventEmitter*, PollInfo> EventPollMap_t;
-int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) {
+int KernelProxy::poll(struct pollfd* fds, nfds_t nfds, int timeout) {
EventPollMap_t event_map;
std::vector<EventRequest> requests;
@@ -1184,7 +1231,6 @@ int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) {
return event_cnt;
}
-
// Socket Functions
int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
if (NULL == addr || NULL == len) {
@@ -1206,7 +1252,7 @@ int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
return -1;
}
- SocketNode* sock = new TcpNode(stream_mount_.get(), new_sock);
+ SocketNode* sock = new TcpNode(stream_fs_.get(), new_sock);
// The SocketNode now holds a reference to the new socket
// so we release ours.
@@ -1218,7 +1264,7 @@ int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
}
ScopedNode node(sock);
- ScopedKernelHandle new_handle(new KernelHandle(stream_mount_, node));
+ ScopedKernelHandle new_handle(new KernelHandle(stream_fs_, node));
error = new_handle->Init(O_RDWR);
if (error != 0) {
errno = error;
@@ -1269,11 +1315,12 @@ int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) {
return 0;
}
-void KernelProxy::freeaddrinfo(struct addrinfo *res) {
+void KernelProxy::freeaddrinfo(struct addrinfo* res) {
return host_resolver_.freeaddrinfo(res);
}
-int KernelProxy::getaddrinfo(const char* node, const char* service,
+int KernelProxy::getaddrinfo(const char* node,
+ const char* service,
const struct addrinfo* hints,
struct addrinfo** res) {
return host_resolver_.getaddrinfo(node, service, hints, res);
@@ -1358,10 +1405,7 @@ int KernelProxy::listen(int fd, int backlog) {
return 0;
}
-ssize_t KernelProxy::recv(int fd,
- void* buf,
- size_t len,
- int flags) {
+ssize_t KernelProxy::recv(int fd, void* buf, size_t len, int flags) {
if (NULL == buf) {
errno = EFAULT;
return -1;
@@ -1418,7 +1462,7 @@ ssize_t KernelProxy::recvfrom(int fd,
}
ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) {
- if (NULL == msg ) {
+ if (NULL == msg) {
errno = EFAULT;
return -1;
}
@@ -1564,11 +1608,11 @@ int KernelProxy::socket(int domain, int type, int protocol) {
SocketNode* sock = NULL;
switch (type) {
case SOCK_DGRAM:
- sock = new UdpNode(stream_mount_.get());
+ sock = new UdpNode(stream_fs_.get());
break;
case SOCK_STREAM:
- sock = new TcpNode(stream_mount_.get());
+ sock = new TcpNode(stream_fs_.get());
break;
case SOCK_SEQPACKET:
@@ -1589,7 +1633,7 @@ int KernelProxy::socket(int domain, int type, int protocol) {
return -1;
}
- ScopedKernelHandle handle(new KernelHandle(stream_mount_, node));
+ ScopedKernelHandle handle(new KernelHandle(stream_fs_, node));
rtn = handle->Init(open_flags);
if (rtn != 0) {
errno = rtn;
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
index 89b8f19..22c9a61 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
@@ -8,6 +8,7 @@
#include <map>
#include <string>
+#include "nacl_io/devfs/dev_fs.h"
#include "nacl_io/event_emitter.h"
#include "nacl_io/fs_factory.h"
#include "nacl_io/host_resolver.h"
@@ -206,8 +207,20 @@ class KernelProxy : protected KernelObject {
#endif // PROVIDES_SOCKET_API
protected:
+ Error MountInternal(const char* source,
+ const char* target,
+ const char* filesystemtype,
+ unsigned long mountflags,
+ const void* data,
+ bool create_fs_node,
+ ScopedFilesystem* out_filesystem);
+
+ Error CreateFsNode(const ScopedFilesystem& fs);
+
+ protected:
FsFactoryMap_t factories_;
- sdk_util::ScopedRef<StreamFs> stream_mount_;
+ sdk_util::ScopedRef<StreamFs> stream_fs_;
+ sdk_util::ScopedRef<DevFs> dev_fs_;
int dev_;
PepperInterface* ppapi_;
static KernelProxy *s_instance_;
diff --git a/native_client_sdk/src/libraries/sdk_util/scoped_ref.h b/native_client_sdk/src/libraries/sdk_util/scoped_ref.h
index 48c4eb9..b3b8f5b 100644
--- a/native_client_sdk/src/libraries/sdk_util/scoped_ref.h
+++ b/native_client_sdk/src/libraries/sdk_util/scoped_ref.h
@@ -81,6 +81,11 @@ class ScopedRef : public ScopedRefBase {
}
};
+template <typename U, typename T>
+ScopedRef<U> static_scoped_ref_cast(const ScopedRef<T>& ptr) {
+ return ScopedRef<U>(static_cast<U*>(ptr.get()));
+}
+
} // namespace sdk_util
#endif // LIBRARIES_SDK_UTIL_SCOPED_REF_H_
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 ffa4eee..98fd431 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
@@ -542,18 +542,27 @@ TEST_F(KernelProxyTest, UseAfterClose) {
namespace {
StringMap_t g_string_map;
+bool g_fs_ioctl_called;
+int g_fs_dev;
class KernelProxyMountTest_Filesystem : public MemFs {
public:
- using MemFs::Init;
-
virtual Error Init(const FsInitArgs& args) {
+ MemFs::Init(args);
+
g_string_map = args.string_map;
+ g_fs_dev = args.dev;
+
if (g_string_map.find("false") != g_string_map.end())
return EINVAL;
return 0;
}
+ virtual Error Filesystem_VIoctl(int request, va_list arglist) {
+ g_fs_ioctl_called = true;
+ return 0;
+ }
+
friend class TypedFsFactory<KernelProxyMountTest_Filesystem>;
};
@@ -570,16 +579,33 @@ class KernelProxyMountTest : public ::testing::Test {
KernelProxyMountTest() {}
void SetUp() {
+ g_string_map.clear();
+ g_fs_dev = -1;
+ g_fs_ioctl_called = false;
+
ASSERT_EQ(0, ki_push_state_for_testing());
ASSERT_EQ(0, ki_init(&kp_));
}
- void TearDown() { ki_uninit(); }
+ void TearDown() {
+ g_string_map.clear();
+ ki_uninit();
+ }
private:
KernelProxyMountTest_KernelProxy kp_;
};
+// Helper function for calling ki_ioctl without having
+// to construct a va_list.
+int ki_ioctl_wrapper(int fd, int request, ...) {
+ va_list ap;
+ va_start(ap, request);
+ int rtn = ki_ioctl(fd, request, ap);
+ va_end(ap);
+ return rtn;
+}
+
} // namespace
TEST_F(KernelProxyMountTest, MountInit) {
@@ -594,6 +620,20 @@ TEST_F(KernelProxyMountTest, MountInit) {
EXPECT_EQ("y", g_string_map["x"]);
}
+TEST_F(KernelProxyMountTest, MountAndIoctl) {
+ ASSERT_EQ(0, ki_mount("/", "/mnt1", "initfs", 0, ""));
+ ASSERT_NE(-1, g_fs_dev);
+
+ char path[100];
+ snprintf(path, 100, "dev/fs/%d", g_fs_dev);
+
+ int fd = ki_open(path, O_RDONLY);
+ ASSERT_GT(fd, -1);
+
+ EXPECT_EQ(0, ki_ioctl_wrapper(fd, 0xdeadbeef));
+ EXPECT_EQ(true, g_fs_ioctl_called);
+}
+
namespace {
int g_MMapCount = 0;
diff --git a/native_client_sdk/src/tests/nacl_io_test/kernel_wrap_test.cc b/native_client_sdk/src/tests/nacl_io_test/kernel_wrap_test.cc
index 1c67fe1..5dc4f13 100644
--- a/native_client_sdk/src/tests/nacl_io_test/kernel_wrap_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/kernel_wrap_test.cc
@@ -126,10 +126,6 @@ class KernelWrapTest : public ::testing::Test {
.WillOnce(Return(0))
.WillOnce(Return(1))
.WillOnce(Return(2));
- // And will call mount / and /dev.
- EXPECT_CALL(mock, mount(_, _, _, _, _))
- .WillOnce(Return(0))
- .WillOnce(Return(0));
ASSERT_EQ(0, ki_push_state_for_testing());
ASSERT_EQ(0, ki_init(&mock));