kernel_proxy.cc revision f2477e01787aa58f445919b809d89e252beef54f
1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// found in the LICENSE file.
4ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/kernel_proxy.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <assert.h>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <errno.h>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <fcntl.h>
103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <limits.h>
113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <poll.h>
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <pthread.h>
13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include <stdio.h>
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string.h>
153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <sys/time.h>
163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <unistd.h>
173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <iterator>
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "nacl_io/host_resolver.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/kernel_handle.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/kernel_wrap_real.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_dev.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_html5fs.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_http.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_mem.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_node.h"
3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "nacl_io/mount_node_pipe.h"
313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "nacl_io/mount_node_tcp.h"
323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "nacl_io/mount_node_udp.h"
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_passthrough.h"
3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "nacl_io/mount_stream.h"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osmman.h"
36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "nacl_io/ossocket.h"
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osstat.h"
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/path.h"
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/pepper_interface.h"
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "nacl_io/typed_mount_factory.h"
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/auto_lock.h"
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/ref_object.h"
4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "sdk_util/string_util.h"
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef MAXPATHLEN
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define MAXPATHLEN 256
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
49ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace nacl_io {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL),
5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                             signal_emitter_(new EventEmitter) {
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   memset(&sigwinch_handler_, 0, sizeof(sigwinch_handler_));
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   sigwinch_handler_.sa_handler = SIG_DFL;
567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochKernelProxy::~KernelProxy() {
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Clean up the MountFactories.
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (MountFactoryMap_t::iterator i = factories_.begin();
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       i != factories_.end();
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       ++i) {
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    delete i->second;
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  delete ppapi_;
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)Error KernelProxy::Init(PepperInterface* ppapi) {
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Error rtn = 0;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ppapi_ = ppapi;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dev_ = 1;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["memfs"] = new TypedMountFactory<MountMem>;
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["dev"] = new TypedMountFactory<MountDev>;
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["html5fs"] = new TypedMountFactory<MountHtml5Fs>;
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["httpfs"] = new TypedMountFactory<MountHttp>;
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["passthroughfs"] = new TypedMountFactory<MountPassthrough>;
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result;
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  result = mount("", "/", "passthroughfs", 0, NULL);
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (result != 0) {
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    assert(false);
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  result = mount("", "/dev", "dev", 0, NULL);
8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (result != 0) {
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    assert(false);
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Open the first three in order to get STDIN, STDOUT, STDERR
9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int fd;
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  fd = open("/dev/stdin", O_RDONLY);
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert(fd == 0);
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (fd < 0)
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  fd = open("/dev/stdout", O_WRONLY);
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert(fd == 1);
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (fd < 0)
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  fd = open("/dev/stderr", O_WRONLY);
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert(fd == 2);
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (fd < 0)
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
109bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
110bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#ifdef PROVIDES_SOCKET_API
111bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  host_resolver_.Init(ppapi_);
112bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#endif
1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StringMap_t args;
11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  stream_mount_.reset(new MountStream());
11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  result = stream_mount_->Init(0, args, ppapi);
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (result != 0) {
11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    assert(false);
11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = result;
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return rtn;
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint KernelProxy::open_resource(const char* path) {
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMount mnt;
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMountNode node;
1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = mnt->OpenResource(rel, &node);
1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // OpenResource failed, try Open().
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    error = mnt->Open(rel, O_RDONLY, &node);
1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (error) {
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      errno = error;
1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return -1;
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedKernelHandle handle(new KernelHandle(mnt, node));
1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Init(O_RDONLY);
1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return AllocateFD(handle);
1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int KernelProxy::open(const char* path, int open_flags) {
1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMount mnt;
1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMountNode node;
1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireMountAndNode(path, open_flags, &mnt, &node);
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle(new KernelHandle(mnt, node));
1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Init(open_flags);
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return AllocateFD(handle);
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int KernelProxy::pipe(int pipefds[2]) {
17768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  MountNodePipe* pipe = new MountNodePipe(stream_mount_.get());
17868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ScopedMountNode node(pipe);
17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (pipe->Init(O_RDWR) == 0) {
18168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ScopedKernelHandle handle0(new KernelHandle(stream_mount_, node));
18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ScopedKernelHandle handle1(new KernelHandle(stream_mount_, node));
18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
18468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Should never fail, but...
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (handle0->Init(O_RDONLY) || handle1->Init(O_WRONLY)) {
18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      errno = EACCES;
18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return -1;
18868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pipefds[0] = AllocateFD(handle0);
19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pipefds[1] = AllocateFD(handle1);
19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return 0;
19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
19468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  errno = ENOSYS;
19668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return -1;
19768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
19868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::close(int fd) {
200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Remove the FD from the process open file descriptor map
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FreeFD(fd);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::dup(int oldfd) {
213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(oldfd, &handle);
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return AllocateFD(handle);
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::dup2(int oldfd, int newfd) {
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If it's the same file handle, just return
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (oldfd == newfd)
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return newfd;
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle old_handle;
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(oldfd, &old_handle);
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FreeAndReassignFD(newfd, old_handle);
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return newfd;
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint KernelProxy::chdir(const char* path) {
2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = SetCWD(path);
2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
2437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
2447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return 0;
2467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)char* KernelProxy::getcwd(char* buf, size_t size) {
2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string cwd = GetCWD();
2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (size <= 0) {
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = EINVAL;
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If size is 0, allocate as much as we need.
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (size == 0) {
2587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    size = cwd.size() + 1;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify the buffer is large enough
2627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (size <= cwd.size()) {
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = ERANGE;
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Allocate the buffer if needed
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (buf == NULL) {
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    buf = static_cast<char*>(malloc(size));
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  strcpy(buf, cwd.c_str());
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return buf;
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)char* KernelProxy::getwd(char* buf) {
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == buf) {
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = EFAULT;
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return getcwd(buf, MAXPATHLEN);
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::chmod(const char* path, mode_t mode) {
285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int fd = KernelProxy::open(path, O_RDONLY);
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (-1 == fd)
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result = fchmod(fd, mode);
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  close(fd);
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::chown(const char* path, uid_t owner, gid_t group) {
295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::fchown(int fd, uid_t owner, gid_t group) {
299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::lchown(const char* path, uid_t owner, gid_t group) {
303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::utime(const char* filename, const struct utimbuf* times) {
307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::mkdir(const char* path, mode_t mode) {
311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMount mnt;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
3137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = mnt->Mkdir(rel, mode);
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::rmdir(const char* path) {
330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMount mnt;
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
3327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = mnt->Rmdir(rel);
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::stat(const char* path, struct stat* buf) {
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = open(path, O_RDONLY);
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (-1 == fd)
351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result = fstat(fd, buf);
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  close(fd);
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::mount(const char* source,
360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const char* target,
361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const char* filesystemtype,
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       unsigned long mountflags,
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const void* data) {
3647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string abs_path = GetAbsParts(target).Join();
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Find a factory of that type
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MountFactoryMap_t::iterator factory = factories_.find(filesystemtype);
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (factory == factories_.end()) {
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = ENODEV;
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Create a map of settings
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StringMap_t smap;
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  smap["SOURCE"] = source;
3767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  smap["TARGET"] = abs_path;
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (data) {
37958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::vector<std::string> elements;
38058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    sdk_util::SplitString(static_cast<const char*>(data), ',', &elements);
38158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
38258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    for (std::vector<std::string>::const_iterator it = elements.begin();
38358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)         it != elements.end(); ++it) {
38458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      size_t location = it->find('=');
38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (location != std::string::npos) {
38658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        std::string key = it->substr(0, location);
38758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        std::string val = it->substr(location + 1);
38858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        smap[key] = val;
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
39058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        smap[*it] = "TRUE";
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMount mnt;
3967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = factory->second->CreateMount(dev_++, smap, ppapi_, &mnt);
3977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
3987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
3997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
4007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
4017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = AttachMountAtPath(mnt, abs_path);
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return 0;
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::umount(const char* path) {
4127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = DetachMountAtPath(path);
4137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
4147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ssize_t KernelProxy::read(int fd, void* buf, size_t nbytes) {
421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
4297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Read(buf, nbytes, &cnt);
430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
438868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ssize_t KernelProxy::write(int fd, const void* buf, size_t nbytes) {
439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
446868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
4477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Write(buf, nbytes, &cnt);
448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fstat(int fd, struct stat* buf) {
457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->GetStat(buf);
465868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
466868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::getdents(int fd, void* buf, unsigned int count) {
474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
475868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
476868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
477868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
478868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
4827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->GetDents(static_cast<dirent*>(buf), count, &cnt);
483868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error)
484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::fchdir(int fd) {
4908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = ENOSYS;
4918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
4928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
4938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
49490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int KernelProxy::ftruncate(int fd, off_t length) {
495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
500868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
50190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->FTruncate(length);
503868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
504868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
50790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
50990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
51090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fsync(int fd) {
512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->FSync();
520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::fdatasync(int fd) {
5298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = ENOSYS;
5308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
5318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
5328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::isatty(int fd) {
534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->IsaTTY();
542868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
543868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int KernelProxy::ioctl(int fd, int request, va_list args) {
551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
552bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->node()->VIoctl(request, args);
559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)off_t KernelProxy::lseek(int fd, off_t offset, int whence) {
568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  off_t new_offset;
576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = handle->Seek(offset, whence, &new_offset);
577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
579eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
580868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return new_offset;
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::unlink(const char* path) {
586eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMount mnt;
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
5887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
593868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
595868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = mnt->Unlink(rel);
596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
597868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::truncate(const char* path, off_t len) {
6058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = ENOSYS;
6068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
6078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::lstat(const char* path, struct stat* buf) {
6108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = ENOSYS;
6118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
6128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::rename(const char* path, const char* newpath) {
615f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ScopedMount mnt;
616f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Path rel;
617f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (error) {
619f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = error;
620f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
621f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
622f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
623f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ScopedMount newmnt;
624f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Path newrel;
625f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  error = AcquireMountAndRelPath(newpath, &newmnt, &newrel);
626f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (error) {
627f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = error;
628f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
629f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
630f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
631f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (newmnt.get() != mnt.get()) {
632f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Renaming accross mountpoints is not allowed
633f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = EXDEV;
634f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
635f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
636f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
637f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // They already point to the same path
638f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (rel == newrel)
639f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return 0;
640f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
641f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  error = mnt->Rename(rel, newrel);
642f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (error) {
643f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = error;
644f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
645f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
646f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
647f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return 0;
6488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::remove(const char* path) {
651eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMount mnt;
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
6537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
6547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
655868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
656868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
657868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
658868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
660868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = mnt->Remove(rel);
661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
663eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
666eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(noelallen): Needs implementation.
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fchmod(int fd, int mode) {
671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Error error = AcquireHandle(fd, &handle);
673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int KernelProxy::fcntl(int fd, int request, va_list args) {
6821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Error error = 0;
6831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
6841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // F_GETFD and F_SETFD are descirptor specific flags that
6851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // are stored in the KernelObject's decriptor map unlink
6861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // F_GETFL and F_SETFL which are handle specific.
6871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  switch (request) {
6881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case F_GETFD: {
6891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      int rtn = -1;
6901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      error = GetFDFlags(fd, &rtn);
6911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (error) {
6921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        errno = error;
6931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        return -1;
6941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      }
6951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return rtn;
6961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
6971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case F_SETFD: {
6981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      int flags = va_arg(args, int);
6991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      error = SetFDFlags(fd, flags);
7001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (error) {
7011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        errno = error;
7021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        return -1;
7031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      }
7041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return 0;
7051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
7061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
7071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
70868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ScopedKernelHandle handle;
7091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  error = AcquireHandle(fd, &handle);
71068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error) {
71168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    errno = error;
71268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return -1;
71368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
71468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int rtn = 0;
7164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->VFcntl(request, &rtn, args);
7174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
7184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
7194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
7204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
7214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return rtn;
72368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
72468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::access(const char* path, int amode) {
7267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMount mnt;
727eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Path rel;
728eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
7297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
730eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
731eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
732eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
733eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
734eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
735eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  error = mnt->Access(rel, amode);
736eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
738eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
739eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
740eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::readlink(const char *path, char *buf, size_t count) {
7448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = EINVAL;
7458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
7468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
7478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::utimes(const char *filename, const struct timeval times[2]) {
7498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = EINVAL;
7508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
7518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
7528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
753eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// TODO(noelallen): Needs implementation.
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::link(const char* oldpath, const char* newpath) {
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::symlink(const char* oldpath, const char* newpath) {
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
764868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void* KernelProxy::mmap(void* addr,
765868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        size_t length,
766868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int prot,
767868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int flags,
768868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int fd,
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        size_t offset) {
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We shouldn't be getting anonymous mmaps here.
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert((flags & MAP_ANONYMOUS) == 0);
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert(fd != -1);
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
774eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
775868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
776868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
777868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return MAP_FAILED;
779868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void* new_addr;
7827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->MMap(addr, length, prot, flags, offset, &new_addr);
783eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
784eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
785eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return MAP_FAILED;
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return new_addr;
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::munmap(void* addr, size_t length) {
79290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // NOTE: The comment below is from a previous discarded implementation that
79390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // tracks mmap'd regions. For simplicity, we no longer do this; because we
79490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // "snapshot" the contents of the file in mmap(), and don't support
79590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // write-back or updating the mapped region when the file is written, holding
79690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // on to the KernelHandle is pointless.
79790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
79890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If we ever do, these threading issues should be considered.
79990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
80090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
80190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // WARNING: this function may be called by free().
80290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
80390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // There is a potential deadlock scenario:
80490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Thread 1: open() -> takes lock1 -> free() -> takes lock2
80590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Thread 2: free() -> takes lock2 -> munmap() -> takes lock1
80690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
80790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Note that open() above could be any function that takes a lock that is
80890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // shared with munmap (this includes munmap!)
80990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
81090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // To prevent this, we avoid taking locks in munmap() that are used by other
81190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // nacl_io functions that may call free. Specifically, we only take the
81290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // mmap_lock, which is only shared with mmap() above. There is still a
81390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // possibility of deadlock if mmap() or munmap() calls free(), so this is not
81490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // allowed.
81590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
81690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Unfortunately, munmap still needs to acquire other locks; see the call to
81790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // ReleaseHandle below which takes the process lock. This is safe as long as
81890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // this is never executed from free() -- we can be reasonably sure this is
81990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // true, because malloc only makes anonymous mmap() requests, and should only
82090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // be munmapping those allocations. We never add to mmap_info_list_ for
82190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // anonymous maps, so the unmap_list should always be empty when called from
82290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // free().
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
826bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint KernelProxy::tcflush(int fd, int queue_selector) {
827bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ScopedKernelHandle handle;
828bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
829bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
830bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
831bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
832bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
833bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
834bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  error = handle->node()->Tcflush(queue_selector);
835bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
836bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
837bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
838bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
839bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
840bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return 0;
841bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
842bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
843bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint KernelProxy::tcgetattr(int fd, struct termios* termios_p) {
844bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ScopedKernelHandle handle;
845bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
846bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
847bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
848bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
849bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
850bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
851bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  error = handle->node()->Tcgetattr(termios_p);
852bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
853bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
854bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
855bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
856bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
857bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return 0;
858bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
859bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
860bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint KernelProxy::tcsetattr(int fd, int optional_actions,
861bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                           const struct termios *termios_p) {
862bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ScopedKernelHandle handle;
863bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
864bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
865bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
866bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
867bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
868bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
869bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  error = handle->node()->Tcsetattr(optional_actions, termios_p);
870bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
871bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
872bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
873bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
874bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
875bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return 0;
876bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
877bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
8783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int KernelProxy::kill(pid_t pid, int sig) {
8793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Currently we don't even pretend that other processes exist
8803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // so we can only send a signal to outselves.  For kill(2)
8813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // pid 0 means the current process group and -1 means all the
8823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // processes we have permission to send signals to.
8833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (pid != getpid() && pid != -1 && pid != 0) {
8843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = ESRCH;
8853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
8863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
8873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
8883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Raise an event so that select/poll get interrupted.
88968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  AUTO_LOCK(signal_emitter_->GetLock())
89068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  signal_emitter_->RaiseEvents_Locked(POLLERR);
8913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (sig) {
8923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGWINCH:
893f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (sigwinch_handler_.sa_handler != SIG_IGN &&
894f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          sigwinch_handler_.sa_handler != SIG_DFL) {
895f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        sigwinch_handler_.sa_handler(SIGWINCH);
896f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
8973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
8983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
8993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGUSR1:
9003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGUSR2:
9013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
9023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
9033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    default:
9043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      errno = EINVAL;
9053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return -1;
9063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
9073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
9083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
9093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
910f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)int KernelProxy::sigaction(int signum, const struct sigaction* action,
911f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           struct sigaction* oaction) {
912f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (action && action->sa_flags & SA_SIGINFO) {
913f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // We don't support SA_SIGINFO (sa_sigaction field) yet
914f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = EINVAL;
915f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
916f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
917f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
9183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (signum) {
9193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Handled signals.
9203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGWINCH: {
921f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (oaction)
922f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        *oaction = sigwinch_handler_;
923f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (action) {
924f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        sigwinch_handler_ = *action;
925f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
926f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return 0;
9273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
9283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
9293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Known signals
9303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGHUP:
9313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGINT:
9323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGPIPE:
9333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGPOLL:
9343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGPROF:
9353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGTERM:
9363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGCHLD:
9373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGURG:
9383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGFPE:
9393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGILL:
9403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGQUIT:
9413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGSEGV:
9423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGTRAP:
943f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (action && action->sa_handler != SIG_DFL) {
944f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        // Trying to set this action to anything other than SIG_DFL
945f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        // is not yet supported.
946f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        errno = EINVAL;
947f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return -1;
948f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
949f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
950f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (oaction) {
951f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        memset(oaction, 0, sizeof(*oaction));
952f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        oaction->sa_handler = SIG_DFL;
953f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
954f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return 0;
955f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
956f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // KILL and STOP cannot be handled
957f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SIGKILL:
958f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SIGSTOP:
959f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      errno = EINVAL;
960f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return -1;
9613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
9623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
963f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Unknown signum
9643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  errno = EINVAL;
965f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return -1;
9663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
9673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
968a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#ifdef PROVIDES_SOCKET_API
969ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
9703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochint KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds,
9713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                        fd_set* exceptfds, struct timeval* timeout) {
97268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  fd_set ignore;
97368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<pollfd> pollfds;
97468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
97568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Simplify logic, by using an IGNORE set for any undefined set
97668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FD_ZERO(&ignore);
97768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (NULL == readfds)
97868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    readfds = &ignore;
97968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (NULL == writefds)
98068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    writefds = &ignore;
98168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (NULL == exceptfds)
98268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    exceptfds = &ignore;
98368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
98468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (int fd = 0; fd < nfds; fd++) {
9853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    int events = 0;
98668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (FD_ISSET(fd, readfds))
9873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      events |= POLLIN;
9883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
98968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (FD_ISSET(fd, writefds))
9903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      events |= POLLOUT;
9913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
99268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (FD_ISSET(fd, exceptfds))
9933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      events |= POLLERR | POLLHUP;
9943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
99568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (events) {
99668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pollfd info;
99768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      info.fd = fd;
99868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      info.events = events;
99968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pollfds.push_back(info);
10003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
100168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
10023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
100368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FD_ZERO(readfds);
100468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FD_ZERO(writefds);
100568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FD_ZERO(exceptfds);
10063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
100768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // NULL timeout signals wait forever.
100868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int ms_timeout = -1;
100968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (timeout != NULL) {
101068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int64_t ms = timeout->tv_sec * 1000 + ((timeout->tv_usec + 500) / 1000);
10113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
101268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // If the timeout is invalid or too long (larger than signed 32 bit).
101368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) ||
101468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) ||
101568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        (ms < 0) || (ms >= INT_MAX)) {
101668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      errno = EINVAL;
101768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return -1;
10183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
10193240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
102068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ms_timeout = static_cast<int>(ms);
10213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
10223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
102368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int result = poll(&pollfds[0], pollfds.size(), ms_timeout);
102468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (result == -1)
102568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return -1;
10263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
102768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int event_cnt = 0;
102868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t index = 0; index < pollfds.size(); index++) {
102968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pollfd* info = &pollfds[index];
103068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->revents & POLLIN) {
103168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FD_SET(info->fd, readfds);
103268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_cnt++;
10333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
103468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->revents & POLLOUT) {
103568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FD_SET(info->fd, writefds);
103668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_cnt++;
10373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
103868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->revents & (POLLHUP | POLLERR)) {
103968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FD_SET(info->fd, exceptfds);
104068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_cnt++;
10413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
10423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
10433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
104468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return event_cnt;
104568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
10463240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
104768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)struct PollInfo {
104868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  PollInfo() : index(-1) {};
10493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
105068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<struct pollfd*> fds;
105168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int index;
105268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
10533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
105468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)typedef std::map<EventEmitter*, PollInfo> EventPollMap_t;
10553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
10563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochint KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) {
105768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EventPollMap_t event_map;
10583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
105968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<EventRequest> requests;
10603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  size_t event_cnt = 0;
106168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
106268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (int index = 0; static_cast<nfds_t>(index) < nfds; index++) {
10633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    ScopedKernelHandle handle;
106468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    struct pollfd* fd_info = &fds[index];
106568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Error err = AcquireHandle(fd_info->fd, &handle);
106668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
106768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    fd_info->revents = 0;
10683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
10693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // If the node isn't open, or somehow invalid, mark it so.
10703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (err != 0) {
107168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      fd_info->revents = POLLNVAL;
10723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      event_cnt++;
10733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
10743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
10753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
10763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // If it's already signaled, then just capture the event
107768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ScopedEventEmitter emitter(handle->node()->GetEventEmitter());
107868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int events = POLLIN | POLLOUT;
107968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (emitter)
108068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      events = emitter->GetEventStatus();
108168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
108268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (events & fd_info->events) {
108368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      fd_info->revents = events & fd_info->events;
10843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      event_cnt++;
10853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
10863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
10873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
108868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (NULL == emitter) {
108968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      fd_info->revents = POLLNVAL;
10903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      event_cnt++;
10913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
10923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
109368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
109468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Otherwise try to track it.
109568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    PollInfo* info = &event_map[emitter.get()];
109668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->index == -1) {
109768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EventRequest request;
109868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      request.emitter = emitter;
109968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      request.filter = fd_info->events;
110068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      request.events = 0;
110168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
110268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      info->index = requests.size();
110368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      requests.push_back(request);
110468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
110568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    info->fds.push_back(fd_info);
110668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    requests[info->index].filter |= fd_info->events;
11073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
11083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
110968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // If nothing is signaled, then we must wait on the event map
11103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (0 == event_cnt) {
111168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EventListenerPoll wait;
111268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Error err = wait.WaitOnAny(&requests[0], requests.size(), timeout);
111368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if ((err != 0) && (err != ETIMEDOUT)) {
111468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      errno = err;
11153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return -1;
11163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
111768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
111868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    for (size_t rindex = 0; rindex < requests.size(); rindex++) {
111968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EventRequest* request = &requests[rindex];
112068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (request->events) {
112168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        PollInfo* poll_info = &event_map[request->emitter.get()];
112268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        for (size_t findex = 0; findex < poll_info->fds.size(); findex++) {
112368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          struct pollfd* fd_info = poll_info->fds[findex];
112468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          uint32_t events = fd_info->events & request->events;
112568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          if (events) {
112668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            fd_info->revents = events;
112768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            event_cnt++;
112868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          }
112968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        }
113068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
113168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
11323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
11333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
11343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return event_cnt;
11353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
11363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
11373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Socket Functions
1139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
1140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr || NULL == len) {
1141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1143a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1145a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
11464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
11474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
11484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
11504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1151a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
11524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  PP_Resource new_sock = 0;
11534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Accept(&new_sock, addr, len);
11544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
11554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
11564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
11574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
11584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
11594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  MountNodeSocket* sock = new MountNodeTCP(stream_mount_.get(), new_sock);
11604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
11614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // The MountNodeSocket now holds a reference to the new socket
11624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // so we release ours.
11634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ppapi_->ReleaseResource(new_sock);
1164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  error = sock->Init(O_RDWR);
11654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
11664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
11674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
11684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
11694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
11704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScopedMountNode node(sock);
11714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScopedKernelHandle new_handle(new KernelHandle(stream_mount_, node));
1172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  error = new_handle->Init(O_RDWR);
11731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (error != 0) {
11741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    errno = error;
11751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return -1;
11761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
11771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
11784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return AllocateFD(new_handle);
1179a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1180a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1181a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::bind(int fd, const struct sockaddr* addr, socklen_t len) {
1182a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1183a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1184a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1185a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1186a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1187a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1188a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1189a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1190a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
11913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->Bind(addr, len);
11923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
11933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
11943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
11953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
11963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
11973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1198a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1199a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1200a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) {
1201a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1202a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1203a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1204a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1205a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1206a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
12074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
12084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
12094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1210a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
12114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1212a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
12134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Connect(addr, len);
12144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
12154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
12163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
12173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
12183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
12193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1220a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1221a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1222bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochstruct hostent* KernelProxy::gethostbyname(const char* name) {
1223bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return host_resolver_.gethostbyname(name);
1224bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
1225bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1226a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
1227a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr || NULL == len) {
1228a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1229a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1230a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1231a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1232a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1233a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1234a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1235a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
12363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->GetPeerName(addr, len);
12373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
12383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
12393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
12403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
12413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
12423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1243a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1244a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1245a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
1246a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr || NULL == len) {
1247a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1248a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1249a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1250a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1251a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1252a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1253a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1254a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
12553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->GetSockName(addr, len);
12563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
12573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
12583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
12593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
12603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
12613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1262a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1263a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1264a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::getsockopt(int fd,
12654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            int lvl,
12664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            int optname,
12674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            void* optval,
12684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            socklen_t* len) {
1269a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == optval || NULL == len) {
1270a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1271a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1272a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1273a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1274a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1275a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1276a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1277a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
12784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = handle->socket_node()->GetSockOpt(lvl, optname, optval, len);
12794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != 0) {
12804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = err;
12814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
12824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
12834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
12844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0;
1285a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1286a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1287a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::listen(int fd, int backlog) {
1288a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1289a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1290a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1291a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
12924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = handle->socket_node()->Listen(backlog);
12934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != 0) {
12944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = err;
12954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
12964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
12974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
12984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0;
1299a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1300a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1301a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::recv(int fd,
1302a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          void* buf,
1303a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          size_t len,
1304a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          int flags) {
1305a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf) {
1306a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1307a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1308a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1309a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1310a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
13114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
13124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
13134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1314a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
13154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1316a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
13184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Recv(buf, len, flags, &out_len);
13194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
13204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
13213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
13223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
13233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
13243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1325a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1326a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1327a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::recvfrom(int fd,
1328a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              void* buf,
1329a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              size_t len,
1330a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              int flags,
1331a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              struct sockaddr* addr,
1332a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              socklen_t* addrlen) {
1333a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // According to the manpage, recvfrom with a null addr is identical to recv.
1334a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1335a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return recv(fd, buf, len, flags);
1336a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1337a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1338a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf || NULL == addrlen) {
1339a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1340a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1341a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1342a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1343a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
13444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
13454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
13464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1347a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
13484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1349a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
13514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->RecvFrom(buf, len, flags, addr, addrlen, &out_len);
13524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
13534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
13543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
13553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
13563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
13573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1358a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1359a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1360a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) {
1361a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == msg ) {
1362a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1363a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1364a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1365a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1366a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1367a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1368a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1369a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1370a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = EOPNOTSUPP;
1371a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1372a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1373a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1374a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::send(int fd, const void* buf, size_t len, int flags) {
1375a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf) {
1376a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1377a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1378a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1379a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1380a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
13814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
13824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
13834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1384a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
13854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1386a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
13884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Send(buf, len, flags, &out_len);
13894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
13904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
13913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
13923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
13933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
13943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1395a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1396a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1397a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::sendto(int fd,
1398a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const void* buf,
1399a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            size_t len,
1400a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            int flags,
1401a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const struct sockaddr* addr,
1402a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            socklen_t addrlen) {
1403a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // According to the manpage, sendto with a null addr is identical to send.
1404a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1405a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return send(fd, buf, len, flags);
1406a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1407a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1408a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf) {
1409a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1410a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1411a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1412a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1413a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
14144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
14154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
14164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1417a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
14184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1419a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
14203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
14214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->SendTo(buf, len, flags, addr, addrlen, &out_len);
14224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
14234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
14243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
14253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
14263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
14273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1428a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1429a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1430a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::sendmsg(int fd, const struct msghdr* msg, int flags) {
1431a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == msg) {
1432a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1433a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1434a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1435a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1436a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1437a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1438a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1439a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1440a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = EOPNOTSUPP;
1441a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1442a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1443a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1444a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::setsockopt(int fd,
1445a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            int lvl,
1446a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            int optname,
1447a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const void* optval,
1448a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            socklen_t len) {
1449a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == optval) {
1450a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1451a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1452a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1453a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1454a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1455a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1456a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1457a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
14584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = handle->socket_node()->SetSockOpt(lvl, optname, optval, len);
14594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != 0) {
14604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = err;
14614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
14624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
14634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
14644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0;
1465a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1466a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1467a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::shutdown(int fd, int how) {
1468a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1469a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1470a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1471a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
14723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->Shutdown(how);
14733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
14743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
14753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
14763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
14773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
14783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1479a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1480a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1481a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::socket(int domain, int type, int protocol) {
1482a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AF_INET != domain && AF_INET6 != domain) {
1483a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EAFNOSUPPORT;
1484a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1485a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1486a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1487f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int open_flags = O_RDWR;
1488f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1489f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (type & SOCK_CLOEXEC) {
1490f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#ifdef O_CLOEXEC
1491f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // The NaCl newlib version of fcntl.h doesn't currently define
1492f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // O_CLOEXEC.
1493f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // TODO(sbc): remove this guard once it gets added.
1494f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    open_flags |= O_CLOEXEC;
1495f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
1496f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    type &= ~SOCK_CLOEXEC;
1497f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1498f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1499f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (type & SOCK_NONBLOCK) {
1500f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    open_flags |= O_NONBLOCK;
1501f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    type &= ~SOCK_NONBLOCK;
1502f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1503f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
15043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  MountNodeSocket* sock = NULL;
15053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (type) {
15063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SOCK_DGRAM:
150768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      sock = new MountNodeUDP(stream_mount_.get());
15083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
15093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
15103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SOCK_STREAM:
151168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      sock = new MountNodeTCP(stream_mount_.get());
15123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
15133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1514f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SOCK_SEQPACKET:
1515f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SOCK_RDM:
1516f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SOCK_RAW:
15173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      errno = EPROTONOSUPPORT;
15183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return -1;
1519f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1520f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    default:
1521f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      errno = EINVAL;
1522f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return -1;
1523a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1524a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
15253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ScopedMountNode node(sock);
1526f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Error rtn = sock->Init(O_RDWR);
15274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (rtn != 0) {
15284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = rtn;
15294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
15303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
15313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
15324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScopedKernelHandle handle(new KernelHandle(stream_mount_, node));
1533f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  rtn = handle->Init(open_flags);
15341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (rtn != 0) {
15351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    errno = rtn;
15361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return -1;
15371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
15381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
15394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return AllocateFD(handle);
1540a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1541a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1542a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::socketpair(int domain, int type, int protocol, int* sv) {
1543a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == sv) {
1544a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1545a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1546a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1547a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1548a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Catch-22: We don't support AF_UNIX, but any other AF doesn't support
1549a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // socket pairs. Thus, this function always fails.
1550a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AF_UNIX != domain) {
1551a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EPROTONOSUPPORT;
1552a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1553a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1554a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1555a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AF_INET != domain && AF_INET6 != domain) {
1556a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EAFNOSUPPORT;
1557a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1558a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1559a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1560a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // We cannot reach this point.
1561a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = ENOSYS;
1562a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1563a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1564a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1565a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::AcquireSocketHandle(int fd, ScopedKernelHandle* handle) {
1566a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Error error = AcquireHandle(fd, handle);
1567a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1568a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (error) {
1569a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = error;
1570a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1571a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1572a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1573a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if ((handle->get()->node_->GetType() & S_IFSOCK) == 0) {
1574a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = ENOTSOCK;
1575a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1576a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1577a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1578a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return 0;
1579a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1580a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1581bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#endif  // PROVIDES_SOCKET_API
1582a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1583bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}  // namespace_nacl_io
1584