diff options
author | binji@chromium.org <binji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-29 19:41:38 +0000 |
---|---|---|
committer | binji@chromium.org <binji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-29 19:41:38 +0000 |
commit | 3db8ba82c016850681ea0b8993e23e8367f6d03d (patch) | |
tree | 5942d22094b7415d3dc583efdf15635ce0a6deba /native_client_sdk | |
parent | 326995c7daabb1376a7beb2182316818a667e64d (diff) | |
download | chromium_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')
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)); |