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