kernel_proxy.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
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)
73240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <assert.h>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <errno.h>
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <fcntl.h>
113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <limits.h>
123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <poll.h>
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <pthread.h>
14a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include <stdio.h>
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string.h>
163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <sys/time.h>
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <unistd.h>
183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <iterator>
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "nacl_io/dbgprint.h"
23bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "nacl_io/host_resolver.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/kernel_handle.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/kernel_wrap_real.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_dev.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_html5fs.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_http.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_mem.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_node.h"
3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "nacl_io/mount_node_pipe.h"
333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "nacl_io/mount_node_tcp.h"
343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "nacl_io/mount_node_udp.h"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_passthrough.h"
3668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "nacl_io/mount_stream.h"
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osmman.h"
38a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "nacl_io/ossocket.h"
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osstat.h"
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/path.h"
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/pepper_interface.h"
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "nacl_io/typed_mount_factory.h"
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/auto_lock.h"
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/ref_object.h"
4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "sdk_util/string_util.h"
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef MAXPATHLEN
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define MAXPATHLEN 256
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
51ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace nacl_io {
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL),
553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                             sigwinch_handler_(SIG_IGN),
5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                             signal_emitter_(new EventEmitter) {
573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochKernelProxy::~KernelProxy() {
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Clean up the MountFactories.
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (MountFactoryMap_t::iterator i = factories_.begin();
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       i != factories_.end();
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       ++i) {
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    delete i->second;
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  delete ppapi_;
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)Error KernelProxy::Init(PepperInterface* ppapi) {
7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Error rtn = 0;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ppapi_ = ppapi;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dev_ = 1;
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["memfs"] = new TypedMountFactory<MountMem>;
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["dev"] = new TypedMountFactory<MountDev>;
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["html5fs"] = new TypedMountFactory<MountHtml5Fs>;
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["httpfs"] = new TypedMountFactory<MountHttp>;
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["passthroughfs"] = new TypedMountFactory<MountPassthrough>;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result;
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  result = mount("", "/", "passthroughfs", 0, NULL);
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (result != 0) {
8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    assert(false);
8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  result = mount("", "/dev", "dev", 0, NULL);
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (result != 0) {
9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    assert(false);
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Open the first three in order to get STDIN, STDOUT, STDERR
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int fd;
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  fd = open("/dev/stdin", O_RDONLY);
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert(fd == 0);
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (fd < 0)
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  fd = open("/dev/stdout", O_WRONLY);
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert(fd == 1);
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (fd < 0)
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  fd = open("/dev/stderr", O_WRONLY);
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert(fd == 2);
10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (fd < 0)
11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
111bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
112bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#ifdef PROVIDES_SOCKET_API
113bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  host_resolver_.Init(ppapi_);
114bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#endif
1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StringMap_t args;
11768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  stream_mount_.reset(new MountStream());
11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  result = stream_mount_->Init(0, args, ppapi);
11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (result != 0) {
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    assert(false);
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = result;
12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return rtn;
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint KernelProxy::open_resource(const char* path) {
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMount mnt;
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMountNode node;
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = mnt->OpenResource(rel, &node);
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // OpenResource failed, try Open().
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    error = mnt->Open(rel, O_RDONLY, &node);
1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (error) {
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      errno = error;
1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return -1;
1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedKernelHandle handle(new KernelHandle(mnt, node));
1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Init(O_RDONLY);
1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return AllocateFD(handle);
1567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint KernelProxy::open(const char* path, int oflags) {
1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMount mnt;
1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMountNode node;
1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndNode(path, oflags, &mnt, &node);
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle(new KernelHandle(mnt, node));
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = handle->Init(oflags);
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return AllocateFD(handle);
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int KernelProxy::pipe(int pipefds[2]) {
17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  MountNodePipe* pipe = new MountNodePipe(stream_mount_.get());
18068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ScopedMountNode node(pipe);
18168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (pipe->Init(S_IREAD | S_IWRITE) == 0) {
18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ScopedKernelHandle handle0(new KernelHandle(stream_mount_, node));
18468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ScopedKernelHandle handle1(new KernelHandle(stream_mount_, node));
18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Should never fail, but...
18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (handle0->Init(S_IREAD) || handle1->Init(S_IWRITE)) {
18868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      errno = EACCES;
18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return -1;
19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pipefds[0] = AllocateFD(handle0);
19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pipefds[1] = AllocateFD(handle1);
19468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return 0;
19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
19668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
19768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  errno = ENOSYS;
19868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return -1;
19968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
20068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::close(int fd) {
202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Remove the FD from the process open file descriptor map
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FreeFD(fd);
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::dup(int oldfd) {
215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(oldfd, &handle);
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return AllocateFD(handle);
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::dup2(int oldfd, int newfd) {
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If it's the same file handle, just return
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (oldfd == newfd)
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return newfd;
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle old_handle;
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(oldfd, &old_handle);
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FreeAndReassignFD(newfd, old_handle);
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return newfd;
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint KernelProxy::chdir(const char* path) {
2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = SetCWD(path);
2437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
2447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
2457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
2467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return 0;
2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)char* KernelProxy::getcwd(char* buf, size_t size) {
2517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string cwd = GetCWD();
2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (size <= 0) {
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = EINVAL;
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If size is 0, allocate as much as we need.
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (size == 0) {
2607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    size = cwd.size() + 1;
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify the buffer is large enough
2647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (size <= cwd.size()) {
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = ERANGE;
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Allocate the buffer if needed
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (buf == NULL) {
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    buf = static_cast<char*>(malloc(size));
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  strcpy(buf, cwd.c_str());
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return buf;
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)char* KernelProxy::getwd(char* buf) {
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == buf) {
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = EFAULT;
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return getcwd(buf, MAXPATHLEN);
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::chmod(const char* path, mode_t mode) {
287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int fd = KernelProxy::open(path, O_RDONLY);
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (-1 == fd)
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result = fchmod(fd, mode);
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  close(fd);
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::chown(const char* path, uid_t owner, gid_t group) {
297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::fchown(int fd, uid_t owner, gid_t group) {
301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::lchown(const char* path, uid_t owner, gid_t group) {
305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::utime(const char* filename, const struct utimbuf* times) {
309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::mkdir(const char* path, mode_t mode) {
313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMount mnt;
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
3157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = mnt->Mkdir(rel, mode);
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::rmdir(const char* path) {
332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMount mnt;
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
3347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = mnt->Rmdir(rel);
342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::stat(const char* path, struct stat* buf) {
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = open(path, O_RDONLY);
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (-1 == fd)
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result = fstat(fd, buf);
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  close(fd);
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::mount(const char* source,
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const char* target,
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const char* filesystemtype,
364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       unsigned long mountflags,
365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const void* data) {
3667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string abs_path = GetAbsParts(target).Join();
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Find a factory of that type
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MountFactoryMap_t::iterator factory = factories_.find(filesystemtype);
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (factory == factories_.end()) {
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = ENODEV;
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Create a map of settings
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StringMap_t smap;
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  smap["SOURCE"] = source;
3787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  smap["TARGET"] = abs_path;
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (data) {
38158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::vector<std::string> elements;
38258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    sdk_util::SplitString(static_cast<const char*>(data), ',', &elements);
38358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
38458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    for (std::vector<std::string>::const_iterator it = elements.begin();
38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)         it != elements.end(); ++it) {
38658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      size_t location = it->find('=');
38758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (location != std::string::npos) {
38858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        std::string key = it->substr(0, location);
38958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        std::string val = it->substr(location + 1);
39058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        smap[key] = val;
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
39258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        smap[*it] = "TRUE";
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMount mnt;
3987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = factory->second->CreateMount(dev_++, smap, ppapi_, &mnt);
3997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
4007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
4017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
4027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
4037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = AttachMountAtPath(mnt, abs_path);
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return 0;
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::umount(const char* path) {
4147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = DetachMountAtPath(path);
4157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
4167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ssize_t KernelProxy::read(int fd, void* buf, size_t nbytes) {
423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
4317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Read(buf, nbytes, &cnt);
432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
436868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ssize_t KernelProxy::write(int fd, const void* buf, size_t nbytes) {
441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
445868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
446868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
4497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Write(buf, nbytes, &cnt);
450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fstat(int fd, struct stat* buf) {
459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
463868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->GetStat(buf);
467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
470868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::getdents(int fd, void* buf, unsigned int count) {
476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
477868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
478868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
483868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
4847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->GetDents(static_cast<dirent*>(buf), count, &cnt);
485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error)
486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
49190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int KernelProxy::ftruncate(int fd, off_t length) {
492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
493868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
495868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
49890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->FTruncate(length);
500868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
501868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
503868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
50490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
50690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
50790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fsync(int fd) {
509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->FSync();
517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::isatty(int fd) {
526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->IsaTTY();
534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
542bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint KernelProxy::ioctl(int fd, int request, char* argp) {
543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
544bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->Ioctl(request, argp);
551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)off_t KernelProxy::lseek(int fd, off_t offset, int whence) {
560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
565868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  off_t new_offset;
568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = handle->Seek(offset, whence, &new_offset);
569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return new_offset;
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::unlink(const char* path) {
578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMount mnt;
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
5807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
584868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
586868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = mnt->Unlink(rel);
588868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::remove(const char* path) {
597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMount mnt;
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
5997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
6007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
601868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
602868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
603868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = mnt->Remove(rel);
607868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
610868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(noelallen): Needs implementation.
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fchmod(int fd, int mode) {
617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
618eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Error error = AcquireHandle(fd, &handle);
619eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
620eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
621eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
622eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
623eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
624eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
62768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int KernelProxy::fcntl(int fd, int request, char *argp) {
62868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ScopedKernelHandle handle;
62968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
63068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error) {
63168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    errno = error;
63268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return -1;
63368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
63468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
63568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // TODO(sbc): Needs implementation.
63668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  errno = ENOSYS;
63768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return -1;
63868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
63968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::access(const char* path, int amode) {
6417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMount mnt;
642eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Path rel;
643eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
645eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
646eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
647eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
649eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
650eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  error = mnt->Access(rel, amode);
651eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
653eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
655eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
658eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// TODO(noelallen): Needs implementation.
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::link(const char* oldpath, const char* newpath) {
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::symlink(const char* oldpath, const char* newpath) {
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
669868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void* KernelProxy::mmap(void* addr,
670868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        size_t length,
671868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int prot,
672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int flags,
673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int fd,
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        size_t offset) {
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We shouldn't be getting anonymous mmaps here.
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert((flags & MAP_ANONYMOUS) == 0);
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert(fd != -1);
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
679eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
680868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
681868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
682868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return MAP_FAILED;
684868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void* new_addr;
6877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->MMap(addr, length, prot, flags, offset, &new_addr);
688eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
689eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
690eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return MAP_FAILED;
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return new_addr;
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::munmap(void* addr, size_t length) {
69790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // NOTE: The comment below is from a previous discarded implementation that
69890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // tracks mmap'd regions. For simplicity, we no longer do this; because we
69990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // "snapshot" the contents of the file in mmap(), and don't support
70090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // write-back or updating the mapped region when the file is written, holding
70190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // on to the KernelHandle is pointless.
70290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
70390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If we ever do, these threading issues should be considered.
70490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
70590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
70690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // WARNING: this function may be called by free().
70790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
70890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // There is a potential deadlock scenario:
70990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Thread 1: open() -> takes lock1 -> free() -> takes lock2
71090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Thread 2: free() -> takes lock2 -> munmap() -> takes lock1
71190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
71290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Note that open() above could be any function that takes a lock that is
71390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // shared with munmap (this includes munmap!)
71490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
71590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // To prevent this, we avoid taking locks in munmap() that are used by other
71690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // nacl_io functions that may call free. Specifically, we only take the
71790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // mmap_lock, which is only shared with mmap() above. There is still a
71890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // possibility of deadlock if mmap() or munmap() calls free(), so this is not
71990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // allowed.
72090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
72190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Unfortunately, munmap still needs to acquire other locks; see the call to
72290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // ReleaseHandle below which takes the process lock. This is safe as long as
72390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // this is never executed from free() -- we can be reasonably sure this is
72490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // true, because malloc only makes anonymous mmap() requests, and should only
72590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // be munmapping those allocations. We never add to mmap_info_list_ for
72690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // anonymous maps, so the unmap_list should always be empty when called from
72790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // free().
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
731bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint KernelProxy::tcflush(int fd, int queue_selector) {
732bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ScopedKernelHandle handle;
733bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
734bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
735bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
736bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
737bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
738bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
739bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  error = handle->node()->Tcflush(queue_selector);
740bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
741bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
742bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
743bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
744bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
745bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return 0;
746bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
747bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
748bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint KernelProxy::tcgetattr(int fd, struct termios* termios_p) {
749bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ScopedKernelHandle handle;
750bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
751bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
752bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
753bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
754bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
755bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
756bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  error = handle->node()->Tcgetattr(termios_p);
757bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
758bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
759bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
760bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
761bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
762bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return 0;
763bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
764bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
765bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint KernelProxy::tcsetattr(int fd, int optional_actions,
766bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                           const struct termios *termios_p) {
767bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ScopedKernelHandle handle;
768bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
769bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
770bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
771bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
772bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
773bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
774bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  error = handle->node()->Tcsetattr(optional_actions, termios_p);
775bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
776bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
777bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
778bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
779bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
780bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return 0;
781bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
782bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
7833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int KernelProxy::kill(pid_t pid, int sig) {
7843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Currently we don't even pretend that other processes exist
7853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // so we can only send a signal to outselves.  For kill(2)
7863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // pid 0 means the current process group and -1 means all the
7873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // processes we have permission to send signals to.
7883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (pid != getpid() && pid != -1 && pid != 0) {
7893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = ESRCH;
7903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
7913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
7923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Raise an event so that select/poll get interrupted.
79468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  AUTO_LOCK(signal_emitter_->GetLock())
79568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  signal_emitter_->RaiseEvents_Locked(POLLERR);
7963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (sig) {
7973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGWINCH:
7983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      if (sigwinch_handler_ != SIG_IGN)
7993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        sigwinch_handler_(SIGWINCH);
8003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
8013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
8023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGUSR1:
8033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGUSR2:
8043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
8053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
8063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    default:
8073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      errno = EINVAL;
8083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return -1;
8093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
8103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
8113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
8123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
8133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)sighandler_t KernelProxy::sigset(int signum, sighandler_t handler) {
8143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (signum) {
8153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Handled signals.
8163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGWINCH: {
8173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      sighandler_t old_value = sigwinch_handler_;
8183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      if (handler == SIG_DFL)
8193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        handler = SIG_IGN;
8203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      sigwinch_handler_ = handler;
8213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return old_value;
8223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
8233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
8243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Known signals
8253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGHUP:
8263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGINT:
8273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGKILL:
8283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGPIPE:
8293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGPOLL:
8303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGPROF:
8313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGTERM:
8323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGCHLD:
8333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGURG:
8343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGFPE:
8353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGILL:
8363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGQUIT:
8373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGSEGV:
8383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGTRAP:
8393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      if (handler == SIG_DFL)
8403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        return SIG_DFL;
8413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
8423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
8433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
8443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  errno = EINVAL;
8453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return SIG_ERR;
8463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
8473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
848a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#ifdef PROVIDES_SOCKET_API
849ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
8503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochint KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds,
8513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                        fd_set* exceptfds, struct timeval* timeout) {
85268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  fd_set ignore;
85368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<pollfd> pollfds;
85468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
85568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Simplify logic, by using an IGNORE set for any undefined set
85668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FD_ZERO(&ignore);
85768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (NULL == readfds)
85868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    readfds = &ignore;
85968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (NULL == writefds)
86068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    writefds = &ignore;
86168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (NULL == exceptfds)
86268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    exceptfds = &ignore;
86368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
86468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (int fd = 0; fd < nfds; fd++) {
8653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    int events = 0;
86668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (FD_ISSET(fd, readfds))
8673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      events |= POLLIN;
8683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
86968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (FD_ISSET(fd, writefds))
8703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      events |= POLLOUT;
8713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
87268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (FD_ISSET(fd, exceptfds))
8733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      events |= POLLERR | POLLHUP;
8743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
87568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (events) {
87668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pollfd info;
87768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      info.fd = fd;
87868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      info.events = events;
87968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pollfds.push_back(info);
8803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
88168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
8823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
88368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FD_ZERO(readfds);
88468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FD_ZERO(writefds);
88568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FD_ZERO(exceptfds);
8863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
88768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // NULL timeout signals wait forever.
88868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int ms_timeout = -1;
88968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (timeout != NULL) {
89068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int64_t ms = timeout->tv_sec * 1000 + ((timeout->tv_usec + 500) / 1000);
8913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
89268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // If the timeout is invalid or too long (larger than signed 32 bit).
89368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) ||
89468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) ||
89568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        (ms < 0) || (ms >= INT_MAX)) {
89668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      errno = EINVAL;
89768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return -1;
8983240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
8993240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
90068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ms_timeout = static_cast<int>(ms);
9013240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
9023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
90368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int result = poll(&pollfds[0], pollfds.size(), ms_timeout);
90468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (result == -1)
90568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return -1;
9063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
90768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int event_cnt = 0;
90868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t index = 0; index < pollfds.size(); index++) {
90968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pollfd* info = &pollfds[index];
91068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->revents & POLLIN) {
91168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FD_SET(info->fd, readfds);
91268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_cnt++;
9133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
91468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->revents & POLLOUT) {
91568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FD_SET(info->fd, writefds);
91668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_cnt++;
9173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
91868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->revents & (POLLHUP | POLLERR)) {
91968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FD_SET(info->fd, exceptfds);
92068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_cnt++;
9213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
9223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
9233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
92468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return event_cnt;
92568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
9263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
92768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)struct PollInfo {
92868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  PollInfo() : index(-1) {};
9293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
93068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<struct pollfd*> fds;
93168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int index;
93268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
9333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
93468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)typedef std::map<EventEmitter*, PollInfo> EventPollMap_t;
9353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
9363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochint KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) {
93768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EventPollMap_t event_map;
9383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
93968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<EventRequest> requests;
9403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  size_t event_cnt = 0;
94168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
94268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (int index = 0; static_cast<nfds_t>(index) < nfds; index++) {
9433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    ScopedKernelHandle handle;
94468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    struct pollfd* fd_info = &fds[index];
94568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Error err = AcquireHandle(fd_info->fd, &handle);
94668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
94768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    fd_info->revents = 0;
9483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
9493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // If the node isn't open, or somehow invalid, mark it so.
9503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (err != 0) {
95168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      fd_info->revents = POLLNVAL;
9523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      event_cnt++;
9533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
9543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
9553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
9563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // If it's already signaled, then just capture the event
95768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ScopedEventEmitter emitter(handle->node()->GetEventEmitter());
95868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int events = POLLIN | POLLOUT;
95968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (emitter)
96068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      events = emitter->GetEventStatus();
96168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
96268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (events & fd_info->events) {
96368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      fd_info->revents = events & fd_info->events;
9643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      event_cnt++;
9653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
9663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
9673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
96868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (NULL == emitter) {
96968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      fd_info->revents = POLLNVAL;
9703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      event_cnt++;
9713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
9723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
97368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
97468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Otherwise try to track it.
97568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    PollInfo* info = &event_map[emitter.get()];
97668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->index == -1) {
97768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EventRequest request;
97868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      request.emitter = emitter;
97968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      request.filter = fd_info->events;
98068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      request.events = 0;
98168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
98268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      info->index = requests.size();
98368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      requests.push_back(request);
98468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
98568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    info->fds.push_back(fd_info);
98668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    requests[info->index].filter |= fd_info->events;
9873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
9883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
98968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // If nothing is signaled, then we must wait on the event map
9903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (0 == event_cnt) {
99168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EventListenerPoll wait;
99268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Error err = wait.WaitOnAny(&requests[0], requests.size(), timeout);
99368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if ((err != 0) && (err != ETIMEDOUT)) {
99468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      errno = err;
9953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return -1;
9963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
99768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
99868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    for (size_t rindex = 0; rindex < requests.size(); rindex++) {
99968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EventRequest* request = &requests[rindex];
100068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (request->events) {
100168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        PollInfo* poll_info = &event_map[request->emitter.get()];
100268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        for (size_t findex = 0; findex < poll_info->fds.size(); findex++) {
100368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          struct pollfd* fd_info = poll_info->fds[findex];
100468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          uint32_t events = fd_info->events & request->events;
100568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          if (events) {
100668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            fd_info->revents = events;
100768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            event_cnt++;
100868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          }
100968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        }
101068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
101168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
10123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
10133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
10143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return event_cnt;
10153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
10163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
10173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
10183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1019a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Socket Functions
1020a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
1021a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr || NULL == len) {
1022a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1023a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1024a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1025a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1026a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1027a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1028a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1029a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1030a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = EINVAL;
1031a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1032a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1033a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1034a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::bind(int fd, const struct sockaddr* addr, socklen_t len) {
1035a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1036a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1037a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1038a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1039a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1040a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1041a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1042a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1043a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
10443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->Bind(addr, len);
10453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
10463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
10473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
10483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
10493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
10503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1051a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1052a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1053a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) {
1054a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1055a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1056a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1057a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1058a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1059a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1060a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1061a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1062a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
10633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->Connect(addr, len);
10643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
10653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
10663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
10673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
10683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
10693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1070a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1071a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1072bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochstruct hostent* KernelProxy::gethostbyname(const char* name) {
1073bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return host_resolver_.gethostbyname(name);
1074bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
1075bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1076a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
1077a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr || NULL == len) {
1078a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1079a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1080a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1081a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1082a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1083a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1084a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1085a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
10863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->GetPeerName(addr, len);
10873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
10883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
10893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
10903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
10913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
10923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1093a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1094a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1095a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
1096a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr || NULL == len) {
1097a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1098a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1099a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1103a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
11053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->GetSockName(addr, len);
11063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
11073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
11083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
11093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
11103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
11113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::getsockopt(int fd,
1115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                         int lvl,
1116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                         int optname,
1117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                         void* optval,
1118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                         socklen_t* len) {
1119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == optval || NULL == len) {
1120a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1121a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1125a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1126a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1128a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = EINVAL;
1129a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1131a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1132a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::listen(int fd, int backlog) {
1133a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = EOPNOTSUPP;
1138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::recv(int fd,
1142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          void* buf,
1143a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          size_t len,
1144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          int flags) {
1145a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf) {
1146a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1150a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1151a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1152a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1153a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
11543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
11553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->Recv(buf, len, flags, &out_len);
11563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
11573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
11583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
11593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
11603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
11613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::recvfrom(int fd,
1165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              void* buf,
1166a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              size_t len,
1167a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              int flags,
1168a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              struct sockaddr* addr,
1169a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              socklen_t* addrlen) {
1170a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // According to the manpage, recvfrom with a null addr is identical to recv.
1171a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1172a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return recv(fd, buf, len, flags);
1173a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1174a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1175a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf || NULL == addrlen) {
1176a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1177a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1178a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1179a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1180a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1181a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1182a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1183a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
11843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
11853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->RecvFrom(buf,
11863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              len,
11873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              flags,
11883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              addr,
11893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              addrlen,
11903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              &out_len);
11913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
11923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
11933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
11943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
11953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
11963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1197a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1198a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1199a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) {
1200a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == msg ) {
1201a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1202a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1203a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1204a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1205a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1206a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1207a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1208a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1209a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = EOPNOTSUPP;
1210a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1211a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1212a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1213a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::send(int fd, const void* buf, size_t len, int flags) {
1214a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf) {
1215a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1216a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1217a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1218a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1219a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1220a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1221a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1222a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
12233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
12243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->Send(buf, len, flags, &out_len);
12253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
12263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
12273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
12283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
12293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
12303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1231a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1232a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1233a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::sendto(int fd,
1234a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const void* buf,
1235a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            size_t len,
1236a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            int flags,
1237a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const struct sockaddr* addr,
1238a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            socklen_t addrlen) {
1239a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // According to the manpage, sendto with a null addr is identical to send.
1240a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1241a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return send(fd, buf, len, flags);
1242a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1243a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1244a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf) {
1245a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1246a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1247a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1248a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1249a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1250a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1251a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1252a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
12533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
12543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err =
12553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      handle->socket_node()->SendTo(buf, len, flags, addr, addrlen, &out_len);
12563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
12573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
12583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
12593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
12603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
12613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
12623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1263a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1264a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1265a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::sendmsg(int fd, const struct msghdr* msg, int flags) {
1266a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == msg) {
1267a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1268a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1269a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1270a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1271a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1272a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1273a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1274a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1275a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = EOPNOTSUPP;
1276a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1277a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1278a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1279a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::setsockopt(int fd,
1280a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            int lvl,
1281a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            int optname,
1282a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const void* optval,
1283a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            socklen_t len) {
1284a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == optval) {
1285a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1286a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1287a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1288a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1289a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1290a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1291a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1292a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1293a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = EINVAL;
1294a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1295a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1296a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1297a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::shutdown(int fd, int how) {
1298a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1299a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1300a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1301a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->Shutdown(how);
13033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
13043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
13053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
13063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
13073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
13083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1309a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1310a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1311a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::socket(int domain, int type, int protocol) {
1312a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AF_INET != domain && AF_INET6 != domain) {
1313a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EAFNOSUPPORT;
1314a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1315a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1316a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  MountNodeSocket* sock = NULL;
13183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (type) {
13193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SOCK_DGRAM:
132068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      sock = new MountNodeUDP(stream_mount_.get());
13213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
13223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
13233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SOCK_STREAM:
132468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      sock = new MountNodeTCP(stream_mount_.get());
13253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
13263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
13273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    default:
13283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      errno = EPROTONOSUPPORT;
13293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return -1;
1330a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1331a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ScopedMountNode node(sock);
13333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (sock->Init(S_IREAD | S_IWRITE) == 0) {
133468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ScopedKernelHandle handle(new KernelHandle(stream_mount_, node));
13353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return AllocateFD(handle);
13363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
13373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
13383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // If we failed to init, assume we don't have access.
13393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return EACCES;
1340a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1341a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1342a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::socketpair(int domain, int type, int protocol, int* sv) {
1343a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == sv) {
1344a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1345a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1346a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1347a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1348a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Catch-22: We don't support AF_UNIX, but any other AF doesn't support
1349a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // socket pairs. Thus, this function always fails.
1350a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AF_UNIX != domain) {
1351a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EPROTONOSUPPORT;
1352a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1353a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1354a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1355a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AF_INET != domain && AF_INET6 != domain) {
1356a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EAFNOSUPPORT;
1357a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1358a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1359a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1360a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // We cannot reach this point.
1361a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = ENOSYS;
1362a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1363a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1364a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1365a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::AcquireSocketHandle(int fd, ScopedKernelHandle* handle) {
1366a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Error error = AcquireHandle(fd, handle);
1367a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1368a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (error) {
1369a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = error;
1370a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1371a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1372a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1373a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if ((handle->get()->node_->GetType() & S_IFSOCK) == 0) {
1374a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = ENOTSOCK;
1375a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1376a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1377a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1378a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return 0;
1379a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1380a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1381bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#endif  // PROVIDES_SOCKET_API
1382a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1383bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}  // namespace_nacl_io
1384