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 #include "nacl_io/kernel_proxy.h" 6 7 #include <assert.h> 8 #include <errno.h> 9 #include <fcntl.h> 10 #include <limits.h> 11 #include <poll.h> 12 #include <pthread.h> 13 #include <stdio.h> 14 #include <string.h> 15 #include <sys/time.h> 16 #include <unistd.h> 17 18 #include <iterator> 19 #include <string> 20 21 #include "nacl_io/devfs/dev_fs.h" 22 #include "nacl_io/filesystem.h" 23 #include "nacl_io/fusefs/fuse_fs_factory.h" 24 #include "nacl_io/host_resolver.h" 25 #include "nacl_io/html5fs/html5_fs.h" 26 #include "nacl_io/httpfs/http_fs.h" 27 #include "nacl_io/kernel_handle.h" 28 #include "nacl_io/kernel_wrap_real.h" 29 #include "nacl_io/log.h" 30 #include "nacl_io/memfs/mem_fs.h" 31 #include "nacl_io/node.h" 32 #include "nacl_io/osmman.h" 33 #include "nacl_io/ossocket.h" 34 #include "nacl_io/osstat.h" 35 #include "nacl_io/passthroughfs/passthrough_fs.h" 36 #include "nacl_io/path.h" 37 #include "nacl_io/pepper_interface.h" 38 #include "nacl_io/pipe/pipe_node.h" 39 #include "nacl_io/socket/tcp_node.h" 40 #include "nacl_io/socket/udp_node.h" 41 #include "nacl_io/stream/stream_fs.h" 42 #include "nacl_io/typed_fs_factory.h" 43 #include "sdk_util/auto_lock.h" 44 #include "sdk_util/ref_object.h" 45 #include "sdk_util/string_util.h" 46 47 #ifndef MAXPATHLEN 48 #define MAXPATHLEN 256 49 #endif 50 51 namespace nacl_io { 52 53 KernelProxy::KernelProxy() 54 : dev_(0), 55 ppapi_(NULL), 56 exit_callback_(NULL), 57 exit_callback_user_data_(NULL), 58 mount_callback_(NULL), 59 mount_callback_user_data_(NULL), 60 signal_emitter_(new EventEmitter) { 61 memset(&sigwinch_handler_, 0, sizeof(sigwinch_handler_)); 62 sigwinch_handler_.sa_handler = SIG_DFL; 63 } 64 65 KernelProxy::~KernelProxy() { 66 // Clean up the FsFactories. 67 for (FsFactoryMap_t::iterator i = factories_.begin(); i != factories_.end(); 68 ++i) { 69 delete i->second; 70 } 71 } 72 73 Error KernelProxy::Init(PepperInterface* ppapi) { 74 Error rtn = 0; 75 ppapi_ = ppapi; 76 dev_ = 1; 77 78 factories_["memfs"] = new TypedFsFactory<MemFs>; 79 factories_["dev"] = new TypedFsFactory<DevFs>; 80 factories_["html5fs"] = new TypedFsFactory<Html5Fs>; 81 factories_["httpfs"] = new TypedFsFactory<HttpFs>; 82 factories_["passthroughfs"] = new TypedFsFactory<PassthroughFs>; 83 84 ScopedFilesystem root_fs; 85 rtn = MountInternal("", "/", "passthroughfs", 0, NULL, false, &root_fs); 86 if (rtn != 0) 87 assert(false); 88 89 ScopedFilesystem fs; 90 rtn = MountInternal("", "/dev", "dev", 0, NULL, false, &fs); 91 if (rtn != 0) 92 assert(false); 93 dev_fs_ = sdk_util::static_scoped_ref_cast<DevFs>(fs); 94 95 // Create the filesystem nodes for / and /dev afterward. They can't be 96 // created the normal way because the dev filesystem didn't exist yet. 97 rtn = CreateFsNode(root_fs); 98 if (rtn != 0) 99 assert(false); 100 101 rtn = CreateFsNode(dev_fs_); 102 if (rtn != 0) 103 assert(false); 104 105 // Open the first three in order to get STDIN, STDOUT, STDERR 106 int fd; 107 fd = open("/dev/stdin", O_RDONLY, 0); 108 assert(fd == 0); 109 if (fd < 0) 110 rtn = errno; 111 112 fd = open("/dev/stdout", O_WRONLY, 0); 113 assert(fd == 1); 114 if (fd < 0) 115 rtn = errno; 116 117 fd = open("/dev/stderr", O_WRONLY, 0); 118 assert(fd == 2); 119 if (fd < 0) 120 rtn = errno; 121 122 #ifdef PROVIDES_SOCKET_API 123 host_resolver_.Init(ppapi_); 124 #endif 125 126 FsInitArgs args; 127 args.dev = dev_++; 128 args.ppapi = ppapi_; 129 stream_fs_.reset(new StreamFs()); 130 int result = stream_fs_->Init(args); 131 if (result != 0) { 132 assert(false); 133 rtn = result; 134 } 135 136 return rtn; 137 } 138 139 bool KernelProxy::RegisterFsType(const char* fs_type, 140 fuse_operations* fuse_ops) { 141 FsFactoryMap_t::iterator iter = factories_.find(fs_type); 142 if (iter != factories_.end()) 143 return false; 144 145 factories_[fs_type] = new FuseFsFactory(fuse_ops); 146 return true; 147 } 148 149 bool KernelProxy::UnregisterFsType(const char* fs_type) { 150 FsFactoryMap_t::iterator iter = factories_.find(fs_type); 151 if (iter == factories_.end()) 152 return false; 153 154 delete iter->second; 155 factories_.erase(iter); 156 return true; 157 } 158 159 void KernelProxy::SetExitCallback(nacl_io_exit_callback_t exit_callback, 160 void* user_data) { 161 exit_callback_ = exit_callback; 162 exit_callback_user_data_ = user_data; 163 } 164 165 void KernelProxy::SetMountCallback(nacl_io_mount_callback_t mount_callback, 166 void* user_data) { 167 mount_callback_ = mount_callback; 168 mount_callback_user_data_ = user_data; 169 } 170 171 int KernelProxy::open_resource(const char* path) { 172 ScopedFilesystem fs; 173 Path rel; 174 175 Error error = AcquireFsAndRelPath(path, &fs, &rel); 176 if (error) { 177 errno = error; 178 return -1; 179 } 180 181 ScopedNode node; 182 error = fs->OpenResource(rel, &node); 183 if (error) { 184 // OpenResource failed, try Open(). 185 error = fs->Open(rel, O_RDONLY, &node); 186 if (error) { 187 errno = error; 188 return -1; 189 } 190 } 191 192 ScopedKernelHandle handle(new KernelHandle(fs, node)); 193 error = handle->Init(O_RDONLY); 194 if (error) { 195 errno = error; 196 return -1; 197 } 198 199 return AllocateFD(handle, path); 200 } 201 202 int KernelProxy::open(const char* path, int open_flags, mode_t mode) { 203 ScopedFilesystem fs; 204 ScopedNode node; 205 206 Error error = AcquireFsAndNode(path, open_flags, mode, &fs, &node); 207 if (error) { 208 errno = error; 209 return -1; 210 } 211 212 ScopedKernelHandle handle(new KernelHandle(fs, node)); 213 error = handle->Init(open_flags); 214 if (error) { 215 errno = error; 216 return -1; 217 } 218 219 return AllocateFD(handle, path); 220 } 221 222 int KernelProxy::pipe(int pipefds[2]) { 223 PipeNode* pipe = new PipeNode(stream_fs_.get()); 224 ScopedNode node(pipe); 225 226 if (pipe->Init(O_RDWR) == 0) { 227 ScopedKernelHandle handle0(new KernelHandle(stream_fs_, node)); 228 ScopedKernelHandle handle1(new KernelHandle(stream_fs_, node)); 229 230 // Should never fail, but... 231 if (handle0->Init(O_RDONLY) || handle1->Init(O_WRONLY)) { 232 errno = EACCES; 233 return -1; 234 } 235 236 pipefds[0] = AllocateFD(handle0); 237 pipefds[1] = AllocateFD(handle1); 238 return 0; 239 } 240 241 errno = ENOSYS; 242 return -1; 243 } 244 245 int KernelProxy::close(int fd) { 246 ScopedKernelHandle handle; 247 Error error = AcquireHandle(fd, &handle); 248 if (error) { 249 errno = error; 250 return -1; 251 } 252 253 // Remove the FD from the process open file descriptor map 254 FreeFD(fd); 255 return 0; 256 } 257 258 int KernelProxy::dup(int oldfd) { 259 ScopedKernelHandle handle; 260 std::string path; 261 Error error = AcquireHandleAndPath(oldfd, &handle, &path); 262 if (error) { 263 errno = error; 264 return -1; 265 } 266 return AllocateFD(handle, path); 267 } 268 269 int KernelProxy::dup2(int oldfd, int newfd) { 270 // If it's the same file handle, just return 271 if (oldfd == newfd) 272 return newfd; 273 274 ScopedKernelHandle old_handle; 275 std::string old_path; 276 Error error = AcquireHandleAndPath(oldfd, &old_handle, &old_path); 277 if (error) { 278 errno = error; 279 return -1; 280 } 281 282 FreeAndReassignFD(newfd, old_handle, old_path); 283 return newfd; 284 } 285 286 int KernelProxy::chdir(const char* path) { 287 Error error = SetCWD(path); 288 if (error) { 289 errno = error; 290 return -1; 291 } 292 return 0; 293 } 294 295 void KernelProxy::exit(int status) { 296 if (exit_callback_) 297 exit_callback_(status, exit_callback_user_data_); 298 } 299 300 char* KernelProxy::getcwd(char* buf, size_t size) { 301 if (NULL == buf) { 302 errno = EFAULT; 303 return NULL; 304 } 305 306 std::string cwd = GetCWD(); 307 308 // Verify the buffer is large enough 309 if (size <= cwd.size()) { 310 errno = ERANGE; 311 return NULL; 312 } 313 314 strcpy(buf, cwd.c_str()); 315 return buf; 316 } 317 318 char* KernelProxy::getwd(char* buf) { 319 if (NULL == buf) { 320 errno = EFAULT; 321 return NULL; 322 } 323 return getcwd(buf, MAXPATHLEN); 324 } 325 326 int KernelProxy::chmod(const char* path, mode_t mode) { 327 int fd = open(path, O_RDONLY, mode); 328 if (-1 == fd) 329 return -1; 330 331 int result = fchmod(fd, mode); 332 close(fd); 333 return result; 334 } 335 336 int KernelProxy::chown(const char* path, uid_t owner, gid_t group) { 337 return 0; 338 } 339 340 int KernelProxy::fchown(int fd, uid_t owner, gid_t group) { 341 return 0; 342 } 343 344 int KernelProxy::lchown(const char* path, uid_t owner, gid_t group) { 345 return 0; 346 } 347 348 int KernelProxy::mkdir(const char* path, mode_t mode) { 349 ScopedFilesystem fs; 350 Path rel; 351 352 Error error = AcquireFsAndRelPath(path, &fs, &rel); 353 if (error) { 354 errno = error; 355 return -1; 356 } 357 358 error = fs->Mkdir(rel, mode); 359 if (error) { 360 errno = error; 361 return -1; 362 } 363 364 return 0; 365 } 366 367 int KernelProxy::rmdir(const char* path) { 368 ScopedFilesystem fs; 369 Path rel; 370 371 Error error = AcquireFsAndRelPath(path, &fs, &rel); 372 if (error) { 373 errno = error; 374 return -1; 375 } 376 377 error = fs->Rmdir(rel); 378 if (error) { 379 errno = error; 380 return -1; 381 } 382 383 return 0; 384 } 385 386 int KernelProxy::stat(const char* path, struct stat* buf) { 387 int fd = open(path, O_RDONLY, 0); 388 if (-1 == fd) 389 return -1; 390 391 int result = fstat(fd, buf); 392 close(fd); 393 return result; 394 } 395 396 int KernelProxy::mount(const char* source, 397 const char* target, 398 const char* filesystemtype, 399 unsigned long mountflags, 400 const void* data) { 401 ScopedFilesystem fs; 402 Error error = MountInternal( 403 source, target, filesystemtype, mountflags, data, true, &fs); 404 if (error) { 405 errno = error; 406 return -1; 407 } 408 409 return 0; 410 } 411 412 Error KernelProxy::MountInternal(const char* source, 413 const char* target, 414 const char* filesystemtype, 415 unsigned long mountflags, 416 const void* data, 417 bool create_fs_node, 418 ScopedFilesystem* out_filesystem) { 419 std::string abs_path = GetAbsParts(target).Join(); 420 421 // Find a factory of that type 422 FsFactoryMap_t::iterator factory = factories_.find(filesystemtype); 423 if (factory == factories_.end()) { 424 LOG_ERROR("Unknown filesystem type: %s", filesystemtype); 425 return ENODEV; 426 } 427 428 // Create a map of settings 429 StringMap_t smap; 430 smap["SOURCE"] = source; 431 432 if (data) { 433 std::vector<std::string> elements; 434 sdk_util::SplitString(static_cast<const char*>(data), ',', &elements); 435 436 for (std::vector<std::string>::const_iterator it = elements.begin(); 437 it != elements.end(); 438 ++it) { 439 size_t location = it->find('='); 440 if (location != std::string::npos) { 441 std::string key = it->substr(0, location); 442 std::string val = it->substr(location + 1); 443 smap[key] = val; 444 } else { 445 smap[*it] = "TRUE"; 446 } 447 } 448 } 449 450 FsInitArgs args; 451 args.dev = dev_++; 452 args.string_map = smap; 453 args.ppapi = ppapi_; 454 455 ScopedFilesystem fs; 456 Error error = factory->second->CreateFilesystem(args, &fs); 457 if (error) 458 return error; 459 460 error = AttachFsAtPath(fs, abs_path); 461 if (error) 462 return error; 463 464 if (create_fs_node) { 465 error = CreateFsNode(fs); 466 if (error) { 467 DetachFsAtPath(abs_path, &fs); 468 return error; 469 } 470 } 471 472 *out_filesystem = fs; 473 474 if (mount_callback_) { 475 mount_callback_(source, 476 target, 477 filesystemtype, 478 mountflags, 479 data, 480 fs->dev(), 481 mount_callback_user_data_); 482 } 483 484 return 0; 485 } 486 487 Error KernelProxy::CreateFsNode(const ScopedFilesystem& fs) { 488 assert(dev_fs_); 489 490 return dev_fs_->CreateFsNode(fs.get()); 491 } 492 493 int KernelProxy::umount(const char* path) { 494 ScopedFilesystem fs; 495 Error error = DetachFsAtPath(path, &fs); 496 if (error) { 497 errno = error; 498 return -1; 499 } 500 501 error = dev_fs_->DestroyFsNode(fs.get()); 502 if (error) { 503 // Ignore any errors here, just log. 504 LOG_ERROR("Unable to destroy FsNode: %s", strerror(error)); 505 } 506 return 0; 507 } 508 509 ssize_t KernelProxy::read(int fd, void* buf, size_t nbytes) { 510 ScopedKernelHandle handle; 511 Error error = AcquireHandle(fd, &handle); 512 if (error) { 513 errno = error; 514 return -1; 515 } 516 517 int cnt = 0; 518 error = handle->Read(buf, nbytes, &cnt); 519 if (error) { 520 errno = error; 521 return -1; 522 } 523 524 return cnt; 525 } 526 527 ssize_t KernelProxy::write(int fd, const void* buf, size_t nbytes) { 528 ScopedKernelHandle handle; 529 Error error = AcquireHandle(fd, &handle); 530 if (error) { 531 errno = error; 532 return -1; 533 } 534 535 int cnt = 0; 536 error = handle->Write(buf, nbytes, &cnt); 537 if (error) { 538 errno = error; 539 return -1; 540 } 541 542 return cnt; 543 } 544 545 int KernelProxy::fstat(int fd, struct stat* buf) { 546 ScopedKernelHandle handle; 547 Error error = AcquireHandle(fd, &handle); 548 if (error) { 549 errno = error; 550 return -1; 551 } 552 553 error = handle->node()->GetStat(buf); 554 if (error) { 555 errno = error; 556 return -1; 557 } 558 559 return 0; 560 } 561 562 int KernelProxy::getdents(int fd, void* buf, unsigned int count) { 563 ScopedKernelHandle handle; 564 Error error = AcquireHandle(fd, &handle); 565 if (error) { 566 errno = error; 567 return -1; 568 } 569 570 int cnt = 0; 571 error = handle->GetDents(static_cast<dirent*>(buf), count, &cnt); 572 if (error) 573 errno = error; 574 575 return cnt; 576 } 577 578 int KernelProxy::fchdir(int fd) { 579 ScopedKernelHandle handle; 580 std::string path; 581 Error error = AcquireHandleAndPath(fd, &handle, &path); 582 if (error) { 583 errno = error; 584 return -1; 585 } 586 587 if (!handle->node()->IsaDir()) { 588 errno = ENOTDIR; 589 return -1; 590 } 591 592 if (path.empty()) { 593 errno = EBADF; 594 return -1; 595 } 596 597 error = SetCWD(path); 598 if (error) { 599 // errno is return value from SetCWD 600 errno = error; 601 return -1; 602 } 603 return 0; 604 } 605 606 int KernelProxy::ftruncate(int fd, off_t length) { 607 ScopedKernelHandle handle; 608 Error error = AcquireHandle(fd, &handle); 609 if (error) { 610 errno = error; 611 return -1; 612 } 613 614 error = handle->node()->FTruncate(length); 615 if (error) { 616 errno = error; 617 return -1; 618 } 619 620 return 0; 621 } 622 623 int KernelProxy::fsync(int fd) { 624 ScopedKernelHandle handle; 625 Error error = AcquireHandle(fd, &handle); 626 if (error) { 627 errno = error; 628 return -1; 629 } 630 631 error = handle->node()->FSync(); 632 if (error) { 633 errno = error; 634 return -1; 635 } 636 637 return 0; 638 } 639 640 int KernelProxy::fdatasync(int fd) { 641 errno = ENOSYS; 642 return -1; 643 } 644 645 int KernelProxy::isatty(int fd) { 646 ScopedKernelHandle handle; 647 Error error = AcquireHandle(fd, &handle); 648 if (error) { 649 errno = error; 650 return 0; 651 } 652 653 error = handle->node()->Isatty(); 654 if (error) { 655 errno = error; 656 return 0; 657 } 658 659 return 1; 660 } 661 662 int KernelProxy::ioctl(int fd, int request, va_list args) { 663 ScopedKernelHandle handle; 664 Error error = AcquireHandle(fd, &handle); 665 if (error) { 666 errno = error; 667 return -1; 668 } 669 670 error = handle->node()->VIoctl(request, args); 671 if (error) { 672 errno = error; 673 return -1; 674 } 675 676 return 0; 677 } 678 679 int KernelProxy::futimens(int fd, const struct timespec times[2]) { 680 ScopedKernelHandle handle; 681 Error error = AcquireHandle(fd, &handle); 682 if (error) { 683 errno = error; 684 return -1; 685 } 686 687 error = handle->node()->Futimens(times); 688 if (error) { 689 errno = error; 690 return -1; 691 } 692 693 return 0; 694 } 695 696 off_t KernelProxy::lseek(int fd, off_t offset, int whence) { 697 ScopedKernelHandle handle; 698 Error error = AcquireHandle(fd, &handle); 699 if (error) { 700 errno = error; 701 return -1; 702 } 703 704 off_t new_offset; 705 error = handle->Seek(offset, whence, &new_offset); 706 if (error) { 707 errno = error; 708 return -1; 709 } 710 711 return new_offset; 712 } 713 714 int KernelProxy::unlink(const char* path) { 715 ScopedFilesystem fs; 716 Path rel; 717 718 Error error = AcquireFsAndRelPath(path, &fs, &rel); 719 if (error) { 720 errno = error; 721 return -1; 722 } 723 724 error = fs->Unlink(rel); 725 if (error) { 726 errno = error; 727 return -1; 728 } 729 730 return 0; 731 } 732 733 int KernelProxy::truncate(const char* path, off_t len) { 734 int fd = open(path, O_WRONLY, 0); 735 if (-1 == fd) 736 return -1; 737 738 int result = ftruncate(fd, len); 739 close(fd); 740 return result; 741 } 742 743 int KernelProxy::lstat(const char* path, struct stat* buf) { 744 return stat(path, buf); 745 } 746 747 int KernelProxy::rename(const char* path, const char* newpath) { 748 ScopedFilesystem fs; 749 Path rel; 750 Error error = AcquireFsAndRelPath(path, &fs, &rel); 751 if (error) { 752 errno = error; 753 return -1; 754 } 755 756 ScopedFilesystem newfs; 757 Path newrel; 758 error = AcquireFsAndRelPath(newpath, &newfs, &newrel); 759 if (error) { 760 errno = error; 761 return -1; 762 } 763 764 if (newfs.get() != fs.get()) { 765 // Renaming accross mountpoints is not allowed 766 errno = EXDEV; 767 return -1; 768 } 769 770 // They already point to the same path 771 if (rel == newrel) 772 return 0; 773 774 error = fs->Rename(rel, newrel); 775 if (error) { 776 errno = error; 777 return -1; 778 } 779 780 return 0; 781 } 782 783 int KernelProxy::remove(const char* path) { 784 ScopedFilesystem fs; 785 Path rel; 786 787 Error error = AcquireFsAndRelPath(path, &fs, &rel); 788 if (error) { 789 errno = error; 790 return -1; 791 } 792 793 error = fs->Remove(rel); 794 if (error) { 795 errno = error; 796 return -1; 797 } 798 799 return 0; 800 } 801 802 int KernelProxy::fchmod(int fd, mode_t mode) { 803 ScopedKernelHandle handle; 804 Error error = AcquireHandle(fd, &handle); 805 if (error) { 806 errno = error; 807 return -1; 808 } 809 810 error = handle->node()->Fchmod(mode); 811 if (error) { 812 errno = error; 813 return -1; 814 } 815 816 return 0; 817 } 818 819 int KernelProxy::fcntl(int fd, int request, va_list args) { 820 Error error = 0; 821 822 // F_GETFD and F_SETFD are descriptor specific flags that 823 // are stored in the KernelObject's decriptor map unlike 824 // F_GETFL and F_SETFL which are handle specific. 825 switch (request) { 826 case F_GETFD: { 827 int rtn = -1; 828 error = GetFDFlags(fd, &rtn); 829 if (error) { 830 errno = error; 831 return -1; 832 } 833 return rtn; 834 } 835 case F_SETFD: { 836 int flags = va_arg(args, int); 837 error = SetFDFlags(fd, flags); 838 if (error) { 839 errno = error; 840 return -1; 841 } 842 return 0; 843 } 844 } 845 846 ScopedKernelHandle handle; 847 error = AcquireHandle(fd, &handle); 848 if (error) { 849 errno = error; 850 return -1; 851 } 852 853 int rtn = 0; 854 error = handle->VFcntl(request, &rtn, args); 855 if (error) { 856 errno = error; 857 return -1; 858 } 859 860 return rtn; 861 } 862 863 int KernelProxy::access(const char* path, int amode) { 864 struct stat buf; 865 int rtn = stat(path, &buf); 866 if (rtn != 0) 867 return rtn; 868 869 if (((amode & R_OK) && !(buf.st_mode & S_IREAD)) || 870 ((amode & W_OK) && !(buf.st_mode & S_IWRITE)) || 871 ((amode & X_OK) && !(buf.st_mode & S_IEXEC))) { 872 errno = EACCES; 873 return -1; 874 } 875 876 return 0; 877 } 878 879 int KernelProxy::readlink(const char* path, char* buf, size_t count) { 880 LOG_TRACE("readlink is not implemented."); 881 errno = EINVAL; 882 return -1; 883 } 884 885 int KernelProxy::utimens(const char* path, const struct timespec times[2]) { 886 int fd = open(path, O_RDONLY, 0); 887 if (-1 == fd) 888 return -1; 889 890 int result = futimens(fd, times); 891 close(fd); 892 return result; 893 } 894 895 // TODO(noelallen): Needs implementation. 896 int KernelProxy::link(const char* oldpath, const char* newpath) { 897 LOG_TRACE("link is not implemented."); 898 errno = EINVAL; 899 return -1; 900 } 901 902 int KernelProxy::symlink(const char* oldpath, const char* newpath) { 903 LOG_TRACE("symlink is not implemented."); 904 errno = EINVAL; 905 return -1; 906 } 907 908 void* KernelProxy::mmap(void* addr, 909 size_t length, 910 int prot, 911 int flags, 912 int fd, 913 size_t offset) { 914 // We shouldn't be getting anonymous mmaps here. 915 assert((flags & MAP_ANONYMOUS) == 0); 916 assert(fd != -1); 917 918 ScopedKernelHandle handle; 919 Error error = AcquireHandle(fd, &handle); 920 if (error) { 921 errno = error; 922 return MAP_FAILED; 923 } 924 925 void* new_addr; 926 error = handle->node()->MMap(addr, length, prot, flags, offset, &new_addr); 927 if (error) { 928 errno = error; 929 return MAP_FAILED; 930 } 931 932 return new_addr; 933 } 934 935 int KernelProxy::munmap(void* addr, size_t length) { 936 // NOTE: The comment below is from a previous discarded implementation that 937 // tracks mmap'd regions. For simplicity, we no longer do this; because we 938 // "snapshot" the contents of the file in mmap(), and don't support 939 // write-back or updating the mapped region when the file is written, holding 940 // on to the KernelHandle is pointless. 941 // 942 // If we ever do, these threading issues should be considered. 943 944 // 945 // WARNING: this function may be called by free(). 946 // 947 // There is a potential deadlock scenario: 948 // Thread 1: open() -> takes lock1 -> free() -> takes lock2 949 // Thread 2: free() -> takes lock2 -> munmap() -> takes lock1 950 // 951 // Note that open() above could be any function that takes a lock that is 952 // shared with munmap (this includes munmap!) 953 // 954 // To prevent this, we avoid taking locks in munmap() that are used by other 955 // nacl_io functions that may call free. Specifically, we only take the 956 // mmap_lock, which is only shared with mmap() above. There is still a 957 // possibility of deadlock if mmap() or munmap() calls free(), so this is not 958 // allowed. 959 // 960 // Unfortunately, munmap still needs to acquire other locks; see the call to 961 // ReleaseHandle below which takes the process lock. This is safe as long as 962 // this is never executed from free() -- we can be reasonably sure this is 963 // true, because malloc only makes anonymous mmap() requests, and should only 964 // be munmapping those allocations. We never add to mmap_info_list_ for 965 // anonymous maps, so the unmap_list should always be empty when called from 966 // free(). 967 return 0; 968 } 969 970 int KernelProxy::tcflush(int fd, int queue_selector) { 971 ScopedKernelHandle handle; 972 Error error = AcquireHandle(fd, &handle); 973 if (error) { 974 errno = error; 975 return -1; 976 } 977 978 error = handle->node()->Tcflush(queue_selector); 979 if (error) { 980 errno = error; 981 return -1; 982 } 983 984 return 0; 985 } 986 987 int KernelProxy::tcgetattr(int fd, struct termios* termios_p) { 988 ScopedKernelHandle handle; 989 Error error = AcquireHandle(fd, &handle); 990 if (error) { 991 errno = error; 992 return -1; 993 } 994 995 error = handle->node()->Tcgetattr(termios_p); 996 if (error) { 997 errno = error; 998 return -1; 999 } 1000 1001 return 0; 1002 } 1003 1004 int KernelProxy::tcsetattr(int fd, 1005 int optional_actions, 1006 const struct termios* termios_p) { 1007 ScopedKernelHandle handle; 1008 Error error = AcquireHandle(fd, &handle); 1009 if (error) { 1010 errno = error; 1011 return -1; 1012 } 1013 1014 error = handle->node()->Tcsetattr(optional_actions, termios_p); 1015 if (error) { 1016 errno = error; 1017 return -1; 1018 } 1019 1020 return 0; 1021 } 1022 1023 int KernelProxy::kill(pid_t pid, int sig) { 1024 // Currently we don't even pretend that other processes exist 1025 // so we can only send a signal to outselves. For kill(2) 1026 // pid 0 means the current process group and -1 means all the 1027 // processes we have permission to send signals to. 1028 if (pid != getpid() && pid != -1 && pid != 0) { 1029 errno = ESRCH; 1030 return -1; 1031 } 1032 1033 // Raise an event so that select/poll get interrupted. 1034 AUTO_LOCK(signal_emitter_->GetLock()) 1035 signal_emitter_->RaiseEvents_Locked(POLLERR); 1036 switch (sig) { 1037 case SIGWINCH: 1038 if (sigwinch_handler_.sa_handler != SIG_IGN && 1039 sigwinch_handler_.sa_handler != SIG_DFL) { 1040 sigwinch_handler_.sa_handler(SIGWINCH); 1041 } 1042 break; 1043 1044 case SIGUSR1: 1045 case SIGUSR2: 1046 break; 1047 1048 default: 1049 LOG_TRACE("Unsupported signal: %d", sig); 1050 errno = EINVAL; 1051 return -1; 1052 } 1053 return 0; 1054 } 1055 1056 int KernelProxy::sigaction(int signum, 1057 const struct sigaction* action, 1058 struct sigaction* oaction) { 1059 if (action && action->sa_flags & SA_SIGINFO) { 1060 // We don't support SA_SIGINFO (sa_sigaction field) yet 1061 errno = EINVAL; 1062 return -1; 1063 } 1064 1065 switch (signum) { 1066 // Handled signals. 1067 case SIGWINCH: { 1068 if (oaction) 1069 *oaction = sigwinch_handler_; 1070 if (action) { 1071 sigwinch_handler_ = *action; 1072 } 1073 return 0; 1074 } 1075 1076 // Known signals 1077 case SIGHUP: 1078 case SIGINT: 1079 case SIGPIPE: 1080 case SIGPOLL: 1081 case SIGPROF: 1082 case SIGTERM: 1083 case SIGCHLD: 1084 case SIGURG: 1085 case SIGFPE: 1086 case SIGILL: 1087 case SIGQUIT: 1088 case SIGSEGV: 1089 case SIGTRAP: 1090 if (action && action->sa_handler != SIG_DFL) { 1091 // Trying to set this action to anything other than SIG_DFL 1092 // is not yet supported. 1093 LOG_TRACE("sigaction on signal %d != SIG_DFL not supported.", sig); 1094 errno = EINVAL; 1095 return -1; 1096 } 1097 1098 if (oaction) { 1099 memset(oaction, 0, sizeof(*oaction)); 1100 oaction->sa_handler = SIG_DFL; 1101 } 1102 return 0; 1103 1104 // KILL and STOP cannot be handled 1105 case SIGKILL: 1106 case SIGSTOP: 1107 LOG_TRACE("sigaction on SIGKILL/SIGSTOP not supported."); 1108 errno = EINVAL; 1109 return -1; 1110 } 1111 1112 // Unknown signum 1113 errno = EINVAL; 1114 return -1; 1115 } 1116 1117 #ifdef PROVIDES_SOCKET_API 1118 1119 int KernelProxy::select(int nfds, 1120 fd_set* readfds, 1121 fd_set* writefds, 1122 fd_set* exceptfds, 1123 struct timeval* timeout) { 1124 std::vector<pollfd> pollfds; 1125 1126 for (int fd = 0; fd < nfds; fd++) { 1127 int events = 0; 1128 if (readfds && FD_ISSET(fd, readfds)) { 1129 events |= POLLIN; 1130 FD_CLR(fd, readfds); 1131 } 1132 1133 if (writefds && FD_ISSET(fd, writefds)) { 1134 events |= POLLOUT; 1135 FD_CLR(fd, writefds); 1136 } 1137 1138 if (exceptfds && FD_ISSET(fd, exceptfds)) { 1139 events |= POLLERR | POLLHUP; 1140 FD_CLR(fd, exceptfds); 1141 } 1142 1143 if (events) { 1144 pollfd info; 1145 info.fd = fd; 1146 info.events = events; 1147 pollfds.push_back(info); 1148 } 1149 } 1150 1151 // NULL timeout signals wait forever. 1152 int ms_timeout = -1; 1153 if (timeout != NULL) { 1154 int64_t ms = timeout->tv_sec * 1000 + ((timeout->tv_usec + 500) / 1000); 1155 1156 // If the timeout is invalid or too long (larger than signed 32 bit). 1157 if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) || 1158 (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) || (ms < 0) || 1159 (ms >= INT_MAX)) { 1160 LOG_TRACE("Invalid timeout: tv_sec=%d tv_usec=%d.", 1161 timeout->tv_sec, 1162 timeout->tv_usec); 1163 errno = EINVAL; 1164 return -1; 1165 } 1166 1167 ms_timeout = static_cast<int>(ms); 1168 } 1169 1170 int result = poll(&pollfds[0], pollfds.size(), ms_timeout); 1171 if (result == -1) 1172 return -1; 1173 1174 int event_cnt = 0; 1175 for (size_t index = 0; index < pollfds.size(); index++) { 1176 pollfd* info = &pollfds[index]; 1177 if (info->revents & POLLIN) { 1178 FD_SET(info->fd, readfds); 1179 event_cnt++; 1180 } 1181 if (info->revents & POLLOUT) { 1182 FD_SET(info->fd, writefds); 1183 event_cnt++; 1184 } 1185 if (info->revents & (POLLHUP | POLLERR)) { 1186 FD_SET(info->fd, exceptfds); 1187 event_cnt++; 1188 } 1189 } 1190 1191 return event_cnt; 1192 } 1193 1194 struct PollInfo { 1195 PollInfo() : index(-1) {}; 1196 1197 std::vector<struct pollfd*> fds; 1198 int index; 1199 }; 1200 1201 typedef std::map<EventEmitter*, PollInfo> EventPollMap_t; 1202 1203 int KernelProxy::poll(struct pollfd* fds, nfds_t nfds, int timeout) { 1204 EventPollMap_t event_map; 1205 1206 std::vector<EventRequest> requests; 1207 size_t event_cnt = 0; 1208 1209 for (int index = 0; static_cast<nfds_t>(index) < nfds; index++) { 1210 ScopedKernelHandle handle; 1211 struct pollfd* fd_info = &fds[index]; 1212 Error err = AcquireHandle(fd_info->fd, &handle); 1213 1214 fd_info->revents = 0; 1215 1216 // If the node isn't open, or somehow invalid, mark it so. 1217 if (err != 0) { 1218 fd_info->revents = POLLNVAL; 1219 event_cnt++; 1220 continue; 1221 } 1222 1223 // If it's already signaled, then just capture the event 1224 ScopedEventEmitter emitter(handle->node()->GetEventEmitter()); 1225 int events = POLLIN | POLLOUT; 1226 if (emitter) 1227 events = emitter->GetEventStatus(); 1228 1229 if (events & fd_info->events) { 1230 fd_info->revents = events & fd_info->events; 1231 event_cnt++; 1232 continue; 1233 } 1234 1235 if (NULL == emitter) { 1236 fd_info->revents = POLLNVAL; 1237 event_cnt++; 1238 continue; 1239 } 1240 1241 // Otherwise try to track it. 1242 PollInfo* info = &event_map[emitter.get()]; 1243 if (info->index == -1) { 1244 EventRequest request; 1245 request.emitter = emitter; 1246 request.filter = fd_info->events; 1247 request.events = 0; 1248 1249 info->index = requests.size(); 1250 requests.push_back(request); 1251 } 1252 info->fds.push_back(fd_info); 1253 requests[info->index].filter |= fd_info->events; 1254 } 1255 1256 // If nothing is signaled, then we must wait on the event map 1257 if (0 == event_cnt) { 1258 EventListenerPoll wait; 1259 Error err = wait.WaitOnAny(&requests[0], requests.size(), timeout); 1260 if ((err != 0) && (err != ETIMEDOUT)) { 1261 errno = err; 1262 return -1; 1263 } 1264 1265 for (size_t rindex = 0; rindex < requests.size(); rindex++) { 1266 EventRequest* request = &requests[rindex]; 1267 if (request->events) { 1268 PollInfo* poll_info = &event_map[request->emitter.get()]; 1269 for (size_t findex = 0; findex < poll_info->fds.size(); findex++) { 1270 struct pollfd* fd_info = poll_info->fds[findex]; 1271 uint32_t events = fd_info->events & request->events; 1272 if (events) { 1273 fd_info->revents = events; 1274 event_cnt++; 1275 } 1276 } 1277 } 1278 } 1279 } 1280 1281 return event_cnt; 1282 } 1283 1284 // Socket Functions 1285 int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) { 1286 if (NULL == addr || NULL == len) { 1287 errno = EFAULT; 1288 return -1; 1289 } 1290 1291 ScopedKernelHandle handle; 1292 Error error = AcquireHandle(fd, &handle); 1293 if (error) { 1294 errno = error; 1295 return -1; 1296 } 1297 1298 PP_Resource new_sock = 0; 1299 error = handle->Accept(&new_sock, addr, len); 1300 if (error != 0) { 1301 errno = error; 1302 return -1; 1303 } 1304 1305 SocketNode* sock = new TcpNode(stream_fs_.get(), new_sock); 1306 1307 // The SocketNode now holds a reference to the new socket 1308 // so we release ours. 1309 ppapi_->ReleaseResource(new_sock); 1310 error = sock->Init(O_RDWR); 1311 if (error != 0) { 1312 errno = error; 1313 return -1; 1314 } 1315 1316 ScopedNode node(sock); 1317 ScopedKernelHandle new_handle(new KernelHandle(stream_fs_, node)); 1318 error = new_handle->Init(O_RDWR); 1319 if (error != 0) { 1320 errno = error; 1321 return -1; 1322 } 1323 1324 return AllocateFD(new_handle); 1325 } 1326 1327 int KernelProxy::bind(int fd, const struct sockaddr* addr, socklen_t len) { 1328 if (NULL == addr) { 1329 errno = EFAULT; 1330 return -1; 1331 } 1332 1333 ScopedKernelHandle handle; 1334 if (AcquireSocketHandle(fd, &handle) == -1) 1335 return -1; 1336 1337 Error err = handle->socket_node()->Bind(addr, len); 1338 if (err != 0) { 1339 errno = err; 1340 return -1; 1341 } 1342 1343 return 0; 1344 } 1345 1346 int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) { 1347 if (NULL == addr) { 1348 errno = EFAULT; 1349 return -1; 1350 } 1351 1352 ScopedKernelHandle handle; 1353 Error error = AcquireHandle(fd, &handle); 1354 if (error) { 1355 errno = error; 1356 return -1; 1357 } 1358 1359 error = handle->Connect(addr, len); 1360 if (error != 0) { 1361 errno = error; 1362 return -1; 1363 } 1364 1365 return 0; 1366 } 1367 1368 void KernelProxy::freeaddrinfo(struct addrinfo* res) { 1369 return host_resolver_.freeaddrinfo(res); 1370 } 1371 1372 int KernelProxy::getaddrinfo(const char* node, 1373 const char* service, 1374 const struct addrinfo* hints, 1375 struct addrinfo** res) { 1376 return host_resolver_.getaddrinfo(node, service, hints, res); 1377 } 1378 1379 int KernelProxy::getnameinfo(const struct sockaddr *sa, 1380 socklen_t salen, 1381 char *host, 1382 size_t hostlen, 1383 char *serv, 1384 size_t servlen, 1385 int flags) { 1386 return host_resolver_.getnameinfo(sa, salen, host, hostlen, serv, servlen, 1387 flags); 1388 } 1389 1390 struct hostent* KernelProxy::gethostbyname(const char* name) { 1391 return host_resolver_.gethostbyname(name); 1392 } 1393 1394 int KernelProxy::getpeername(int fd, struct sockaddr* addr, socklen_t* len) { 1395 if (NULL == addr || NULL == len) { 1396 errno = EFAULT; 1397 return -1; 1398 } 1399 1400 ScopedKernelHandle handle; 1401 if (AcquireSocketHandle(fd, &handle) == -1) 1402 return -1; 1403 1404 Error err = handle->socket_node()->GetPeerName(addr, len); 1405 if (err != 0) { 1406 errno = err; 1407 return -1; 1408 } 1409 1410 return 0; 1411 } 1412 1413 int KernelProxy::getsockname(int fd, struct sockaddr* addr, socklen_t* len) { 1414 if (NULL == addr || NULL == len) { 1415 errno = EFAULT; 1416 return -1; 1417 } 1418 1419 ScopedKernelHandle handle; 1420 if (AcquireSocketHandle(fd, &handle) == -1) 1421 return -1; 1422 1423 Error err = handle->socket_node()->GetSockName(addr, len); 1424 if (err != 0) { 1425 errno = err; 1426 return -1; 1427 } 1428 1429 return 0; 1430 } 1431 1432 int KernelProxy::getsockopt(int fd, 1433 int lvl, 1434 int optname, 1435 void* optval, 1436 socklen_t* len) { 1437 if (NULL == optval || NULL == len) { 1438 errno = EFAULT; 1439 return -1; 1440 } 1441 1442 ScopedKernelHandle handle; 1443 if (AcquireSocketHandle(fd, &handle) == -1) 1444 return -1; 1445 1446 Error err = handle->socket_node()->GetSockOpt(lvl, optname, optval, len); 1447 if (err != 0) { 1448 errno = err; 1449 return -1; 1450 } 1451 1452 return 0; 1453 } 1454 1455 int KernelProxy::listen(int fd, int backlog) { 1456 ScopedKernelHandle handle; 1457 if (AcquireSocketHandle(fd, &handle) == -1) 1458 return -1; 1459 1460 Error err = handle->socket_node()->Listen(backlog); 1461 if (err != 0) { 1462 errno = err; 1463 return -1; 1464 } 1465 1466 return 0; 1467 } 1468 1469 ssize_t KernelProxy::recv(int fd, void* buf, size_t len, int flags) { 1470 if (NULL == buf) { 1471 errno = EFAULT; 1472 return -1; 1473 } 1474 1475 ScopedKernelHandle handle; 1476 Error error = AcquireHandle(fd, &handle); 1477 if (error) { 1478 errno = error; 1479 return -1; 1480 } 1481 1482 int out_len = 0; 1483 error = handle->Recv(buf, len, flags, &out_len); 1484 if (error != 0) { 1485 errno = error; 1486 return -1; 1487 } 1488 1489 return static_cast<ssize_t>(out_len); 1490 } 1491 1492 ssize_t KernelProxy::recvfrom(int fd, 1493 void* buf, 1494 size_t len, 1495 int flags, 1496 struct sockaddr* addr, 1497 socklen_t* addrlen) { 1498 // According to the manpage, recvfrom with a null addr is identical to recv. 1499 if (NULL == addr) { 1500 return recv(fd, buf, len, flags); 1501 } 1502 1503 if (NULL == buf || NULL == addrlen) { 1504 errno = EFAULT; 1505 return -1; 1506 } 1507 1508 ScopedKernelHandle handle; 1509 Error error = AcquireHandle(fd, &handle); 1510 if (error) { 1511 errno = error; 1512 return -1; 1513 } 1514 1515 int out_len = 0; 1516 error = handle->RecvFrom(buf, len, flags, addr, addrlen, &out_len); 1517 if (error != 0) { 1518 errno = error; 1519 return -1; 1520 } 1521 1522 return static_cast<ssize_t>(out_len); 1523 } 1524 1525 ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) { 1526 if (NULL == msg) { 1527 errno = EFAULT; 1528 return -1; 1529 } 1530 1531 ScopedKernelHandle handle; 1532 if (AcquireSocketHandle(fd, &handle) == -1) 1533 return -1; 1534 1535 errno = EOPNOTSUPP; 1536 return -1; 1537 } 1538 1539 ssize_t KernelProxy::send(int fd, const void* buf, size_t len, int flags) { 1540 if (NULL == buf) { 1541 errno = EFAULT; 1542 return -1; 1543 } 1544 1545 ScopedKernelHandle handle; 1546 Error error = AcquireHandle(fd, &handle); 1547 if (error) { 1548 errno = error; 1549 return -1; 1550 } 1551 1552 int out_len = 0; 1553 error = handle->Send(buf, len, flags, &out_len); 1554 if (error != 0) { 1555 errno = error; 1556 return -1; 1557 } 1558 1559 return static_cast<ssize_t>(out_len); 1560 } 1561 1562 ssize_t KernelProxy::sendto(int fd, 1563 const void* buf, 1564 size_t len, 1565 int flags, 1566 const struct sockaddr* addr, 1567 socklen_t addrlen) { 1568 // According to the manpage, sendto with a null addr is identical to send. 1569 if (NULL == addr) { 1570 return send(fd, buf, len, flags); 1571 } 1572 1573 if (NULL == buf) { 1574 errno = EFAULT; 1575 return -1; 1576 } 1577 1578 ScopedKernelHandle handle; 1579 Error error = AcquireHandle(fd, &handle); 1580 if (error) { 1581 errno = error; 1582 return -1; 1583 } 1584 1585 int out_len = 0; 1586 error = handle->SendTo(buf, len, flags, addr, addrlen, &out_len); 1587 if (error != 0) { 1588 errno = error; 1589 return -1; 1590 } 1591 1592 return static_cast<ssize_t>(out_len); 1593 } 1594 1595 ssize_t KernelProxy::sendmsg(int fd, const struct msghdr* msg, int flags) { 1596 if (NULL == msg) { 1597 errno = EFAULT; 1598 return -1; 1599 } 1600 1601 ScopedKernelHandle handle; 1602 if (AcquireSocketHandle(fd, &handle) == -1) 1603 return -1; 1604 1605 errno = EOPNOTSUPP; 1606 return -1; 1607 } 1608 1609 int KernelProxy::setsockopt(int fd, 1610 int lvl, 1611 int optname, 1612 const void* optval, 1613 socklen_t len) { 1614 if (NULL == optval) { 1615 errno = EFAULT; 1616 return -1; 1617 } 1618 1619 ScopedKernelHandle handle; 1620 if (AcquireSocketHandle(fd, &handle) == -1) 1621 return -1; 1622 1623 Error err = handle->socket_node()->SetSockOpt(lvl, optname, optval, len); 1624 if (err != 0) { 1625 errno = err; 1626 return -1; 1627 } 1628 1629 return 0; 1630 } 1631 1632 int KernelProxy::shutdown(int fd, int how) { 1633 ScopedKernelHandle handle; 1634 if (AcquireSocketHandle(fd, &handle) == -1) 1635 return -1; 1636 1637 Error err = handle->socket_node()->Shutdown(how); 1638 if (err != 0) { 1639 errno = err; 1640 return -1; 1641 } 1642 1643 return 0; 1644 } 1645 1646 int KernelProxy::socket(int domain, int type, int protocol) { 1647 if (AF_INET != domain && AF_INET6 != domain) { 1648 errno = EAFNOSUPPORT; 1649 return -1; 1650 } 1651 1652 int open_flags = O_RDWR; 1653 1654 if (type & SOCK_CLOEXEC) { 1655 #ifdef O_CLOEXEC 1656 // The NaCl newlib version of fcntl.h doesn't currently define 1657 // O_CLOEXEC. 1658 // TODO(sbc): remove this guard once it gets added. 1659 open_flags |= O_CLOEXEC; 1660 #endif 1661 type &= ~SOCK_CLOEXEC; 1662 } 1663 1664 if (type & SOCK_NONBLOCK) { 1665 open_flags |= O_NONBLOCK; 1666 type &= ~SOCK_NONBLOCK; 1667 } 1668 1669 SocketNode* sock = NULL; 1670 switch (type) { 1671 case SOCK_DGRAM: 1672 sock = new UdpNode(stream_fs_.get()); 1673 break; 1674 1675 case SOCK_STREAM: 1676 sock = new TcpNode(stream_fs_.get()); 1677 break; 1678 1679 case SOCK_SEQPACKET: 1680 case SOCK_RDM: 1681 case SOCK_RAW: 1682 errno = EPROTONOSUPPORT; 1683 return -1; 1684 1685 default: 1686 errno = EINVAL; 1687 return -1; 1688 } 1689 1690 ScopedNode node(sock); 1691 Error rtn = sock->Init(O_RDWR); 1692 if (rtn != 0) { 1693 errno = rtn; 1694 return -1; 1695 } 1696 1697 ScopedKernelHandle handle(new KernelHandle(stream_fs_, node)); 1698 rtn = handle->Init(open_flags); 1699 if (rtn != 0) { 1700 errno = rtn; 1701 return -1; 1702 } 1703 1704 return AllocateFD(handle); 1705 } 1706 1707 int KernelProxy::socketpair(int domain, int type, int protocol, int* sv) { 1708 if (NULL == sv) { 1709 errno = EFAULT; 1710 return -1; 1711 } 1712 1713 // Catch-22: We don't support AF_UNIX, but any other AF doesn't support 1714 // socket pairs. Thus, this function always fails. 1715 if (AF_UNIX != domain) { 1716 errno = EPROTONOSUPPORT; 1717 return -1; 1718 } 1719 1720 if (AF_INET != domain && AF_INET6 != domain) { 1721 errno = EAFNOSUPPORT; 1722 return -1; 1723 } 1724 1725 // We cannot reach this point. 1726 errno = ENOSYS; 1727 return -1; 1728 } 1729 1730 int KernelProxy::AcquireSocketHandle(int fd, ScopedKernelHandle* handle) { 1731 Error error = AcquireHandle(fd, handle); 1732 1733 if (error) { 1734 errno = error; 1735 return -1; 1736 } 1737 1738 if ((handle->get()->node_->GetType() & S_IFSOCK) == 0) { 1739 errno = ENOTSOCK; 1740 return -1; 1741 } 1742 1743 return 0; 1744 } 1745 1746 #endif // PROVIDES_SOCKET_API 1747 1748 } // namespace_nacl_io 1749