Index: native_client_sdk/src/libraries/nacl_io/devfs/dev_fs.cc |
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 3b5f44ce56b9a55f278f4776c9f08833cb4a9b72..a88021dad2ca29efe1f9ed613e91e4d917d552a3 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; |
} |