- add sources.
[platform/framework/web/crosswalk.git] / src / native_client_sdk / src / libraries / nacl_io / mount_dev.cc
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.
4
5 #if defined(WIN32)
6 #define _CRT_RAND_S
7 #endif
8
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <pthread.h>
12 #include <string.h>
13
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"
22
23 #if defined(__native_client__)
24 #include <irt.h>
25 #elif defined(WIN32)
26 #include <stdlib.h>
27 #endif
28
29 namespace nacl_io {
30
31 namespace {
32
33 class RealNode : public MountNode {
34  public:
35   RealNode(Mount* mount, int fd);
36
37   virtual Error Read(const HandleAttr& attr,
38                      void* buf,
39                      size_t count,
40                      int* out_bytes);
41   virtual Error Write(const HandleAttr& attr,
42                       const void* buf,
43                       size_t count,
44                       int* out_bytes);
45   virtual Error GetStat(struct stat* stat);
46
47  protected:
48   int fd_;
49 };
50
51 class NullNode : public MountNodeCharDevice {
52  public:
53   explicit NullNode(Mount* mount) : MountNodeCharDevice(mount) {}
54
55   virtual Error Read(const HandleAttr& attr,
56                      void* buf,
57                      size_t count,
58                      int* out_bytes);
59   virtual Error Write(const HandleAttr& attr,
60                       const void* buf,
61                       size_t count,
62                       int* out_bytes);
63 };
64
65 class ConsoleNode : public MountNodeCharDevice {
66  public:
67   ConsoleNode(Mount* mount, PP_LogLevel level);
68
69   virtual Error Write(const HandleAttr& attr,
70                       const void* buf,
71                       size_t count,
72                       int* out_bytes);
73
74  private:
75   PP_LogLevel level_;
76 };
77
78 class ZeroNode : public MountNode {
79  public:
80   explicit ZeroNode(Mount* mount);
81
82   virtual Error Read(const HandleAttr& attr,
83                      void* buf,
84                      size_t count,
85                      int* out_bytes);
86   virtual Error Write(const HandleAttr& attr,
87                       const void* buf,
88                       size_t count,
89                       int* out_bytes);
90 };
91
92 class UrandomNode : public MountNode {
93  public:
94   explicit UrandomNode(Mount* mount);
95
96   virtual Error Read(const HandleAttr& attr,
97                      void* buf,
98                      size_t count,
99                      int* out_bytes);
100   virtual Error Write(const HandleAttr& attr,
101                       const void* buf,
102                       size_t count,
103                       int* out_bytes);
104
105  private:
106 #if defined(__native_client__)
107   nacl_irt_random random_interface_;
108   bool interface_ok_;
109 #endif
110 };
111
112 RealNode::RealNode(Mount* mount, int fd) : MountNode(mount), fd_(fd) {
113   SetType(S_IFCHR);
114 }
115
116 Error RealNode::Read(const HandleAttr& attr,
117                      void* buf,
118                      size_t count,
119                      int* out_bytes) {
120   *out_bytes = 0;
121
122   size_t readcnt;
123   int err = _real_read(fd_, buf, count, &readcnt);
124   if (err)
125     return err;
126
127   *out_bytes = static_cast<int>(readcnt);
128   return 0;
129 }
130
131 Error RealNode::Write(const HandleAttr& attr,
132                       const void* buf,
133                       size_t count,
134                       int* out_bytes) {
135   *out_bytes = 0;
136
137   size_t writecnt;
138   int err = _real_write(fd_, buf, count, &writecnt);
139   if (err)
140     return err;
141
142   *out_bytes = static_cast<int>(writecnt);
143   return 0;
144 }
145
146 Error RealNode::GetStat(struct stat* stat) { return _real_fstat(fd_, stat); }
147
148 Error NullNode::Read(const HandleAttr& attr,
149                      void* buf,
150                      size_t count,
151                      int* out_bytes) {
152   *out_bytes = 0;
153   return 0;
154 }
155
156 Error NullNode::Write(const HandleAttr& attr,
157                       const void* buf,
158                       size_t count,
159                       int* out_bytes) {
160   *out_bytes = count;
161   return 0;
162 }
163
164 ConsoleNode::ConsoleNode(Mount* mount, PP_LogLevel level)
165     : MountNodeCharDevice(mount), level_(level) {
166 }
167
168 Error ConsoleNode::Write(const HandleAttr& attr,
169                          const void* buf,
170                          size_t count,
171                          int* out_bytes) {
172   *out_bytes = 0;
173
174   ConsoleInterface* con_intr = mount_->ppapi()->GetConsoleInterface();
175   VarInterface* var_intr = mount_->ppapi()->GetVarInterface();
176
177   if (!(var_intr && con_intr))
178     return ENOSYS;
179
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);
184
185   *out_bytes = count;
186   return 0;
187 }
188
189 ZeroNode::ZeroNode(Mount* mount) : MountNode(mount) { SetType(S_IFCHR); }
190
191 Error ZeroNode::Read(const HandleAttr& attr,
192                      void* buf,
193                      size_t count,
194                      int* out_bytes) {
195   memset(buf, 0, count);
196   *out_bytes = count;
197   return 0;
198 }
199
200 Error ZeroNode::Write(const HandleAttr& attr,
201                       const void* buf,
202                       size_t count,
203                       int* out_bytes) {
204   *out_bytes = count;
205   return 0;
206 }
207
208 UrandomNode::UrandomNode(Mount* mount) : MountNode(mount) {
209   SetType(S_IFCHR);
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;
214 #endif
215 }
216
217 Error UrandomNode::Read(const HandleAttr& attr,
218                         void* buf,
219                         size_t count,
220                         int* out_bytes) {
221   *out_bytes = 0;
222
223 #if defined(__native_client__)
224   if (!interface_ok_)
225     return EBADF;
226
227   size_t nread;
228   int error = (*random_interface_.get_random_bytes)(buf, count, &nread);
229   if (error)
230     return error;
231
232   *out_bytes = count;
233   return 0;
234 #elif defined(WIN32)
235   char* out = static_cast<char*>(buf);
236   size_t bytes_left = count;
237   while (bytes_left) {
238     unsigned int random_int;
239     errno_t err = rand_s(&random_int);
240     if (err) {
241       *out_bytes = count - bytes_left;
242       return err;
243     }
244
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;
249   }
250
251   *out_bytes = count;
252   return 0;
253 #endif
254 }
255
256 Error UrandomNode::Write(const HandleAttr& attr,
257                          const void* buf,
258                          size_t count,
259                          int* out_bytes) {
260   *out_bytes = count;
261   return 0;
262 }
263
264 }  // namespace
265
266 Error MountDev::Access(const Path& path, int a_mode) {
267   ScopedMountNode node;
268   int error = root_->FindChild(path.Join(), &node);
269   if (error)
270     return error;
271
272   // Don't allow execute access.
273   if (a_mode & X_OK)
274     return EACCES;
275
276   return 0;
277 }
278
279 Error MountDev::Open(const Path& path,
280                      int open_flags,
281                      ScopedMountNode* out_node) {
282   out_node->reset(NULL);
283
284   // Don't allow creating any files.
285   if (open_flags & O_CREAT)
286     return EINVAL;
287
288   return root_->FindChild(path.Join(), out_node);
289 }
290
291 Error MountDev::Unlink(const Path& path) { return EINVAL; }
292
293 Error MountDev::Mkdir(const Path& path, int permissions) { return EINVAL; }
294
295 Error MountDev::Rmdir(const Path& path) { return EINVAL; }
296
297 Error MountDev::Remove(const Path& path) { return EINVAL; }
298
299 MountDev::MountDev() {}
300
301 #define INITIALIZE_DEV_NODE(path, klass)                           \
302   error = root_->AddChild(path, ScopedMountNode(new klass(this))); \
303   if (error)                                                       \
304     return error;
305
306 #define INITIALIZE_DEV_NODE_1(path, klass, arg)                         \
307   error = root_->AddChild(path, ScopedMountNode(new klass(this, arg))); \
308   if (error)                                                            \
309     return error;
310
311 Error MountDev::Init(int dev, StringMap_t& args, PepperInterface* ppapi) {
312   Error error = Mount::Init(dev, args, ppapi);
313   if (error)
314     return error;
315
316   root_.reset(new MountNodeDir(this));
317
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);
329
330   return 0;
331 }
332
333 }  // namespace nacl_io
334