OLD | NEW |
| (Empty) |
1 /* Copyright (c) 2012 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 <string.h> | |
12 #include "nacl_mounts/mount_dev.h" | |
13 #include "nacl_mounts/mount_node.h" | |
14 #include "nacl_mounts/mount_node_dir.h" | |
15 #include "nacl_mounts/pepper_interface.h" | |
16 #include "utils/auto_lock.h" | |
17 | |
18 #if defined(__native_client__) | |
19 # include <irt.h> | |
20 #elif defined(WIN32) | |
21 # include <stdlib.h> | |
22 #endif | |
23 | |
24 namespace { | |
25 | |
26 void ReleaseAndNullNode(MountNode** node) { | |
27 if (*node) | |
28 (*node)->Release(); | |
29 *node = NULL; | |
30 } | |
31 | |
32 class NullNode : public MountNode { | |
33 public: | |
34 explicit NullNode(Mount* mount); | |
35 | |
36 virtual int Read(size_t offs, void* buf, size_t count); | |
37 virtual int Write(size_t offs, const void* buf, size_t count); | |
38 }; | |
39 | |
40 class ConsoleNode : public NullNode { | |
41 public: | |
42 ConsoleNode(Mount* mount, PP_LogLevel level); | |
43 | |
44 virtual int Write(size_t offs, const void* buf, size_t count); | |
45 | |
46 private: | |
47 PP_LogLevel level_; | |
48 }; | |
49 | |
50 | |
51 class TtyNode : public NullNode { | |
52 public: | |
53 explicit TtyNode(Mount* mount); | |
54 | |
55 virtual int Write(size_t offs, const void* buf, size_t count); | |
56 }; | |
57 | |
58 | |
59 class ZeroNode : public MountNode { | |
60 public: | |
61 explicit ZeroNode(Mount* mount); | |
62 | |
63 virtual int Read(size_t offs, void* buf, size_t count); | |
64 virtual int Write(size_t offs, const void* buf, size_t count); | |
65 }; | |
66 | |
67 class UrandomNode : public MountNode { | |
68 public: | |
69 explicit UrandomNode(Mount* mount); | |
70 | |
71 virtual int Read(size_t offs, void* buf, size_t count); | |
72 virtual int Write(size_t offs, const void* buf, size_t count); | |
73 | |
74 private: | |
75 #if defined(__native_client__) | |
76 nacl_irt_random random_interface_; | |
77 bool interface_ok_; | |
78 #endif | |
79 }; | |
80 | |
81 NullNode::NullNode(Mount* mount) | |
82 : MountNode(mount) { | |
83 stat_.st_mode = S_IFCHR; | |
84 } | |
85 | |
86 int NullNode::Read(size_t offs, void* buf, size_t count) { | |
87 return 0; | |
88 } | |
89 | |
90 int NullNode::Write(size_t offs, const void* buf, size_t count) { | |
91 return count; | |
92 } | |
93 | |
94 ConsoleNode::ConsoleNode(Mount* mount, PP_LogLevel level) | |
95 : NullNode(mount), | |
96 level_(level) { | |
97 stat_.st_mode = S_IFCHR; | |
98 } | |
99 | |
100 int ConsoleNode::Write(size_t offs, const void* buf, size_t count) { | |
101 ConsoleInterface* con_intr = mount_->ppapi()->GetConsoleInterface(); | |
102 VarInterface* var_intr = mount_->ppapi()->GetVarInterface(); | |
103 | |
104 if (var_intr && con_intr) { | |
105 const char* data = static_cast<const char *>(buf); | |
106 uint32_t len = static_cast<uint32_t>(count); | |
107 struct PP_Var val = var_intr->VarFromUtf8(data, len); | |
108 con_intr->Log(mount_->ppapi()->GetInstance(), level_, val); | |
109 return count; | |
110 } | |
111 return 0; | |
112 } | |
113 | |
114 | |
115 TtyNode::TtyNode(Mount* mount) | |
116 : NullNode(mount) { | |
117 } | |
118 | |
119 int TtyNode::Write(size_t offs, const void* buf, size_t count) { | |
120 MessagingInterface* msg_intr = mount_->ppapi()->GetMessagingInterface(); | |
121 VarInterface* var_intr = mount_->ppapi()->GetVarInterface(); | |
122 | |
123 if (var_intr && msg_intr) { | |
124 const char* data = static_cast<const char *>(buf); | |
125 uint32_t len = static_cast<uint32_t>(count); | |
126 struct PP_Var val = var_intr->VarFromUtf8(data, len); | |
127 msg_intr->PostMessage(mount_->ppapi()->GetInstance(), val); | |
128 return count; | |
129 } | |
130 return 0; | |
131 } | |
132 | |
133 | |
134 ZeroNode::ZeroNode(Mount* mount) | |
135 : MountNode(mount) { | |
136 stat_.st_mode = S_IFCHR; | |
137 } | |
138 | |
139 int ZeroNode::Read(size_t offs, void* buf, size_t count) { | |
140 memset(buf, 0, count); | |
141 return count; | |
142 } | |
143 | |
144 int ZeroNode::Write(size_t offs, const void* buf, size_t count) { | |
145 return count; | |
146 } | |
147 | |
148 UrandomNode::UrandomNode(Mount* mount) | |
149 : MountNode(mount) { | |
150 stat_.st_mode = S_IFCHR; | |
151 #if defined(__native_client__) | |
152 size_t result = nacl_interface_query(NACL_IRT_RANDOM_v0_1, &random_interface_, | |
153 sizeof(random_interface_)); | |
154 interface_ok_ = result != 0; | |
155 #endif | |
156 } | |
157 | |
158 int UrandomNode::Read(size_t offs, void* buf, size_t count) { | |
159 #if defined(__native_client__) | |
160 if (interface_ok_) { | |
161 size_t nread; | |
162 int result = (*random_interface_.get_random_bytes)(buf, count, &nread); | |
163 if (result != 0) { | |
164 errno = result; | |
165 return 0; | |
166 } | |
167 | |
168 return count; | |
169 } | |
170 | |
171 errno = EBADF; | |
172 return 0; | |
173 #elif defined(WIN32) | |
174 char* out = static_cast<char*>(buf); | |
175 size_t bytes_left = count; | |
176 while (bytes_left) { | |
177 unsigned int random_int; | |
178 errno_t err = rand_s(&random_int); | |
179 if (err) { | |
180 errno = err; | |
181 return count - bytes_left; | |
182 } | |
183 | |
184 int bytes_to_copy = std::min(bytes_left, sizeof(random_int)); | |
185 memcpy(out, &random_int, bytes_to_copy); | |
186 out += bytes_to_copy; | |
187 bytes_left -= bytes_to_copy; | |
188 } | |
189 | |
190 return count; | |
191 #endif | |
192 } | |
193 | |
194 int UrandomNode::Write(size_t offs, const void* buf, size_t count) { | |
195 return count; | |
196 } | |
197 | |
198 | |
199 | |
200 } // namespace | |
201 | |
202 MountNode *MountDev::Open(const Path& path, int mode) { | |
203 AutoLock lock(&lock_); | |
204 | |
205 // Don't allow creating any files. | |
206 if (mode & O_CREAT) | |
207 return NULL; | |
208 | |
209 MountNode* node = root_->FindChild(path.Join()); | |
210 if (node) | |
211 node->Acquire(); | |
212 return node; | |
213 } | |
214 | |
215 int MountDev::Unlink(const Path& path) { | |
216 errno = EINVAL; | |
217 return -1; | |
218 } | |
219 | |
220 int MountDev::Mkdir(const Path& path, int permissions) { | |
221 errno = EINVAL; | |
222 return -1; | |
223 } | |
224 | |
225 int MountDev::Rmdir(const Path& path) { | |
226 errno = EINVAL; | |
227 return -1; | |
228 } | |
229 | |
230 int MountDev::Remove(const Path& path) { | |
231 errno = EINVAL; | |
232 return -1; | |
233 } | |
234 | |
235 MountDev::MountDev() | |
236 : null_node_(NULL), | |
237 zero_node_(NULL), | |
238 random_node_(NULL), | |
239 console0_node_(NULL), | |
240 console1_node_(NULL), | |
241 console2_node_(NULL), | |
242 console3_node_(NULL), | |
243 tty_node_(NULL) { | |
244 } | |
245 | |
246 bool MountDev::Init(int dev, StringMap_t& args, PepperInterface* ppapi) { | |
247 if (!Mount::Init(dev, args, ppapi)) | |
248 return false; | |
249 | |
250 root_ = new MountNodeDir(this); | |
251 null_node_ = new NullNode(this); | |
252 root_->AddChild("/null", null_node_); | |
253 zero_node_ = new ZeroNode(this); | |
254 root_->AddChild("/zero", zero_node_); | |
255 random_node_ = new UrandomNode(this); | |
256 root_->AddChild("/urandom", random_node_); | |
257 | |
258 console0_node_ = new ConsoleNode(this, PP_LOGLEVEL_TIP); | |
259 root_->AddChild("/console0", console0_node_); | |
260 console1_node_ = new ConsoleNode(this, PP_LOGLEVEL_LOG); | |
261 root_->AddChild("/console1", console1_node_); | |
262 console2_node_ = new ConsoleNode(this, PP_LOGLEVEL_WARNING); | |
263 root_->AddChild("/console2", console2_node_); | |
264 console3_node_ = new ConsoleNode(this, PP_LOGLEVEL_ERROR); | |
265 root_->AddChild("/console3", console3_node_); | |
266 | |
267 tty_node_ = new TtyNode(this); | |
268 root_->AddChild("/tty", tty_node_); | |
269 return true; | |
270 } | |
271 | |
272 void MountDev::Destroy() { | |
273 ReleaseAndNullNode(&tty_node_); | |
274 ReleaseAndNullNode(&console3_node_); | |
275 ReleaseAndNullNode(&console2_node_); | |
276 ReleaseAndNullNode(&console1_node_); | |
277 ReleaseAndNullNode(&console0_node_); | |
278 ReleaseAndNullNode(&random_node_); | |
279 ReleaseAndNullNode(&zero_node_); | |
280 ReleaseAndNullNode(&null_node_); | |
281 ReleaseAndNullNode(&root_); | |
282 } | |
OLD | NEW |