Home | History | Annotate | Download | only in nacl_io
      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 
      8 #include <assert.h>
      9 #include <errno.h>
     10 #include <fcntl.h>
     11 #include <limits.h>
     12 #include <poll.h>
     13 #include <pthread.h>
     14 #include <stdio.h>
     15 #include <string.h>
     16 #include <sys/time.h>
     17 
     18 #include <iterator>
     19 #include <string>
     20 
     21 #include "nacl_io/host_resolver.h"
     22 #include "nacl_io/kernel_handle.h"
     23 #include "nacl_io/kernel_wrap_real.h"
     24 #include "nacl_io/mount.h"
     25 #include "nacl_io/mount_dev.h"
     26 #include "nacl_io/mount_html5fs.h"
     27 #include "nacl_io/mount_http.h"
     28 #include "nacl_io/mount_mem.h"
     29 #include "nacl_io/mount_node.h"
     30 #include "nacl_io/mount_passthrough.h"
     31 #include "nacl_io/osmman.h"
     32 #include "nacl_io/ossocket.h"
     33 #include "nacl_io/osstat.h"
     34 #include "nacl_io/path.h"
     35 #include "nacl_io/pepper_interface.h"
     36 #include "nacl_io/typed_mount_factory.h"
     37 #include "sdk_util/auto_lock.h"
     38 #include "sdk_util/ref_object.h"
     39 
     40 #ifndef MAXPATHLEN
     41 #define MAXPATHLEN 256
     42 #endif
     43 
     44 namespace nacl_io {
     45 
     46 KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL) {
     47 }
     48 
     49 KernelProxy::~KernelProxy() {
     50   // Clean up the MountFactories.
     51   for (MountFactoryMap_t::iterator i = factories_.begin();
     52        i != factories_.end();
     53        ++i) {
     54     delete i->second;
     55   }
     56 
     57   delete ppapi_;
     58 }
     59 
     60 void KernelProxy::Init(PepperInterface* ppapi) {
     61   ppapi_ = ppapi;
     62   dev_ = 1;
     63 
     64   factories_["memfs"] = new TypedMountFactory<MountMem>;
     65   factories_["dev"] = new TypedMountFactory<MountDev>;
     66   factories_["html5fs"] = new TypedMountFactory<MountHtml5Fs>;
     67   factories_["httpfs"] = new TypedMountFactory<MountHttp>;
     68   factories_["passthroughfs"] = new TypedMountFactory<MountPassthrough>;
     69 
     70   int result;
     71   result = mount("", "/", "passthroughfs", 0, NULL);
     72   assert(result == 0);
     73 
     74   result = mount("", "/dev", "dev", 0, NULL);
     75   assert(result == 0);
     76 
     77   // Open the first three in order to get STDIN, STDOUT, STDERR
     78   open("/dev/stdin", O_RDONLY);
     79   open("/dev/stdout", O_WRONLY);
     80   open("/dev/stderr", O_WRONLY);
     81 
     82 #ifdef PROVIDES_SOCKET_API
     83   host_resolver_.Init(ppapi_);
     84 #endif
     85 }
     86 
     87 int KernelProxy::open_resource(const char* path) {
     88   ScopedMount mnt;
     89   Path rel;
     90 
     91   Error error = AcquireMountAndRelPath(path, &mnt, &rel);
     92   if (error) {
     93     errno = error;
     94     return -1;
     95   }
     96 
     97   ScopedMountNode node;
     98   error = mnt->OpenResource(rel, &node);
     99   if (error) {
    100     // OpenResource failed, try Open().
    101     error = mnt->Open(rel, O_RDONLY, &node);
    102     if (error) {
    103       errno = error;
    104       return -1;
    105     }
    106   }
    107 
    108   ScopedKernelHandle handle(new KernelHandle(mnt, node));
    109   error = handle->Init(O_RDONLY);
    110   if (error) {
    111     errno = error;
    112     return -1;
    113   }
    114 
    115   return AllocateFD(handle);
    116 }
    117 
    118 int KernelProxy::open(const char* path, int oflags) {
    119   ScopedMount mnt;
    120   ScopedMountNode node;
    121 
    122   Error error = AcquireMountAndNode(path, oflags, &mnt, &node);
    123   if (error) {
    124     errno = error;
    125     return -1;
    126   }
    127 
    128   ScopedKernelHandle handle(new KernelHandle(mnt, node));
    129   error = handle->Init(oflags);
    130   if (error) {
    131     errno = error;
    132     return -1;
    133   }
    134 
    135   return AllocateFD(handle);
    136 }
    137 
    138 int KernelProxy::close(int fd) {
    139   ScopedKernelHandle handle;
    140   Error error = AcquireHandle(fd, &handle);
    141   if (error) {
    142     errno = error;
    143     return -1;
    144   }
    145 
    146   // Remove the FD from the process open file descriptor map
    147   FreeFD(fd);
    148   return 0;
    149 }
    150 
    151 int KernelProxy::dup(int oldfd) {
    152   ScopedKernelHandle handle;
    153   Error error = AcquireHandle(oldfd, &handle);
    154   if (error) {
    155     errno = error;
    156     return -1;
    157   }
    158 
    159   return AllocateFD(handle);
    160 }
    161 
    162 int KernelProxy::dup2(int oldfd, int newfd) {
    163   // If it's the same file handle, just return
    164   if (oldfd == newfd)
    165     return newfd;
    166 
    167   ScopedKernelHandle old_handle;
    168   Error error = AcquireHandle(oldfd, &old_handle);
    169   if (error) {
    170     errno = error;
    171     return -1;
    172   }
    173 
    174   FreeAndReassignFD(newfd, old_handle);
    175   return newfd;
    176 }
    177 
    178 int KernelProxy::chdir(const char* path) {
    179   Error error = SetCWD(path);
    180   if (error) {
    181     errno = error;
    182     return -1;
    183   }
    184   return 0;
    185 }
    186 
    187 char* KernelProxy::getcwd(char* buf, size_t size) {
    188   std::string cwd = GetCWD();
    189 
    190   if (size <= 0) {
    191     errno = EINVAL;
    192     return NULL;
    193   }
    194 
    195   // If size is 0, allocate as much as we need.
    196   if (size == 0) {
    197     size = cwd.size() + 1;
    198   }
    199 
    200   // Verify the buffer is large enough
    201   if (size <= cwd.size()) {
    202     errno = ERANGE;
    203     return NULL;
    204   }
    205 
    206   // Allocate the buffer if needed
    207   if (buf == NULL) {
    208     buf = static_cast<char*>(malloc(size));
    209   }
    210 
    211   strcpy(buf, cwd.c_str());
    212   return buf;
    213 }
    214 
    215 char* KernelProxy::getwd(char* buf) {
    216   if (NULL == buf) {
    217     errno = EFAULT;
    218     return NULL;
    219   }
    220   return getcwd(buf, MAXPATHLEN);
    221 }
    222 
    223 int KernelProxy::chmod(const char* path, mode_t mode) {
    224   int fd = KernelProxy::open(path, O_RDONLY);
    225   if (-1 == fd)
    226     return -1;
    227 
    228   int result = fchmod(fd, mode);
    229   close(fd);
    230   return result;
    231 }
    232 
    233 int KernelProxy::chown(const char* path, uid_t owner, gid_t group) {
    234   return 0;
    235 }
    236 
    237 int KernelProxy::fchown(int fd, uid_t owner, gid_t group) {
    238   return 0;
    239 }
    240 
    241 int KernelProxy::lchown(const char* path, uid_t owner, gid_t group) {
    242   return 0;
    243 }
    244 
    245 int KernelProxy::utime(const char* filename, const struct utimbuf* times) {
    246   return 0;
    247 }
    248 
    249 int KernelProxy::mkdir(const char* path, mode_t mode) {
    250   ScopedMount mnt;
    251   Path rel;
    252 
    253   Error error = AcquireMountAndRelPath(path, &mnt, &rel);
    254   if (error) {
    255     errno = error;
    256     return -1;
    257   }
    258 
    259   error = mnt->Mkdir(rel, mode);
    260   if (error) {
    261     errno = error;
    262     return -1;
    263   }
    264 
    265   return 0;
    266 }
    267 
    268 int KernelProxy::rmdir(const char* path) {
    269   ScopedMount mnt;
    270   Path rel;
    271 
    272   Error error = AcquireMountAndRelPath(path, &mnt, &rel);
    273   if (error) {
    274     errno = error;
    275     return -1;
    276   }
    277 
    278   error = mnt->Rmdir(rel);
    279   if (error) {
    280     errno = error;
    281     return -1;
    282   }
    283 
    284   return 0;
    285 }
    286 
    287 int KernelProxy::stat(const char* path, struct stat* buf) {
    288   int fd = open(path, O_RDONLY);
    289   if (-1 == fd)
    290     return -1;
    291 
    292   int result = fstat(fd, buf);
    293   close(fd);
    294   return result;
    295 }
    296 
    297 
    298 int KernelProxy::mount(const char* source,
    299                        const char* target,
    300                        const char* filesystemtype,
    301                        unsigned long mountflags,
    302                        const void* data) {
    303   std::string abs_path = GetAbsParts(target).Join();
    304 
    305   // Find a factory of that type
    306   MountFactoryMap_t::iterator factory = factories_.find(filesystemtype);
    307   if (factory == factories_.end()) {
    308     errno = ENODEV;
    309     return -1;
    310   }
    311 
    312   // Create a map of settings
    313   StringMap_t smap;
    314   smap["SOURCE"] = source;
    315   smap["TARGET"] = abs_path;
    316 
    317   if (data) {
    318     char* str = strdup(static_cast<const char*>(data));
    319     char* ptr = strtok(str, ",");
    320     char* val;
    321     while (ptr != NULL) {
    322       val = strchr(ptr, '=');
    323       if (val) {
    324         *val = 0;
    325         smap[ptr] = val + 1;
    326       } else {
    327         smap[ptr] = "TRUE";
    328       }
    329       ptr = strtok(NULL, ",");
    330     }
    331     free(str);
    332   }
    333 
    334   ScopedMount mnt;
    335   Error error = factory->second->CreateMount(dev_++, smap, ppapi_, &mnt);
    336   if (error) {
    337     errno = error;
    338     return -1;
    339   }
    340 
    341   error = AttachMountAtPath(mnt, abs_path);
    342   if (error) {
    343     errno = error;
    344     return -1;
    345   }
    346 
    347   return 0;
    348 }
    349 
    350 int KernelProxy::umount(const char* path) {
    351   Error error = DetachMountAtPath(path);
    352   if (error) {
    353     errno = error;
    354     return -1;
    355   }
    356   return 0;
    357 }
    358 
    359 ssize_t KernelProxy::read(int fd, void* buf, size_t nbytes) {
    360   ScopedKernelHandle handle;
    361   Error error = AcquireHandle(fd, &handle);
    362   if (error) {
    363     errno = error;
    364     return -1;
    365   }
    366 
    367   int cnt = 0;
    368   error = handle->Read(buf, nbytes, &cnt);
    369   if (error) {
    370     errno = error;
    371     return -1;
    372   }
    373 
    374   return cnt;
    375 }
    376 
    377 ssize_t KernelProxy::write(int fd, const void* buf, size_t nbytes) {
    378   ScopedKernelHandle handle;
    379   Error error = AcquireHandle(fd, &handle);
    380   if (error) {
    381     errno = error;
    382     return -1;
    383   }
    384 
    385   int cnt = 0;
    386   error = handle->Write(buf, nbytes, &cnt);
    387   if (error) {
    388     errno = error;
    389     return -1;
    390   }
    391 
    392   return cnt;
    393 }
    394 
    395 int KernelProxy::fstat(int fd, struct stat* buf) {
    396   ScopedKernelHandle handle;
    397   Error error = AcquireHandle(fd, &handle);
    398   if (error) {
    399     errno = error;
    400     return -1;
    401   }
    402 
    403   error = handle->node()->GetStat(buf);
    404   if (error) {
    405     errno = error;
    406     return -1;
    407   }
    408 
    409   return 0;
    410 }
    411 
    412 int KernelProxy::getdents(int fd, void* buf, unsigned int count) {
    413   ScopedKernelHandle handle;
    414   Error error = AcquireHandle(fd, &handle);
    415   if (error) {
    416     errno = error;
    417     return -1;
    418   }
    419 
    420   int cnt = 0;
    421   error = handle->GetDents(static_cast<dirent*>(buf), count, &cnt);
    422   if (error)
    423     errno = error;
    424 
    425   return cnt;
    426 }
    427 
    428 int KernelProxy::ftruncate(int fd, off_t length) {
    429   ScopedKernelHandle handle;
    430   Error error = AcquireHandle(fd, &handle);
    431   if (error) {
    432     errno = error;
    433     return -1;
    434   }
    435 
    436   error = handle->node()->FTruncate(length);
    437   if (error) {
    438     errno = error;
    439     return -1;
    440   }
    441 
    442   return 0;
    443 }
    444 
    445 int KernelProxy::fsync(int fd) {
    446   ScopedKernelHandle handle;
    447   Error error = AcquireHandle(fd, &handle);
    448   if (error) {
    449     errno = error;
    450     return -1;
    451   }
    452 
    453   error = handle->node()->FSync();
    454   if (error) {
    455     errno = error;
    456     return -1;
    457   }
    458 
    459   return 0;
    460 }
    461 
    462 int KernelProxy::isatty(int fd) {
    463   ScopedKernelHandle handle;
    464   Error error = AcquireHandle(fd, &handle);
    465   if (error) {
    466     errno = error;
    467     return -1;
    468   }
    469 
    470   error = handle->node()->IsaTTY();
    471   if (error) {
    472     errno = error;
    473     return -1;
    474   }
    475 
    476   return 0;
    477 }
    478 
    479 int KernelProxy::ioctl(int fd, int request, char* argp) {
    480   ScopedKernelHandle handle;
    481   Error error = AcquireHandle(fd, &handle);
    482   if (error) {
    483     errno = error;
    484     return -1;
    485   }
    486 
    487   error = handle->node()->Ioctl(request, argp);
    488   if (error) {
    489     errno = error;
    490     return -1;
    491   }
    492 
    493   return 0;
    494 }
    495 
    496 off_t KernelProxy::lseek(int fd, off_t offset, int whence) {
    497   ScopedKernelHandle handle;
    498   Error error = AcquireHandle(fd, &handle);
    499   if (error) {
    500     errno = error;
    501     return -1;
    502   }
    503 
    504   off_t new_offset;
    505   error = handle->Seek(offset, whence, &new_offset);
    506   if (error) {
    507     errno = error;
    508     return -1;
    509   }
    510 
    511   return new_offset;
    512 }
    513 
    514 int KernelProxy::unlink(const char* path) {
    515   ScopedMount mnt;
    516   Path rel;
    517 
    518   Error error = AcquireMountAndRelPath(path, &mnt, &rel);
    519   if (error) {
    520     errno = error;
    521     return -1;
    522   }
    523 
    524   error = mnt->Unlink(rel);
    525   if (error) {
    526     errno = error;
    527     return -1;
    528   }
    529 
    530   return 0;
    531 }
    532 
    533 int KernelProxy::remove(const char* path) {
    534   ScopedMount mnt;
    535   Path rel;
    536 
    537   Error error = AcquireMountAndRelPath(path, &mnt, &rel);
    538   if (error) {
    539     errno = error;
    540     return -1;
    541   }
    542 
    543   error = mnt->Remove(rel);
    544   if (error) {
    545     errno = error;
    546     return -1;
    547   }
    548 
    549   return 0;
    550 }
    551 
    552 // TODO(noelallen): Needs implementation.
    553 int KernelProxy::fchmod(int fd, int mode) {
    554   ScopedKernelHandle handle;
    555   Error error = AcquireHandle(fd, &handle);
    556   if (error) {
    557     errno = error;
    558     return -1;
    559   }
    560 
    561   return 0;
    562 }
    563 
    564 int KernelProxy::access(const char* path, int amode) {
    565   ScopedMount mnt;
    566   Path rel;
    567 
    568   Error error = AcquireMountAndRelPath(path, &mnt, &rel);
    569   if (error) {
    570     errno = error;
    571     return -1;
    572   }
    573 
    574   error = mnt->Access(rel, amode);
    575   if (error) {
    576     errno = error;
    577     return -1;
    578   }
    579   return 0;
    580 }
    581 
    582 // TODO(noelallen): Needs implementation.
    583 int KernelProxy::link(const char* oldpath, const char* newpath) {
    584   errno = EINVAL;
    585   return -1;
    586 }
    587 
    588 int KernelProxy::symlink(const char* oldpath, const char* newpath) {
    589   errno = EINVAL;
    590   return -1;
    591 }
    592 
    593 void* KernelProxy::mmap(void* addr,
    594                         size_t length,
    595                         int prot,
    596                         int flags,
    597                         int fd,
    598                         size_t offset) {
    599   // We shouldn't be getting anonymous mmaps here.
    600   assert((flags & MAP_ANONYMOUS) == 0);
    601   assert(fd != -1);
    602 
    603   ScopedKernelHandle handle;
    604   Error error = AcquireHandle(fd, &handle);
    605   if (error) {
    606     errno = error;
    607     return MAP_FAILED;
    608   }
    609 
    610   void* new_addr;
    611   error = handle->node()->MMap(addr, length, prot, flags, offset, &new_addr);
    612   if (error) {
    613     errno = error;
    614     return MAP_FAILED;
    615   }
    616 
    617   return new_addr;
    618 }
    619 
    620 int KernelProxy::munmap(void* addr, size_t length) {
    621   // NOTE: The comment below is from a previous discarded implementation that
    622   // tracks mmap'd regions. For simplicity, we no longer do this; because we
    623   // "snapshot" the contents of the file in mmap(), and don't support
    624   // write-back or updating the mapped region when the file is written, holding
    625   // on to the KernelHandle is pointless.
    626   //
    627   // If we ever do, these threading issues should be considered.
    628 
    629   //
    630   // WARNING: this function may be called by free().
    631   //
    632   // There is a potential deadlock scenario:
    633   // Thread 1: open() -> takes lock1 -> free() -> takes lock2
    634   // Thread 2: free() -> takes lock2 -> munmap() -> takes lock1
    635   //
    636   // Note that open() above could be any function that takes a lock that is
    637   // shared with munmap (this includes munmap!)
    638   //
    639   // To prevent this, we avoid taking locks in munmap() that are used by other
    640   // nacl_io functions that may call free. Specifically, we only take the
    641   // mmap_lock, which is only shared with mmap() above. There is still a
    642   // possibility of deadlock if mmap() or munmap() calls free(), so this is not
    643   // allowed.
    644   //
    645   // Unfortunately, munmap still needs to acquire other locks; see the call to
    646   // ReleaseHandle below which takes the process lock. This is safe as long as
    647   // this is never executed from free() -- we can be reasonably sure this is
    648   // true, because malloc only makes anonymous mmap() requests, and should only
    649   // be munmapping those allocations. We never add to mmap_info_list_ for
    650   // anonymous maps, so the unmap_list should always be empty when called from
    651   // free().
    652   return 0;
    653 }
    654 
    655 int KernelProxy::tcflush(int fd, int queue_selector) {
    656   ScopedKernelHandle handle;
    657   Error error = AcquireHandle(fd, &handle);
    658   if (error) {
    659     errno = error;
    660     return -1;
    661   }
    662 
    663   error = handle->node()->Tcflush(queue_selector);
    664   if (error) {
    665     errno = error;
    666     return -1;
    667   }
    668 
    669   return 0;
    670 }
    671 
    672 int KernelProxy::tcgetattr(int fd, struct termios* termios_p) {
    673   ScopedKernelHandle handle;
    674   Error error = AcquireHandle(fd, &handle);
    675   if (error) {
    676     errno = error;
    677     return -1;
    678   }
    679 
    680   error = handle->node()->Tcgetattr(termios_p);
    681   if (error) {
    682     errno = error;
    683     return -1;
    684   }
    685 
    686   return 0;
    687 }
    688 
    689 int KernelProxy::tcsetattr(int fd, int optional_actions,
    690                            const struct termios *termios_p) {
    691   ScopedKernelHandle handle;
    692   Error error = AcquireHandle(fd, &handle);
    693   if (error) {
    694     errno = error;
    695     return -1;
    696   }
    697 
    698   error = handle->node()->Tcsetattr(optional_actions, termios_p);
    699   if (error) {
    700     errno = error;
    701     return -1;
    702   }
    703 
    704   return 0;
    705 }
    706 
    707 #ifdef PROVIDES_SOCKET_API
    708 
    709 int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds,
    710                         fd_set* exceptfds, struct timeval* timeout) {
    711   ScopedEventListener listener(new EventListener);
    712   std::vector<struct pollfd> fds;
    713 
    714   fd_set readout, writeout, exceptout;
    715 
    716   FD_ZERO(&readout);
    717   FD_ZERO(&writeout);
    718   FD_ZERO(&exceptout);
    719 
    720   int fd;
    721   size_t event_cnt = 0;
    722   int event_track = 0;
    723   for (fd = 0; fd < nfds; fd++) {
    724     int events = 0;
    725 
    726     if (readfds != NULL && FD_ISSET(fd, readfds))
    727       events |= POLLIN;
    728 
    729     if (writefds != NULL && FD_ISSET(fd, writefds))
    730       events |= POLLOUT;
    731 
    732     if (exceptfds != NULL && FD_ISSET(fd, exceptfds))
    733       events |= POLLERR | POLLHUP;
    734 
    735     // If we are not interested in this FD, skip it
    736     if (0 == events) continue;
    737 
    738     ScopedKernelHandle handle;
    739     Error err = AcquireHandle(fd, &handle);
    740 
    741     // Select will return immediately if there are bad FDs.
    742     if (err != 0) {
    743       errno = EBADF;
    744       return -1;
    745     }
    746 
    747     int status = handle->node()->GetEventStatus() & events;
    748     if (status & POLLIN) {
    749       FD_SET(fd, &readout);
    750       event_cnt++;
    751     }
    752 
    753     if (status & POLLOUT) {
    754       FD_SET(fd, &writeout);
    755       event_cnt++;
    756     }
    757 
    758     if (status & (POLLERR | POLLHUP)) {
    759       FD_SET(fd, &exceptout);
    760       event_cnt++;
    761     }
    762 
    763     // Otherwise track it.
    764     if (0 == status) {
    765       err = listener->Track(fd, handle->node(), events, fd);
    766       if (err != 0) {
    767         errno = EBADF;
    768         return -1;
    769       }
    770       event_track++;
    771     }
    772   }
    773 
    774   // If nothing is signaled, then we must wait.
    775   if (event_cnt == 0) {
    776     std::vector<EventData> events;
    777     int ready_cnt;
    778     int ms_timeout;
    779 
    780     // NULL timeout signals wait forever.
    781     if (timeout == NULL) {
    782       ms_timeout = -1;
    783     } else {
    784       int64_t ms = timeout->tv_sec * 1000 + ((timeout->tv_usec + 500) / 1000);
    785 
    786       // If the timeout is invalid or too long (larger than signed 32 bit).
    787       if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) ||
    788           (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000) ||
    789           (ms < 0) || (ms >= INT_MAX)) {
    790         errno = EINVAL;
    791         return -1;
    792       }
    793 
    794       ms_timeout = static_cast<int>(ms);
    795     }
    796 
    797     events.resize(event_track);
    798     listener->Wait(events.data(), event_track, ms_timeout, &ready_cnt);
    799     for (fd = 0; static_cast<int>(fd) < ready_cnt; fd++) {
    800       if (events[fd].events & POLLIN) {
    801         FD_SET(events[fd].user_data, &readout);
    802         event_cnt++;
    803       }
    804 
    805       if (events[fd].events & POLLOUT) {
    806         FD_SET(events[fd].user_data, &writeout);
    807         event_cnt++;
    808       }
    809 
    810       if (events[fd].events & (POLLERR | POLLHUP)) {
    811         FD_SET(events[fd].user_data, &exceptout);
    812         event_cnt++;
    813       }
    814     }
    815   }
    816 
    817   // Copy out the results
    818   if (readfds != NULL)
    819     *readfds = readout;
    820 
    821   if (writefds != NULL)
    822     *writefds = writeout;
    823 
    824   if (exceptfds != NULL)
    825     *exceptfds = exceptout;
    826 
    827   return event_cnt;
    828 }
    829 
    830 int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) {
    831   ScopedEventListener listener(new EventListener);
    832 
    833   int index;
    834   size_t event_cnt = 0;
    835   size_t event_track = 0;
    836   for (index = 0; static_cast<nfds_t>(index) < nfds; index++) {
    837     ScopedKernelHandle handle;
    838     struct pollfd* info = &fds[index];
    839     Error err = AcquireHandle(info->fd, &handle);
    840 
    841     // If the node isn't open, or somehow invalid, mark it so.
    842     if (err != 0) {
    843       info->revents = POLLNVAL;
    844       event_cnt++;
    845       continue;
    846     }
    847 
    848     // If it's already signaled, then just capture the event
    849     if (handle->node()->GetEventStatus() & info->events) {
    850       info->revents = info->events & handle->node()->GetEventStatus();
    851       event_cnt++;
    852       continue;
    853     }
    854 
    855     // Otherwise try to track it.
    856     err = listener->Track(info->fd, handle->node(), info->events, index);
    857     if (err != 0) {
    858       info->revents = POLLNVAL;
    859       event_cnt++;
    860       continue;
    861     }
    862     event_track++;
    863   }
    864 
    865   // If nothing is signaled, then we must wait.
    866   if (0 == event_cnt) {
    867     std::vector<EventData> events;
    868     int ready_cnt;
    869 
    870     events.resize(event_track);
    871     listener->Wait(events.data(), event_track, timeout, &ready_cnt);
    872     for (index = 0; index < ready_cnt; index++) {
    873       struct pollfd* info = &fds[events[index].user_data];
    874 
    875       info->revents = events[index].events;
    876       event_cnt++;
    877     }
    878   }
    879 
    880   return event_cnt;
    881 }
    882 
    883 
    884 
    885 // Socket Functions
    886 int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
    887   if (NULL == addr || NULL == len) {
    888     errno = EFAULT;
    889     return -1;
    890   }
    891 
    892   ScopedKernelHandle handle;
    893   if (AcquireSocketHandle(fd, &handle) == -1)
    894     return -1;
    895 
    896   errno = EINVAL;
    897   return -1;
    898 }
    899 
    900 int KernelProxy::bind(int fd, const struct sockaddr* addr, socklen_t len) {
    901   if (NULL == addr) {
    902     errno = EFAULT;
    903     return -1;
    904   }
    905 
    906   ScopedKernelHandle handle;
    907   if (AcquireSocketHandle(fd, &handle) == -1)
    908     return -1;
    909 
    910   errno = EINVAL;
    911   return -1;
    912 }
    913 
    914 int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) {
    915   if (NULL == addr) {
    916     errno = EFAULT;
    917     return -1;
    918   }
    919 
    920   ScopedKernelHandle handle;
    921   if (AcquireSocketHandle(fd, &handle) == -1)
    922     return -1;
    923 
    924   errno = EACCES;
    925   return -1;
    926 }
    927 
    928 struct hostent* KernelProxy::gethostbyname(const char* name) {
    929   return host_resolver_.gethostbyname(name);
    930 }
    931 
    932 int KernelProxy::getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
    933   if (NULL == addr || NULL == len) {
    934     errno = EFAULT;
    935     return -1;
    936   }
    937 
    938   ScopedKernelHandle handle;
    939   if (AcquireSocketHandle(fd, &handle) == -1)
    940     return -1;
    941 
    942   errno = EINVAL;
    943   return -1;
    944 }
    945 
    946 int KernelProxy::getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
    947   if (NULL == addr || NULL == len) {
    948     errno = EFAULT;
    949     return -1;
    950   }
    951 
    952   ScopedKernelHandle handle;
    953   if (AcquireSocketHandle(fd, &handle) == -1)
    954     return -1;
    955 
    956   errno = EINVAL;
    957   return -1;
    958 }
    959 
    960 int KernelProxy::getsockopt(int fd,
    961                          int lvl,
    962                          int optname,
    963                          void* optval,
    964                          socklen_t* len) {
    965   if (NULL == optval || NULL == len) {
    966     errno = EFAULT;
    967     return -1;
    968   }
    969 
    970   ScopedKernelHandle handle;
    971   if (AcquireSocketHandle(fd, &handle) == -1)
    972     return -1;
    973 
    974   errno = EINVAL;
    975   return -1;
    976 }
    977 
    978 int KernelProxy::listen(int fd, int backlog) {
    979   ScopedKernelHandle handle;
    980   if (AcquireSocketHandle(fd, &handle) == -1)
    981     return -1;
    982 
    983   errno = EOPNOTSUPP;
    984   return -1;
    985 }
    986 
    987 ssize_t KernelProxy::recv(int fd,
    988                           void* buf,
    989                           size_t len,
    990                           int flags) {
    991   if (NULL == buf) {
    992     errno = EFAULT;
    993     return -1;
    994   }
    995 
    996   ScopedKernelHandle handle;
    997   if (AcquireSocketHandle(fd, &handle) == -1)
    998     return -1;
    999 
   1000   errno = EINVAL;
   1001   return -1;
   1002 }
   1003 
   1004 ssize_t KernelProxy::recvfrom(int fd,
   1005                               void* buf,
   1006                               size_t len,
   1007                               int flags,
   1008                               struct sockaddr* addr,
   1009                               socklen_t* addrlen) {
   1010   // According to the manpage, recvfrom with a null addr is identical to recv.
   1011   if (NULL == addr) {
   1012     return recv(fd, buf, len, flags);
   1013   }
   1014 
   1015   if (NULL == buf || NULL == addrlen) {
   1016     errno = EFAULT;
   1017     return -1;
   1018   }
   1019 
   1020   ScopedKernelHandle handle;
   1021   if (AcquireSocketHandle(fd, &handle) == -1)
   1022     return -1;
   1023 
   1024   errno = EINVAL;
   1025   return -1;
   1026 }
   1027 
   1028 ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) {
   1029   if (NULL == msg ) {
   1030     errno = EFAULT;
   1031     return -1;
   1032   }
   1033 
   1034   ScopedKernelHandle handle;
   1035   if (AcquireSocketHandle(fd, &handle) == -1)
   1036     return -1;
   1037 
   1038   errno = EOPNOTSUPP;
   1039   return -1;
   1040 }
   1041 
   1042 ssize_t KernelProxy::send(int fd, const void* buf, size_t len, int flags) {
   1043   if (NULL == buf) {
   1044     errno = EFAULT;
   1045     return -1;
   1046   }
   1047 
   1048   ScopedKernelHandle handle;
   1049   if (AcquireSocketHandle(fd, &handle) == -1)
   1050     return -1;
   1051 
   1052   errno = EINVAL;
   1053   return -1;
   1054 }
   1055 
   1056 ssize_t KernelProxy::sendto(int fd,
   1057                             const void* buf,
   1058                             size_t len,
   1059                             int flags,
   1060                             const struct sockaddr* addr,
   1061                             socklen_t addrlen) {
   1062   // According to the manpage, sendto with a null addr is identical to send.
   1063   if (NULL == addr) {
   1064     return send(fd, buf, len, flags);
   1065   }
   1066 
   1067   if (NULL == buf) {
   1068     errno = EFAULT;
   1069     return -1;
   1070   }
   1071 
   1072   ScopedKernelHandle handle;
   1073   if (AcquireSocketHandle(fd, &handle) == -1)
   1074     return -1;
   1075 
   1076   errno = EINVAL;
   1077   return -1;
   1078 }
   1079 
   1080 ssize_t KernelProxy::sendmsg(int fd, const struct msghdr* msg, int flags) {
   1081   if (NULL == msg) {
   1082     errno = EFAULT;
   1083     return -1;
   1084   }
   1085 
   1086   ScopedKernelHandle handle;
   1087   if (AcquireSocketHandle(fd, &handle) == -1)
   1088     return -1;
   1089 
   1090   errno = EOPNOTSUPP;
   1091   return -1;
   1092 }
   1093 
   1094 int KernelProxy::setsockopt(int fd,
   1095                             int lvl,
   1096                             int optname,
   1097                             const void* optval,
   1098                             socklen_t len) {
   1099   if (NULL == optval) {
   1100     errno = EFAULT;
   1101     return -1;
   1102   }
   1103 
   1104   ScopedKernelHandle handle;
   1105   if (AcquireSocketHandle(fd, &handle) == -1)
   1106     return -1;
   1107 
   1108   errno = EINVAL;
   1109   return -1;
   1110 }
   1111 
   1112 int KernelProxy::shutdown(int fd, int how) {
   1113   ScopedKernelHandle handle;
   1114   if (AcquireSocketHandle(fd, &handle) == -1)
   1115     return -1;
   1116 
   1117   errno = EINVAL;
   1118   return -1;
   1119 }
   1120 
   1121 int KernelProxy::socket(int domain, int type, int protocol) {
   1122   if (AF_INET != domain && AF_INET6 != domain) {
   1123     errno = EAFNOSUPPORT;
   1124     return -1;
   1125   }
   1126 
   1127   if (SOCK_STREAM != type && SOCK_DGRAM != type) {
   1128     errno = EPROTONOSUPPORT;
   1129     return -1;
   1130   }
   1131 
   1132   errno = EACCES;
   1133   return -1;
   1134 }
   1135 
   1136 int KernelProxy::socketpair(int domain, int type, int protocol, int* sv) {
   1137   if (NULL == sv) {
   1138     errno = EFAULT;
   1139     return -1;
   1140   }
   1141 
   1142   // Catch-22: We don't support AF_UNIX, but any other AF doesn't support
   1143   // socket pairs. Thus, this function always fails.
   1144   if (AF_UNIX != domain) {
   1145     errno = EPROTONOSUPPORT;
   1146     return -1;
   1147   }
   1148 
   1149   if (AF_INET != domain && AF_INET6 != domain) {
   1150     errno = EAFNOSUPPORT;
   1151     return -1;
   1152   }
   1153 
   1154   // We cannot reach this point.
   1155   errno = ENOSYS;
   1156   return -1;
   1157 }
   1158 
   1159 int KernelProxy::AcquireSocketHandle(int fd, ScopedKernelHandle* handle) {
   1160   Error error = AcquireHandle(fd, handle);
   1161 
   1162   if (error) {
   1163     errno = error;
   1164     return -1;
   1165   }
   1166 
   1167   if ((handle->get()->node_->GetType() & S_IFSOCK) == 0) {
   1168     errno = ENOTSOCK;
   1169     return -1;
   1170   }
   1171 
   1172   return 0;
   1173 }
   1174 
   1175 #endif  // PROVIDES_SOCKET_API
   1176 
   1177 }  // namespace_nacl_io
   1178