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