OLD | NEW |
1 /* Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 * Use of this source code is governed by a BSD-style license that can be |
3 * found in the LICENSE file. | 3 * found in the LICENSE file. |
4 */ | 4 */ |
5 #if defined(WIN32) | 5 #if defined(WIN32) |
6 #define _CRT_RAND_S | 6 #define _CRT_RAND_S |
7 #endif | 7 #endif |
8 | 8 |
9 #include <errno.h> | 9 #include <errno.h> |
10 #include <fcntl.h> | 10 #include <fcntl.h> |
11 #include <string.h> | 11 #include <string.h> |
12 #include "nacl_io/kernel_wrap_real.h" | 12 #include "nacl_io/kernel_wrap_real.h" |
13 #include "nacl_io/mount_dev.h" | 13 #include "nacl_io/mount_dev.h" |
14 #include "nacl_io/mount_node.h" | 14 #include "nacl_io/mount_node.h" |
15 #include "nacl_io/mount_node_dir.h" | 15 #include "nacl_io/mount_node_dir.h" |
16 #include "nacl_io/pepper_interface.h" | 16 #include "nacl_io/pepper_interface.h" |
17 #include "utils/auto_lock.h" | 17 #include "utils/auto_lock.h" |
18 | 18 |
19 #if defined(__native_client__) | 19 #if defined(__native_client__) |
20 # include <irt.h> | 20 #include <irt.h> |
21 #elif defined(WIN32) | 21 #elif defined(WIN32) |
22 # include <stdlib.h> | 22 #include <stdlib.h> |
23 #endif | 23 #endif |
24 | 24 |
25 | |
26 namespace { | 25 namespace { |
27 | 26 |
28 void ReleaseAndNullNode(MountNode** node) { | |
29 if (*node) | |
30 (*node)->Release(); | |
31 *node = NULL; | |
32 } | |
33 | |
34 | |
35 class RealNode : public MountNode { | 27 class RealNode : public MountNode { |
36 public: | 28 public: |
37 RealNode(Mount* mount, int fd); | 29 RealNode(Mount* mount, int fd); |
38 | 30 |
39 virtual int Read(size_t offs, void* buf, size_t count); | 31 virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes); |
40 virtual int Write(size_t offs, const void* buf, size_t count); | 32 virtual Error Write(size_t offs, |
41 virtual int GetStat(struct stat* stat); | 33 const void* buf, |
| 34 size_t count, |
| 35 int* out_bytes); |
| 36 virtual Error GetStat(struct stat* stat); |
42 | 37 |
43 protected: | 38 protected: |
44 int fd_; | 39 int fd_; |
45 }; | 40 }; |
46 | 41 |
47 class NullNode : public MountNode { | 42 class NullNode : public MountNode { |
48 public: | 43 public: |
49 explicit NullNode(Mount* mount); | 44 explicit NullNode(Mount* mount); |
50 | 45 |
51 virtual int Read(size_t offs, void* buf, size_t count); | 46 virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes); |
52 virtual int Write(size_t offs, const void* buf, size_t count); | 47 virtual Error Write(size_t offs, |
| 48 const void* buf, |
| 49 size_t count, |
| 50 int* out_bytes); |
53 }; | 51 }; |
54 | 52 |
55 class ConsoleNode : public NullNode { | 53 class ConsoleNode : public NullNode { |
56 public: | 54 public: |
57 ConsoleNode(Mount* mount, PP_LogLevel level); | 55 ConsoleNode(Mount* mount, PP_LogLevel level); |
58 | 56 |
59 virtual int Write(size_t offs, const void* buf, size_t count); | 57 virtual Error Write(size_t offs, |
| 58 const void* buf, |
| 59 size_t count, |
| 60 int* out_bytes); |
60 | 61 |
61 private: | 62 private: |
62 PP_LogLevel level_; | 63 PP_LogLevel level_; |
63 }; | 64 }; |
64 | 65 |
65 | |
66 class TtyNode : public NullNode { | 66 class TtyNode : public NullNode { |
67 public: | 67 public: |
68 explicit TtyNode(Mount* mount); | 68 explicit TtyNode(Mount* mount); |
69 | 69 |
70 virtual int Write(size_t offs, const void* buf, size_t count); | 70 virtual Error Write(size_t offs, |
| 71 const void* buf, |
| 72 size_t count, |
| 73 int* out_bytes); |
71 }; | 74 }; |
72 | 75 |
73 | |
74 class ZeroNode : public MountNode { | 76 class ZeroNode : public MountNode { |
75 public: | 77 public: |
76 explicit ZeroNode(Mount* mount); | 78 explicit ZeroNode(Mount* mount); |
77 | 79 |
78 virtual int Read(size_t offs, void* buf, size_t count); | 80 virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes); |
79 virtual int Write(size_t offs, const void* buf, size_t count); | 81 virtual Error Write(size_t offs, |
| 82 const void* buf, |
| 83 size_t count, |
| 84 int* out_bytes); |
80 }; | 85 }; |
81 | 86 |
82 class UrandomNode : public MountNode { | 87 class UrandomNode : public MountNode { |
83 public: | 88 public: |
84 explicit UrandomNode(Mount* mount); | 89 explicit UrandomNode(Mount* mount); |
85 | 90 |
86 virtual int Read(size_t offs, void* buf, size_t count); | 91 virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes); |
87 virtual int Write(size_t offs, const void* buf, size_t count); | 92 virtual Error Write(size_t offs, |
| 93 const void* buf, |
| 94 size_t count, |
| 95 int* out_bytes); |
88 | 96 |
89 private: | 97 private: |
90 #if defined(__native_client__) | 98 #if defined(__native_client__) |
91 nacl_irt_random random_interface_; | 99 nacl_irt_random random_interface_; |
92 bool interface_ok_; | 100 bool interface_ok_; |
93 #endif | 101 #endif |
94 }; | 102 }; |
95 | 103 |
96 RealNode::RealNode(Mount* mount, int fd) | 104 RealNode::RealNode(Mount* mount, int fd) : MountNode(mount), fd_(fd) { |
97 : MountNode(mount), | |
98 fd_(fd) { | |
99 stat_.st_mode = S_IFCHR; | 105 stat_.st_mode = S_IFCHR; |
100 } | 106 } |
101 | 107 |
102 int RealNode::Read(size_t offs, void* buf, size_t count) { | 108 Error RealNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) { |
| 109 *out_bytes = 0; |
| 110 |
103 size_t readcnt; | 111 size_t readcnt; |
104 int err = _real_read(fd_, buf, count, &readcnt); | 112 int err = _real_read(fd_, buf, count, &readcnt); |
105 if (err) { | 113 if (err) |
106 errno = err; | 114 return err; |
107 return -1; | |
108 } | |
109 return static_cast<int>(readcnt); | |
110 } | |
111 | 115 |
112 int RealNode::Write(size_t offs, const void* buf, size_t count) { | 116 *out_bytes = static_cast<int>(readcnt); |
113 size_t writecnt; | |
114 int err = _real_write(fd_, buf, count, &writecnt); | |
115 if (err) { | |
116 errno = err; | |
117 return -1; | |
118 } | |
119 return static_cast<int>(writecnt); | |
120 } | |
121 | |
122 int RealNode::GetStat(struct stat* stat) { | |
123 int err = _real_fstat(fd_, stat); | |
124 if (err) { | |
125 errno = err; | |
126 return -1; | |
127 } | |
128 return 0; | 117 return 0; |
129 } | 118 } |
130 | 119 |
131 NullNode::NullNode(Mount* mount) | 120 Error RealNode::Write(size_t offs, |
132 : MountNode(mount) { | 121 const void* buf, |
| 122 size_t count, |
| 123 int* out_bytes) { |
| 124 *out_bytes = 0; |
| 125 |
| 126 size_t writecnt; |
| 127 int err = _real_write(fd_, buf, count, &writecnt); |
| 128 if (err) |
| 129 return err; |
| 130 |
| 131 *out_bytes = static_cast<int>(writecnt); |
| 132 return 0; |
| 133 } |
| 134 |
| 135 Error RealNode::GetStat(struct stat* stat) { return _real_fstat(fd_, stat); } |
| 136 |
| 137 NullNode::NullNode(Mount* mount) : MountNode(mount) { stat_.st_mode = S_IFCHR; } |
| 138 |
| 139 Error NullNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) { |
| 140 *out_bytes = 0; |
| 141 return 0; |
| 142 } |
| 143 |
| 144 Error NullNode::Write(size_t offs, |
| 145 const void* buf, |
| 146 size_t count, |
| 147 int* out_bytes) { |
| 148 *out_bytes = count; |
| 149 return 0; |
| 150 } |
| 151 |
| 152 ConsoleNode::ConsoleNode(Mount* mount, PP_LogLevel level) |
| 153 : NullNode(mount), level_(level) { |
133 stat_.st_mode = S_IFCHR; | 154 stat_.st_mode = S_IFCHR; |
134 } | 155 } |
135 | 156 |
136 int NullNode::Read(size_t offs, void* buf, size_t count) { | 157 Error ConsoleNode::Write(size_t offs, |
| 158 const void* buf, |
| 159 size_t count, |
| 160 int* out_bytes) { |
| 161 *out_bytes = 0; |
| 162 |
| 163 ConsoleInterface* con_intr = mount_->ppapi()->GetConsoleInterface(); |
| 164 VarInterface* var_intr = mount_->ppapi()->GetVarInterface(); |
| 165 |
| 166 if (!(var_intr && con_intr)) |
| 167 return ENOSYS; |
| 168 |
| 169 const char* data = static_cast<const char*>(buf); |
| 170 uint32_t len = static_cast<uint32_t>(count); |
| 171 struct PP_Var val = var_intr->VarFromUtf8(data, len); |
| 172 con_intr->Log(mount_->ppapi()->GetInstance(), level_, val); |
| 173 |
| 174 *out_bytes = count; |
137 return 0; | 175 return 0; |
138 } | 176 } |
139 | 177 |
140 int NullNode::Write(size_t offs, const void* buf, size_t count) { | 178 TtyNode::TtyNode(Mount* mount) : NullNode(mount) {} |
141 return count; | |
142 } | |
143 | 179 |
144 ConsoleNode::ConsoleNode(Mount* mount, PP_LogLevel level) | 180 Error TtyNode::Write(size_t offs, |
145 : NullNode(mount), | 181 const void* buf, |
146 level_(level) { | 182 size_t count, |
147 stat_.st_mode = S_IFCHR; | 183 int* out_bytes) { |
148 } | 184 *out_bytes = 0; |
149 | 185 |
150 int ConsoleNode::Write(size_t offs, const void* buf, size_t count) { | 186 MessagingInterface* msg_intr = mount_->ppapi()->GetMessagingInterface(); |
151 ConsoleInterface* con_intr = mount_->ppapi()->GetConsoleInterface(); | |
152 VarInterface* var_intr = mount_->ppapi()->GetVarInterface(); | 187 VarInterface* var_intr = mount_->ppapi()->GetVarInterface(); |
153 | 188 |
154 if (var_intr && con_intr) { | 189 if (!(var_intr && msg_intr)) |
155 const char* data = static_cast<const char *>(buf); | 190 return ENOSYS; |
156 uint32_t len = static_cast<uint32_t>(count); | 191 |
157 struct PP_Var val = var_intr->VarFromUtf8(data, len); | 192 const char* data = static_cast<const char*>(buf); |
158 con_intr->Log(mount_->ppapi()->GetInstance(), level_, val); | 193 uint32_t len = static_cast<uint32_t>(count); |
159 return count; | 194 struct PP_Var val = var_intr->VarFromUtf8(data, len); |
160 } | 195 msg_intr->PostMessage(mount_->ppapi()->GetInstance(), val); |
| 196 |
| 197 *out_bytes = count; |
161 return 0; | 198 return 0; |
162 } | 199 } |
163 | 200 |
| 201 ZeroNode::ZeroNode(Mount* mount) : MountNode(mount) { stat_.st_mode = S_IFCHR; } |
164 | 202 |
165 TtyNode::TtyNode(Mount* mount) | 203 Error ZeroNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) { |
166 : NullNode(mount) { | 204 memset(buf, 0, count); |
167 } | 205 *out_bytes = count; |
168 | |
169 int TtyNode::Write(size_t offs, const void* buf, size_t count) { | |
170 MessagingInterface* msg_intr = mount_->ppapi()->GetMessagingInterface(); | |
171 VarInterface* var_intr = mount_->ppapi()->GetVarInterface(); | |
172 | |
173 if (var_intr && msg_intr) { | |
174 const char* data = static_cast<const char *>(buf); | |
175 uint32_t len = static_cast<uint32_t>(count); | |
176 struct PP_Var val = var_intr->VarFromUtf8(data, len); | |
177 msg_intr->PostMessage(mount_->ppapi()->GetInstance(), val); | |
178 return count; | |
179 } | |
180 return 0; | 206 return 0; |
181 } | 207 } |
182 | 208 |
183 | 209 Error ZeroNode::Write(size_t offs, |
184 ZeroNode::ZeroNode(Mount* mount) | 210 const void* buf, |
185 : MountNode(mount) { | 211 size_t count, |
186 stat_.st_mode = S_IFCHR; | 212 int* out_bytes) { |
| 213 *out_bytes = count; |
| 214 return 0; |
187 } | 215 } |
188 | 216 |
189 int ZeroNode::Read(size_t offs, void* buf, size_t count) { | 217 UrandomNode::UrandomNode(Mount* mount) : MountNode(mount) { |
190 memset(buf, 0, count); | |
191 return count; | |
192 } | |
193 | |
194 int ZeroNode::Write(size_t offs, const void* buf, size_t count) { | |
195 return count; | |
196 } | |
197 | |
198 UrandomNode::UrandomNode(Mount* mount) | |
199 : MountNode(mount) { | |
200 stat_.st_mode = S_IFCHR; | 218 stat_.st_mode = S_IFCHR; |
201 #if defined(__native_client__) | 219 #if defined(__native_client__) |
202 size_t result = nacl_interface_query(NACL_IRT_RANDOM_v0_1, &random_interface_, | 220 size_t result = nacl_interface_query( |
203 sizeof(random_interface_)); | 221 NACL_IRT_RANDOM_v0_1, &random_interface_, sizeof(random_interface_)); |
204 interface_ok_ = result != 0; | 222 interface_ok_ = result != 0; |
205 #endif | 223 #endif |
206 } | 224 } |
207 | 225 |
208 int UrandomNode::Read(size_t offs, void* buf, size_t count) { | 226 Error UrandomNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) { |
| 227 *out_bytes = 0; |
| 228 |
209 #if defined(__native_client__) | 229 #if defined(__native_client__) |
210 if (interface_ok_) { | 230 if (!interface_ok_) |
211 size_t nread; | 231 return EBADF; |
212 int result = (*random_interface_.get_random_bytes)(buf, count, &nread); | |
213 if (result != 0) { | |
214 errno = result; | |
215 return 0; | |
216 } | |
217 | 232 |
218 return count; | 233 size_t nread; |
219 } | 234 int error = (*random_interface_.get_random_bytes)(buf, count, &nread); |
| 235 if (error) |
| 236 return error; |
220 | 237 |
221 errno = EBADF; | 238 *out_bytes = count; |
222 return 0; | 239 return 0; |
223 #elif defined(WIN32) | 240 #elif defined(WIN32) |
224 char* out = static_cast<char*>(buf); | 241 char* out = static_cast<char*>(buf); |
225 size_t bytes_left = count; | 242 size_t bytes_left = count; |
226 while (bytes_left) { | 243 while (bytes_left) { |
227 unsigned int random_int; | 244 unsigned int random_int; |
228 errno_t err = rand_s(&random_int); | 245 errno_t err = rand_s(&random_int); |
229 if (err) { | 246 if (err) { |
230 errno = err; | 247 *out_bytes = count - bytes_left; |
231 return count - bytes_left; | 248 return err; |
232 } | 249 } |
233 | 250 |
234 int bytes_to_copy = std::min(bytes_left, sizeof(random_int)); | 251 int bytes_to_copy = std::min(bytes_left, sizeof(random_int)); |
235 memcpy(out, &random_int, bytes_to_copy); | 252 memcpy(out, &random_int, bytes_to_copy); |
236 out += bytes_to_copy; | 253 out += bytes_to_copy; |
237 bytes_left -= bytes_to_copy; | 254 bytes_left -= bytes_to_copy; |
238 } | 255 } |
239 | 256 |
240 return count; | 257 *out_bytes = count; |
| 258 return 0; |
241 #endif | 259 #endif |
242 } | 260 } |
243 | 261 |
244 int UrandomNode::Write(size_t offs, const void* buf, size_t count) { | 262 Error UrandomNode::Write(size_t offs, |
245 return count; | 263 const void* buf, |
| 264 size_t count, |
| 265 int* out_bytes) { |
| 266 *out_bytes = count; |
| 267 return 0; |
246 } | 268 } |
247 | 269 |
248 | |
249 | |
250 } // namespace | 270 } // namespace |
251 | 271 |
252 MountNode *MountDev::Open(const Path& path, int mode) { | 272 Error MountDev::Open(const Path& path, int mode, MountNode** out_node) { |
| 273 *out_node = NULL; |
| 274 |
253 AutoLock lock(&lock_); | 275 AutoLock lock(&lock_); |
254 | 276 |
255 // Don't allow creating any files. | 277 // Don't allow creating any files. |
256 if (mode & O_CREAT) | 278 if (mode & O_CREAT) |
257 return NULL; | 279 return EINVAL; |
258 | 280 |
259 MountNode* node = root_->FindChild(path.Join()); | 281 MountNode* node = NULL; |
260 if (node) | 282 int error = root_->FindChild(path.Join(), &node); |
261 node->Acquire(); | 283 if (error) |
262 return node; | 284 return error; |
| 285 |
| 286 node->Acquire(); |
| 287 *out_node = node; |
| 288 return 0; |
263 } | 289 } |
264 | 290 |
265 int MountDev::Unlink(const Path& path) { | 291 Error MountDev::Unlink(const Path& path) { return EINVAL; } |
266 errno = EINVAL; | |
267 return -1; | |
268 } | |
269 | 292 |
270 int MountDev::Mkdir(const Path& path, int permissions) { | 293 Error MountDev::Mkdir(const Path& path, int permissions) { return EINVAL; } |
271 errno = EINVAL; | |
272 return -1; | |
273 } | |
274 | 294 |
275 int MountDev::Rmdir(const Path& path) { | 295 Error MountDev::Rmdir(const Path& path) { return EINVAL; } |
276 errno = EINVAL; | |
277 return -1; | |
278 } | |
279 | 296 |
280 int MountDev::Remove(const Path& path) { | 297 Error MountDev::Remove(const Path& path) { return EINVAL; } |
281 errno = EINVAL; | |
282 return -1; | |
283 } | |
284 | 298 |
285 MountDev::MountDev() | 299 MountDev::MountDev() {} |
286 : null_node_(NULL), | |
287 zero_node_(NULL), | |
288 random_node_(NULL), | |
289 console0_node_(NULL), | |
290 console1_node_(NULL), | |
291 console2_node_(NULL), | |
292 console3_node_(NULL), | |
293 tty_node_(NULL) { | |
294 } | |
295 | 300 |
296 bool MountDev::Init(int dev, StringMap_t& args, PepperInterface* ppapi) { | 301 #define INITIALIZE_DEV_NODE(path, klass) \ |
297 if (!Mount::Init(dev, args, ppapi)) | 302 error = root_->AddChild(path, new klass(this)); \ |
298 return false; | 303 if (error) \ |
| 304 return error; |
| 305 |
| 306 #define INITIALIZE_DEV_NODE_1(path, klass, arg) \ |
| 307 error = root_->AddChild(path, 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; |
299 | 315 |
300 root_ = new MountNodeDir(this); | 316 root_ = new MountNodeDir(this); |
301 null_node_ = new NullNode(this); | |
302 root_->AddChild("/null", null_node_); | |
303 zero_node_ = new ZeroNode(this); | |
304 root_->AddChild("/zero", zero_node_); | |
305 random_node_ = new UrandomNode(this); | |
306 root_->AddChild("/urandom", random_node_); | |
307 | 317 |
308 console0_node_ = new ConsoleNode(this, PP_LOGLEVEL_TIP); | 318 INITIALIZE_DEV_NODE("/null", NullNode); |
309 root_->AddChild("/console0", console0_node_); | 319 INITIALIZE_DEV_NODE("/zero", ZeroNode); |
310 console1_node_ = new ConsoleNode(this, PP_LOGLEVEL_LOG); | 320 INITIALIZE_DEV_NODE("/urandom", UrandomNode); |
311 root_->AddChild("/console1", console1_node_); | 321 INITIALIZE_DEV_NODE_1("/console0", ConsoleNode, PP_LOGLEVEL_TIP); |
312 console2_node_ = new ConsoleNode(this, PP_LOGLEVEL_WARNING); | 322 INITIALIZE_DEV_NODE_1("/console1", ConsoleNode, PP_LOGLEVEL_LOG); |
313 root_->AddChild("/console2", console2_node_); | 323 INITIALIZE_DEV_NODE_1("/console2", ConsoleNode, PP_LOGLEVEL_WARNING); |
314 console3_node_ = new ConsoleNode(this, PP_LOGLEVEL_ERROR); | 324 INITIALIZE_DEV_NODE_1("/console3", ConsoleNode, PP_LOGLEVEL_ERROR); |
315 root_->AddChild("/console3", console3_node_); | 325 INITIALIZE_DEV_NODE("/tty", TtyNode); |
| 326 INITIALIZE_DEV_NODE_1("/stdin", RealNode, 0); |
| 327 INITIALIZE_DEV_NODE_1("/stdout", RealNode, 1); |
| 328 INITIALIZE_DEV_NODE_1("/stderr", RealNode, 2); |
316 | 329 |
317 tty_node_ = new TtyNode(this); | 330 return 0; |
318 root_->AddChild("/tty", tty_node_); | |
319 | |
320 stdin_node_ = new RealNode(this, 0); | |
321 root_->AddChild("/stdin", stdin_node_); | |
322 stdout_node_ = new RealNode(this, 1); | |
323 root_->AddChild("/stdout", stdout_node_); | |
324 stderr_node_ = new RealNode(this, 2); | |
325 root_->AddChild("/stderr", stderr_node_); | |
326 | |
327 return true; | |
328 } | 331 } |
329 | 332 |
330 void MountDev::Destroy() { | 333 void MountDev::Destroy() { |
331 ReleaseAndNullNode(&stdin_node_); | 334 if (root_) |
332 ReleaseAndNullNode(&stdout_node_); | 335 root_->Release(); |
333 ReleaseAndNullNode(&stderr_node_); | 336 root_ = NULL; |
334 ReleaseAndNullNode(&tty_node_); | |
335 ReleaseAndNullNode(&console3_node_); | |
336 ReleaseAndNullNode(&console2_node_); | |
337 ReleaseAndNullNode(&console1_node_); | |
338 ReleaseAndNullNode(&console0_node_); | |
339 ReleaseAndNullNode(&random_node_); | |
340 ReleaseAndNullNode(&zero_node_); | |
341 ReleaseAndNullNode(&null_node_); | |
342 ReleaseAndNullNode(&root_); | |
343 } | 337 } |
OLD | NEW |