1 // Copyright (c) 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.
14 #include "nacl_io/kernel_wrap_real.h"
15 #include "nacl_io/mount_dev.h"
16 #include "nacl_io/mount_node.h"
17 #include "nacl_io/mount_node_dir.h"
18 #include "nacl_io/mount_node_tty.h"
19 #include "nacl_io/osunistd.h"
20 #include "nacl_io/pepper_interface.h"
21 #include "sdk_util/auto_lock.h"
23 #if defined(__native_client__)
33 class RealNode : public MountNode {
35 RealNode(Mount* mount, int fd);
37 virtual Error Read(const HandleAttr& attr,
41 virtual Error Write(const HandleAttr& attr,
45 virtual Error GetStat(struct stat* stat);
51 class NullNode : public MountNodeCharDevice {
53 explicit NullNode(Mount* mount) : MountNodeCharDevice(mount) {}
55 virtual Error Read(const HandleAttr& attr,
59 virtual Error Write(const HandleAttr& attr,
65 class ConsoleNode : public MountNodeCharDevice {
67 ConsoleNode(Mount* mount, PP_LogLevel level);
69 virtual Error Write(const HandleAttr& attr,
78 class ZeroNode : public MountNode {
80 explicit ZeroNode(Mount* mount);
82 virtual Error Read(const HandleAttr& attr,
86 virtual Error Write(const HandleAttr& attr,
92 class UrandomNode : public MountNode {
94 explicit UrandomNode(Mount* mount);
96 virtual Error Read(const HandleAttr& attr,
100 virtual Error Write(const HandleAttr& attr,
106 #if defined(__native_client__)
107 nacl_irt_random random_interface_;
112 RealNode::RealNode(Mount* mount, int fd) : MountNode(mount), fd_(fd) {
116 Error RealNode::Read(const HandleAttr& attr,
123 int err = _real_read(fd_, buf, count, &readcnt);
127 *out_bytes = static_cast<int>(readcnt);
131 Error RealNode::Write(const HandleAttr& attr,
138 int err = _real_write(fd_, buf, count, &writecnt);
142 *out_bytes = static_cast<int>(writecnt);
146 Error RealNode::GetStat(struct stat* stat) { return _real_fstat(fd_, stat); }
148 Error NullNode::Read(const HandleAttr& attr,
156 Error NullNode::Write(const HandleAttr& attr,
164 ConsoleNode::ConsoleNode(Mount* mount, PP_LogLevel level)
165 : MountNodeCharDevice(mount), level_(level) {
168 Error ConsoleNode::Write(const HandleAttr& attr,
174 ConsoleInterface* con_intr = mount_->ppapi()->GetConsoleInterface();
175 VarInterface* var_intr = mount_->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(mount_->ppapi()->GetInstance(), level_, val);
189 ZeroNode::ZeroNode(Mount* mount) : MountNode(mount) { SetType(S_IFCHR); }
191 Error ZeroNode::Read(const HandleAttr& attr,
195 memset(buf, 0, count);
200 Error ZeroNode::Write(const HandleAttr& attr,
208 UrandomNode::UrandomNode(Mount* mount) : MountNode(mount) {
210 #if defined(__native_client__)
211 size_t result = nacl_interface_query(
212 NACL_IRT_RANDOM_v0_1, &random_interface_, sizeof(random_interface_));
213 interface_ok_ = result != 0;
217 Error UrandomNode::Read(const HandleAttr& attr,
223 #if defined(__native_client__)
228 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 MountDev::Access(const Path& path, int a_mode) {
267 ScopedMountNode node;
268 int error = root_->FindChild(path.Join(), &node);
272 // Don't allow execute access.
279 Error MountDev::Open(const Path& path,
281 ScopedMountNode* out_node) {
282 out_node->reset(NULL);
284 // Don't allow creating any files.
285 if (open_flags & O_CREAT)
288 return root_->FindChild(path.Join(), out_node);
291 Error MountDev::Unlink(const Path& path) { return EINVAL; }
293 Error MountDev::Mkdir(const Path& path, int permissions) { return EINVAL; }
295 Error MountDev::Rmdir(const Path& path) { return EINVAL; }
297 Error MountDev::Remove(const Path& path) { return EINVAL; }
299 MountDev::MountDev() {}
301 #define INITIALIZE_DEV_NODE(path, klass) \
302 error = root_->AddChild(path, ScopedMountNode(new klass(this))); \
306 #define INITIALIZE_DEV_NODE_1(path, klass, arg) \
307 error = root_->AddChild(path, ScopedMountNode(new klass(this, arg))); \
311 Error MountDev::Init(int dev, StringMap_t& args, PepperInterface* ppapi) {
312 Error error = Mount::Init(dev, args, ppapi);
316 root_.reset(new MountNodeDir(this));
318 INITIALIZE_DEV_NODE("/null", NullNode);
319 INITIALIZE_DEV_NODE("/zero", ZeroNode);
320 INITIALIZE_DEV_NODE("/urandom", UrandomNode);
321 INITIALIZE_DEV_NODE_1("/console0", ConsoleNode, PP_LOGLEVEL_TIP);
322 INITIALIZE_DEV_NODE_1("/console1", ConsoleNode, PP_LOGLEVEL_LOG);
323 INITIALIZE_DEV_NODE_1("/console2", ConsoleNode, PP_LOGLEVEL_WARNING);
324 INITIALIZE_DEV_NODE_1("/console3", ConsoleNode, PP_LOGLEVEL_ERROR);
325 INITIALIZE_DEV_NODE("/tty", MountNodeTty);
326 INITIALIZE_DEV_NODE_1("/stdin", RealNode, 0);
327 INITIALIZE_DEV_NODE_1("/stdout", RealNode, 1);
328 INITIALIZE_DEV_NODE_1("/stderr", RealNode, 2);
333 } // namespace nacl_io