OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
| 6 #include "base/KernelProxy.h" |
6 #include <assert.h> | 7 #include <assert.h> |
| 8 #include <netinet/in.h> |
| 9 #include <sys/time.h> |
7 #include <list> | 10 #include <list> |
8 #include <utility> | 11 #include <utility> |
9 #include "../console/ConsoleMount.h" | 12 #include "console/ConsoleMount.h" |
10 #include "../dev/DevMount.h" | 13 #include "dev/DevMount.h" |
11 #include "KernelProxy.h" | |
12 #include "MountManager.h" | 14 #include "MountManager.h" |
| 15 #include "net/BaseSocketSubSystem.h" |
| 16 #include "net/SocketSubSystem.h" |
| 17 #include "util/DebugPrint.h" |
13 | 18 |
14 static pthread_once_t kp_once_ = PTHREAD_ONCE_INIT; | 19 static pthread_once_t kp_once_ = PTHREAD_ONCE_INIT; |
15 KernelProxy *KernelProxy::kp_instance_; | 20 KernelProxy *KernelProxy::kp_instance_; |
16 | 21 |
17 #ifndef MAXPATHLEN | 22 #ifndef MAXPATHLEN |
18 #define MAXPATHLEN 256 | 23 #define MAXPATHLEN 256 |
19 #endif | 24 #endif |
20 | 25 |
21 KernelProxy::KernelProxy() { | 26 KernelProxy::KernelProxy() { |
22 if (pthread_mutex_init(&kp_lock_, NULL)) assert(0); | 27 if (pthread_mutex_init(&kp_lock_, NULL)) assert(0); |
(...skipping 12 matching lines...) Expand all Loading... |
35 ret = mm_.AddMount(console_mount, "/dev/fd"); | 40 ret = mm_.AddMount(console_mount, "/dev/fd"); |
36 assert(ret == 0); | 41 assert(ret == 0); |
37 int fd = open("/dev/fd/0", O_CREAT | O_RDWR, 0); | 42 int fd = open("/dev/fd/0", O_CREAT | O_RDWR, 0); |
38 assert(fd == 0); | 43 assert(fd == 0); |
39 fd = open("/dev/fd/1", O_CREAT | O_RDWR, 0); | 44 fd = open("/dev/fd/1", O_CREAT | O_RDWR, 0); |
40 assert(fd == 1); | 45 assert(fd == 1); |
41 fd = open("/dev/fd/2", O_CREAT | O_RDWR, 0); | 46 fd = open("/dev/fd/2", O_CREAT | O_RDWR, 0); |
42 assert(fd == 2); | 47 assert(fd == 2); |
43 } | 48 } |
44 | 49 |
| 50 void KernelProxy::SetSocketSubSystem(BaseSocketSubSystem* bss) { |
| 51 ss = bss; |
| 52 } |
| 53 |
| 54 void KernelProxy::RemoveFileStream(int fd) { |
| 55 this->close(fd); |
| 56 } |
| 57 |
| 58 int KernelProxy::AddFileStream(FileStream* stream, int fd) { |
| 59 SimpleAutoLock lock(&kp_lock_); |
| 60 |
| 61 // Setup file handle. |
| 62 int handle_slot = open_files_.AllocAt(fd); |
| 63 if (fds_.AllocAt(fd) != fd) return -1; |
| 64 FileDescriptor* file = fds_.At(fd); |
| 65 file->handle = handle_slot; |
| 66 FileHandle* handle = open_files_.At(handle_slot); |
| 67 |
| 68 // init should be safe because we have the kernel proxy lock |
| 69 if (pthread_mutex_init(&handle->lock, NULL)) assert(0); |
| 70 |
| 71 handle->mount = (Mount*) NULL; |
| 72 handle->stream = (FileStream*) NULL; |
| 73 handle->use_count = 1; |
| 74 |
| 75 return fd; |
| 76 } |
| 77 |
| 78 int KernelProxy::AddFileStream(FileStream* stream) { |
| 79 SimpleAutoLock lock(&kp_lock_); |
| 80 |
| 81 // Setup file handle. |
| 82 int handle_slot = open_files_.Alloc(); |
| 83 int fd = fds_.Alloc(); |
| 84 FileDescriptor* file = fds_.At(fd); |
| 85 file->handle = handle_slot; |
| 86 FileHandle* handle = open_files_.At(handle_slot); |
| 87 |
| 88 // init should be safe because we have the kernel proxy lock |
| 89 if (pthread_mutex_init(&handle->lock, NULL)) assert(0); |
| 90 |
| 91 handle->mount = (Mount*) NULL; |
| 92 handle->stream = (FileStream*) NULL; |
| 93 handle->use_count = 1; |
| 94 |
| 95 return fd; |
| 96 } |
| 97 |
45 KernelProxy *KernelProxy::KPInstance() { | 98 KernelProxy *KernelProxy::KPInstance() { |
46 pthread_once(&kp_once_, Instantiate); | 99 pthread_once(&kp_once_, Instantiate); |
47 return kp_instance_; | 100 return kp_instance_; |
48 } | 101 } |
49 | 102 |
50 void KernelProxy::Instantiate() { | 103 void KernelProxy::Instantiate() { |
51 assert(!kp_instance_); | 104 assert(!kp_instance_); |
52 kp_instance_ = new KernelProxy(); | 105 kp_instance_ = new KernelProxy(); |
53 } | 106 } |
54 | 107 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 } | 223 } |
171 } | 224 } |
172 | 225 |
173 mount->Ref(st.st_ino); | 226 mount->Ref(st.st_ino); |
174 mount->Ref(); | 227 mount->Ref(); |
175 // Setup file handle. | 228 // Setup file handle. |
176 int handle_slot = open_files_.Alloc(); | 229 int handle_slot = open_files_.Alloc(); |
177 int fd = fds_.Alloc(); | 230 int fd = fds_.Alloc(); |
178 FileDescriptor* file = fds_.At(fd); | 231 FileDescriptor* file = fds_.At(fd); |
179 file->handle = handle_slot; | 232 file->handle = handle_slot; |
180 FileHandle *handle = open_files_.At(handle_slot); | 233 FileHandle* handle = open_files_.At(handle_slot); |
181 | 234 |
182 // init should be safe because we have the kernel proxy lock | 235 // init should be safe because we have the kernel proxy lock |
183 if (pthread_mutex_init(&handle->lock, NULL)) assert(0); | 236 if (pthread_mutex_init(&handle->lock, NULL)) assert(0); |
184 | 237 |
185 handle->mount = mount; | 238 handle->mount = mount; |
| 239 handle->stream = NULL; |
186 handle->node = st.st_ino; | 240 handle->node = st.st_ino; |
187 handle->flags = flags; | 241 handle->flags = flags; |
188 handle->use_count = 1; | 242 handle->use_count = 1; |
189 | 243 |
190 if (flags & O_APPEND) { | 244 if (flags & O_APPEND) { |
191 handle->offset = st.st_size; | 245 handle->offset = st.st_size; |
192 } else { | 246 } else { |
193 handle->offset = 0; | 247 handle->offset = 0; |
194 } | 248 } |
195 | 249 |
196 return fd; | 250 return fd; |
197 } | 251 } |
198 | 252 |
| 253 struct hostent* KernelProxy::gethostbyname(const char* name) { |
| 254 struct hostent *res = (struct hostent*) malloc(sizeof(struct hostent)); |
| 255 if (!res) return NULL; |
| 256 res->h_addr_list = (char**) malloc(sizeof(char*) * 2); |
| 257 if (!res->h_addr_list) return NULL; |
| 258 res->h_addr_list[0] = (char*) malloc(sizeof(long int)); |
| 259 if (!res->h_addr_list[0]) return NULL; |
| 260 *((long int*)res->h_addr_list[0]) = ss->gethostbyname(name); |
| 261 res->h_addr_list[1] = NULL; |
| 262 res->h_length = sizeof(long int); |
| 263 return res; |
| 264 } |
| 265 |
199 int KernelProxy::open(const std::string& path, int flags, mode_t mode) { | 266 int KernelProxy::open(const std::string& path, int flags, mode_t mode) { |
200 if (path.empty()) { | 267 if (path.empty()) { |
201 errno = EINVAL; | 268 errno = EINVAL; |
202 return -1; | 269 return -1; |
203 } | 270 } |
204 | 271 |
205 Path p(path); | 272 Path p(path); |
206 if (path[0] != '/') { | 273 if (path[0] != '/') { |
207 p = Path(cwd_.FormulatePath() + "/" + path); | 274 p = Path(cwd_.FormulatePath() + "/" + path); |
208 } | 275 } |
(...skipping 12 matching lines...) Expand all Loading... |
221 int KernelProxy::close(int fd) { | 288 int KernelProxy::close(int fd) { |
222 SimpleAutoLock lock(&kp_lock_); | 289 SimpleAutoLock lock(&kp_lock_); |
223 | 290 |
224 FileDescriptor* file = fds_.At(fd); | 291 FileDescriptor* file = fds_.At(fd); |
225 if (file == NULL) { | 292 if (file == NULL) { |
226 errno = EBADF; | 293 errno = EBADF; |
227 return -1; | 294 return -1; |
228 } | 295 } |
229 int h = file->handle; | 296 int h = file->handle; |
230 fds_.Free(fd); | 297 fds_.Free(fd); |
231 FileHandle *handle = open_files_.At(h); | 298 FileHandle* handle = open_files_.At(h); |
232 if (handle == NULL) { | 299 if (handle == NULL) { |
233 errno = EBADF; | 300 errno = EBADF; |
234 return -1; | 301 return -1; |
235 } | 302 } |
236 handle->use_count--; | 303 handle->use_count--; |
237 ino_t node = handle->node; | 304 ino_t node = handle->node; |
238 Mount *mount = handle->mount; | 305 if (handle->mount) { |
239 if (handle->use_count <= 0) { | 306 Mount* mount = handle->mount; |
240 open_files_.Free(h); | 307 if (handle->use_count <= 0) { |
241 mount->Unref(node); | 308 open_files_.Free(h); |
| 309 mount->Unref(node); |
| 310 } |
| 311 mount->Unref(); |
| 312 } else { |
| 313 ss->close(handle->stream); |
242 } | 314 } |
243 mount->Unref(); | |
244 return 0; | 315 return 0; |
245 } | 316 } |
246 | 317 |
247 ssize_t KernelProxy::read(int fd, void *buf, size_t count) { | 318 ssize_t KernelProxy::read(int fd, void *buf, size_t count) { |
248 FileHandle *handle; | 319 FileHandle* handle; |
249 // check if fd is valid and handle exists | 320 // check if fd is valid and handle exists |
250 if (!(handle = GetFileHandle(fd))) { | 321 if (!(handle = GetFileHandle(fd))) { |
251 errno = EBADF; | 322 errno = EBADF; |
252 return -1; | 323 return -1; |
253 } | 324 } |
254 | 325 |
255 SimpleAutoLock(&handle->lock); | 326 SimpleAutoLock(&handle->lock); |
256 | 327 |
257 // Check that this file handle can be read from. | 328 if (handle->mount) { |
258 if ((handle->flags & O_ACCMODE) == O_WRONLY || | 329 // Check that this file handle can be read from. |
259 is_dir(handle->mount, handle->node)) { | 330 if ((handle->flags & O_ACCMODE) == O_WRONLY || |
| 331 is_dir(handle->mount, handle->node)) { |
| 332 errno = EBADF; |
| 333 return -1; |
| 334 } |
| 335 |
| 336 ssize_t n = handle->mount->Read(handle->node, handle->offset, buf, count); |
| 337 if (n > 0) { |
| 338 handle->offset += n; |
| 339 } |
| 340 return n; |
| 341 } else if (handle->stream) { |
| 342 // TODO(vissi): more elaborate implementation |
| 343 return recv(fd, buf, count, 0); |
| 344 } else { |
260 errno = EBADF; | 345 errno = EBADF; |
261 return -1; | 346 return -1; |
262 } | 347 } |
263 | |
264 ssize_t n = handle->mount->Read(handle->node, handle->offset, buf, count); | |
265 if (n > 0) { | |
266 handle->offset += n; | |
267 } | |
268 return n; | |
269 } | 348 } |
270 | 349 |
271 ssize_t KernelProxy::write(int fd, const void *buf, size_t count) { | 350 ssize_t KernelProxy::write(int fd, const void *buf, size_t count) { |
272 FileHandle *handle; | 351 FileHandle* handle; |
273 | 352 |
274 // check if fd is valid and handle exists | 353 // check if fd is valid and handle exists |
275 if (!(handle = GetFileHandle(fd))) { | 354 if (!(handle = GetFileHandle(fd))) { |
276 errno = EBADF; | 355 errno = EBADF; |
277 return -1; | 356 return -1; |
278 } | 357 } |
279 | 358 |
280 SimpleAutoLock(&handle->lock); | 359 SimpleAutoLock(&handle->lock); |
281 | 360 |
282 // Check that this file handle can be written to. | 361 if (handle->mount) { |
283 if ((handle->flags & O_ACCMODE) == O_RDONLY || | 362 // Check that this file handle can be written to. |
284 is_dir(handle->mount, handle->node)) { | 363 if ((handle->flags & O_ACCMODE) == O_RDONLY || |
| 364 is_dir(handle->mount, handle->node)) { |
| 365 errno = EBADF; |
| 366 return -1; |
| 367 } |
| 368 |
| 369 ssize_t n = handle->mount->Write(handle->node, handle->offset, buf, count); |
| 370 |
| 371 if (n > 0) { |
| 372 handle->offset += n; |
| 373 } |
| 374 return n; |
| 375 } else if (handle->stream) { |
| 376 // TODO(vissi): more elaborate implementation |
| 377 return send(fd, buf, count, 0); |
| 378 } else { |
285 errno = EBADF; | 379 errno = EBADF; |
286 return -1; | 380 return -1; |
287 } | 381 } |
288 | |
289 ssize_t n = handle->mount->Write(handle->node, handle->offset, buf, count); | |
290 | |
291 if (n > 0) { | |
292 handle->offset += n; | |
293 } | |
294 return n; | |
295 } | 382 } |
296 | 383 |
297 int KernelProxy::fstat(int fd, struct stat *buf) { | 384 int KernelProxy::fstat(int fd, struct stat *buf) { |
298 FileHandle *handle; | 385 FileHandle* handle; |
299 | 386 |
300 // check if fd is valid and handle exists | 387 // check if fd is valid and handle exists |
301 if (!(handle = GetFileHandle(fd))) { | 388 if (!(handle = GetFileHandle(fd))) { |
302 errno = EBADF; | 389 errno = EBADF; |
303 return -1; | 390 return -1; |
304 } | 391 } |
305 SimpleAutoLock(&handle->lock); | 392 SimpleAutoLock(&handle->lock); |
306 return handle->mount->Stat(handle->node, buf); | 393 return handle->mount->Stat(handle->node, buf); |
307 } | 394 } |
308 | 395 |
309 int KernelProxy::ioctl(int fd, unsigned long request) { | 396 int KernelProxy::ioctl(int fd, unsigned long request) { |
310 errno = ENOSYS; | 397 errno = ENOSYS; |
311 fprintf(stderr, "ioctl has not been implemented!\n"); | 398 fprintf(stderr, "ioctl has not been implemented!\n"); |
312 assert(0); | 399 assert(0); |
313 return -1; | 400 return -1; |
314 } | 401 } |
315 | 402 |
316 int KernelProxy::kill(pid_t pid, int sig) { | 403 int KernelProxy::kill(pid_t pid, int sig) { |
317 errno = ENOSYS; | 404 errno = ENOSYS; |
318 fprintf(stderr, "kill has not been implemented!\n"); | 405 fprintf(stderr, "kill has not been implemented!\n"); |
319 assert(0); | 406 assert(0); |
320 return -1; | 407 return -1; |
321 } | 408 } |
322 | 409 |
323 int KernelProxy::getdents(int fd, void *buf, unsigned int count) { | 410 int KernelProxy::getdents(int fd, void *buf, unsigned int count) { |
324 FileHandle *handle; | 411 FileHandle* handle; |
325 | 412 |
326 // check if fd is valid and handle exists | 413 // check if fd is valid and handle exists |
327 if (!(handle = GetFileHandle(fd))) { | 414 if (!(handle = GetFileHandle(fd))) { |
328 errno = EBADF; | 415 errno = EBADF; |
329 return -1; | 416 return -1; |
330 } | 417 } |
331 | 418 |
332 SimpleAutoLock(&handle->lock); | 419 SimpleAutoLock(&handle->lock); |
333 | 420 |
334 int ret = handle->mount->Getdents(handle->node, handle->offset, | 421 int ret = handle->mount->Getdents(handle->node, handle->offset, |
335 (struct dirent*)buf, count); | 422 (struct dirent*)buf, count); |
336 | 423 |
337 if (ret != -1) { | 424 if (ret != -1) { |
338 // TODO(bradnelson): think of a better interface for Mount::Getdents. | 425 // TODO(bradnelson): think of a better interface for Mount::Getdents. |
339 // http://code.google.com/p/naclports/issues/detail?id=18 | 426 // http://code.google.com/p/naclports/issues/detail?id=18 |
340 handle->offset += ret / sizeof(struct dirent); | 427 handle->offset += ret / sizeof(struct dirent); |
341 } | 428 } |
342 return ret; | 429 return ret; |
343 } | 430 } |
344 | 431 |
345 int KernelProxy::fsync(int fd) { | 432 int KernelProxy::fsync(int fd) { |
346 FileHandle *handle; | 433 FileHandle* handle; |
347 | 434 |
348 if (!(handle = GetFileHandle(fd))) { | 435 if (!(handle = GetFileHandle(fd))) { |
349 errno = EBADF; | 436 errno = EBADF; |
350 return -1; | 437 return -1; |
351 } | 438 } |
352 SimpleAutoLock(&handle->lock); | 439 SimpleAutoLock(&handle->lock); |
353 return handle->mount->Fsync(handle->node); | 440 return handle->mount->Fsync(handle->node); |
354 } | 441 } |
355 | 442 |
356 int KernelProxy::isatty(int fd) { | 443 int KernelProxy::isatty(int fd) { |
357 FileHandle *handle; | 444 FileHandle* handle; |
358 | 445 |
359 if (!(handle = GetFileHandle(fd))) { | 446 if (!(handle = GetFileHandle(fd))) { |
360 errno = EBADF; | 447 errno = EBADF; |
361 return 0; | 448 return 0; |
362 } | 449 } |
363 SimpleAutoLock(&handle->lock); | |
364 return handle->mount->Isatty(handle->node); | 450 return handle->mount->Isatty(handle->node); |
365 } | 451 } |
366 | 452 |
| 453 int KernelProxy::dup2(int fd, int newfd) { |
| 454 FileStream* stream = GetFileHandle(fd) > 0 |
| 455 ? GetFileHandle(fd)->stream : NULL; |
| 456 if (!stream) |
| 457 return EBADF; |
| 458 |
| 459 AddFileStream(stream, newfd); |
| 460 return 0; |
| 461 } |
| 462 |
| 463 int KernelProxy::IsReady(int nfds, fd_set* fds, |
| 464 bool (FileStream::*is_ready)(), bool apply) { |
| 465 if (!fds) |
| 466 return 0; |
| 467 |
| 468 int nset = 0; |
| 469 for (int i = 0; i < nfds; i++) { |
| 470 if (FD_ISSET(i, fds)) { |
| 471 FileStream* stream = GetFileHandle(i) > 0 ? |
| 472 GetFileHandle(i)->stream : NULL; |
| 473 if (!stream) |
| 474 return -1; |
| 475 if ((stream->*is_ready)()) { |
| 476 if (!apply) |
| 477 return 1; |
| 478 else |
| 479 nset++; |
| 480 } else { |
| 481 if (apply) |
| 482 FD_CLR(i, fds); |
| 483 } |
| 484 } |
| 485 } |
| 486 return nset; |
| 487 } |
| 488 |
367 int KernelProxy::dup(int oldfd) { | 489 int KernelProxy::dup(int oldfd) { |
368 SimpleAutoLock lock(&kp_lock_); | 490 SimpleAutoLock lock(&kp_lock_); |
369 | 491 |
| 492 FileHandle* fh = GetFileHandle(oldfd); |
| 493 if (!fh) { |
| 494 errno = EBADF; |
| 495 return -1; |
| 496 } |
| 497 if (fh->mount == NULL) { |
| 498 FileStream* stream = GetFileHandle(oldfd) > 0 |
| 499 ? GetFileHandle(oldfd)->stream : NULL; |
| 500 if (!stream) |
| 501 return EBADF; |
| 502 int new_fd = AddFileStream(stream); |
| 503 return new_fd; |
| 504 } |
370 FileDescriptor* oldfile = fds_.At(oldfd); | 505 FileDescriptor* oldfile = fds_.At(oldfd); |
371 if (oldfile == NULL) { | 506 if (oldfile == NULL) { |
372 errno = EBADF; | 507 errno = EBADF; |
373 return -1; | 508 return -1; |
374 } | 509 } |
375 int newfd = fds_.Alloc(); | 510 int newfd = fds_.Alloc(); |
376 FileDescriptor *newfile = fds_.At(newfd); | 511 FileDescriptor *newfile = fds_.At(newfd); |
377 int h = oldfile->handle; | 512 int h = oldfile->handle; |
378 newfile->handle = h; | 513 newfile->handle = h; |
379 FileHandle *handle = open_files_.At(h); | 514 FileHandle* handle = open_files_.At(h); |
380 // init should be safe because we have the kernel proxy lock | 515 // init should be safe because we have the kernel proxy lock |
381 if (pthread_mutex_init(&handle->lock, NULL)) assert(0); | 516 if (pthread_mutex_init(&handle->lock, NULL)) assert(0); |
382 | 517 |
383 if (handle == NULL) { | 518 if (handle == NULL) { |
384 errno = EBADF; | 519 errno = EBADF; |
385 return -1; | 520 return -1; |
386 } | 521 } |
387 ++handle->use_count; | 522 ++handle->use_count; |
388 handle->mount->Ref(handle->node); | 523 handle->mount->Ref(handle->node); |
389 handle->mount->Ref(); | 524 handle->mount->Ref(); |
390 return newfd; | 525 return newfd; |
391 } | 526 } |
392 | 527 |
393 off_t KernelProxy::lseek(int fd, off_t offset, int whence) { | 528 off_t KernelProxy::lseek(int fd, off_t offset, int whence) { |
394 FileHandle *handle; | 529 FileHandle* handle; |
395 // check if fd is valid and handle exists | 530 // check if fd is valid and handle exists |
396 if (!(handle = GetFileHandle(fd))) { | 531 if (!(handle = GetFileHandle(fd))) { |
397 errno = EBADF; | 532 errno = EBADF; |
398 return -1; | 533 return -1; |
399 } | 534 } |
400 | 535 |
401 SimpleAutoLock(&handle->lock); | 536 SimpleAutoLock(&handle->lock); |
402 | 537 |
403 off_t next; | 538 off_t next; |
404 ssize_t len; | 539 ssize_t len; |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 ((amode & X_OK) && !(mode & X_OK))) { | 746 ((amode & X_OK) && !(mode & X_OK))) { |
612 errno = EACCES; | 747 errno = EACCES; |
613 return -1; | 748 return -1; |
614 } | 749 } |
615 } | 750 } |
616 // By now we have checked access permissions for | 751 // By now we have checked access permissions for |
617 // each component of the path. | 752 // each component of the path. |
618 return 0; | 753 return 0; |
619 } | 754 } |
620 | 755 |
621 KernelProxy::FileHandle *KernelProxy::GetFileHandle(int fd) { | 756 KernelProxy::FileHandle* KernelProxy::GetFileHandle(int fd) { |
622 SimpleAutoLock lock(&kp_lock_); | 757 SimpleAutoLock lock(&kp_lock_); |
623 FileDescriptor *file = fds_.At(fd); | 758 FileDescriptor *file = fds_.At(fd); |
624 if (!file) { | 759 if (!file) { |
625 return NULL; | 760 return NULL; |
626 } | 761 } |
627 return open_files_.At(file->handle); | 762 return open_files_.At(file->handle); |
628 } | 763 } |
629 | 764 |
630 int KernelProxy::mkdir(const std::string& path, mode_t mode) { | 765 int KernelProxy::mkdir(const std::string& path, mode_t mode) { |
631 if (path.empty()) { | 766 if (path.empty()) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 if (mm_.InMountRootPath(abs_path)) { | 804 if (mm_.InMountRootPath(abs_path)) { |
670 errno = EBUSY; | 805 errno = EBUSY; |
671 return -1; | 806 return -1; |
672 } | 807 } |
673 | 808 |
674 return mount->Rmdir(buf.st_ino); | 809 return mount->Rmdir(buf.st_ino); |
675 } | 810 } |
676 | 811 |
677 #ifdef __GLIBC__ | 812 #ifdef __GLIBC__ |
678 int KernelProxy::socket(int domain, int type, int protocol) { | 813 int KernelProxy::socket(int domain, int type, int protocol) { |
679 errno = ENOSYS; | 814 SimpleAutoLock lock(&kp_lock_); |
680 fprintf(stderr, "socket has not been implemented!\n"); | 815 int handle_slot = open_files_.Alloc(); |
681 return -1; | 816 int fd = fds_.Alloc(); |
| 817 FileDescriptor* file = fds_.At(fd); |
| 818 file->handle = handle_slot; |
| 819 FileHandle* handle = open_files_.At(handle_slot); |
| 820 // this means it is a socket (not a mount handle) and it's implementation |
| 821 // determined by handle->stream type is defined later |
| 822 handle->mount = NULL; |
| 823 handle->stream = NULL; |
| 824 handle->use_count = 1; |
| 825 return fd; |
682 } | 826 } |
683 | 827 |
684 int KernelProxy::accept(int sockfd, struct sockaddr *addr, | 828 int KernelProxy::accept(int sockfd, struct sockaddr *addr, |
685 socklen_t* addrlen) { | 829 socklen_t* addrlen) { |
686 errno = ENOSYS; | 830 if (GetFileHandle(sockfd) == 0) return EBADF; |
687 fprintf(stderr, "accept has not been implemented!\n"); | 831 FileStream* ret = ss->accept(GetFileHandle(sockfd)->stream, addr, addrlen); |
688 return -1; | 832 if (!ret) |
| 833 return AddFileStream(ret); |
| 834 else |
| 835 return -1; |
689 } | 836 } |
690 | 837 |
691 int KernelProxy::bind(int sockfd, const struct sockaddr *addr, | 838 int KernelProxy::bind(int sockfd, const struct sockaddr *addr, |
692 socklen_t addrlen) { | 839 socklen_t addrlen) { |
693 errno = ENOSYS; | 840 if (GetFileHandle(sockfd) == 0) return EBADF; |
694 fprintf(stderr, "bind has not been implemented!\n"); | 841 struct sockaddr_in* in_addr = (struct sockaddr_in*)addr; |
695 return -1; | 842 return ss->bind(&(GetFileHandle(sockfd)->stream), in_addr->sin_addr.s_addr, |
| 843 (unsigned short) ntohs(in_addr->sin_port)); |
696 } | 844 } |
697 | 845 |
698 int KernelProxy::listen(int sockfd, int backlog) { | 846 int KernelProxy::listen(int sockfd, int backlog) { |
699 errno = ENOSYS; | 847 if (GetFileHandle(sockfd) == 0) return EBADF; |
700 fprintf(stderr, "listen has not been implemented!\n"); | 848 return ss->listen(GetFileHandle(sockfd)->stream, backlog); |
701 return -1; | |
702 } | 849 } |
703 | 850 |
704 int KernelProxy::connect(int sockfd, const struct sockaddr *addr, | 851 int KernelProxy::connect(int sockfd, const struct sockaddr *addr, |
705 socklen_t addrlen) { | 852 socklen_t addrlen) { |
706 errno = ENOSYS; | 853 if (GetFileHandle(sockfd) == 0) return EBADF; |
707 fprintf(stderr, "connect has not been implemented!\n"); | 854 struct sockaddr_in* in_addr = (struct sockaddr_in*)addr; |
708 return -1; | 855 return ss->connect(&(GetFileHandle(sockfd)->stream), in_addr->sin_addr.s_addr, |
| 856 (unsigned short) ntohs(in_addr->sin_port)); |
709 } | 857 } |
710 | 858 |
711 int KernelProxy::send(int sockfd, const void *buf, size_t len, int flags) { | 859 int KernelProxy::send(int sockfd, const void *buf, size_t len, int flags) { |
712 errno = ENOSYS; | 860 size_t nwr; |
713 fprintf(stderr, "send has not been implemented!\n"); | 861 if (GetFileHandle(sockfd) == 0) return EBADF; |
714 return -1; | 862 ss->write(GetFileHandle(sockfd)->stream, (const char*)buf, len, &nwr); |
| 863 return nwr; |
715 } | 864 } |
716 | 865 |
717 int KernelProxy::sendmsg(int sockfd, const struct msghdr *msg, int flags) { | 866 int KernelProxy::sendmsg(int sockfd, const struct msghdr *msg, int flags) { |
718 errno = ENOSYS; | 867 errno = ENOSYS; |
719 fprintf(stderr, "sendmsg has not been implemented!\n"); | 868 fprintf(stderr, "sendmsg has not been implemented!\n"); |
720 return -1; | 869 return -1; |
721 } | 870 } |
722 | 871 |
723 int KernelProxy::sendto(int sockfd, const void *buf, size_t len, int flags, | 872 int KernelProxy::sendto(int sockfd, const void *buf, size_t len, int flags, |
724 const struct sockaddr *dest_addr, socklen_t addrlen) { | 873 const struct sockaddr *dest_addr, socklen_t addrlen) { |
725 errno = ENOSYS; | 874 errno = ENOSYS; |
726 fprintf(stderr, "sendto has not been implemented!\n"); | 875 fprintf(stderr, "sendto has not been implemented!\n"); |
727 return -1; | 876 return -1; |
728 } | 877 } |
729 | 878 |
730 int KernelProxy::recv(int sockfd, void *buf, size_t len, int flags) { | 879 int KernelProxy::recv(int sockfd, void *buf, size_t len, int flags) { |
731 errno = ENOSYS; | 880 size_t nread; |
732 fprintf(stderr, "recv has not been implemented!\n"); | 881 if (GetFileHandle(sockfd) == 0) return EBADF; |
733 return -1; | 882 ss->read(GetFileHandle(sockfd)->stream, |
| 883 reinterpret_cast<char*>(buf), len, &nread); |
| 884 return nread; |
734 } | 885 } |
735 | 886 |
736 int KernelProxy::recvmsg(int sockfd, struct msghdr *msg, int flags) { | 887 int KernelProxy::recvmsg(int sockfd, struct msghdr *msg, int flags) { |
737 errno = ENOSYS; | 888 errno = ENOSYS; |
738 fprintf(stderr, "recvmsg has not been implemented!\n"); | 889 fprintf(stderr, "recvmsg has not been implemented!\n"); |
739 return -1; | 890 return -1; |
740 } | 891 } |
741 | 892 |
742 int KernelProxy::recvfrom(int sockfd, void *buf, size_t len, int flags, | 893 int KernelProxy::recvfrom(int sockfd, void *buf, size_t len, int flags, |
743 struct sockaddr *dest_addr, socklen_t* addrlen) { | 894 struct sockaddr *dest_addr, socklen_t* addrlen) { |
744 errno = ENOSYS; | 895 errno = ENOSYS; |
745 fprintf(stderr, "recvfrom has not been implemented!\n"); | 896 fprintf(stderr, "recvfrom has not been implemented!\n"); |
746 return -1; | 897 return -1; |
747 } | 898 } |
748 | 899 |
749 int KernelProxy::select(int nfds, fd_set *readfds, fd_set *writefds, | 900 int KernelProxy::select(int nfds, fd_set *readfds, fd_set *writefds, |
750 fd_set* exceptfds, const struct timeval *timeout) { | 901 fd_set* exceptfds, const struct timeval *timeout) { |
751 errno = ENOSYS; | 902 Mutex::Lock lock(mutex()); |
752 fprintf(stderr, "select has not been implemented!\n"); | 903 |
753 return -1; | 904 timespec ts_abs; |
| 905 if (timeout) { |
| 906 timespec ts; |
| 907 TIMEVAL_TO_TIMESPEC(timeout, &ts); |
| 908 timeval tv_now; |
| 909 gettimeofday(&tv_now, NULL); |
| 910 int64_t current_time_us = |
| 911 tv_now.tv_sec * kMicrosecondsPerSecond + tv_now.tv_usec; |
| 912 int64_t wakeup_time_us = |
| 913 current_time_us + |
| 914 timeout->tv_sec * kMicrosecondsPerSecond + timeout->tv_usec; |
| 915 ts_abs.tv_sec = wakeup_time_us / kMicrosecondsPerSecond; |
| 916 ts_abs.tv_nsec = |
| 917 (wakeup_time_us - ts_abs.tv_sec * kMicrosecondsPerSecond) * |
| 918 kNanosecondsPerMicrosecond; |
| 919 } |
| 920 |
| 921 while (!(IsReady(nfds, readfds, &FileStream::is_read_ready, false) || |
| 922 IsReady(nfds, writefds, &FileStream::is_write_ready, false) || |
| 923 IsReady(nfds, exceptfds, &FileStream::is_exception, false))) { |
| 924 if (timeout) { |
| 925 if (!timeout->tv_sec && !timeout->tv_usec) |
| 926 break; |
| 927 |
| 928 if (cond().timedwait(mutex(), &ts_abs)) { |
| 929 if (errno == ETIMEDOUT) |
| 930 break; |
| 931 else |
| 932 return -1; |
| 933 } |
| 934 } else { |
| 935 cond().wait(mutex()); |
| 936 } |
| 937 } |
| 938 |
| 939 int nread = IsReady(nfds, readfds, &FileStream::is_read_ready, true); |
| 940 int nwrite = IsReady(nfds, writefds, &FileStream::is_write_ready, true); |
| 941 int nexcpt = IsReady(nfds, exceptfds, &FileStream::is_exception, true); |
| 942 if (nread < 0 || nwrite < 0 || nexcpt < 0) { |
| 943 errno = EBADF; |
| 944 return -1; |
| 945 } |
| 946 return nread + nwrite + nexcpt; |
754 } | 947 } |
755 | 948 |
756 int KernelProxy::pselect(int nfds, fd_set *readfds, fd_set *writefds, | 949 int KernelProxy::pselect(int nfds, fd_set *readfds, fd_set *writefds, |
757 fd_set* exceptfds, const struct timeval *timeout, void* sigmask) { | 950 fd_set* exceptfds, const struct timeval *timeout, void* sigmask) { |
758 errno = ENOSYS; | 951 errno = ENOSYS; |
759 fprintf(stderr, "pselect has not been implemented!\n"); | 952 fprintf(stderr, "pselect has not been implemented!\n"); |
760 return -1; | 953 return -1; |
761 } | 954 } |
762 | 955 |
763 int KernelProxy::getpeername(int sockfd, struct sockaddr *addr, | 956 int KernelProxy::getpeername(int sockfd, struct sockaddr *addr, |
(...skipping 18 matching lines...) Expand all Loading... |
782 } | 975 } |
783 | 976 |
784 int KernelProxy::setsockopt(int sockfd, int level, int optname, | 977 int KernelProxy::setsockopt(int sockfd, int level, int optname, |
785 const void *optval, socklen_t optlen) { | 978 const void *optval, socklen_t optlen) { |
786 errno = ENOSYS; | 979 errno = ENOSYS; |
787 fprintf(stderr, "setsockopt has not been implemented!\n"); | 980 fprintf(stderr, "setsockopt has not been implemented!\n"); |
788 return -1; | 981 return -1; |
789 } | 982 } |
790 | 983 |
791 int KernelProxy::shutdown(int sockfd, int how) { | 984 int KernelProxy::shutdown(int sockfd, int how) { |
792 errno = ENOSYS; | 985 if (GetFileHandle(sockfd) == 0) return EBADF; |
793 fprintf(stderr, "shutdown has not been implemented!\n"); | 986 return ss->shutdown(GetFileHandle(sockfd)->stream, how); |
794 return -1; | |
795 } | 987 } |
796 | 988 |
797 int KernelProxy::epoll_create(int size) { | 989 int KernelProxy::epoll_create(int size) { |
798 errno = ENOSYS; | 990 errno = ENOSYS; |
799 fprintf(stderr, "epoll_create has not been implemented!\n"); | 991 fprintf(stderr, "epoll_create has not been implemented!\n"); |
800 return -1; | 992 return -1; |
801 } | 993 } |
802 | 994 |
803 int KernelProxy::epoll_create1(int flags) { | 995 int KernelProxy::epoll_create1(int flags) { |
804 errno = ENOSYS; | 996 errno = ENOSYS; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
841 | 1033 |
842 int KernelProxy::ppoll(struct pollfd *fds, nfds_t nfds, | 1034 int KernelProxy::ppoll(struct pollfd *fds, nfds_t nfds, |
843 const struct timespec *timeout, | 1035 const struct timespec *timeout, |
844 const sigset_t *sigmask, size_t sigset_size) { | 1036 const sigset_t *sigmask, size_t sigset_size) { |
845 errno = ENOSYS; | 1037 errno = ENOSYS; |
846 fprintf(stderr, "ppoll has not been implemented!\n"); | 1038 fprintf(stderr, "ppoll has not been implemented!\n"); |
847 return -1; | 1039 return -1; |
848 } | 1040 } |
849 #endif | 1041 #endif |
850 | 1042 |
OLD | NEW |