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