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/jspipe_node.h"
17 #include "nacl_io/devfs/tty_node.h"
18 #include "nacl_io/dir_node.h"
19 #include "nacl_io/kernel_wrap_real.h"
20 #include "nacl_io/node.h"
21 #include "nacl_io/osunistd.h"
22 #include "nacl_io/pepper_interface.h"
23 #include "sdk_util/auto_lock.h"
25 #if defined(__native_client__)
35 class RealNode : public Node {
37 RealNode(Filesystem* filesystem, int fd);
39 virtual Error Read(const HandleAttr& attr,
43 virtual Error Write(const HandleAttr& attr,
47 virtual Error GetStat(struct stat* stat);
53 class NullNode : public CharNode {
55 explicit NullNode(Filesystem* filesystem) : CharNode(filesystem) {}
57 virtual Error Read(const HandleAttr& attr,
61 virtual Error Write(const HandleAttr& attr,
67 class ConsoleNode : public CharNode {
69 ConsoleNode(Filesystem* filesystem, PP_LogLevel level);
71 virtual Error Write(const HandleAttr& attr,
80 class ZeroNode : public Node {
82 explicit ZeroNode(Filesystem* filesystem);
84 virtual Error Read(const HandleAttr& attr,
88 virtual Error Write(const HandleAttr& attr,
94 class UrandomNode : public Node {
96 explicit UrandomNode(Filesystem* filesystem);
98 virtual Error Read(const HandleAttr& attr,
102 virtual Error Write(const HandleAttr& attr,
108 #if defined(__native_client__)
109 nacl_irt_random random_interface_;
114 RealNode::RealNode(Filesystem* filesystem, int fd) : Node(filesystem), fd_(fd) {
118 Error RealNode::Read(const HandleAttr& attr,
125 int err = _real_read(fd_, buf, count, &readcnt);
129 *out_bytes = static_cast<int>(readcnt);
133 Error RealNode::Write(const HandleAttr& attr,
140 int err = _real_write(fd_, buf, count, &writecnt);
144 *out_bytes = static_cast<int>(writecnt);
148 Error RealNode::GetStat(struct stat* stat) { return _real_fstat(fd_, stat); }
150 Error NullNode::Read(const HandleAttr& attr,
158 Error NullNode::Write(const HandleAttr& attr,
166 ConsoleNode::ConsoleNode(Filesystem* filesystem, PP_LogLevel level)
167 : CharNode(filesystem), level_(level) {}
169 Error ConsoleNode::Write(const HandleAttr& attr,
175 ConsoleInterface* con_intr = filesystem_->ppapi()->GetConsoleInterface();
176 VarInterface* var_intr = filesystem_->ppapi()->GetVarInterface();
178 if (!(var_intr && con_intr))
181 const char* var_data = static_cast<const char*>(buf);
182 uint32_t len = static_cast<uint32_t>(count);
183 struct PP_Var val = var_intr->VarFromUtf8(var_data, len);
184 con_intr->Log(filesystem_->ppapi()->GetInstance(), level_, val);
190 ZeroNode::ZeroNode(Filesystem* filesystem) : Node(filesystem) {
194 Error ZeroNode::Read(const HandleAttr& attr,
198 memset(buf, 0, count);
203 Error ZeroNode::Write(const HandleAttr& attr,
211 UrandomNode::UrandomNode(Filesystem* filesystem) : Node(filesystem) {
213 #if defined(__native_client__)
214 size_t result = nacl_interface_query(
215 NACL_IRT_RANDOM_v0_1, &random_interface_, sizeof(random_interface_));
216 interface_ok_ = result != 0;
220 Error UrandomNode::Read(const HandleAttr& attr,
226 #if defined(__native_client__)
231 int error = (*random_interface_.get_random_bytes)(buf, count, &nread);
235 char* out = static_cast<char*>(buf);
236 size_t bytes_left = count;
238 unsigned int random_int;
239 errno_t err = rand_s(&random_int);
241 *out_bytes = count - bytes_left;
245 int bytes_to_copy = std::min(bytes_left, sizeof(random_int));
246 memcpy(out, &random_int, bytes_to_copy);
247 out += bytes_to_copy;
248 bytes_left -= bytes_to_copy;
256 Error UrandomNode::Write(const HandleAttr& attr,
266 Error DevFs::Access(const Path& path, int a_mode) {
268 int error = root_->FindChild(path.Join(), &node);
272 // Don't allow execute access.
279 Error DevFs::Open(const Path& path, int open_flags, ScopedNode* out_node) {
280 out_node->reset(NULL);
281 int error = root_->FindChild(path.Join(), out_node);
282 // Only return EACCES when trying to create a node that does not exist.
283 if ((error == ENOENT) && (open_flags & O_CREAT))
289 Error DevFs::Unlink(const Path& path) { return EPERM; }
291 Error DevFs::Mkdir(const Path& path, int permissions) { return EPERM; }
293 Error DevFs::Rmdir(const Path& path) { return EPERM; }
295 Error DevFs::Remove(const Path& path) { return EPERM; }
297 Error DevFs::Rename(const Path& path, const Path& newpath) { return EPERM; }
301 #define INITIALIZE_DEV_NODE(path, klass) \
302 new_node = ScopedNode(new klass(this)); \
303 error = root_->AddChild(path, new_node); \
307 #define INITIALIZE_DEV_NODE_1(path, klass, arg) \
308 new_node = ScopedNode(new klass(this, arg)); \
309 error = root_->AddChild(path, new_node); \
313 Error DevFs::Init(const FsInitArgs& args) {
314 Error error = Filesystem::Init(args);
318 root_.reset(new DirNode(this));
321 INITIALIZE_DEV_NODE("/null", NullNode);
322 INITIALIZE_DEV_NODE("/zero", ZeroNode);
323 INITIALIZE_DEV_NODE("/urandom", UrandomNode);
324 INITIALIZE_DEV_NODE_1("/console0", ConsoleNode, PP_LOGLEVEL_TIP);
325 INITIALIZE_DEV_NODE_1("/console1", ConsoleNode, PP_LOGLEVEL_LOG);
326 INITIALIZE_DEV_NODE_1("/console2", ConsoleNode, PP_LOGLEVEL_WARNING);
327 INITIALIZE_DEV_NODE_1("/console3", ConsoleNode, PP_LOGLEVEL_ERROR);
328 INITIALIZE_DEV_NODE("/tty", TtyNode);
329 INITIALIZE_DEV_NODE_1("/stdin", RealNode, 0);
330 INITIALIZE_DEV_NODE_1("/stdout", RealNode, 1);
331 INITIALIZE_DEV_NODE_1("/stderr", RealNode, 2);
332 INITIALIZE_DEV_NODE("/jspipe1", JSPipeNode);
333 new_node->Ioctl(TIOCNACLPIPENAME, "jspipe1");
334 INITIALIZE_DEV_NODE("/jspipe2", JSPipeNode);
335 new_node->Ioctl(TIOCNACLPIPENAME, "jspipe2");
336 INITIALIZE_DEV_NODE("/jspipe3", JSPipeNode);
337 new_node->Ioctl(TIOCNACLPIPENAME, "jspipe3");
342 } // namespace nacl_io