1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
9 #include "nacl_io/devfs/dev_fs.h"
16 #include "nacl_io/devfs/tty_node.h"
17 #include "nacl_io/dir_node.h"
18 #include "nacl_io/kernel_wrap_real.h"
19 #include "nacl_io/node.h"
20 #include "nacl_io/osunistd.h"
21 #include "nacl_io/pepper_interface.h"
22 #include "sdk_util/auto_lock.h"
24 #if defined(__native_client__)
34 class RealNode : public Node {
36 RealNode(Filesystem* filesystem, int fd);
38 virtual Error Read(const HandleAttr& attr,
42 virtual Error Write(const HandleAttr& attr,
46 virtual Error GetStat(struct stat* stat);
52 class NullNode : public CharNode {
54 explicit NullNode(Filesystem* filesystem) : CharNode(filesystem) {}
56 virtual Error Read(const HandleAttr& attr,
60 virtual Error Write(const HandleAttr& attr,
66 class ConsoleNode : public CharNode {
68 ConsoleNode(Filesystem* filesystem, PP_LogLevel level);
70 virtual Error Write(const HandleAttr& attr,
79 class ZeroNode : public Node {
81 explicit ZeroNode(Filesystem* filesystem);
83 virtual Error Read(const HandleAttr& attr,
87 virtual Error Write(const HandleAttr& attr,
93 class UrandomNode : public Node {
95 explicit UrandomNode(Filesystem* filesystem);
97 virtual Error Read(const HandleAttr& attr,
101 virtual Error Write(const HandleAttr& attr,
107 #if defined(__native_client__)
108 nacl_irt_random random_interface_;
113 RealNode::RealNode(Filesystem* filesystem, int fd) : Node(filesystem), fd_(fd) {
117 Error RealNode::Read(const HandleAttr& attr,
124 int err = _real_read(fd_, buf, count, &readcnt);
128 *out_bytes = static_cast<int>(readcnt);
132 Error RealNode::Write(const HandleAttr& attr,
139 int err = _real_write(fd_, buf, count, &writecnt);
143 *out_bytes = static_cast<int>(writecnt);
147 Error RealNode::GetStat(struct stat* stat) { return _real_fstat(fd_, stat); }
149 Error NullNode::Read(const HandleAttr& attr,
157 Error NullNode::Write(const HandleAttr& attr,
165 ConsoleNode::ConsoleNode(Filesystem* filesystem, PP_LogLevel level)
166 : CharNode(filesystem), level_(level) {}
168 Error ConsoleNode::Write(const HandleAttr& attr,
174 ConsoleInterface* con_intr = filesystem_->ppapi()->GetConsoleInterface();
175 VarInterface* var_intr = filesystem_->ppapi()->GetVarInterface();
177 if (!(var_intr && con_intr))
180 const char* var_data = static_cast<const char*>(buf);
181 uint32_t len = static_cast<uint32_t>(count);
182 struct PP_Var val = var_intr->VarFromUtf8(var_data, len);
183 con_intr->Log(filesystem_->ppapi()->GetInstance(), level_, val);
189 ZeroNode::ZeroNode(Filesystem* filesystem) : Node(filesystem) {
193 Error ZeroNode::Read(const HandleAttr& attr,
197 memset(buf, 0, count);
202 Error ZeroNode::Write(const HandleAttr& attr,
210 UrandomNode::UrandomNode(Filesystem* filesystem) : Node(filesystem) {
212 #if defined(__native_client__)
213 size_t result = nacl_interface_query(
214 NACL_IRT_RANDOM_v0_1, &random_interface_, sizeof(random_interface_));
215 interface_ok_ = result != 0;
219 Error UrandomNode::Read(const HandleAttr& attr,
225 #if defined(__native_client__)
230 int error = (*random_interface_.get_random_bytes)(buf, count, &nread);
234 char* out = static_cast<char*>(buf);
235 size_t bytes_left = count;
237 unsigned int random_int;
238 errno_t err = rand_s(&random_int);
240 *out_bytes = count - bytes_left;
244 int bytes_to_copy = std::min(bytes_left, sizeof(random_int));
245 memcpy(out, &random_int, bytes_to_copy);
246 out += bytes_to_copy;
247 bytes_left -= bytes_to_copy;
255 Error UrandomNode::Write(const HandleAttr& attr,
265 Error DevFs::Access(const Path& path, int a_mode) {
267 int error = root_->FindChild(path.Join(), &node);
271 // Don't allow execute access.
278 Error DevFs::Open(const Path& path, int open_flags, ScopedNode* out_node) {
279 out_node->reset(NULL);
280 int error = root_->FindChild(path.Join(), out_node);
281 // Only return EACCES when trying to create a node that does not exist.
282 if ((error == ENOENT) && (open_flags & O_CREAT))
288 Error DevFs::Unlink(const Path& path) { return EPERM; }
290 Error DevFs::Mkdir(const Path& path, int permissions) { return EPERM; }
292 Error DevFs::Rmdir(const Path& path) { return EPERM; }
294 Error DevFs::Remove(const Path& path) { return EPERM; }
296 Error DevFs::Rename(const Path& path, const Path& newpath) { return EPERM; }
300 #define INITIALIZE_DEV_NODE(path, klass) \
301 error = root_->AddChild(path, ScopedNode(new klass(this))); \
305 #define INITIALIZE_DEV_NODE_1(path, klass, arg) \
306 error = root_->AddChild(path, ScopedNode(new klass(this, arg))); \
310 Error DevFs::Init(const FsInitArgs& args) {
311 Error error = Filesystem::Init(args);
315 root_.reset(new DirNode(this));
317 INITIALIZE_DEV_NODE("/null", NullNode);
318 INITIALIZE_DEV_NODE("/zero", ZeroNode);
319 INITIALIZE_DEV_NODE("/urandom", UrandomNode);
320 INITIALIZE_DEV_NODE_1("/console0", ConsoleNode, PP_LOGLEVEL_TIP);
321 INITIALIZE_DEV_NODE_1("/console1", ConsoleNode, PP_LOGLEVEL_LOG);
322 INITIALIZE_DEV_NODE_1("/console2", ConsoleNode, PP_LOGLEVEL_WARNING);
323 INITIALIZE_DEV_NODE_1("/console3", ConsoleNode, PP_LOGLEVEL_ERROR);
324 INITIALIZE_DEV_NODE("/tty", TtyNode);
325 INITIALIZE_DEV_NODE_1("/stdin", RealNode, 0);
326 INITIALIZE_DEV_NODE_1("/stdout", RealNode, 1);
327 INITIALIZE_DEV_NODE_1("/stderr", RealNode, 2);
332 } // namespace nacl_io